quickjs-emscripten-sync 1.9.1 → 1.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,23 +1,23 @@
1
- (function(_,b){typeof exports=="object"&&typeof module!="undefined"?b(exports):typeof define=="function"&&define.amd?define(["exports"],b):(_=typeof globalThis!="undefined"?globalThis:_||self,b(_.QuickjsEmscriptenSync={}))})(this,(function(_){"use strict";var Fe=Object.defineProperty;var ee=Object.getOwnPropertySymbols;var Ie=Object.prototype.hasOwnProperty,Ne=Object.prototype.propertyIsEnumerable;var J=(_,b,g)=>b in _?Fe(_,b,{enumerable:!0,configurable:!0,writable:!0,value:g}):_[b]=g,te=(_,b)=>{for(var g in b||(b={}))Ie.call(b,g)&&J(_,g,b[g]);if(ee)for(var g of ee(b))Ne.call(b,g)&&J(_,g,b[g]);return _};var p=(_,b,g)=>J(_,typeof b!="symbol"?b+"":b,g);var ne=(_,b,g)=>new Promise((A,k)=>{var I=O=>{try{C(g.next(O))}catch(h){k(h)}},R=O=>{try{C(g.throw(O))}catch(h){k(h)}},C=O=>O.done?A(O.value):Promise.resolve(O.value).then(I,R);C((g=g.apply(_,b)).next())});const b=n=>{const e=new g(n);return new Proxy(n,{get(t,r,s){return r in e?e[r]:Reflect.get(t,r,s)}})};class g{constructor(e){p(this,"context");p(this,"fn");p(this,"fnGenerator");p(this,"fnCounter",Number.MIN_SAFE_INTEGER);p(this,"fnMap",new Map);p(this,"newFunction",(e,t)=>{this.fnCounter++;const r=this.fnCounter;return this.fnMap.set(r,t),this.context.unwrapResult(this.context.callFunction(this.fnGenerator,this.context.undefined,this.context.newString(e),this.context.newNumber(t.length),this.context.newNumber(r),this.fn))});this.context=e;const t=this.fnMap;this.fn=this.context.newFunction("",function(r,...s){const i=e.getNumber(r),o=t.get(i);if(!o)throw new Error("function is not registered");return o.call(this,...s)}),this.fnGenerator=e.unwrapResult(e.evalCode(`((name, length, id, f) => {
1
+ (function(_,b){typeof exports=="object"&&typeof module!="undefined"?b(exports):typeof define=="function"&&define.amd?define(["exports"],b):(_=typeof globalThis!="undefined"?globalThis:_||self,b(_.QuickjsEmscriptenSync={}))})(this,(function(_){"use strict";var Fe=Object.defineProperty;var ee=Object.getOwnPropertySymbols;var Ie=Object.prototype.hasOwnProperty,Ne=Object.prototype.propertyIsEnumerable;var J=(_,b,j)=>b in _?Fe(_,b,{enumerable:!0,configurable:!0,writable:!0,value:j}):_[b]=j,te=(_,b)=>{for(var j in b||(b={}))Ie.call(b,j)&&J(_,j,b[j]);if(ee)for(var j of ee(b))Ne.call(b,j)&&J(_,j,b[j]);return _};var l=(_,b,j)=>J(_,typeof b!="symbol"?b+"":b,j);var ne=(_,b,j)=>new Promise((A,k)=>{var I=R=>{try{C(j.next(R))}catch(h){k(h)}},O=R=>{try{C(j.throw(R))}catch(h){k(h)}},C=R=>R.done?A(R.value):Promise.resolve(R.value).then(I,O);C((j=j.apply(_,b)).next())});const b=n=>{const e=new j(n);return new Proxy(n,{get(t,r,s){return r in e?e[r]:Reflect.get(t,r,s)}})};class j{constructor(e){l(this,"context");l(this,"fn");l(this,"fnGenerator");l(this,"fnCounter",Number.MIN_SAFE_INTEGER);l(this,"fnMap",new Map);l(this,"newFunction",(e,t)=>{this.fnCounter++;const r=this.fnCounter;return this.fnMap.set(r,t),this.context.unwrapResult(this.context.callFunction(this.fnGenerator,this.context.undefined,this.context.newString(e),this.context.newNumber(t.length),this.context.newNumber(r),this.fn))});this.context=e;const t=this.fnMap;this.fn=this.context.newFunction("",function(r,...s){const i=e.getNumber(r),o=t.get(i);if(!o)throw new Error("function is not registered");return o.call(this,...s)}),this.fnGenerator=e.unwrapResult(e.evalCode(`((name, length, id, f) => {
2
2
  const fn = function(...args) {
3
3
  return f.call(this, id, ...args);
4
4
  };
5
5
  fn.name = name;
6
6
  fn.length = length;
7
7
  return fn;
8
- })`))}disposeEx(){this.fnGenerator.dispose(),this.fn.dispose()}}const A=[[Symbol,"Symbol"],[Symbol.prototype,"Symbol.prototype"],[Object,"Object"],[Object.prototype,"Object.prototype"],[Function,"Function"],[Function.prototype,"Function.prototype"],[Boolean,"Boolean"],[Boolean.prototype,"Boolean.prototype"],[Array,"Array"],[Array.prototype,"Array.prototype"],[Error,"Error"],[Error.prototype,"Error.prototype"],[EvalError,"EvalError"],[EvalError.prototype,"EvalError.prototype"],[RangeError,"RangeError"],[RangeError.prototype,"RangeError.prototype"],[ReferenceError,"ReferenceError"],[ReferenceError.prototype,"ReferenceError.prototype"],[SyntaxError,"SyntaxError"],[SyntaxError.prototype,"SyntaxError.prototype"],[TypeError,"TypeError"],[TypeError.prototype,"TypeError.prototype"],[URIError,"URIError"],[URIError.prototype,"URIError.prototype"],...Object.getOwnPropertyNames(Symbol).filter(n=>typeof Symbol[n]=="symbol").map(n=>[Symbol[n],`Symbol.${n}`])];function k(n,e){if("error"in e&&e.error){const{error:t}=e;let r;try{r=n.dump(t)}catch(i){}finally{t.alive&&t.dispose()}const s=new Error(typeof r=="object"&&r&&"message"in r?String(r.message):r!==void 0?String(r):"quickjs-emscripten-sync: VM evaluation failed");throw typeof r=="object"&&r&&("name"in r&&(s.name=String(r.name)),"stack"in r&&(s.stack=String(r.stack))),s}return e.value}function I(n,e){const t=k(n,n.evalCode(e)),r=(i,...o)=>k(n,n.callFunction(t,i!=null?i:n.undefined,...o)),s=()=>t.dispose();return r.dispose=s,r[Symbol.dispose]=s,Object.defineProperty(r,"alive",{get:()=>t.alive}),r}const R=new WeakMap;function C(n){R.has(n)||R.set(n,new Map)}function O(n){const e=R.get(n);if(e){for(const t of e.values())t.alive&&t.dispose();R.delete(n)}}function h(n,e,t,...r){const s=R.get(n);if(!s){const o=I(n,e);try{return o(t,...r)}finally{o.dispose()}}let i=s.get(e);return(!i||!i.alive)&&(i=k(n,n.evalCode(e)),s.set(e,i)),k(n,n.callFunction(i,t!=null?t:n.undefined,...r))}function re(n,e,t){return n.dump(h(n,"(a, b) => a instanceof b",void 0,e,t))}function W(n,e){const t=n.typeof(e);return t==="function"||t==="object"&&!n.sameValue(e,n.null)}function z(n,e){const t=JSON.stringify(e);return t?n.newString(t).consume(r=>h(n,"JSON.parse",void 0,r)):n.undefined}function P(n,e){try{return e(n)}finally{n.alive&&n.dispose()}}function $(n,e){try{return e(n)}finally{for(const t of n)t.alive&&t.dispose()}}function se([n,e],t){try{return t(n)}finally{e&&n.dispose()}}function B(n,e){try{return e(...n.map(t=>t[0]))}finally{for(const[t,r]of n)r&&t.dispose()}}function ie(n){return"handle"in n}function N(n){return ie(n)?n.handle:n}function oe(n,e,t,r){var i;let s;for(const o of r)if(s=o(e,n),s)break;return s?(i=t(e,s))!=null?i:s:void 0}function ue(n,e){return typeof n!="symbol"?void 0:h(e,"d => Symbol(d)",void 0,n.description?e.newString(n.description):e.undefined)}function ae(n,e){return n instanceof Date?h(e,"d => new Date(d)",void 0,e.newNumber(n.getTime())):void 0}function fe(n,e){if(n instanceof ArrayBuffer)return e.newArrayBuffer(n.slice(0));if(ArrayBuffer.isView(n)){const t=new Uint8Array(n.buffer,n.byteOffset,n.byteLength).slice();return $([e.newArrayBuffer(t.buffer),e.newString(n.constructor.name)],([r,s])=>h(e,"(buf, name) => new globalThis[name](buf)",void 0,r,s))}}const ce=[ue,ae,fe];function L(n){return typeof n=="function"&&/^class\s/.test(Function.prototype.toString.call(n))}function H(n){return typeof n=="function"||typeof n=="object"&&n!==null}function D(n,e){const t=new Set,r=s=>{if(!(!H(s)||t.has(s)||(e==null?void 0:e(s,t))===!1)){if(t.add(s),Array.isArray(s)){for(const i of s)r(i);return}if(typeof s=="object"){const i=Object.getPrototypeOf(s);i&&i!==Object.prototype&&r(i)}for(const i of Object.values(Object.getOwnPropertyDescriptors(s)))"value"in i&&r(i.value),"get"in i&&r(i.get),"set"in i&&r(i.set)}};return r(n),t}function le(n,e){return D(n,e?(t,r)=>r.size<e:void 0).size}function pe(){let n=()=>{},e=()=>{};return{promise:new Promise((r,s)=>{n=r,e=s}),resolve:n,reject:e}}function K(n,e,t,r,s=()=>{}){const i=n.newObject(),o=[],f=(a,u)=>{const l=r(a),y=typeof u.value=="undefined"?void 0:r(u.value),m=typeof u.get=="undefined"?void 0:r(u.get),c=typeof u.set=="undefined"?void 0:r(u.set);y&&o.push(y),m&&o.push(m),c&&o.push(c),n.newObject().consume(d=>{Object.entries(u).forEach(([v,w])=>{const j=v==="value"?y:v==="get"?m:v==="set"?c:w?n.true:n.false;j&&n.setProp(d,v,j)}),n.setProp(i,l,d)})};try{const a=Object.getOwnPropertyDescriptors(e);Object.entries(a).forEach(([u,l])=>f(u,l)),Object.getOwnPropertySymbols(a).forEach(u=>f(u,a[u])),h(n,"Object.defineProperties",void 0,t,i).dispose();for(const u of o)s(u)}finally{i.dispose()}}function de(n,e,t,r,s,i,o=()=>{}){var u;if(typeof e!="function")return;const f=n.newFunction(e.name,function(...l){const y=r(this),m=l.map(c=>r(c));if(L(e)&&H(y)){const c=new e(...m);return Object.entries(c).forEach(([d,v])=>{const w=t(v);n.setProp(this,d,w),o(w)}),this}return t(i?i(e,y,m):e.apply(y,m))}).consume(l=>h(n,`Cls => {
8
+ })`))}disposeEx(){this.fnGenerator.dispose(),this.fn.dispose()}}const A=[[Symbol,"Symbol"],[Symbol.prototype,"Symbol.prototype"],[Object,"Object"],[Object.prototype,"Object.prototype"],[Function,"Function"],[Function.prototype,"Function.prototype"],[Boolean,"Boolean"],[Boolean.prototype,"Boolean.prototype"],[Array,"Array"],[Array.prototype,"Array.prototype"],[Error,"Error"],[Error.prototype,"Error.prototype"],[EvalError,"EvalError"],[EvalError.prototype,"EvalError.prototype"],[RangeError,"RangeError"],[RangeError.prototype,"RangeError.prototype"],[ReferenceError,"ReferenceError"],[ReferenceError.prototype,"ReferenceError.prototype"],[SyntaxError,"SyntaxError"],[SyntaxError.prototype,"SyntaxError.prototype"],[TypeError,"TypeError"],[TypeError.prototype,"TypeError.prototype"],[URIError,"URIError"],[URIError.prototype,"URIError.prototype"],...Object.getOwnPropertyNames(Symbol).filter(n=>typeof Symbol[n]=="symbol").map(n=>[Symbol[n],`Symbol.${n}`])];function k(n,e){if("error"in e&&e.error){const{error:t}=e;let r;try{r=n.dump(t)}catch(i){}finally{t.alive&&t.dispose()}const s=new Error(typeof r=="object"&&r&&"message"in r?String(r.message):r!==void 0?String(r):"quickjs-emscripten-sync: VM evaluation failed");throw typeof r=="object"&&r&&("name"in r&&(s.name=String(r.name)),"stack"in r&&(s.stack=String(r.stack))),s}return e.value}function I(n,e){const t=k(n,n.evalCode(e)),r=(i,...o)=>k(n,n.callFunction(t,i!=null?i:n.undefined,...o)),s=()=>t.dispose();return r.dispose=s,r[Symbol.dispose]=s,Object.defineProperty(r,"alive",{get:()=>t.alive}),r}const O=new WeakMap;function C(n){O.has(n)||O.set(n,new Map)}function R(n){const e=O.get(n);if(e){for(const t of e.values())t.alive&&t.dispose();O.delete(n)}}function h(n,e,t,...r){const s=O.get(n);if(!s){const o=I(n,e);try{return o(t,...r)}finally{o.dispose()}}let i=s.get(e);return(!i||!i.alive)&&(i=k(n,n.evalCode(e)),s.set(e,i)),k(n,n.callFunction(i,t!=null?t:n.undefined,...r))}function re(n,e,t){return n.dump(h(n,"(a, b) => a instanceof b",void 0,e,t))}function W(n,e){const t=n.typeof(e);return t==="function"||t==="object"&&!n.sameValue(e,n.null)}function z(n,e){const t=JSON.stringify(e);return t?n.newString(t).consume(r=>h(n,"JSON.parse",void 0,r)):n.undefined}function P(n,e){try{return e(n)}finally{n.alive&&n.dispose()}}function $(n,e){try{return e(n)}finally{for(const t of n)t.alive&&t.dispose()}}function se([n,e],t){try{return t(n)}finally{e&&n.dispose()}}function B(n,e){try{return e(...n.map(t=>t[0]))}finally{for(const[t,r]of n)r&&t.dispose()}}function ie(n){return"handle"in n}function N(n){return ie(n)?n.handle:n}function oe(n,e,t,r){var i;let s;for(const o of r)if(s=o(e,n),s)break;return s?(i=t(e,s))!=null?i:s:void 0}function ue(n,e){return typeof n!="symbol"?void 0:h(e,"d => Symbol(d)",void 0,n.description?e.newString(n.description):e.undefined)}function ae(n,e){return n instanceof Date?h(e,"d => new Date(d)",void 0,e.newNumber(n.getTime())):void 0}function fe(n,e){if(n instanceof ArrayBuffer)return e.newArrayBuffer(n.slice(0));if(ArrayBuffer.isView(n)){const t=new Uint8Array(n.buffer,n.byteOffset,n.byteLength).slice();return $([e.newArrayBuffer(t.buffer),e.newString(n.constructor.name)],([r,s])=>h(e,"(buf, name) => new globalThis[name](buf)",void 0,r,s))}}const ce=[ue,ae,fe];function L(n){return typeof n=="function"&&/^class\s/.test(Function.prototype.toString.call(n))}function E(n){return typeof n=="function"||typeof n=="object"&&n!==null}function D(n,e){const t=new Set,r=s=>{if(!(!E(s)||t.has(s)||(e==null?void 0:e(s,t))===!1)){if(t.add(s),Array.isArray(s)){for(const i of s)r(i);return}if(typeof s=="object"){const i=Object.getPrototypeOf(s);i&&i!==Object.prototype&&r(i)}for(const i of Object.values(Object.getOwnPropertyDescriptors(s)))"value"in i&&r(i.value),"get"in i&&r(i.get),"set"in i&&r(i.set)}};return r(n),t}function le(n,e){return D(n,e?(t,r)=>r.size<e:void 0).size}function pe(){let n=()=>{},e=()=>{};return{promise:new Promise((r,s)=>{n=r,e=s}),resolve:n,reject:e}}function K(n,e,t,r,s=()=>{}){const i=n.newObject(),o=[],f=(a,u)=>{const d=r(a),y=typeof u.value=="undefined"?void 0:r(u.value),m=typeof u.get=="undefined"?void 0:r(u.get),c=typeof u.set=="undefined"?void 0:r(u.set);y&&o.push(y),m&&o.push(m),c&&o.push(c),n.newObject().consume(p=>{Object.entries(u).forEach(([v,g])=>{const w=v==="value"?y:v==="get"?m:v==="set"?c:g?n.true:n.false;w&&n.setProp(p,v,w)}),n.setProp(i,d,p)})};try{const a=Object.getOwnPropertyDescriptors(e);Object.entries(a).forEach(([u,d])=>f(u,d)),Object.getOwnPropertySymbols(a).forEach(u=>f(u,a[u])),h(n,"Object.defineProperties",void 0,t,i).dispose();for(const u of o)s(u)}finally{i.dispose()}}function de(n,e,t,r,s,i,o=()=>{},f=a=>a){var d;if(typeof e!="function")return;const a=n.newFunction(e.name,function(...y){const m=n.sameValue(this,n.global)?void 0:r(this),c=y.map(p=>r(p));if(L(e)&&E(m)){const p=new e(...c);return Object.entries(p).forEach(([v,g])=>{const w=t(g);n.setProp(this,v,w),o(w)}),this}return f(t(i?i(e,m,c):e.apply(m,c)))}).consume(y=>h(n,`Cls => {
9
9
  const fn = function(...args) { return Cls.apply(this, args); };
10
10
  fn.name = Cls.name;
11
11
  fn.length = Cls.length;
12
12
  return fn;
13
- }`,void 0,l)),a=(u=s(e,f))!=null?u:f;return K(n,e,f,t,o),a}function ye(n,e,t){if(!(typeof e!="object"&&typeof e!="function")&&e!==null)return t(e,n.newHostRef(e).handle)}function he(n,e,t){var i;const r=z(n,e);return(i=t(e,r))!=null?i:r}function me(n,e,t,r,s=()=>{}){var i,o;if(e instanceof Map){const f=h(n,"() => new Map()"),a=(i=r(e,f))!=null?i:f;for(const[u,l]of e){const y=t(u),m=t(l);h(n,"(m, k, v) => m.set(k, v)",void 0,f,y,m).dispose(),s(y),s(m)}return a}if(e instanceof Set){const f=h(n,"() => new Set()"),a=(o=r(e,f))!=null?o:f;for(const u of e){const l=t(u);h(n,"(s, v) => s.add(v)",void 0,f,l).dispose(),s(l)}return a}}function _e(n,e,t,r,s=()=>{}){var u;if(typeof e!="object"||e===null)return;const i=Array.isArray(e)?n.newArray():n.newObject(),o=(u=r(e,i))!=null?u:i,f=Object.getPrototypeOf(e),a=f&&f!==Object.prototype&&f!==Array.prototype?t(f):void 0;return a&&(h(n,"Object.setPrototypeOf",void 0,o,a).dispose(),s(a)),K(n,e,i,t,s),o}function ve(n,e){switch(typeof e){case"undefined":return n.undefined;case"number":return n.newNumber(e);case"string":return n.newString(e);case"boolean":return e?n.true:n.false;case"bigint":return n.newBigInt(e);case"object":return e===null?n.null:void 0}}function be(n,e,t,r){var i;if(!(e instanceof Promise))return;const s=n.newPromise();return e.then(o=>s.resolve(t(o)),o=>s.reject(t(o))),(i=r(e,s))!=null?i:s.handle}function U(n,e){var y,m,c,d,v,w,j,T;const{ctx:t,unmarshal:r,isMarshalable:s,find:i,pre:o}=e;{const S=ve(t,n);if(S)return typeof n=="bigint"&&((y=e.registerTransient)==null||y.call(e,S)),S}{const S=i(n);if(S)return S}if((m=e.marshalByReference)!=null&&m.call(e,n)&&e.registerHostRef){const S=ye(t,n,e.registerHostRef);if(S)return S}const f=s==null?void 0:s(n);if(f===!1)return t.undefined;const a=(S,M)=>o(S,M,f);if(f==="json")return he(t,n,a);const u=S=>U(S,e),l=e.disposeTransient;return(T=(j=(w=(v=(d=oe(t,n,a,[...ce,...(c=e.custom)!=null?c:[]]))!=null?d:be(t,n,u,a))!=null?v:de(t,n,u,r,a,e.preApply,l))!=null?w:me(t,n,u,a,l))!=null?j:_e(t,n,u,a,l))!=null?T:t.undefined}function we(n,e,t,r){var i;let s;for(const o of r)if(s=o(e,n),s)break;return s?(i=t(s,e))!=null?i:s:void 0}function ge(n,e){if(e.typeof(n)!=="symbol")return;const t=e.getString(e.getProp(n,"description"));return Symbol(t)}function je(n,e){if(!P(h(e,"a => a instanceof Date",void 0,n),r=>e.dump(r)))return;const t=P(h(e,"a => a.getTime()",void 0,n),r=>e.getNumber(r));return new Date(t)}function Se(n,e){if(P(h(e,"a => a instanceof ArrayBuffer",void 0,n),t=>e.dump(t))){const t=e.getArrayBuffer(n),r=t.value.slice();return t.dispose(),r.buffer}if(P(h(e,"a => ArrayBuffer.isView(a)",void 0,n),t=>e.dump(t))){const t=P(h(e,"a => a.constructor.name",void 0,n),f=>e.getString(f)),r=globalThis[t];if(typeof r!="function")return;const s=h(e,"a => a.buffer.slice(a.byteOffset, a.byteOffset + a.byteLength)",void 0,n),i=e.getArrayBuffer(s),o=i.value.slice();return i.dispose(),s.dispose(),new r(o.buffer)}}const Pe=[ge,je,Se];function Q(n,e,t,r){P(n.newFunction("",(s,i)=>{const[o]=r(s);if(typeof o!="string"&&typeof o!="number"&&typeof o!="symbol")return;const f=[["value",!0],["get",!0],["set",!0],["configurable",!1],["enumerable",!1],["writable",!1]].reduce((a,[u,l])=>{const y=n.getProp(i,u),m=n.typeof(y);if(m==="undefined")return a;if(!l&&m==="boolean")return a[u]=n.dump(n.getProp(i,u)),a;const[c,d]=r(y);return d&&y.dispose(),a[u]=c,a},{});Object.defineProperty(t,o,f)}),s=>{h(n,`(o, fn) => {
13
+ }`,void 0,y)),u=(d=s(e,a))!=null?d:a;return K(n,e,a,t,o),u}function ye(n,e,t){if(!(typeof e!="object"&&typeof e!="function")&&e!==null)return t(e,n.newHostRef(e).handle)}function he(n,e,t){var i;const r=z(n,e);return(i=t(e,r))!=null?i:r}function me(n,e,t,r,s=()=>{}){var i,o;if(e instanceof Map){const f=h(n,"() => new Map()"),a=(i=r(e,f))!=null?i:f;for(const[u,d]of e){const y=t(u),m=t(d);h(n,"(m, k, v) => m.set(k, v)",void 0,f,y,m).dispose(),s(y),s(m)}return a}if(e instanceof Set){const f=h(n,"() => new Set()"),a=(o=r(e,f))!=null?o:f;for(const u of e){const d=t(u);h(n,"(s, v) => s.add(v)",void 0,f,d).dispose(),s(d)}return a}}function _e(n,e,t,r,s=()=>{}){var u;if(typeof e!="object"||e===null)return;const i=Array.isArray(e)?n.newArray():n.newObject(),o=(u=r(e,i))!=null?u:i,f=Object.getPrototypeOf(e),a=f&&f!==Object.prototype&&f!==Array.prototype?t(f):void 0;return a&&(h(n,"Object.setPrototypeOf",void 0,o,a).dispose(),s(a)),K(n,e,i,t,s),o}function ve(n,e){switch(typeof e){case"undefined":return n.undefined;case"number":return n.newNumber(e);case"string":return n.newString(e);case"boolean":return e?n.true:n.false;case"bigint":return n.newBigInt(e);case"object":return e===null?n.null:void 0}}function be(n,e,t,r){var i;if(!(e instanceof Promise))return;const s=n.newPromise();return e.then(o=>s.resolve(t(o)),o=>s.reject(t(o))),(i=r(e,s))!=null?i:s.handle}function U(n,e){var y,m,c,p,v,g,w,T;const{ctx:t,unmarshal:r,isMarshalable:s,find:i,pre:o}=e;{const S=ve(t,n);if(S)return typeof n=="bigint"&&((y=e.registerTransient)==null||y.call(e,S)),S}{const S=i(n);if(S)return S}if((m=e.marshalByReference)!=null&&m.call(e,n)&&e.registerHostRef){const S=ye(t,n,e.registerHostRef);if(S)return S}const f=s==null?void 0:s(n);if(f===!1)return t.undefined;const a=(S,M)=>o(S,M,f);if(f==="json")return he(t,n,a);const u=S=>U(S,e),d=e.disposeTransient;return(T=(w=(g=(v=(p=oe(t,n,a,[...ce,...(c=e.custom)!=null?c:[]]))!=null?p:be(t,n,u,a))!=null?v:de(t,n,u,r,a,e.preApply,d,e.prepareReturn))!=null?g:me(t,n,u,a,d))!=null?w:_e(t,n,u,a,d))!=null?T:t.undefined}function we(n,e,t,r){var i;let s;for(const o of r)if(s=o(e,n),s)break;return s?(i=t(s,e))!=null?i:s:void 0}function ge(n,e){if(e.typeof(n)!=="symbol")return;const t=e.getString(e.getProp(n,"description"));return Symbol(t)}function je(n,e){if(!P(h(e,"a => a instanceof Date",void 0,n),r=>e.dump(r)))return;const t=P(h(e,"a => a.getTime()",void 0,n),r=>e.getNumber(r));return new Date(t)}function Se(n,e){if(P(h(e,"a => a instanceof ArrayBuffer",void 0,n),t=>e.dump(t))){const t=e.getArrayBuffer(n),r=t.value.slice();return t.dispose(),r.buffer}if(P(h(e,"a => ArrayBuffer.isView(a)",void 0,n),t=>e.dump(t))){const t=P(h(e,"a => a.constructor.name",void 0,n),f=>e.getString(f)),r=globalThis[t];if(typeof r!="function")return;const s=h(e,"a => a.buffer.slice(a.byteOffset, a.byteOffset + a.byteLength)",void 0,n),i=e.getArrayBuffer(s),o=i.value.slice();return i.dispose(),s.dispose(),new r(o.buffer)}}const Pe=[ge,je,Se];function Q(n,e,t,r){P(n.newFunction("",(s,i)=>{const[o]=r(s);if(typeof o!="string"&&typeof o!="number"&&typeof o!="symbol")return;const f=[["value",!0],["get",!0],["set",!0],["configurable",!1],["enumerable",!1],["writable",!1]].reduce((a,[u,d])=>{const y=n.getProp(i,u),m=n.typeof(y);if(m==="undefined")return a;if(!d&&m==="boolean")return a[u]=n.dump(n.getProp(i,u)),a;const[c,p]=r(y);return p&&y.dispose(),a[u]=c,a},{});Object.defineProperty(t,o,f)}),s=>{h(n,`(o, fn) => {
14
14
  const descs = Object.getOwnPropertyDescriptors(o);
15
15
  Object.entries(descs).forEach(([k, v]) => fn(k, v));
16
16
  Object.getOwnPropertySymbols(descs).forEach(k => fn(k, descs[k]));
17
- }`,void 0,e,s).dispose()})}function Te(n,e,t,r,s){var f;if(n.typeof(e)!=="function")return;const i=function(...a){return B([t(this),...a.map(u=>t(u))],(u,...l)=>{if(new.target){const[d]=r(h(n,"(Cls, ...args) => new Cls(...args)",u,e,...l));return Object.defineProperties(this,Object.getOwnPropertyDescriptors(d)),this}const y=k(n,n.callFunction(e,u,...l)),[m,c]=r(y);return c&&y.dispose(),m})},o=(f=s(i,e))!=null?f:i;return Q(n,e,i,r),o}function q(n,e){const t=n.toHostRef(e);if(t)try{return{value:t.value}}finally{t.dispose()}}function ke(n,e,t,r){const s=P(h(n,"a => a instanceof Map",void 0,e),a=>n.dump(a)),i=!s&&P(h(n,"a => a instanceof Set",void 0,e),a=>n.dump(a));if(!s&&!i)return;const o=s?new Map:new Set;r(o,e);const f=n.unwrapResult(n.getIterator(e));try{for(const a of f){const u=n.unwrapResult(a);if(s){const l=n.getProp(u,0),y=n.getProp(u,1),[m,c]=t(l),[d,v]=t(y);c&&l.dispose(),v&&y.dispose(),o.set(m,d),u.dispose()}else{const[l,y]=t(u);y&&u.dispose(),o.add(l)}}}finally{f.alive&&f.dispose()}return o}function Oe(n,e,t,r){var f;if(n.typeof(e)!=="object"||n.sameValue(e,n.null))return;const s=P(h(n,"Array.isArray",void 0,e),a=>n.dump(a))?[]:{},i=(f=r(s,e))!=null?f:s,o=P(h(n,`o => {
17
+ }`,void 0,e,s).dispose()})}function Te(n,e,t,r,s){var f;if(n.typeof(e)!=="function")return;const i=function(...a){return B([t(this),...a.map(u=>t(u))],(u,...d)=>{if(new.target){const[p]=r(h(n,"(Cls, ...args) => new Cls(...args)",u,e,...d));return Object.defineProperties(this,Object.getOwnPropertyDescriptors(p)),this}const y=k(n,n.callFunction(e,u,...d)),[m,c]=r(y);return c&&y.dispose(),m})},o=(f=s(i,e))!=null?f:i;return Q(n,e,i,r),o}function q(n,e){const t=n.toHostRef(e);if(t)try{return{value:t.value}}finally{t.dispose()}}function ke(n,e,t,r){const s=P(h(n,"a => a instanceof Map",void 0,e),a=>n.dump(a)),i=!s&&P(h(n,"a => a instanceof Set",void 0,e),a=>n.dump(a));if(!s&&!i)return;const o=s?new Map:new Set;r(o,e);const f=n.unwrapResult(n.getIterator(e));try{for(const a of f){const u=n.unwrapResult(a);if(s){const d=n.getProp(u,0),y=n.getProp(u,1),[m,c]=t(d),[p,v]=t(y);c&&d.dispose(),v&&y.dispose(),o.set(m,p),u.dispose()}else{const[d,y]=t(u);y&&u.dispose(),o.add(d)}}}finally{f.alive&&f.dispose()}return o}function Re(n,e,t,r){var f;if(n.typeof(e)!=="object"||n.sameValue(e,n.null))return;const s=P(h(n,"Array.isArray",void 0,e),a=>n.dump(a))?[]:{},i=(f=r(s,e))!=null?f:s,o=P(h(n,`o => {
18
18
  const p = Object.getPrototypeOf(o);
19
19
  return !p || p === Object.prototype || p === Array.prototype ? undefined : p;
20
- }`,void 0,e),a=>{if(n.typeof(a)==="undefined")return;const[u]=t(a);return u});return typeof o=="object"&&Object.setPrototypeOf(i,o),Q(n,e,s,t),i}function He(n,e){const t=n.typeof(e);return t==="undefined"||t==="number"||t==="string"||t==="boolean"?[n.dump(e),!0]:t==="bigint"?[n.getBigInt(e),!0]:t==="object"&&n.sameValue(e,n.null)?[null,!0]:[void 0,!1]}function Ee(n,e,t,r){var u;if(!Re(n,e))return;const s=pe(),[i,o]=t(s.resolve),[f,a]=t(s.reject);return h(n,"(p, res, rej) => { p.then(res, rej); }",void 0,e,i,f),o&&i.dispose(),a&&f.dispose(),(u=r(s.promise,e))!=null?u:s.promise}function Re(n,e){return e.owner?n.unwrapResult(n.evalCode("Promise")).consume(t=>e.owner?re(n,e,t):!1):!1}function X(n,e){const[t]=Y(n,e);return t}function Y(n,e){var l,y,m;const{ctx:t,marshal:r,find:s,pre:i}=e;{const[c,d]=He(t,n);if(d)return[c,!1]}{const c=s(n);if(c)return[c,!0]}const o=c=>Y(c,e);if(e.hostRef){const c=q(t,n);if(c)return[c.value,!0]}const f=we(t,n,i,[...Pe,...(l=e.custom)!=null?l:[]]);if(f)return[f,!0];const a=ke(t,n,o,i);return a?[a,!0]:[(m=(y=Ee(t,n,r,i))!=null?y:Te(t,n,r,o,i))!=null?m:Oe(t,n,o,i),!1]}class V{constructor(e){p(this,"ctx");p(this,"_keyToId",new Map);p(this,"_key2ToId",new Map);p(this,"_idToHandle",new Map);p(this,"_idToHandle2",new Map);p(this,"_idToKey",new Map);p(this,"_idToKey2",new Map);p(this,"_disposables",new Set);p(this,"_mapGet");p(this,"_mapSet");p(this,"_mapDelete");p(this,"_mapClear");p(this,"_nextId",Number.MIN_SAFE_INTEGER);this.ctx=e;const t=e.unwrapResult(e.evalCode(`() => {
20
+ }`,void 0,e),a=>{if(n.typeof(a)==="undefined")return;const[u]=t(a);return u});return typeof o=="object"&&Object.setPrototypeOf(i,o),Q(n,e,s,t),i}function Ee(n,e){const t=n.typeof(e);return t==="undefined"||t==="number"||t==="string"||t==="boolean"?[n.dump(e),!0]:t==="bigint"?[n.getBigInt(e),!0]:t==="object"&&n.sameValue(e,n.null)?[null,!0]:[void 0,!1]}function He(n,e,t,r){var u;if(!Oe(n,e))return;const s=pe(),[i,o]=t(s.resolve),[f,a]=t(s.reject);return h(n,"(p, res, rej) => { p.then(res, rej); }",void 0,e,i,f),o&&i.dispose(),a&&f.dispose(),(u=r(s.promise,e))!=null?u:s.promise}function Oe(n,e){return e.owner?n.unwrapResult(n.evalCode("Promise")).consume(t=>e.owner?re(n,e,t):!1):!1}function X(n,e){const[t]=Y(n,e);return t}function Y(n,e){var d,y,m;const{ctx:t,marshal:r,find:s,pre:i}=e;{const[c,p]=Ee(t,n);if(p)return[c,!1]}{const c=s(n);if(c)return[c,!0]}const o=c=>Y(c,e);if(e.hostRef){const c=q(t,n);if(c)return[c.value,!0]}const f=we(t,n,i,[...Pe,...(d=e.custom)!=null?d:[]]);if(f)return[f,!0];const a=ke(t,n,o,i);return a?[a,!0]:[(m=(y=He(t,n,r,i))!=null?y:Te(t,n,r,o,i))!=null?m:Re(t,n,o,i),!1]}class V{constructor(e){l(this,"ctx");l(this,"_keyToId",new Map);l(this,"_key2ToId",new Map);l(this,"_idToHandle",new Map);l(this,"_idToHandle2",new Map);l(this,"_idToKey",new Map);l(this,"_idToKey2",new Map);l(this,"_disposables",new Set);l(this,"_mapGet");l(this,"_mapSet");l(this,"_mapDelete");l(this,"_mapClear");l(this,"_nextId",Number.MIN_SAFE_INTEGER);this.ctx=e;const t=e.unwrapResult(e.evalCode(`() => {
21
21
  const mapSym = new Map();
22
22
  let map = new WeakMap();
23
23
  let map2 = new WeakMap();
@@ -40,7 +40,7 @@
40
40
  map2 = new WeakMap();
41
41
  }
42
42
  };
43
- }`)).consume(r=>this._call(r,void 0));this._mapGet=e.getProp(t,"get"),this._mapSet=e.getProp(t,"set"),this._mapDelete=e.getProp(t,"delete"),this._mapClear=e.getProp(t,"clear"),t.dispose(),this._disposables.add(this._mapGet),this._disposables.add(this._mapSet),this._disposables.add(this._mapDelete),this._disposables.add(this._mapClear)}set(e,t,r,s){var f;if(!t.alive||s&&!s.alive)return!1;const i=(f=this.get(e))!=null?f:this.get(r);if(i)return i===t||i===s;const o=this._nextId++;return this._keyToId.set(e,o),this._idToHandle.set(o,t),this._idToKey.set(o,e),r&&(this._key2ToId.set(r,o),this._idToKey2.set(o,r),s&&this._idToHandle2.set(o,s)),this.ctx.newNumber(o).consume(a=>{this._call(this._mapSet,void 0,t,a,s!=null?s:this.ctx.undefined)}),!0}merge(e){if(e)for(const t of e)t&&t[1]&&this.set(t[0],t[1],t[2],t[3])}get(e){var s;const t=(s=this._keyToId.get(e))!=null?s:this._key2ToId.get(e),r=typeof t=="number"?this._idToHandle.get(t):void 0;if(r){if(!r.alive){this.delete(e);return}return r}}getByHandle(e){if(e.alive)return this._idToKey.get(this.ctx.getNumber(this._call(this._mapGet,void 0,e)))}has(e){return!!this.get(e)}hasHandle(e){return typeof this.getByHandle(e)!="undefined"}keys(){return this._keyToId.keys()}delete(e,t){var a;const r=(a=this._keyToId.get(e))!=null?a:this._key2ToId.get(e);if(typeof r=="undefined")return;const s=this._idToHandle.get(r),i=this._idToHandle2.get(r);this._call(this._mapDelete,void 0,...[s,i].filter(u=>!!(u!=null&&u.alive)));const o=this._idToKey.get(r),f=this._idToKey2.get(r);typeof o!="undefined"&&this._keyToId.delete(o),typeof f!="undefined"&&this._key2ToId.delete(f),this._idToHandle.delete(r),this._idToHandle2.delete(r),this._idToKey.delete(r),this._idToKey2.delete(r),t&&(s!=null&&s.alive&&s.dispose(),i!=null&&i.alive&&i.dispose())}deleteByHandle(e,t){const r=this.getByHandle(e);typeof r!="undefined"&&this.delete(r,t)}clear(){this._nextId=0,this._keyToId.clear(),this._key2ToId.clear(),this._idToHandle.clear(),this._idToHandle2.clear(),this._idToKey.clear(),this._idToKey2.clear(),this._mapClear.alive&&this._call(this._mapClear,void 0)}dispose(){for(const e of this._disposables.values())e.alive&&e.dispose();for(const e of this._idToHandle.values())e.alive&&e.dispose();for(const e of this._idToHandle2.values())e.alive&&e.dispose();this._disposables.clear(),this.clear()}get size(){return this._keyToId.size}[Symbol.iterator](){const e=this._keyToId.keys();return{next:()=>{for(;;){const t=e.next();if(t.done)return{value:void 0,done:!0};const r=this._keyToId.get(t.value);if(typeof r=="undefined")continue;const s=this._idToHandle.get(r),i=this._idToHandle2.get(r);if(!s)continue;const o=this._idToKey2.get(r);return{value:[t.value,s,o,i],done:!1}}}}}_call(e,t,...r){return k(this.ctx,this.ctx.callFunction(e,typeof t=="undefined"?this.ctx.undefined:t,...r))}}function Me(n,e,t,r,s,i,o,f=!0){if(!H(e)||e instanceof Promise||e instanceof Date||e instanceof ArrayBuffer||ArrayBuffer.isView(e)||e instanceof Map||e instanceof Set||o&&!o(e))return;if(Ae(e,t)||!f)return e;const a=new Proxy(e,{get(u,l){return l===t?u:Reflect.get(u,l)},set(u,l,y,m){var v;const c=E(y,t),d=(v=i==null?void 0:i(m))!=null?v:"host";return d!=="vm"&&!Reflect.set(u,l,c)||d==="host"||!n.alive||B([s(m),s(l),s(c)],(w,j,T)=>{const[S,M]=F(n,w,r);M?S.consume(G=>n.setProp(G,j,T)):n.setProp(S,j,T)}),!0},deleteProperty(u,l){var m;const y=(m=i==null?void 0:i(a))!=null?m:"host";return B([s(a),s(l)],(c,d)=>{const[v,w]=F(n,c,r);if(y==="vm"||Reflect.deleteProperty(u,l)){if(y==="host"||!n.alive)return!0;w?v.consume(j=>h(n,"(a, b) => delete a[b]",void 0,j,d)):h(n,"(a, b) => delete a[b]",void 0,v,d)}return!0})},defineProperty(u,l,y){var d;const m=(d=i==null?void 0:i(a))!=null?d:"host",c=te({},y);return"value"in c&&(c.value=E(c.value,t)),typeof c.get=="function"&&(c.get=E(c.get,t)),typeof c.set=="function"&&(c.set=E(c.set,t)),m!=="vm"&&!Reflect.defineProperty(u,l,c)?!1:(m==="host"||!n.alive||B([s(a),s(l),s(c)],(v,w,j)=>{const[T,S]=F(n,v,r),M=G=>h(n,"(o, k, d) => { Object.defineProperty(o, k, d); }",void 0,G,w,j).dispose();S?T.consume(M):M(T)}),!0)}});return a}function Ce(n,e,t,r,s,i,o,f=!0){if(!W(n,e)||o&&!o(e,n))return[void 0,!1];if(Z(n,e,r))return[e,!1];if(!f)return[e,!1];const a=c=>{const d=i==null?void 0:i(s(c));return typeof d=="string"?n.newString(d):n.undefined},u=(c,d,v)=>{const w=s(c);if(!w)return;const j=s(d);if(j==="__proto__")return;const T=s(v);E(w,t)[j]=T},l=(c,d)=>{const v=s(c);if(!v)return;const w=s(d);Reflect.deleteProperty(E(v,t),w)},y=(c,d,v)=>{const w=s(c);if(!w)return;const j=s(d);if(j==="__proto__")return;const T=s(v);Object.defineProperty(E(w,t),j,T)},m=n.newFunction("proxyFuncs",(c,...d)=>{switch(n.getNumber(c)){case 1:return a(d[0]);case 2:return u(d[0],d[1],d[2]);case 3:return l(d[0],d[1]);case 4:return y(d[0],d[1],d[2])}return n.undefined});return P(m,c=>[h(n,`(target, sym, proxyFuncs) => {
43
+ }`)).consume(r=>this._call(r,void 0));this._mapGet=e.getProp(t,"get"),this._mapSet=e.getProp(t,"set"),this._mapDelete=e.getProp(t,"delete"),this._mapClear=e.getProp(t,"clear"),t.dispose(),this._disposables.add(this._mapGet),this._disposables.add(this._mapSet),this._disposables.add(this._mapDelete),this._disposables.add(this._mapClear)}set(e,t,r,s){var f;if(!t.alive||s&&!s.alive)return!1;const i=(f=this.get(e))!=null?f:this.get(r);if(i)return i===t||i===s;const o=this._nextId++;return this._keyToId.set(e,o),this._idToHandle.set(o,t),this._idToKey.set(o,e),r&&(this._key2ToId.set(r,o),this._idToKey2.set(o,r),s&&this._idToHandle2.set(o,s)),this.ctx.newNumber(o).consume(a=>{this._call(this._mapSet,void 0,t,a,s!=null?s:this.ctx.undefined)}),!0}merge(e){if(e)for(const t of e)t&&t[1]&&this.set(t[0],t[1],t[2],t[3])}get(e){var s;const t=(s=this._keyToId.get(e))!=null?s:this._key2ToId.get(e),r=typeof t=="number"?this._idToHandle.get(t):void 0;if(r){if(!r.alive){this.delete(e,!0);return}return r}}getByHandle(e){if(e.alive)return this._idToKey.get(this.ctx.getNumber(this._call(this._mapGet,void 0,e)))}has(e){return!!this.get(e)}hasHandle(e){return typeof this.getByHandle(e)!="undefined"}keys(){return this._keyToId.keys()}delete(e,t){var a;const r=(a=this._keyToId.get(e))!=null?a:this._key2ToId.get(e);if(typeof r=="undefined")return;const s=this._idToHandle.get(r),i=this._idToHandle2.get(r);this._call(this._mapDelete,void 0,...[s,i].filter(u=>!!(u!=null&&u.alive)));const o=this._idToKey.get(r),f=this._idToKey2.get(r);typeof o!="undefined"&&this._keyToId.delete(o),typeof f!="undefined"&&this._key2ToId.delete(f),this._idToHandle.delete(r),this._idToHandle2.delete(r),this._idToKey.delete(r),this._idToKey2.delete(r),t&&(s!=null&&s.alive&&s.dispose(),i!=null&&i.alive&&i.dispose())}deleteByHandle(e,t){const r=this.getByHandle(e);typeof r!="undefined"&&this.delete(r,t)}clear(){this._nextId=0,this._keyToId.clear(),this._key2ToId.clear(),this._idToHandle.clear(),this._idToHandle2.clear(),this._idToKey.clear(),this._idToKey2.clear(),this._mapClear.alive&&this._call(this._mapClear,void 0)}dispose(){for(const e of this._disposables.values())e.alive&&e.dispose();for(const e of this._idToHandle.values())e.alive&&e.dispose();for(const e of this._idToHandle2.values())e.alive&&e.dispose();this._disposables.clear(),this.clear()}get size(){return this._keyToId.size}[Symbol.iterator](){const e=this._keyToId.keys();return{next:()=>{for(;;){const t=e.next();if(t.done)return{value:void 0,done:!0};const r=this._keyToId.get(t.value);if(typeof r=="undefined")continue;const s=this._idToHandle.get(r),i=this._idToHandle2.get(r);if(!s)continue;const o=this._idToKey2.get(r);return{value:[t.value,s,o,i],done:!1}}}}}_call(e,t,...r){return k(this.ctx,this.ctx.callFunction(e,typeof t=="undefined"?this.ctx.undefined:t,...r))}}function Me(n,e,t,r,s,i,o,f=!0){if(!E(e)||e instanceof Promise||e instanceof Date||e instanceof ArrayBuffer||ArrayBuffer.isView(e)||e instanceof Map||e instanceof Set||o&&!o(e))return;if(Ae(e,t)||!f)return e;const a=new Proxy(e,{get(u,d){return d===t?u:Reflect.get(u,d)},set(u,d,y,m){var v;const c=H(y,t),p=(v=i==null?void 0:i(m))!=null?v:"host";return p!=="vm"&&!Reflect.set(u,d,c)||p==="host"||!n.alive||B([s(m),s(d),s(c)],(g,w,T)=>{const[S,M]=F(n,g,r);M?S.consume(G=>n.setProp(G,w,T)):n.setProp(S,w,T)}),!0},deleteProperty(u,d){var m;const y=(m=i==null?void 0:i(a))!=null?m:"host";return B([s(a),s(d)],(c,p)=>{const[v,g]=F(n,c,r);if(y==="vm"||Reflect.deleteProperty(u,d)){if(y==="host"||!n.alive)return!0;g?v.consume(w=>h(n,"(a, b) => delete a[b]",void 0,w,p)):h(n,"(a, b) => delete a[b]",void 0,v,p)}return!0})},defineProperty(u,d,y){var p;const m=(p=i==null?void 0:i(a))!=null?p:"host",c=te({},y);return"value"in c&&(c.value=H(c.value,t)),typeof c.get=="function"&&(c.get=H(c.get,t)),typeof c.set=="function"&&(c.set=H(c.set,t)),m!=="vm"&&!Reflect.defineProperty(u,d,c)?!1:(m==="host"||!n.alive||B([s(a),s(d),s(c)],(v,g,w)=>{const[T,S]=F(n,v,r),M=G=>h(n,"(o, k, d) => { Object.defineProperty(o, k, d); }",void 0,G,g,w).dispose();S?T.consume(M):M(T)}),!0)}});return a}function Ce(n,e,t,r,s,i,o,f=!0){if(!W(n,e)||o&&!o(e,n))return[void 0,!1];if(Z(n,e,r))return[e,!1];if(!f)return[e,!1];const a=c=>{const p=i==null?void 0:i(s(c));return typeof p=="string"?n.newString(p):n.undefined},u=(c,p,v)=>{const g=s(c);if(!g)return;const w=s(p);if(w==="__proto__")return;const T=s(v);H(g,t)[w]=T},d=(c,p)=>{const v=s(c);if(!v)return;const g=s(p);Reflect.deleteProperty(H(v,t),g)},y=(c,p,v)=>{const g=s(c);if(!g)return;const w=s(p);if(w==="__proto__")return;const T=s(v);Object.defineProperty(H(g,t),w,T)},m=n.newFunction("proxyFuncs",(c,...p)=>{switch(n.getNumber(c)){case 1:return a(p[0]);case 2:return u(p[0],p[1],p[2]);case 3:return d(p[0],p[1]);case 4:return y(p[0],p[1],p[2])}return n.undefined});return P(m,c=>[h(n,`(target, sym, proxyFuncs) => {
44
44
  const rec = new Proxy(target, {
45
45
  get(obj, key, receiver) {
46
46
  return key === sym ? obj : Reflect.get(obj, key, receiver)
@@ -77,4 +77,4 @@
77
77
  },
78
78
  });
79
79
  return rec;
80
- }`,void 0,e,r,c),!0])}function E(n,e){var t;return H(n)&&(t=n[e])!=null?t:n}function F(n,e,t){return Z(n,e,t)?[n.getProp(e,t),!0]:[e,!1]}function Ae(n,e){return H(n)&&!!n[e]}function Z(n,e,t){return!!n.dump(h(n,'(a, s) => (a instanceof Promise) || (a instanceof Date) || (a instanceof ArrayBuffer) || (ArrayBuffer.isView(a)) || (a instanceof Map) || (a instanceof Set) || (typeof a === "object" && a !== null || typeof a === "function") && !!a[s]',void 0,e,t))}class x{constructor(e,t){p(this,"context");p(this,"_map");p(this,"_registeredMap");p(this,"_registeredMapDispose",new Set);p(this,"_transientHandles",new Set);p(this,"_sync",new Set);p(this,"_temporalSync",new Set);p(this,"_symbol",Symbol());p(this,"_symbolHandle");p(this,"_options");p(this,"_isMarshalable",e=>{var r,s;const t=(r=this._options)==null?void 0:r.isMarshalable;return(s=typeof t=="function"?t(this._unwrap(e)):t)!=null?s:"json"});p(this,"_marshalByReference",e=>{var t,r;return!!((r=(t=this._options)==null?void 0:t.marshalByReference)!=null&&r.call(t,this._unwrap(e)))});p(this,"_registerHostRef",(e,t)=>{const r=this._unwrap(e),s=this._map.get(r);return s||(this._map.set(r,t),t)});p(this,"_marshalFind",e=>{var s,i,o;const t=this._unwrap(e);return(o=(i=(s=this._registeredMap.get(e))!=null?s:t!==e?this._registeredMap.get(t):void 0)!=null?i:this._map.get(e))!=null?o:t!==e?this._map.get(t):void 0});p(this,"_marshalPre",(e,t,r)=>{if(r==="json"){this._registerTransient(N(t));return}const s=this._register(e,N(t),this._map);if(s)return s[1];this._registeredMap.has(e)||this._registerTransient(N(t))});p(this,"_registerTransient",e=>{this._transientHandles.add(e)});p(this,"_disposeTransient",e=>{this._transientHandles.delete(e)&&e.alive&&e.dispose()});p(this,"_marshalPreApply",(e,t,r)=>{const s=H(t)?this._unwrap(t):void 0;s&&this._temporalSync.add(s);try{return e.apply(t,r)}finally{s&&this._temporalSync.delete(s)}});p(this,"_marshal",e=>{var o,f,a,u;const t=this._registeredMap.get(e);if(t)return[t,!1];const r=this._marshalByReference(e)?this._unwrap(e):(o=this._wrap(e))!=null?o:e,s=U(r,{ctx:this.context,unmarshal:this._unmarshal,isMarshalable:this._isMarshalable,marshalByReference:this._marshalByReference,registerHostRef:this._registerHostRef,find:this._marshalFind,pre:this._marshalPre,registerTransient:this._registerTransient,disposeTransient:this._disposeTransient,preApply:this._marshalPreApply,custom:(f=this._options)==null?void 0:f.customMarshaller});this._transientHandles.delete(s);const i=(u=(a=this._options)==null?void 0:a.syncEnabled)!=null?u:!0;return[s,!i||!this._map.hasHandle(s)]});p(this,"_preUnmarshal",(e,t)=>{var r,s,i;return(i=this._register(e,t,void 0,(s=(r=this._options)==null?void 0:r.syncEnabled)!=null?s:!0))==null?void 0:i[0]});p(this,"_unmarshalFind",e=>{var t;return(t=this._registeredMap.getByHandle(e))!=null?t:this._map.getByHandle(e)});p(this,"_unmarshal",e=>{var s,i,o;const t=this._registeredMap.getByHandle(e);if(typeof t!="undefined")return t;if((s=this._options)!=null&&s.marshalByReference){const f=q(this.context,e);if(f)return f.value}const[r]=this._wrapHandle(e);return X(r!=null?r:e,{ctx:this.context,marshal:this._marshal,find:this._unmarshalFind,pre:this._preUnmarshal,custom:(i=this._options)==null?void 0:i.customUnmarshaller,hostRef:!!((o=this._options)!=null&&o.marshalByReference)})});p(this,"_syncMode",e=>{const t=this._unwrap(e);return this._sync.has(t)||this._temporalSync.has(t)?"both":void 0});p(this,"_unwrapIfNotSynced",e=>{const t=this._unwrap(e);return t instanceof Promise||!this._sync.has(t)?t:e});var r;t!=null&&t.compat&&!("runtime"in e)&&(e.runtime={hasPendingJob:()=>e.hasPendingJob(),executePendingJobs:s=>e.executePendingJobs(s)}),this.context=t!=null&&t.experimentalContextEx?b(e):e,C(this.context),this._options=t,this._symbolHandle=e.unwrapResult(e.evalCode("Symbol()")),this._map=new V(e),this._registeredMap=new V(e),this.registerAll((r=t==null?void 0:t.registeredObjects)!=null?r:A)}dispose(){var e,t;for(const r of this._transientHandles)r.alive&&r.dispose();this._transientHandles.clear(),this._map.dispose(),this._registeredMap.dispose(),this._symbolHandle.dispose(),O(this.context),(t=(e=this.context).disposeEx)==null||t.call(e)}[Symbol.dispose](){this.dispose()}evalCode(e){const t=this.context.evalCode(e);return this._unwrapResultAndUnmarshal(t)}evalModule(e,t="module.js"){const r=this.context.evalCode(e,t,{type:"module"});return this._unwrapResultAndUnmarshal(r)}executePendingJobs(e){const t=this.context.runtime.executePendingJobs(e);if("value"in t)return t.value;throw this._unwrapIfNotSynced(P(t.error,this._unmarshal))}setMemoryLimit(e){this.context.runtime.setMemoryLimit(e)}setMaxStackSize(e){this.context.runtime.setMaxStackSize(e)}getMemoryUsage(){const e=this.context.runtime.computeMemoryUsage();try{return this.context.dump(e)}finally{e.dispose()}}dumpMemoryUsage(){return this.context.runtime.dumpMemoryUsage()}expose(e){for(const[t,r]of Object.entries(e))se(this._marshal(r),s=>{this.context.setProp(this.context.global,t,s)})}sync(e){const t=this._wrap(e);return typeof t=="undefined"?e:(D(t,r=>{const s=this._unwrap(r);this._sync.add(s)}),t)}register(e,t){if(this._registeredMap.has(e))return;const r=typeof t=="string"?this._unwrapResult(this.context.evalCode(t)):t;this.context.sameValue(r,this.context.undefined)||(typeof t=="string"&&this._registeredMapDispose.add(e),this._registeredMap.set(e,r))}registerAll(e){for(const[t,r]of e)this.register(t,r)}unregister(e,t){this._registeredMap.delete(e,this._registeredMapDispose.has(e)||t),this._registeredMapDispose.delete(e)}unregisterAll(e,t){for(const r of e)this.unregister(r,t)}startSync(e){if(!H(e))return;const t=this._unwrap(e);this._sync.add(t)}endSync(e){this._sync.delete(this._unwrap(e))}_unwrapResult(e){if("value"in e)return e.value;throw this._unwrapIfNotSynced(P(e.error,this._unmarshal))}_unwrapResultAndUnmarshal(e){if(e)return this._unwrapIfNotSynced(P(this._unwrapResult(e),this._unmarshal))}_register(e,t,r=this._map,s){if(this._registeredMap.has(e)||this._registeredMap.hasHandle(t))return;let i=this._wrap(e);const[o]=this._wrapHandle(t),f=e instanceof Promise;if(!o||!i&&!f)return;f&&(i=e);const a=this._unwrap(e),[u,l]=this._unwrapHandle(t);if(r.set(i,o,a,u))s&&this._sync.add(a);else throw l&&u.dispose(),new Error("already registered");return[i,o]}_wrap(e){var t,r,s;return Me(this.context,e,this._symbol,this._symbolHandle,this._marshal,this._syncMode,(t=this._options)==null?void 0:t.isWrappable,(s=(r=this._options)==null?void 0:r.syncEnabled)!=null?s:!0)}_unwrap(e){return E(e,this._symbol)}_wrapHandle(e){var t,r,s;return Ce(this.context,e,this._symbol,this._symbolHandle,this._unmarshal,this._syncMode,(t=this._options)==null?void 0:t.isHandleWrappable,(s=(r=this._options)==null?void 0:r.syncEnabled)!=null?s:!0)}_unwrapHandle(e){return F(this.context,e,this._symbolHandle)}}class Be extends x{constructor(t,r){super(t,r);p(this,"asyncContext");this.asyncContext=t}evalCodeAsync(t,r){return ne(this,null,function*(){const s=yield this.asyncContext.evalCodeAsync(t,r);return this._unwrapResultAndUnmarshal(s)})}}_.Arena=x,_.AsyncArena=Be,_.VMMap=V,_.call=h,_.complexity=le,_.consumeAll=$,_.defaultRegisteredObjects=A,_.isES2015Class=L,_.isHandleObject=W,_.isObject=H,_.json=z,_.marshal=U,_.unmarshal=X,_.walkObject=D,Object.defineProperty(_,Symbol.toStringTag,{value:"Module"})}));
80
+ }`,void 0,e,r,c),!0])}function H(n,e){var t;return E(n)&&(t=n[e])!=null?t:n}function F(n,e,t){return Z(n,e,t)?[n.getProp(e,t),!0]:[e,!1]}function Ae(n,e){return E(n)&&!!n[e]}function Z(n,e,t){return!!n.dump(h(n,'(a, s) => (a instanceof Promise) || (a instanceof Date) || (a instanceof ArrayBuffer) || (ArrayBuffer.isView(a)) || (a instanceof Map) || (a instanceof Set) || (typeof a === "object" && a !== null || typeof a === "function") && !!a[s]',void 0,e,t))}class x{constructor(e,t){l(this,"context");l(this,"_map");l(this,"_registeredMap");l(this,"_registeredMapDispose",new Set);l(this,"_transientHandles",new Set);l(this,"_sync",new Set);l(this,"_temporalSync",new Set);l(this,"_symbol",Symbol());l(this,"_symbolHandle");l(this,"_options");l(this,"_isMarshalable",e=>{var r,s;const t=(r=this._options)==null?void 0:r.isMarshalable;return(s=typeof t=="function"?t(this._unwrap(e)):t)!=null?s:"json"});l(this,"_marshalByReference",e=>{var t,r;return!!((r=(t=this._options)==null?void 0:t.marshalByReference)!=null&&r.call(t,this._unwrap(e)))});l(this,"_registerHostRef",(e,t)=>{const r=this._unwrap(e),s=this._map.get(r);return s||(this._map.set(r,t),t)});l(this,"_marshalFind",e=>{var s,i,o;const t=this._unwrap(e);return(o=(i=(s=this._registeredMap.get(e))!=null?s:t!==e?this._registeredMap.get(t):void 0)!=null?i:this._map.get(e))!=null?o:t!==e?this._map.get(t):void 0});l(this,"_marshalPre",(e,t,r)=>{if(r==="json"){this._registerTransient(N(t));return}const s=this._register(e,N(t),this._map);if(s)return s[1];this._registeredMap.has(e)||this._registerTransient(N(t))});l(this,"_registerTransient",e=>{this._transientHandles.add(e)});l(this,"_disposeTransient",e=>{this._transientHandles.delete(e)&&e.alive&&e.dispose()});l(this,"_marshalPreApply",(e,t,r)=>{const s=E(t)?this._unwrap(t):void 0;s&&this._temporalSync.add(s);try{return e.apply(t,r)}finally{s&&this._temporalSync.delete(s)}});l(this,"_marshal",e=>{var o,f,a,u;const t=this._registeredMap.get(e);if(t)return[t,!1];const r=this._marshalByReference(e)?this._unwrap(e):(o=this._wrap(e))!=null?o:e,s=U(r,{ctx:this.context,unmarshal:this._unmarshal,isMarshalable:this._isMarshalable,marshalByReference:this._marshalByReference,registerHostRef:this._registerHostRef,find:this._marshalFind,pre:this._marshalPre,registerTransient:this._registerTransient,disposeTransient:this._disposeTransient,preApply:this._marshalPreApply,prepareReturn:this._prepareMarshalReturn,custom:(f=this._options)==null?void 0:f.customMarshaller});this._transientHandles.delete(s);const i=(u=(a=this._options)==null?void 0:a.syncEnabled)!=null?u:!0;return[s,!i||!this._map.hasHandle(s)]});l(this,"_prepareMarshalReturn",e=>{var r,s;return((s=(r=this._options)==null?void 0:r.syncEnabled)!=null?s:!0)&&e.alive&&this._map.hasHandle(e)?e.dup():e});l(this,"_preUnmarshal",(e,t)=>{var r,s,i;return(i=this._register(e,t,void 0,(s=(r=this._options)==null?void 0:r.syncEnabled)!=null?s:!0))==null?void 0:i[0]});l(this,"_unmarshalFind",e=>{var t;return(t=this._registeredMap.getByHandle(e))!=null?t:this._map.getByHandle(e)});l(this,"_unmarshal",e=>{var s,i,o;const t=this._registeredMap.getByHandle(e);if(typeof t!="undefined")return t;if((s=this._options)!=null&&s.marshalByReference){const f=q(this.context,e);if(f)return f.value}const[r]=this._wrapHandle(e);return X(r!=null?r:e,{ctx:this.context,marshal:this._marshal,find:this._unmarshalFind,pre:this._preUnmarshal,custom:(i=this._options)==null?void 0:i.customUnmarshaller,hostRef:!!((o=this._options)!=null&&o.marshalByReference)})});l(this,"_syncMode",e=>{const t=this._unwrap(e);return this._sync.has(t)||this._temporalSync.has(t)?"both":void 0});l(this,"_unwrapIfNotSynced",e=>{const t=this._unwrap(e);return t instanceof Promise||!this._sync.has(t)?t:e});var r;t!=null&&t.compat&&!("runtime"in e)&&(e.runtime={hasPendingJob:()=>e.hasPendingJob(),executePendingJobs:s=>e.executePendingJobs(s)}),this.context=t!=null&&t.experimentalContextEx?b(e):e,C(this.context),this._options=t,this._symbolHandle=e.unwrapResult(e.evalCode("Symbol()")),this._map=new V(e),this._registeredMap=new V(e),this.registerAll((r=t==null?void 0:t.registeredObjects)!=null?r:A)}dispose(){var e,t;for(const r of this._transientHandles)r.alive&&r.dispose();this._transientHandles.clear(),this._map.dispose(),this._registeredMap.dispose(),this._symbolHandle.dispose(),R(this.context),(t=(e=this.context).disposeEx)==null||t.call(e)}[Symbol.dispose](){this.dispose()}evalCode(e){const t=this.context.evalCode(e);return this._unwrapResultAndUnmarshal(t)}evalModule(e,t="module.js"){const r=this.context.evalCode(e,t,{type:"module"});return this._unwrapResultAndUnmarshal(r)}executePendingJobs(e){const t=this.context.runtime.executePendingJobs(e);if("value"in t)return t.value;throw this._unwrapIfNotSynced(P(t.error,this._unmarshal))}setMemoryLimit(e){this.context.runtime.setMemoryLimit(e)}setMaxStackSize(e){this.context.runtime.setMaxStackSize(e)}getMemoryUsage(){const e=this.context.runtime.computeMemoryUsage();try{return this.context.dump(e)}finally{e.dispose()}}dumpMemoryUsage(){return this.context.runtime.dumpMemoryUsage()}expose(e){for(const[t,r]of Object.entries(e))se(this._marshal(r),s=>{this.context.setProp(this.context.global,t,s)})}sync(e){const t=this._wrap(e);return typeof t=="undefined"?e:(D(t,r=>{const s=this._unwrap(r);this._sync.add(s)}),t)}register(e,t){if(this._registeredMap.has(e))return;const r=typeof t=="string"?this._unwrapResult(this.context.evalCode(t)):t;this.context.sameValue(r,this.context.undefined)||(typeof t=="string"&&this._registeredMapDispose.add(e),this._registeredMap.set(e,r))}registerAll(e){for(const[t,r]of e)this.register(t,r)}unregister(e,t){this._registeredMap.delete(e,this._registeredMapDispose.has(e)||t),this._registeredMapDispose.delete(e)}unregisterAll(e,t){for(const r of e)this.unregister(r,t)}startSync(e){if(!E(e))return;const t=this._unwrap(e);this._sync.add(t)}endSync(e){this._sync.delete(this._unwrap(e))}_unwrapResult(e){if("value"in e)return e.value;throw this._unwrapIfNotSynced(P(e.error,this._unmarshal))}_unwrapResultAndUnmarshal(e){if(e)return this._unwrapIfNotSynced(P(this._unwrapResult(e),this._unmarshal))}_register(e,t,r=this._map,s){if(this._registeredMap.has(e)||this._registeredMap.hasHandle(t))return;let i=this._wrap(e);const[o]=this._wrapHandle(t),f=e instanceof Promise;if(!o||!i&&!f)return;f&&(i=e);const a=this._unwrap(e),[u,d]=this._unwrapHandle(t);if(r.set(i,o,a,u))s&&this._sync.add(a);else throw d&&u.dispose(),new Error("already registered");return[i,o]}_wrap(e){var t,r,s;return Me(this.context,e,this._symbol,this._symbolHandle,this._marshal,this._syncMode,(t=this._options)==null?void 0:t.isWrappable,(s=(r=this._options)==null?void 0:r.syncEnabled)!=null?s:!0)}_unwrap(e){return H(e,this._symbol)}_wrapHandle(e){var t,r,s;return Ce(this.context,e,this._symbol,this._symbolHandle,this._unmarshal,this._syncMode,(t=this._options)==null?void 0:t.isHandleWrappable,(s=(r=this._options)==null?void 0:r.syncEnabled)!=null?s:!0)}_unwrapHandle(e){return F(this.context,e,this._symbolHandle)}}class Be extends x{constructor(t,r){super(t,r);l(this,"asyncContext");this.asyncContext=t}evalCodeAsync(t,r){return ne(this,null,function*(){const s=yield this.asyncContext.evalCodeAsync(t,r);return this._unwrapResultAndUnmarshal(s)})}}_.Arena=x,_.AsyncArena=Be,_.VMMap=V,_.call=h,_.complexity=le,_.consumeAll=$,_.defaultRegisteredObjects=A,_.isES2015Class=L,_.isHandleObject=W,_.isObject=E,_.json=z,_.marshal=U,_.unmarshal=X,_.walkObject=D,Object.defineProperty(_,Symbol.toStringTag,{value:"Module"})}));
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "quickjs-emscripten-sync",
3
3
  "author": "rot1024",
