bridge.js 29 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010
  1. 'use strict';
  2. /**
  3. * __ ___ ____ _ _ ___ _ _ ____
  4. * \ \ / / \ | _ \| \ | |_ _| \ | |/ ___|
  5. * \ \ /\ / / _ \ | |_) | \| || || \| | | _
  6. * \ V V / ___ \| _ <| |\ || || |\ | |_| |
  7. * \_/\_/_/ \_\_| \_\_| \_|___|_| \_|\____|
  8. *
  9. * This file is critical for vm2. It implements the bridge between the host and the sandbox.
  10. * If you do not know exactly what you are doing, you should NOT edit this file.
  11. *
  12. * The file is loaded in the host and sandbox to handle objects in both directions.
  13. * This is done to ensure that RangeErrors are from the correct context.
  14. * The boundary between the sandbox and host might throw RangeErrors from both contexts.
  15. * Therefore, thisFromOther and friends can handle objects from both domains.
  16. *
  17. * Method parameters have comments to tell from which context they came.
  18. *
  19. */
  20. const globalsList = [
  21. 'Number',
  22. 'String',
  23. 'Boolean',
  24. 'Date',
  25. 'RegExp',
  26. 'Map',
  27. 'WeakMap',
  28. 'Set',
  29. 'WeakSet',
  30. 'Promise',
  31. 'Function'
  32. ];
  33. const errorsList = [
  34. 'RangeError',
  35. 'ReferenceError',
  36. 'SyntaxError',
  37. 'TypeError',
  38. 'EvalError',
  39. 'URIError',
  40. 'Error'
  41. ];
  42. const OPNA = 'Operation not allowed on contextified object.';
  43. const thisGlobalPrototypes = {
  44. __proto__: null,
  45. Object: Object.prototype,
  46. Array: Array.prototype
  47. };
  48. for (let i = 0; i < globalsList.length; i++) {
  49. const key = globalsList[i];
  50. const g = global[key];
  51. if (g) thisGlobalPrototypes[key] = g.prototype;
  52. }
  53. for (let i = 0; i < errorsList.length; i++) {
  54. const key = errorsList[i];
  55. const g = global[key];
  56. if (g) thisGlobalPrototypes[key] = g.prototype;
  57. }
  58. const {
  59. getPrototypeOf: thisReflectGetPrototypeOf,
  60. setPrototypeOf: thisReflectSetPrototypeOf,
  61. defineProperty: thisReflectDefineProperty,
  62. deleteProperty: thisReflectDeleteProperty,
  63. getOwnPropertyDescriptor: thisReflectGetOwnPropertyDescriptor,
  64. isExtensible: thisReflectIsExtensible,
  65. preventExtensions: thisReflectPreventExtensions,
  66. apply: thisReflectApply,
  67. construct: thisReflectConstruct,
  68. set: thisReflectSet,
  69. get: thisReflectGet,
  70. has: thisReflectHas,
  71. ownKeys: thisReflectOwnKeys,
  72. enumerate: thisReflectEnumerate,
  73. } = Reflect;
  74. const thisObject = Object;
  75. const {
  76. freeze: thisObjectFreeze,
  77. prototype: thisObjectPrototype
  78. } = thisObject;
  79. const thisObjectHasOwnProperty = thisObjectPrototype.hasOwnProperty;
  80. const ThisProxy = Proxy;
  81. const ThisWeakMap = WeakMap;
  82. const {
  83. get: thisWeakMapGet,
  84. set: thisWeakMapSet
  85. } = ThisWeakMap.prototype;
  86. const ThisMap = Map;
  87. const thisMapGet = ThisMap.prototype.get;
  88. const thisMapSet = ThisMap.prototype.set;
  89. const thisFunction = Function;
  90. const thisFunctionBind = thisFunction.prototype.bind;
  91. const thisArrayIsArray = Array.isArray;
  92. const thisErrorCaptureStackTrace = Error.captureStackTrace;
  93. const thisSymbolToString = Symbol.prototype.toString;
  94. const thisSymbolToStringTag = Symbol.toStringTag;
  95. const thisSymbolIterator = Symbol.iterator;
  96. const thisSymbolNodeJSUtilInspectCustom = Symbol.for('nodejs.util.inspect.custom');
  97. /**
  98. * VMError.
  99. *
  100. * @public
  101. * @extends {Error}
  102. */
  103. class VMError extends Error {
  104. /**
  105. * Create VMError instance.
  106. *
  107. * @public
  108. * @param {string} message - Error message.
  109. * @param {string} code - Error code.
  110. */
  111. constructor(message, code) {
  112. super(message);
  113. this.name = 'VMError';
  114. this.code = code;
  115. thisErrorCaptureStackTrace(this, this.constructor);
  116. }
  117. }
  118. thisGlobalPrototypes['VMError'] = VMError.prototype;
  119. function thisUnexpected() {
  120. return new VMError('Unexpected');
  121. }
  122. if (!thisReflectSetPrototypeOf(exports, null)) throw thisUnexpected();
  123. function thisSafeGetOwnPropertyDescriptor(obj, key) {
  124. const desc = thisReflectGetOwnPropertyDescriptor(obj, key);
  125. if (!desc) return desc;
  126. if (!thisReflectSetPrototypeOf(desc, null)) throw thisUnexpected();
  127. return desc;
  128. }
  129. function thisThrowCallerCalleeArgumentsAccess(key) {
  130. 'use strict';
  131. thisThrowCallerCalleeArgumentsAccess[key];
  132. return thisUnexpected();
  133. }
  134. function thisIdMapping(factory, other) {
  135. return other;
  136. }
  137. const thisThrowOnKeyAccessHandler = thisObjectFreeze({
  138. __proto__: null,
  139. get(target, key, receiver) {
  140. if (typeof key === 'symbol') {
  141. key = thisReflectApply(thisSymbolToString, key, []);
  142. }
  143. throw new VMError(`Unexpected access to key '${key}'`);
  144. }
  145. });
  146. const emptyForzenObject = thisObjectFreeze({
  147. __proto__: null
  148. });
  149. const thisThrowOnKeyAccess = new ThisProxy(emptyForzenObject, thisThrowOnKeyAccessHandler);
  150. function SafeBase() {}
  151. if (!thisReflectDefineProperty(SafeBase, 'prototype', {
  152. __proto__: null,
  153. value: thisThrowOnKeyAccess
  154. })) throw thisUnexpected();
  155. function SHARED_FUNCTION() {}
  156. const TEST_PROXY_HANDLER = thisObjectFreeze({
  157. __proto__: thisThrowOnKeyAccess,
  158. construct() {
  159. return this;
  160. }
  161. });
  162. function thisIsConstructor(obj) {
  163. // Note: obj@any(unsafe)
  164. const Func = new ThisProxy(obj, TEST_PROXY_HANDLER);
  165. try {
  166. // eslint-disable-next-line no-new
  167. new Func();
  168. return true;
  169. } catch (e) {
  170. return false;
  171. }
  172. }
  173. function thisCreateTargetObject(obj, proto) {
  174. // Note: obj@any(unsafe) proto@any(unsafe) returns@this(unsafe) throws@this(unsafe)
  175. let base;
  176. if (typeof obj === 'function') {
  177. if (thisIsConstructor(obj)) {
  178. // Bind the function since bound functions do not have a prototype property.
  179. base = thisReflectApply(thisFunctionBind, SHARED_FUNCTION, [null]);
  180. } else {
  181. base = () => {};
  182. }
  183. } else if (thisArrayIsArray(obj)) {
  184. base = [];
  185. } else {
  186. return {__proto__: proto};
  187. }
  188. if (!thisReflectSetPrototypeOf(base, proto)) throw thisUnexpected();
  189. return base;
  190. }
  191. function createBridge(otherInit, registerProxy) {
  192. const mappingOtherToThis = new ThisWeakMap();
  193. const protoMappings = new ThisMap();
  194. const protoName = new ThisMap();
  195. function thisAddProtoMapping(proto, other, name) {
  196. // Note: proto@this(unsafe) other@other(unsafe) name@this(unsafe) throws@this(unsafe)
  197. thisReflectApply(thisMapSet, protoMappings, [proto, thisIdMapping]);
  198. thisReflectApply(thisMapSet, protoMappings, [other,
  199. (factory, object) => thisProxyOther(factory, object, proto)]);
  200. if (name) thisReflectApply(thisMapSet, protoName, [proto, name]);
  201. }
  202. function thisAddProtoMappingFactory(protoFactory, other, name) {
  203. // Note: protoFactory@this(unsafe) other@other(unsafe) name@this(unsafe) throws@this(unsafe)
  204. let proto;
  205. thisReflectApply(thisMapSet, protoMappings, [other,
  206. (factory, object) => {
  207. if (!proto) {
  208. proto = protoFactory();
  209. thisReflectApply(thisMapSet, protoMappings, [proto, thisIdMapping]);
  210. if (name) thisReflectApply(thisMapSet, protoName, [proto, name]);
  211. }
  212. return thisProxyOther(factory, object, proto);
  213. }]);
  214. }
  215. const result = {
  216. __proto__: null,
  217. globalPrototypes: thisGlobalPrototypes,
  218. safeGetOwnPropertyDescriptor: thisSafeGetOwnPropertyDescriptor,
  219. fromArguments: thisFromOtherArguments,
  220. from: thisFromOther,
  221. fromWithFactory: thisFromOtherWithFactory,
  222. ensureThis: thisEnsureThis,
  223. mapping: mappingOtherToThis,
  224. connect: thisConnect,
  225. reflectSet: thisReflectSet,
  226. reflectGet: thisReflectGet,
  227. reflectDefineProperty: thisReflectDefineProperty,
  228. reflectDeleteProperty: thisReflectDeleteProperty,
  229. reflectApply: thisReflectApply,
  230. reflectConstruct: thisReflectConstruct,
  231. reflectHas: thisReflectHas,
  232. reflectOwnKeys: thisReflectOwnKeys,
  233. reflectEnumerate: thisReflectEnumerate,
  234. reflectGetPrototypeOf: thisReflectGetPrototypeOf,
  235. reflectIsExtensible: thisReflectIsExtensible,
  236. reflectPreventExtensions: thisReflectPreventExtensions,
  237. objectHasOwnProperty: thisObjectHasOwnProperty,
  238. weakMapSet: thisWeakMapSet,
  239. addProtoMapping: thisAddProtoMapping,
  240. addProtoMappingFactory: thisAddProtoMappingFactory,
  241. defaultFactory,
  242. protectedFactory,
  243. readonlyFactory,
  244. VMError
  245. };
  246. const isHost = typeof otherInit !== 'object';
  247. if (isHost) {
  248. otherInit = otherInit(result, registerProxy);
  249. }
  250. result.other = otherInit;
  251. const {
  252. globalPrototypes: otherGlobalPrototypes,
  253. safeGetOwnPropertyDescriptor: otherSafeGetOwnPropertyDescriptor,
  254. fromArguments: otherFromThisArguments,
  255. from: otherFromThis,
  256. mapping: mappingThisToOther,
  257. reflectSet: otherReflectSet,
  258. reflectGet: otherReflectGet,
  259. reflectDefineProperty: otherReflectDefineProperty,
  260. reflectDeleteProperty: otherReflectDeleteProperty,
  261. reflectApply: otherReflectApply,
  262. reflectConstruct: otherReflectConstruct,
  263. reflectHas: otherReflectHas,
  264. reflectOwnKeys: otherReflectOwnKeys,
  265. reflectEnumerate: otherReflectEnumerate,
  266. reflectGetPrototypeOf: otherReflectGetPrototypeOf,
  267. reflectIsExtensible: otherReflectIsExtensible,
  268. reflectPreventExtensions: otherReflectPreventExtensions,
  269. objectHasOwnProperty: otherObjectHasOwnProperty,
  270. weakMapSet: otherWeakMapSet
  271. } = otherInit;
  272. function thisOtherHasOwnProperty(object, key) {
  273. // Note: object@other(safe) key@prim throws@this(unsafe)
  274. try {
  275. return otherReflectApply(otherObjectHasOwnProperty, object, [key]) === true;
  276. } catch (e) { // @other(unsafe)
  277. throw thisFromOtherForThrow(e);
  278. }
  279. }
  280. function thisDefaultGet(handler, object, key, desc) {
  281. // Note: object@other(unsafe) key@prim desc@other(safe)
  282. let ret; // @other(unsafe)
  283. if (desc.get || desc.set) {
  284. const getter = desc.get;
  285. if (!getter) return undefined;
  286. try {
  287. ret = otherReflectApply(getter, object, [key]);
  288. } catch (e) {
  289. throw thisFromOtherForThrow(e);
  290. }
  291. } else {
  292. ret = desc.value;
  293. }
  294. return handler.fromOtherWithContext(ret);
  295. }
  296. function otherFromThisIfAvailable(to, from, key) {
  297. // Note: to@other(safe) from@this(safe) key@prim throws@this(unsafe)
  298. if (!thisReflectApply(thisObjectHasOwnProperty, from, [key])) return false;
  299. try {
  300. to[key] = otherFromThis(from[key]);
  301. } catch (e) { // @other(unsafe)
  302. throw thisFromOtherForThrow(e);
  303. }
  304. return true;
  305. }
  306. class BaseHandler extends SafeBase {
  307. constructor(object) {
  308. // Note: object@other(unsafe) throws@this(unsafe)
  309. super();
  310. this.objectWrapper = () => object;
  311. }
  312. getObject() {
  313. return this.objectWrapper();
  314. }
  315. getFactory() {
  316. return defaultFactory;
  317. }
  318. fromOtherWithContext(other) {
  319. // Note: other@other(unsafe) throws@this(unsafe)
  320. return thisFromOtherWithFactory(this.getFactory(), other);
  321. }
  322. doPreventExtensions(target, object, factory) {
  323. // Note: target@this(unsafe) object@other(unsafe) throws@this(unsafe)
  324. let keys; // @other(safe-array-of-prim)
  325. try {
  326. keys = otherReflectOwnKeys(object);
  327. } catch (e) { // @other(unsafe)
  328. throw thisFromOtherForThrow(e);
  329. }
  330. for (let i = 0; i < keys.length; i++) {
  331. const key = keys[i]; // @prim
  332. let desc;
  333. try {
  334. desc = otherSafeGetOwnPropertyDescriptor(object, key);
  335. } catch (e) { // @other(unsafe)
  336. throw thisFromOtherForThrow(e);
  337. }
  338. if (!desc) continue;
  339. if (!desc.configurable) {
  340. const current = thisSafeGetOwnPropertyDescriptor(target, key);
  341. if (current && !current.configurable) continue;
  342. if (desc.get || desc.set) {
  343. desc.get = this.fromOtherWithContext(desc.get);
  344. desc.set = this.fromOtherWithContext(desc.set);
  345. } else if (typeof object === 'function' && (key === 'caller' || key === 'callee' || key === 'arguments')) {
  346. desc.value = null;
  347. } else {
  348. desc.value = this.fromOtherWithContext(desc.value);
  349. }
  350. } else {
  351. if (desc.get || desc.set) {
  352. desc = {
  353. __proto__: null,
  354. configurable: true,
  355. enumerable: desc.enumerable,
  356. writable: true,
  357. value: null
  358. };
  359. } else {
  360. desc.value = null;
  361. }
  362. }
  363. if (!thisReflectDefineProperty(target, key, desc)) throw thisUnexpected();
  364. }
  365. if (!thisReflectPreventExtensions(target)) throw thisUnexpected();
  366. }
  367. get(target, key, receiver) {
  368. // Note: target@this(unsafe) key@prim receiver@this(unsafe) throws@this(unsafe)
  369. const object = this.getObject(); // @other(unsafe)
  370. switch (key) {
  371. case 'constructor': {
  372. const desc = otherSafeGetOwnPropertyDescriptor(object, key);
  373. if (desc) return thisDefaultGet(this, object, key, desc);
  374. const proto = thisReflectGetPrototypeOf(target);
  375. return proto === null ? undefined : proto.constructor;
  376. }
  377. case '__proto__': {
  378. const desc = otherSafeGetOwnPropertyDescriptor(object, key);
  379. if (desc) return thisDefaultGet(this, object, key, desc);
  380. return thisReflectGetPrototypeOf(target);
  381. }
  382. case thisSymbolToStringTag:
  383. if (!thisOtherHasOwnProperty(object, thisSymbolToStringTag)) {
  384. const proto = thisReflectGetPrototypeOf(target);
  385. const name = thisReflectApply(thisMapGet, protoName, [proto]);
  386. if (name) return name;
  387. }
  388. break;
  389. case 'arguments':
  390. case 'caller':
  391. case 'callee':
  392. if (typeof object === 'function' && thisOtherHasOwnProperty(object, key)) {
  393. throw thisThrowCallerCalleeArgumentsAccess(key);
  394. }
  395. break;
  396. }
  397. let ret; // @other(unsafe)
  398. try {
  399. ret = otherReflectGet(object, key);
  400. } catch (e) { // @other(unsafe)
  401. throw thisFromOtherForThrow(e);
  402. }
  403. return this.fromOtherWithContext(ret);
  404. }
  405. set(target, key, value, receiver) {
  406. // Note: target@this(unsafe) key@prim value@this(unsafe) receiver@this(unsafe) throws@this(unsafe)
  407. const object = this.getObject(); // @other(unsafe)
  408. if (key === '__proto__' && !thisOtherHasOwnProperty(object, key)) {
  409. return this.setPrototypeOf(target, value);
  410. }
  411. try {
  412. value = otherFromThis(value);
  413. return otherReflectSet(object, key, value) === true;
  414. } catch (e) { // @other(unsafe)
  415. throw thisFromOtherForThrow(e);
  416. }
  417. }
  418. getPrototypeOf(target) {
  419. // Note: target@this(unsafe)
  420. return thisReflectGetPrototypeOf(target);
  421. }
  422. setPrototypeOf(target, value) {
  423. // Note: target@this(unsafe) throws@this(unsafe)
  424. throw new VMError(OPNA);
  425. }
  426. apply(target, context, args) {
  427. // Note: target@this(unsafe) context@this(unsafe) args@this(safe-array) throws@this(unsafe)
  428. const object = this.getObject(); // @other(unsafe)
  429. let ret; // @other(unsafe)
  430. try {
  431. context = otherFromThis(context);
  432. args = otherFromThisArguments(args);
  433. ret = otherReflectApply(object, context, args);
  434. } catch (e) { // @other(unsafe)
  435. throw thisFromOtherForThrow(e);
  436. }
  437. return thisFromOther(ret);
  438. }
  439. construct(target, args, newTarget) {
  440. // Note: target@this(unsafe) args@this(safe-array) newTarget@this(unsafe) throws@this(unsafe)
  441. const object = this.getObject(); // @other(unsafe)
  442. let ret; // @other(unsafe)
  443. try {
  444. args = otherFromThisArguments(args);
  445. ret = otherReflectConstruct(object, args);
  446. } catch (e) { // @other(unsafe)
  447. throw thisFromOtherForThrow(e);
  448. }
  449. return thisFromOtherWithFactory(this.getFactory(), ret, thisFromOther(object));
  450. }
  451. getOwnPropertyDescriptorDesc(target, prop, desc) {
  452. // Note: target@this(unsafe) prop@prim desc@other{safe} throws@this(unsafe)
  453. const object = this.getObject(); // @other(unsafe)
  454. if (desc && typeof object === 'function' && (prop === 'arguments' || prop === 'caller' || prop === 'callee')) desc.value = null;
  455. return desc;
  456. }
  457. getOwnPropertyDescriptor(target, prop) {
  458. // Note: target@this(unsafe) prop@prim throws@this(unsafe)
  459. const object = this.getObject(); // @other(unsafe)
  460. let desc; // @other(safe)
  461. try {
  462. desc = otherSafeGetOwnPropertyDescriptor(object, prop);
  463. } catch (e) { // @other(unsafe)
  464. throw thisFromOtherForThrow(e);
  465. }
  466. desc = this.getOwnPropertyDescriptorDesc(target, prop, desc);
  467. if (!desc) return undefined;
  468. let thisDesc;
  469. if (desc.get || desc.set) {
  470. thisDesc = {
  471. __proto__: null,
  472. get: this.fromOtherWithContext(desc.get),
  473. set: this.fromOtherWithContext(desc.set),
  474. enumerable: desc.enumerable === true,
  475. configurable: desc.configurable === true
  476. };
  477. } else {
  478. thisDesc = {
  479. __proto__: null,
  480. value: this.fromOtherWithContext(desc.value),
  481. writable: desc.writable === true,
  482. enumerable: desc.enumerable === true,
  483. configurable: desc.configurable === true
  484. };
  485. }
  486. if (!thisDesc.configurable) {
  487. const oldDesc = thisSafeGetOwnPropertyDescriptor(target, prop);
  488. if (!oldDesc || oldDesc.configurable || oldDesc.writable !== thisDesc.writable) {
  489. if (!thisReflectDefineProperty(target, prop, thisDesc)) throw thisUnexpected();
  490. }
  491. }
  492. return thisDesc;
  493. }
  494. definePropertyDesc(target, prop, desc) {
  495. // Note: target@this(unsafe) prop@prim desc@this(safe) throws@this(unsafe)
  496. return desc;
  497. }
  498. defineProperty(target, prop, desc) {
  499. // Note: target@this(unsafe) prop@prim desc@this(unsafe) throws@this(unsafe)
  500. const object = this.getObject(); // @other(unsafe)
  501. if (!thisReflectSetPrototypeOf(desc, null)) throw thisUnexpected();
  502. desc = this.definePropertyDesc(target, prop, desc);
  503. if (!desc) return false;
  504. let otherDesc = {__proto__: null};
  505. let hasFunc = true;
  506. let hasValue = true;
  507. let hasBasic = true;
  508. hasFunc &= otherFromThisIfAvailable(otherDesc, desc, 'get');
  509. hasFunc &= otherFromThisIfAvailable(otherDesc, desc, 'set');
  510. hasValue &= otherFromThisIfAvailable(otherDesc, desc, 'value');
  511. hasValue &= otherFromThisIfAvailable(otherDesc, desc, 'writable');
  512. hasBasic &= otherFromThisIfAvailable(otherDesc, desc, 'enumerable');
  513. hasBasic &= otherFromThisIfAvailable(otherDesc, desc, 'configurable');
  514. try {
  515. if (!otherReflectDefineProperty(object, prop, otherDesc)) return false;
  516. if (otherDesc.configurable !== true && (!hasBasic || !(hasFunc || hasValue))) {
  517. otherDesc = otherSafeGetOwnPropertyDescriptor(object, prop);
  518. }
  519. } catch (e) { // @other(unsafe)
  520. throw thisFromOtherForThrow(e);
  521. }
  522. if (!otherDesc.configurable) {
  523. let thisDesc;
  524. if (otherDesc.get || otherDesc.set) {
  525. thisDesc = {
  526. __proto__: null,
  527. get: this.fromOtherWithContext(otherDesc.get),
  528. set: this.fromOtherWithContext(otherDesc.set),
  529. enumerable: otherDesc.enumerable,
  530. configurable: otherDesc.configurable
  531. };
  532. } else {
  533. thisDesc = {
  534. __proto__: null,
  535. value: this.fromOtherWithContext(otherDesc.value),
  536. writable: otherDesc.writable,
  537. enumerable: otherDesc.enumerable,
  538. configurable: otherDesc.configurable
  539. };
  540. }
  541. if (!thisReflectDefineProperty(target, prop, thisDesc)) throw thisUnexpected();
  542. }
  543. return true;
  544. }
  545. deleteProperty(target, prop) {
  546. // Note: target@this(unsafe) prop@prim throws@this(unsafe)
  547. const object = this.getObject(); // @other(unsafe)
  548. try {
  549. return otherReflectDeleteProperty(object, prop) === true;
  550. } catch (e) { // @other(unsafe)
  551. throw thisFromOtherForThrow(e);
  552. }
  553. }
  554. has(target, key) {
  555. // Note: target@this(unsafe) key@prim throws@this(unsafe)
  556. const object = this.getObject(); // @other(unsafe)
  557. try {
  558. return otherReflectHas(object, key) === true;
  559. } catch (e) { // @other(unsafe)
  560. throw thisFromOtherForThrow(e);
  561. }
  562. }
  563. isExtensible(target) {
  564. // Note: target@this(unsafe) throws@this(unsafe)
  565. const object = this.getObject(); // @other(unsafe)
  566. try {
  567. if (otherReflectIsExtensible(object)) return true;
  568. } catch (e) { // @other(unsafe)
  569. throw thisFromOtherForThrow(e);
  570. }
  571. if (thisReflectIsExtensible(target)) {
  572. this.doPreventExtensions(target, object, this);
  573. }
  574. return false;
  575. }
  576. ownKeys(target) {
  577. // Note: target@this(unsafe) throws@this(unsafe)
  578. const object = this.getObject(); // @other(unsafe)
  579. let res; // @other(unsafe)
  580. try {
  581. res = otherReflectOwnKeys(object);
  582. } catch (e) { // @other(unsafe)
  583. throw thisFromOtherForThrow(e);
  584. }
  585. return thisFromOther(res);
  586. }
  587. preventExtensions(target) {
  588. // Note: target@this(unsafe) throws@this(unsafe)
  589. const object = this.getObject(); // @other(unsafe)
  590. try {
  591. if (!otherReflectPreventExtensions(object)) return false;
  592. } catch (e) { // @other(unsafe)
  593. throw thisFromOtherForThrow(e);
  594. }
  595. if (thisReflectIsExtensible(target)) {
  596. this.doPreventExtensions(target, object, this);
  597. }
  598. return true;
  599. }
  600. enumerate(target) {
  601. // Note: target@this(unsafe) throws@this(unsafe)
  602. const object = this.getObject(); // @other(unsafe)
  603. let res; // @other(unsafe)
  604. try {
  605. res = otherReflectEnumerate(object);
  606. } catch (e) { // @other(unsafe)
  607. throw thisFromOtherForThrow(e);
  608. }
  609. return this.fromOtherWithContext(res);
  610. }
  611. }
  612. BaseHandler.prototype[thisSymbolNodeJSUtilInspectCustom] = undefined;
  613. BaseHandler.prototype[thisSymbolToStringTag] = 'VM2 Wrapper';
  614. BaseHandler.prototype[thisSymbolIterator] = undefined;
  615. function defaultFactory(object) {
  616. // Note: other@other(unsafe) returns@this(unsafe) throws@this(unsafe)
  617. return new BaseHandler(object);
  618. }
  619. class ProtectedHandler extends BaseHandler {
  620. getFactory() {
  621. return protectedFactory;
  622. }
  623. set(target, key, value, receiver) {
  624. // Note: target@this(unsafe) key@prim value@this(unsafe) receiver@this(unsafe) throws@this(unsafe)
  625. if (typeof value === 'function') {
  626. return thisReflectDefineProperty(receiver, key, {
  627. __proto__: null,
  628. value: value,
  629. writable: true,
  630. enumerable: true,
  631. configurable: true
  632. }) === true;
  633. }
  634. return super.set(target, key, value, receiver);
  635. }
  636. definePropertyDesc(target, prop, desc) {
  637. // Note: target@this(unsafe) prop@prim desc@this(safe) throws@this(unsafe)
  638. if (desc && (desc.set || desc.get || typeof desc.value === 'function')) return undefined;
  639. return desc;
  640. }
  641. }
  642. function protectedFactory(object) {
  643. // Note: other@other(unsafe) returns@this(unsafe) throws@this(unsafe)
  644. return new ProtectedHandler(object);
  645. }
  646. class ReadOnlyHandler extends BaseHandler {
  647. getFactory() {
  648. return readonlyFactory;
  649. }
  650. set(target, key, value, receiver) {
  651. // Note: target@this(unsafe) key@prim value@this(unsafe) receiver@this(unsafe) throws@this(unsafe)
  652. return thisReflectDefineProperty(receiver, key, {
  653. __proto__: null,
  654. value: value,
  655. writable: true,
  656. enumerable: true,
  657. configurable: true
  658. });
  659. }
  660. setPrototypeOf(target, value) {
  661. // Note: target@this(unsafe) throws@this(unsafe)
  662. return false;
  663. }
  664. defineProperty(target, prop, desc) {
  665. // Note: target@this(unsafe) prop@prim desc@this(unsafe) throws@this(unsafe)
  666. return false;
  667. }
  668. deleteProperty(target, prop) {
  669. // Note: target@this(unsafe) prop@prim throws@this(unsafe)
  670. return false;
  671. }
  672. isExtensible(target) {
  673. // Note: target@this(unsafe) throws@this(unsafe)
  674. return false;
  675. }
  676. preventExtensions(target) {
  677. // Note: target@this(unsafe) throws@this(unsafe)
  678. return false;
  679. }
  680. }
  681. function readonlyFactory(object) {
  682. // Note: other@other(unsafe) returns@this(unsafe) throws@this(unsafe)
  683. return new ReadOnlyHandler(object);
  684. }
  685. class ReadOnlyMockHandler extends ReadOnlyHandler {
  686. constructor(object, mock) {
  687. // Note: object@other(unsafe) mock:this(unsafe) throws@this(unsafe)
  688. super(object);
  689. this.mock = mock;
  690. }
  691. get(target, key, receiver) {
  692. // Note: target@this(unsafe) key@prim receiver@this(unsafe) throws@this(unsafe)
  693. const object = this.getObject(); // @other(unsafe)
  694. const mock = this.mock;
  695. if (thisReflectApply(thisObjectHasOwnProperty, mock, key) && !thisOtherHasOwnProperty(object, key)) {
  696. return mock[key];
  697. }
  698. return super.get(target, key, receiver);
  699. }
  700. }
  701. function thisFromOther(other) {
  702. // Note: other@other(unsafe) returns@this(unsafe) throws@this(unsafe)
  703. return thisFromOtherWithFactory(defaultFactory, other);
  704. }
  705. function thisProxyOther(factory, other, proto) {
  706. const target = thisCreateTargetObject(other, proto);
  707. const handler = factory(other);
  708. const proxy = new ThisProxy(target, handler);
  709. try {
  710. otherReflectApply(otherWeakMapSet, mappingThisToOther, [proxy, other]);
  711. registerProxy(proxy, handler);
  712. } catch (e) {
  713. throw new VMError('Unexpected error');
  714. }
  715. if (!isHost) {
  716. thisReflectApply(thisWeakMapSet, mappingOtherToThis, [other, proxy]);
  717. return proxy;
  718. }
  719. const proxy2 = new ThisProxy(proxy, emptyForzenObject);
  720. try {
  721. otherReflectApply(otherWeakMapSet, mappingThisToOther, [proxy2, other]);
  722. registerProxy(proxy2, handler);
  723. } catch (e) {
  724. throw new VMError('Unexpected error');
  725. }
  726. thisReflectApply(thisWeakMapSet, mappingOtherToThis, [other, proxy2]);
  727. return proxy2;
  728. }
  729. function thisEnsureThis(other) {
  730. const type = typeof other;
  731. switch (type) {
  732. case 'object':
  733. if (other === null) {
  734. return null;
  735. }
  736. // fallthrough
  737. case 'function':
  738. let proto = thisReflectGetPrototypeOf(other);
  739. if (!proto) {
  740. return other;
  741. }
  742. while (proto) {
  743. const mapping = thisReflectApply(thisMapGet, protoMappings, [proto]);
  744. if (mapping) {
  745. const mapped = thisReflectApply(thisWeakMapGet, mappingOtherToThis, [other]);
  746. if (mapped) return mapped;
  747. return mapping(defaultFactory, other);
  748. }
  749. proto = thisReflectGetPrototypeOf(proto);
  750. }
  751. return other;
  752. case 'undefined':
  753. case 'string':
  754. case 'number':
  755. case 'boolean':
  756. case 'symbol':
  757. case 'bigint':
  758. return other;
  759. default: // new, unknown types can be dangerous
  760. throw new VMError(`Unknown type '${type}'`);
  761. }
  762. }
  763. function thisFromOtherForThrow(other) {
  764. for (let loop = 0; loop < 10; loop++) {
  765. const type = typeof other;
  766. switch (type) {
  767. case 'object':
  768. if (other === null) {
  769. return null;
  770. }
  771. // fallthrough
  772. case 'function':
  773. const mapped = thisReflectApply(thisWeakMapGet, mappingOtherToThis, [other]);
  774. if (mapped) return mapped;
  775. let proto;
  776. try {
  777. proto = otherReflectGetPrototypeOf(other);
  778. } catch (e) { // @other(unsafe)
  779. other = e;
  780. break;
  781. }
  782. if (!proto) {
  783. return thisProxyOther(defaultFactory, other, null);
  784. }
  785. for (;;) {
  786. const mapping = thisReflectApply(thisMapGet, protoMappings, [proto]);
  787. if (mapping) return mapping(defaultFactory, other);
  788. try {
  789. proto = otherReflectGetPrototypeOf(proto);
  790. } catch (e) { // @other(unsafe)
  791. other = e;
  792. break;
  793. }
  794. if (!proto) return thisProxyOther(defaultFactory, other, thisObjectPrototype);
  795. }
  796. break;
  797. case 'undefined':
  798. case 'string':
  799. case 'number':
  800. case 'boolean':
  801. case 'symbol':
  802. case 'bigint':
  803. return other;
  804. default: // new, unknown types can be dangerous
  805. throw new VMError(`Unknown type '${type}'`);
  806. }
  807. }
  808. throw new VMError('Exception recursion depth');
  809. }
  810. function thisFromOtherWithFactory(factory, other, proto) {
  811. const type = typeof other;
  812. switch (type) {
  813. case 'object':
  814. if (other === null) {
  815. return null;
  816. }
  817. // fallthrough
  818. case 'function':
  819. const mapped = thisReflectApply(thisWeakMapGet, mappingOtherToThis, [other]);
  820. if (mapped) return mapped;
  821. if (proto) {
  822. return thisProxyOther(factory, other, proto);
  823. }
  824. try {
  825. proto = otherReflectGetPrototypeOf(other);
  826. } catch (e) { // @other(unsafe)
  827. throw thisFromOtherForThrow(e);
  828. }
  829. if (!proto) {
  830. return thisProxyOther(factory, other, null);
  831. }
  832. do {
  833. const mapping = thisReflectApply(thisMapGet, protoMappings, [proto]);
  834. if (mapping) return mapping(factory, other);
  835. try {
  836. proto = otherReflectGetPrototypeOf(proto);
  837. } catch (e) { // @other(unsafe)
  838. throw thisFromOtherForThrow(e);
  839. }
  840. } while (proto);
  841. return thisProxyOther(factory, other, thisObjectPrototype);
  842. case 'undefined':
  843. case 'string':
  844. case 'number':
  845. case 'boolean':
  846. case 'symbol':
  847. case 'bigint':
  848. return other;
  849. default: // new, unknown types can be dangerous
  850. throw new VMError(`Unknown type '${type}'`);
  851. }
  852. }
  853. function thisFromOtherArguments(args) {
  854. // Note: args@other(safe-array) returns@this(safe-array) throws@this(unsafe)
  855. const arr = [];
  856. for (let i = 0; i < args.length; i++) {
  857. const value = thisFromOther(args[i]);
  858. thisReflectDefineProperty(arr, i, {
  859. __proto__: null,
  860. value: value,
  861. writable: true,
  862. enumerable: true,
  863. configurable: true
  864. });
  865. }
  866. return arr;
  867. }
  868. function thisConnect(obj, other) {
  869. // Note: obj@this(unsafe) other@other(unsafe) throws@this(unsafe)
  870. try {
  871. otherReflectApply(otherWeakMapSet, mappingThisToOther, [obj, other]);
  872. } catch (e) {
  873. throw new VMError('Unexpected error');
  874. }
  875. thisReflectApply(thisWeakMapSet, mappingOtherToThis, [other, obj]);
  876. }
  877. thisAddProtoMapping(thisGlobalPrototypes.Object, otherGlobalPrototypes.Object);
  878. thisAddProtoMapping(thisGlobalPrototypes.Array, otherGlobalPrototypes.Array);
  879. for (let i = 0; i < globalsList.length; i++) {
  880. const key = globalsList[i];
  881. const tp = thisGlobalPrototypes[key];
  882. const op = otherGlobalPrototypes[key];
  883. if (tp && op) thisAddProtoMapping(tp, op, key);
  884. }
  885. for (let i = 0; i < errorsList.length; i++) {
  886. const key = errorsList[i];
  887. const tp = thisGlobalPrototypes[key];
  888. const op = otherGlobalPrototypes[key];
  889. if (tp && op) thisAddProtoMapping(tp, op, 'Error');
  890. }
  891. thisAddProtoMapping(thisGlobalPrototypes.VMError, otherGlobalPrototypes.VMError, 'Error');
  892. result.BaseHandler = BaseHandler;
  893. result.ProtectedHandler = ProtectedHandler;
  894. result.ReadOnlyHandler = ReadOnlyHandler;
  895. result.ReadOnlyMockHandler = ReadOnlyMockHandler;
  896. return result;
  897. }
  898. exports.createBridge = createBridge;
  899. exports.VMError = VMError;