4
- "version": "1.9.1",
4
+ "version": "1.10.0",
5
5
  "license": "MIT",
6
6
  "repository": {
7
7
  "type": "git",
package/src/edge.test.ts CHANGED
@@ -36,12 +36,54 @@ describe("edge cases", () => {
36
36
  expect(cb.current?.()).toBe(0);
37
37
  expect(called).toEqual(["a", "b"]);
38
38
 
39
+ // The host getters are still traversed on every access, so `called` grows.
40
+ // But `obj` keeps its identity across marshals (sync is on), so the VM holds
41
+ // the value snapshot from the first marshal: a later host-side mutation is
42
+ // not re-marshalled. Use `arena.sync(obj)` to propagate host writes (see the
43
+ // "getter (synced)" test below).
39
44
  obj.c = 1;
40
- expect(cb.current?.()).toBe(1); // this line causes an error when context is disposed
45
+ expect(cb.current?.()).toBe(0);
41
46
  expect(called).toEqual(["a", "b", "a", "b"]);
42
47
 
43
48
  arena.dispose();
44
- // ctx.dispose(); // reports an error
49
+ // Re-marshalling `obj` used to leak a handle, which aborted ctx.dispose().
50
+ // Now that the stale-entry handle is disposed, the context disposes cleanly.
51
+ expect(() => ctx.dispose()).not.toThrow();
52
+ });
53
+
54
+ // this test takes more than about 20s
55
+ test("getter (synced)", async () => {
56
+ const ctx = (await getQuickJS()).newContext();
57
+ const arena = new Arena(ctx, { isMarshalable: true });
58
+
59
+ // A synced object propagates host-side writes to the VM, so re-reads see the
60
+ // updated value while still keeping a stable identity.
61
+ const obj = arena.sync({ c: 0 });
62
+ const exposed = {
63
+ get a() {
64
+ return {
65
+ get b() {
66
+ return obj;
67
+ },
68
+ };
69
+ },
70
+ };
71
+ const cb: { current?: () => any } = {};
72
+ arena.expose({
73
+ exposed,
74
+ register: (fn: () => any) => {
75
+ cb.current = fn;
76
+ },
77
+ });
78
+
79
+ arena.evalCode(`register(() => exposed.a.b.c);`);
80
+ expect(cb.current?.()).toBe(0);
81
+
82
+ obj.c = 1;
83
+ expect(cb.current?.()).toBe(1);
84
+
85
+ arena.dispose();
86
+ expect(() => ctx.dispose()).not.toThrow();
45
87
  });
46
88
 
47
89
  test(
@@ -0,0 +1,57 @@
1
+ import { getQuickJS } from "quickjs-emscripten";
2
+ import { describe, expect, it } from "vitest";
3
+
4
+ import { Arena } from ".";
5
+
6
+ // A host function's return value is disposed by the VM once consumed. Marshalled
7
+ // object handles are retained in the VMMap for identity while sync is on, so the
8
+ // returned handle must be dup'd — otherwise the map entry goes stale and the same
9
+ // value marshalled twice yields two distinct VM objects. These tests pin the
10
+ // identity behaviour (issue #4); the no-leak side is covered by
11
+ // remarshalleak.test.ts under the debug-sync runtime.
12
+ async function withArena(
13
+ options: ConstructorParameters<typeof Arena>[1],
14
+ fn: (arena: Arena) => void,
15
+ ) {
16
+ const ctx = (await getQuickJS()).newContext();
17
+ const arena = new Arena(ctx, options);
18
+ fn(arena);
19
+ arena.dispose();
20
+ ctx.dispose();
21
+ }
22
+
23
+ describe("marshal identity", () => {
24
+ it("preserves identity for a VM object round-tripped through the host", async () => {
25
+ await withArena({ isMarshalable: true }, arena => {
26
+ arena.expose({ id: (x: any) => x });
27
+ // foo originates in the VM, is passed to the host and returned: the
28
+ // round-trip must yield the same object.
29
+ expect(arena.evalCode(`let foo = id({}); foo === id(foo)`)).toBe(true);
30
+ });
31
+ });
32
+
33
+ it("returns the same VM object when a host function returns the same object twice", async () => {
34
+ await withArena({ isMarshalable: true }, arena => {
35
+ const shared = { k: 1 };
36
+ arena.expose({ get: () => shared });
37
+ expect(arena.evalCode(`get() === get()`)).toBe(true);
38
+ });
39
+ });
40
+
41
+ it("keeps identity across retained references", async () => {
42
+ await withArena({ isMarshalable: true }, arena => {
43
+ const shared = { k: 1 };
44
+ arena.expose({ get: () => shared });
45
+ expect(arena.evalCode(`let a = get(); let b = get(); a === b`)).toBe(true);
46
+ });
47
+ });
48
+
49
+ it("does not retain identity when sync is disabled", async () => {
50
+ await withArena({ isMarshalable: true, syncEnabled: false }, arena => {
51
+ const shared = { k: 1 };
52
+ arena.expose({ get: () => shared });
53
+ // With sync off, objects are not retained, so each marshal is independent.
54
+ expect(arena.evalCode(`get() === get()`)).toBe(false);
55
+ });
56
+ });
57
+ });
package/src/index.test.ts CHANGED
@@ -550,6 +550,26 @@ test("register and unregister", async () => {
550
550
  ctx.dispose();
551
551
  });
552
552
 
553
+ test("plain call passes `this` as undefined, method call passes the receiver", async () => {
554
+ const ctx = (await getQuickJS()).newContext();
555
+ const arena = new Arena(ctx, { isMarshalable: true });
556
+
557
+ arena.expose({
558
+ whoAmI() {
559
+ return this;
560
+ },
561
+ });
562
+
563
+ // A plain call would see `this === globalThis` in plain JS; the VM global is
564
+ // intentionally not marshalled to the host, so `this` is undefined here.
565
+ expect(arena.evalCode(`whoAmI()`)).toBe(undefined);
566
+ // A method call still receives its receiver.
567
+ expect(arena.evalCode(`const o = { v: 42, whoAmI }; o.whoAmI().v`)).toBe(42);
568
+
569
+ arena.dispose();
570
+ ctx.dispose();
571
+ });
572
+
553
573
  test("registeredObjects option", async () => {
554
574
  const ctx = (await getQuickJS()).newContext();
555
575
  const arena = new Arena(ctx, {
package/src/index.ts CHANGED
@@ -490,6 +490,7 @@ export class Arena {
490
490
  registerTransient: this._registerTransient,
491
491
  disposeTransient: this._disposeTransient,
492
492
  preApply: this._marshalPreApply,
493
+ prepareReturn: this._prepareMarshalReturn,
493
494
  custom: this._options?.customMarshaller,
494
495
  });
495
496
 
@@ -501,6 +502,17 @@ export class Arena {
501
502
  return [handle, !syncEnabled || !this._map.hasHandle(handle)];
502
503
  };
503
504
 
505
+ _prepareMarshalReturn = (h: QuickJSHandle): QuickJSHandle => {
506
+ // A host function's return value is disposed by the VM once it is consumed.
507
+ // When sync is on, the VMMap retains object handles for identity, so the
508
+ // handle we hand back is the one the map owns: returning it directly would
509
+ // let the VM dispose the map's copy, leaving a stale entry that breaks
510
+ // `x === fn()` identity across calls. Hand the VM a dup instead and keep
511
+ // ours alive. With sync off, handles are not retained, so this is a no-op.
512
+ const syncEnabled = this._options?.syncEnabled ?? true;
513
+ return syncEnabled && h.alive && this._map.hasHandle(h) ? h.dup() : h;
514
+ };
515
+
504
516
  _preUnmarshal = (t: any, h: QuickJSHandle): Wrapped<any> => {
505
517
  return this._register(t, h, undefined, this._options?.syncEnabled ?? true)?.[0];
506
518
  };
@@ -30,10 +30,12 @@ test("normal func", async () => {
30
30
  expect(ctx.dump(result)).toBe("hoge");
31
31
  expect(innerfn).toBeCalledWith(1, true);
32
32
  expect(marshal).toHaveBeenLastCalledWith("hoge");
33
- expect(unmarshal).toBeCalledTimes(3);
34
- expect(unmarshal.mock.results[0].value).toBe(undefined); // this
35
- expect(unmarshal.mock.results[1].value).toBe(1);
36
- expect(unmarshal.mock.results[2].value).toBe(true);
33
+ // `this` coerces to the VM global for a plain call, which marshalFunction
34
+ // treats as undefined without unmarshalling it, so only the two args are
35
+ // unmarshalled.
36
+ expect(unmarshal).toBeCalledTimes(2);
37
+ expect(unmarshal.mock.results[0].value).toBe(1);
38
+ expect(unmarshal.mock.results[1].value).toBe(true);
37
39
 
38
40
  handle.dispose();
39
41
  ctx.dispose();
@@ -13,12 +13,20 @@ export default function marshalFunction(
13
13
  preMarshal: (target: unknown, handle: QuickJSHandle) => QuickJSHandle | undefined,
14
14
  preApply?: (target: (...args: any[]) => any, thisArg: unknown, args: unknown[]) => any,
15
15
  disposeTransient: (handle: QuickJSHandle) => void = () => {},
16
+ prepareReturn: (handle: QuickJSHandle) => QuickJSHandle = h => h,
16
17
  ): QuickJSHandle | undefined {
17
18
  if (typeof target !== "function") return;
18
19
 
19
20
  const raw = ctx
20
21
  .newFunction(target.name, function (...argHandles) {
21
- const that = unmarshal(this);
22
+ // A plain call (`fn()`) passes the VM global object as `this`. Unmarshalling
23
+ // it would eagerly deep-copy the entire global graph (hundreds of handles)
24
+ // on the first call, for a `this` host functions almost never use — and
25
+ // leaking globalThis to the host is undesirable. So global `this` is passed
26
+ // to the host function as `undefined`, which differs from plain JS where a
27
+ // non-strict function sees `this === globalThis` (see README Limitations).
28
+ // Real method calls still get their receiver unmarshalled.
29
+ const that = ctx.sameValue(this, ctx.global) ? undefined : unmarshal(this);
22
30
  const args = argHandles.map(a => unmarshal(a));
23
31
 
24
32
  if (isES2015Class(target) && isObject(that)) {
@@ -33,7 +41,16 @@ export default function marshalFunction(
33
41
  return this;
34
42
  }
35
43
 
36
- return marshal(preApply ? preApply(target as (...args: any[]) => any, that, args) : (target as (...args: any[]) => any).apply(that, args));
44
+ // The VM disposes whatever we return here. `prepareReturn` dups the
45
+ // handle when the VMMap retains it, so the map keeps a live copy and
46
+ // identity (`x === fn()` across calls) survives instead of going stale.
47
+ return prepareReturn(
48
+ marshal(
49
+ preApply
50
+ ? preApply(target as (...args: any[]) => any, that, args)
51
+ : (target as (...args: any[]) => any).apply(that, args),
52
+ ),
53
+ );
37
54
  })
38
55
  .consume(handle2 =>
39
56
  // fucntions created by vm.newFunction are not callable as a class constrcutor
@@ -28,6 +28,11 @@ export type Options = {
28
28
  mode: true | "json" | undefined,
29
29
  ) => QuickJSHandle | undefined;
30
30
  preApply?: (target: (...args: any[]) => any, thisArg: unknown, args: unknown[]) => any;
31
+ // Adjust ownership of a handle that is about to be handed to the VM as a host
32
+ // function's return value. The VM disposes whatever it receives, so a handle
33
+ // the VMMap retains (for identity, while sync is on) must be dup'd here or its
34
+ // map entry goes stale. Defaults to identity (no-op).
35
+ prepareReturn?: (handle: QuickJSHandle) => QuickJSHandle;
31
36
  custom?: Iterable<(obj: unknown, ctx: QuickJSContext) => QuickJSHandle | undefined>;
32
37
  };
33
38
 
@@ -73,7 +78,16 @@ export function marshal(target: unknown, options: Options): QuickJSHandle {
73
78
  return (
74
79
  marshalCustom(ctx, target, pre2, [...defaultCustom, ...(options.custom ?? [])]) ??
75
80
  marshalPromise(ctx, target, marshal2, pre2) ??
76
- marshalFunction(ctx, target, marshal2, unmarshal, pre2, options.preApply, disposeTransient) ??
81
+ marshalFunction(
82
+ ctx,
83
+ target,
84
+ marshal2,
85
+ unmarshal,
86
+ pre2,
87
+ options.preApply,
88
+ disposeTransient,
89
+ options.prepareReturn,
90
+ ) ??
77
91
  marshalMapSet(ctx, target, marshal2, pre2, disposeTransient) ??
78
92
  marshalObject(ctx, target, marshal2, pre2, disposeTransient) ??
79
93
  ctx.undefined
@@ -0,0 +1,50 @@
1
+ import variant from "@jitl/quickjs-wasmfile-debug-sync";
2
+ import { newQuickJSWASMModuleFromVariant } from "quickjs-emscripten";
3
+ import { describe, expect, it } from "vitest";
4
+
5
+ import { Arena } from ".";
6
+
7
+ // Marshalling the same host object into the VM more than once used to leak a
8
+ // handle: the first registration stores both a wrapped (proxy) handle and its
9
+ // unwrapped sibling. Once the VM frees the proxy, the map entry goes stale, and
10
+ // the lazy eviction in VMMap.get dropped the entry without disposing the
11
+ // still-alive sibling. The debug-sync runtime aborts on dispose if any GC
12
+ // object handle leaked, so reaching ctx.dispose() without an abort proves the
13
+ // sibling is now released.
14
+ async function withArena(fn: (arena: Arena) => void) {
15
+ const mod = await newQuickJSWASMModuleFromVariant(variant as any);
16
+ const ctx = mod.newContext();
17
+ const arena = new Arena(ctx, { isMarshalable: true });
18
+ fn(arena);
19
+ arena.dispose();
20
+ expect(() => ctx.dispose()).not.toThrow();
21
+ }
22
+
23
+ describe("re-marshal handle leak", () => {
24
+ // Calling an exposed function from inside the VM marshals the whole global
25
+ // graph on each call, which is slow under the debug-sync runtime + coverage,
26
+ // so these get a generous timeout (cf. the "many newFunction" edge test).
27
+ it(
28
+ "does not leak when a host function returns the same object twice",
29
+ async () => {
30
+ await withArena(arena => {
31
+ const shared = { k: 1 };
32
+ arena.expose({ get: () => shared });
33
+ arena.evalCode(`get(); get();`);
34
+ });
35
+ },
36
+ 90000,
37
+ );
38
+
39
+ it(
40
+ "does not leak when the same object is compared across two calls",
41
+ async () => {
42
+ await withArena(arena => {
43
+ const shared = { k: 1 };
44
+ arena.expose({ get: () => shared });
45
+ arena.evalCode(`get() === get();`);
46
+ });
47
+ },
48
+ 90000,
49
+ );
50
+ });
package/src/vmmap.ts CHANGED
@@ -121,7 +121,11 @@ export default class VMMap {
121
121
 
122
122
  if (!handle) return;
123
123
  if (!handle.alive) {
124
- this.delete(key);
124
+ // The primary handle was freed by the VM, so this entry is stale. Dispose
125
+ // its sibling handle while evicting it: otherwise the sibling (e.g. the
126
+ // unwrapped handle registered alongside a proxy) is orphaned and leaks
127
+ // when the same value is marshalled again.
128
+ this.delete(key, true);
125
129
  return;
126
130
  }
127
131