quickjs-emscripten-sync 1.4.0 → 1.5.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.
- package/README.md +28 -7
- package/dist/index.d.ts +12 -7
- package/dist/quickjs-emscripten-sync.mjs +842 -0
- package/dist/quickjs-emscripten-sync.umd.js +15 -15
- package/package.json +9 -18
- package/src/default.ts +2 -2
- package/src/index.test.ts +21 -13
- package/src/index.ts +30 -43
- package/src/marshal/custom.test.ts +50 -0
- package/src/marshal/custom.ts +36 -0
- package/src/marshal/function.test.ts +17 -37
- package/src/marshal/function.ts +8 -12
- package/src/marshal/index.test.ts +35 -39
- package/src/marshal/index.ts +6 -9
- package/src/marshal/json.test.ts +9 -15
- package/src/marshal/json.ts +1 -4
- package/src/marshal/object.test.ts +19 -51
- package/src/marshal/object.ts +3 -11
- package/src/marshal/primitive.test.ts +4 -13
- package/src/marshal/primitive.ts +1 -1
- package/src/marshal/promise.test.ts +9 -10
- package/src/marshal/promise.ts +4 -11
- package/src/marshal/properties.test.ts +7 -14
- package/src/marshal/properties.ts +6 -9
- package/src/unmarshal/custom.test.ts +50 -0
- package/src/unmarshal/custom.ts +31 -0
- package/src/unmarshal/function.test.ts +20 -44
- package/src/unmarshal/function.ts +7 -17
- package/src/unmarshal/index.test.ts +30 -23
- package/src/unmarshal/index.ts +4 -6
- package/src/unmarshal/object.test.ts +9 -17
- package/src/unmarshal/object.ts +7 -12
- package/src/unmarshal/primitive.test.ts +1 -4
- package/src/unmarshal/primitive.ts +3 -10
- package/src/unmarshal/promise.test.ts +3 -3
- package/src/unmarshal/promise.ts +3 -10
- package/src/unmarshal/properties.test.ts +2 -2
- package/src/unmarshal/properties.ts +4 -8
- package/src/util.test.ts +1 -7
- package/src/util.ts +3 -8
- package/src/vmmap.ts +13 -31
- package/src/vmutil.test.ts +15 -29
- package/src/vmutil.ts +12 -39
- package/src/wrapper.test.ts +27 -90
- package/src/wrapper.ts +43 -50
- package/dist/quickjs-emscripten-sync.es.js +0 -962
- package/src/marshal/symbol.test.ts +0 -24
- package/src/marshal/symbol.ts +0 -21
- package/src/unmarshal/symbol.test.ts +0 -25
- package/src/unmarshal/symbol.ts +0 -12
|
@@ -1,4 +1,16 @@
|
|
|
1
|
-
(function(h,
|
|
1
|
+
(function(h,w){typeof exports=="object"&&typeof module!="undefined"?w(exports):typeof define=="function"&&define.amd?define(["exports"],w):(h=typeof globalThis!="undefined"?globalThis:h||self,w(h.QuickjsEmscriptenSync={}))})(this,function(h){"use strict";const w=[[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(t=>typeof Symbol[t]=="symbol").map(t=>[Symbol[t],`Symbol.${t}`])];function I(t,e){const r=t.unwrapResult(t.evalCode(e)),i=(n,...s)=>t.unwrapResult(t.callFunction(r,n!=null?n:t.undefined,...s));return i.dispose=()=>r.dispose(),i.alive=!0,Object.defineProperty(i,"alive",{get:()=>r.alive}),i}function d(t,e,r,...i){const n=I(t,e);try{return n(r,...i)}finally{n.dispose()}}function M(t,e,r){return t.dump(d(t,"Object.is",void 0,e,r))}function U(t,e,r){return t.dump(d(t,"(a, b) => a instanceof b",void 0,e,r))}function R(t,e){return t.dump(d(t,'a => typeof a === "object" && a !== null || typeof a === "function"',void 0,e))}function k(t,e){const r=JSON.stringify(e);return r?d(t,"JSON.parse",void 0,t.newString(r)):t.undefined}function H(t,e){try{return e(t)}finally{for(const r of t)r.alive&&r.dispose()}}function W([t,e],r){try{return r(t)}finally{e&&t.dispose()}}function j(t,e){try{return e(...t.map(r=>r[0]))}finally{for(const[r,i]of t)i&&r.dispose()}}function z(t){return"handle"in t}function $(t){return z(t)?t.handle:t}function G(t,e,r,i){var s;let n;for(const o of i)if(n=o(e,t),n)break;return n?(s=r(e,n))!=null?s:n:void 0}function q(t,e){return typeof t!="symbol"?void 0:d(e,"d => Symbol(d)",void 0,t.description?e.newString(t.description):e.undefined)}function Q(t,e){return t instanceof Date?d(e,"d => new Date(d)",void 0,e.newNumber(t.getTime())):void 0}const V=[q,Q];function C(t){return typeof t=="function"&&/^class\s/.test(Function.prototype.toString.call(t))}function v(t){return typeof t=="function"||typeof t=="object"&&t!==null}function P(t,e){const r=new Set,i=n=>{if(!(!v(n)||r.has(n)||(e==null?void 0:e(n,r))===!1)){if(r.add(n),Array.isArray(n)){for(const s of n)i(s);return}if(typeof n=="object"){const s=Object.getPrototypeOf(n);s&&s!==Object.prototype&&i(s)}for(const s of Object.values(Object.getOwnPropertyDescriptors(n)))"value"in s&&i(s.value),"get"in s&&i(s.get),"set"in s&&i(s.set)}};return i(t),r}function L(t,e){return P(t,e?(r,i)=>i.size<e:void 0).size}function X(){let t=()=>{},e=()=>{};return{promise:new Promise((i,n)=>{t=i,e=n}),resolve:t,reject:e}}function D(t,e,r,i){const n=t.newObject(),s=(u,a)=>{const p=i(u),l=typeof a.value=="undefined"?void 0:i(a.value),f=typeof a.get=="undefined"?void 0:i(a.get),c=typeof a.set=="undefined"?void 0:i(a.set);t.newObject().consume(m=>{Object.entries(a).forEach(([y,_])=>{const b=y==="value"?l:y==="get"?f:y==="set"?c:_?t.true:t.false;b&&t.setProp(m,y,b)}),t.setProp(n,p,m)})},o=Object.getOwnPropertyDescriptors(e);Object.entries(o).forEach(([u,a])=>s(u,a)),Object.getOwnPropertySymbols(o).forEach(u=>s(u,o[u])),d(t,"Object.defineProperties",void 0,r,n).dispose(),n.dispose()}function Y(t,e,r,i,n,s){var a;if(typeof e!="function")return;const o=t.newFunction(e.name,function(...p){const l=i(this),f=p.map(c=>i(c));if(C(e)&&v(l)){const c=new e(...f);return Object.entries(c).forEach(([m,y])=>{t.setProp(this,m,r(y))}),this}return r(s?s(e,l,f):e.apply(l,f))}).consume(p=>d(t,`Cls => {
|
|
2
|
+
const fn = function(...args) { return Cls.apply(this, args); };
|
|
3
|
+
fn.name = Cls.name;
|
|
4
|
+
fn.length = Cls.length;
|
|
5
|
+
return fn;
|
|
6
|
+
}`,void 0,p)),u=(a=n(e,o))!=null?a:o;return D(t,e,o,r),u}function Z(t,e,r){var s;const i=k(t,e);return(s=r(e,i))!=null?s:i}function K(t,e,r,i){var a;if(typeof e!="object"||e===null)return;const n=Array.isArray(e)?t.newArray():t.newObject(),s=(a=i(e,n))!=null?a:n,o=Object.getPrototypeOf(e),u=o&&o!==Object.prototype&&o!==Array.prototype?r(o):void 0;return u&&d(t,"Object.setPrototypeOf",void 0,s,u).dispose(),D(t,e,n,r),s}function x(t,e){switch(typeof e){case"undefined":return t.undefined;case"number":return t.newNumber(e);case"string":return t.newString(e);case"boolean":return e?t.true:t.false;case"object":return e===null?t.null:void 0}}function ee(t,e,r,i){var s;if(!(e instanceof Promise))return;const n=t.newPromise();return e.then(o=>n.resolve(r(o)),o=>n.reject(r(o))),(s=i(e,n))!=null?s:n.handle}function O(t,e){var l,f,c,m,y;const{ctx:r,unmarshal:i,isMarshalable:n,find:s,pre:o}=e;{const _=x(r,t);if(_)return _}{const _=s(t);if(_)return _}const u=n==null?void 0:n(t);if(u===!1)return r.undefined;const a=(_,b)=>o(_,b,u);if(u==="json")return Z(r,t,a);const p=_=>O(_,e);return(y=(m=(c=(f=G(r,t,a,[...V,...(l=e.custom)!=null?l:[]]))!=null?f:ee(r,t,p,a))!=null?c:Y(r,t,p,i,a,e.preApply))!=null?m:K(r,t,p,a))!=null?y:r.undefined}function te(t,e,r,i){var s;let n;for(const o of i)if(n=o(e,t),n)break;return n?(s=r(n,e))!=null?s:n:void 0}function re(t,e){if(e.typeof(t)!=="symbol")return;const r=e.getString(e.getProp(t,"description"));return Symbol(r)}function ne(t,e){if(!e.dump(d(e,"a => a instanceof Date",void 0,t)))return;const r=e.getNumber(d(e,"a => a.getTime()",void 0,t));return new Date(r)}const se=[re,ne];function F(t,e,r,i){t.newFunction("",(n,s)=>{const[o]=i(n);if(typeof o!="string"&&typeof o!="number"&&typeof o!="symbol")return;const u=[["value",!0],["get",!0],["set",!0],["configurable",!1],["enumerable",!1],["writable",!1]].reduce((a,[p,l])=>{const f=t.getProp(s,p),c=t.typeof(f);if(c==="undefined")return a;if(!l&&c==="boolean")return a[p]=t.dump(t.getProp(s,p)),a;const[m,y]=i(f);return y&&f.dispose(),a[p]=m,a},{});Object.defineProperty(r,o,u)}).consume(n=>{d(t,`(o, fn) => {
|
|
7
|
+
const descs = Object.getOwnPropertyDescriptors(o);
|
|
8
|
+
Object.entries(descs).forEach(([k, v]) => fn(k, v));
|
|
9
|
+
Object.getOwnPropertySymbols(descs).forEach(k => fn(k, descs[k]));
|
|
10
|
+
}`,void 0,e,n).dispose()})}function ie(t,e,r,i,n){var u;if(t.typeof(e)!=="function")return;const s=function(...a){return j([r(this),...a.map(p=>r(p))],(p,...l)=>{if(new.target){const[y]=i(d(t,"(Cls, ...args) => new Cls(...args)",p,e,...l));return Object.defineProperties(this,Object.getOwnPropertyDescriptors(y)),this}const f=t.unwrapResult(t.callFunction(e,p,...l)),[c,m]=i(f);return m&&f.dispose(),c})},o=(u=n(s,e))!=null?u:s;return F(t,e,s,i),o}function oe(t,e,r,i){var u;if(t.typeof(e)!=="object"||t.unwrapResult(t.evalCode("o => o === null")).consume(a=>t.dump(t.unwrapResult(t.callFunction(a,t.undefined,e)))))return;const n=d(t,"Array.isArray",void 0,e).consume(a=>t.dump(a))?[]:{},s=(u=i(n,e))!=null?u:n,o=d(t,`o => {
|
|
11
|
+
const p = Object.getPrototypeOf(o);
|
|
12
|
+
return !p || p === Object.prototype || p === Array.prototype ? undefined : p;
|
|
13
|
+
}`,void 0,e).consume(a=>{if(t.typeof(a)==="undefined")return;const[p]=r(a);return p});return typeof o=="object"&&Object.setPrototypeOf(s,o),F(t,e,n,r),s}function ue(t,e){const r=t.typeof(e);return r==="undefined"||r==="number"||r==="string"||r==="boolean"?[t.dump(e),!0]:r==="object"&&t.unwrapResult(t.evalCode("a => a === null")).consume(n=>t.dump(t.unwrapResult(t.callFunction(n,t.undefined,e))))?[null,!0]:[void 0,!1]}function ae(t,e,r,i){var p;if(!pe(t,e))return;const n=X(),[s,o]=r(n.resolve),[u,a]=r(n.reject);return d(t,"(p, res, rej) => { p.then(res, rej); }",void 0,e,s,u),o&&s.dispose(),a&&u.dispose(),(p=i(n.promise,e))!=null?p:n.promise}function pe(t,e){return e.owner?t.unwrapResult(t.evalCode("Promise")).consume(r=>e.owner?U(t,e,r):!1):!1}function A(t,e){const[r]=N(t,e);return r}function N(t,e){var a,p,l,f;const{ctx:r,marshal:i,find:n,pre:s}=e;{const[c,m]=ue(r,t);if(m)return[c,!1]}{const c=n(t);if(c)return[c,!0]}const o=c=>N(c,e);return[(f=(l=(p=te(r,t,s,[...se,...(a=e.custom)!=null?a:[]]))!=null?p:ae(r,t,i,s))!=null?l:ie(r,t,i,o,s))!=null?f:oe(r,t,o,s),!1]}class S{constructor(e){this._map1=new Map,this._map2=new Map,this._map3=new Map,this._map4=new Map,this._counterMap=new Map,this._disposables=new Set,this._counter=0,this.ctx=e;const r=e.unwrapResult(e.evalCode(`() => {
|
|
2
14
|
const mapSym = new Map();
|
|
3
15
|
let map = new WeakMap();
|
|
4
16
|
let map2 = new WeakMap();
|
|
@@ -21,19 +33,7 @@
|
|
|
21
33
|
map2 = new WeakMap();
|
|
22
34
|
}
|
|
23
35
|
};
|
|
24
|
-
}`)).consume(i=>this._call(i,void 0));this._mapGet=e.getProp(r,"get"),this._mapSet=e.getProp(r,"set"),this._mapDelete=e.getProp(r,"delete"),this._mapClear=e.getProp(r,"clear"),r.dispose(),this._disposables.add(this._mapGet),this._disposables.add(this._mapSet),this._disposables.add(this._mapDelete),this._disposables.add(this._mapClear)}set(e,r,i,n){var u;if(!r.alive||n&&!n.alive)return!1;const s=(u=this.get(e))!=null?u:this.get(i);if(s)return s===r||s===n;const o=this._counter++;return this._map1.set(e,o),this._map3.set(o,r),this._counterMap.set(o,e),i&&(this._map2.set(i,o),n&&this._map4.set(o,n)),this.ctx.newNumber(o).consume(a=>{this._call(this._mapSet,void 0,r,a,n!=null?n:this.ctx.undefined)}),!0}merge(e){if(!!e)for(const r of e)!r||r[1]&&this.set(r[0],r[1],r[2],r[3])}get(e){var n;const r=(n=this._map1.get(e))!=null?n:this._map2.get(e),i=typeof r=="number"?this._map3.get(r):void 0;if(!!i){if(!i.alive){this.delete(e);return}return i}}getByHandle(e){if(!!e.alive)return this._counterMap.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._map1.keys()}delete(e,r){var o;const i=(o=this._map1.get(e))!=null?o:this._map2.get(e);if(typeof i=="undefined")return;const n=this._map3.get(i),s=this._map4.get(i);this._call(this._mapDelete,void 0,...[n,s].filter(u=>!!(u!=null&&u.alive))),this._map1.delete(e),this._map2.delete(e),this._map3.delete(i),this._map4.delete(i);for(const[u,a]of this._map1)if(a===i){this._map1.delete(u);break}for(const[u,a]of this._map2)if(a===i){this._map2.delete(u);break}for(const[u,a]of this._counterMap)if(a===e){this._counterMap.delete(u);break}r&&(n!=null&&n.alive&&n.dispose(),s!=null&&s.alive&&s.dispose())}deleteByHandle(e,r){const i=this.getByHandle(e);typeof i!="undefined"&&this.delete(i,r)}clear(){this._counter=0,this._map1.clear(),this._map2.clear(),this._map3.clear(),this._map4.clear(),this._counterMap.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._map3.values())e.alive&&e.dispose();for(const e of this._map4.values())e.alive&&e.dispose();this._disposables.clear(),this.clear()}get size(){return this._map1.size}[Symbol.iterator](){const e=this._map1.keys();return{next:()=>{for(;;){const r=e.next();if(r.done)return{value:void 0,done:!0};const i=this._map1.get(r.value);if(typeof i=="undefined")continue;const n=this._map3.get(i),s=this._map4.get(i);if(!n)continue;const o=this._get2(i);return{value:[r.value,n,o,s],done:!1}}}}}_get2(e){for(const[r,i]of this._map2)if(i===e)return r}_call(e,r,...i){return this.ctx.unwrapResult(this.ctx.callFunction(e,typeof r=="undefined"?this.ctx.undefined:r,...i))}}function
|
|
25
|
-
const fn = function(...args) { return Cls.apply(this, args); };
|
|
26
|
-
fn.name = Cls.name;
|
|
27
|
-
fn.length = Cls.length;
|
|
28
|
-
return fn;
|
|
29
|
-
}`,void 0,p)),u=(a=n(e,o))!=null?a:o;return F(t,e,o,r),u}function V(t,e,r,i){var a;if(typeof e!="object"||e===null)return;const n=Array.isArray(e)?t.newArray():t.newObject(),s=(a=i(e,n))!=null?a:n,o=Object.getPrototypeOf(e),u=o&&o!==Object.prototype&&o!==Array.prototype?r(o):void 0;return u&&m(t,"Object.setPrototypeOf",void 0,s,u).dispose(),F(t,e,n,r),s}function $(t,e){switch(typeof e){case"undefined":return t.undefined;case"number":return t.newNumber(e);case"string":return t.newString(e);case"boolean":return e?t.true:t.false;case"object":return e===null?t.null:void 0}}function L(t,e,r){var n;if(typeof e!="symbol")return;const i=m(t,"d => Symbol(d)",void 0,e.description?t.newString(e.description):t.undefined);return(n=r(e,i))!=null?n:i}function X(t,e,r){var s;const i=k(t,e);return(s=r(e,i))!=null?s:i}function Y(t,e,r,i){var s;if(!(e instanceof Promise))return;const n=t.newPromise();return e.then(o=>n.resolve(r(o)),o=>n.reject(r(o))),(s=i(e,n))!=null?s:n.handle}function O(t,e){var l,f,d,y;const{ctx:r,unmarshal:i,isMarshalable:n,find:s,pre:o}=e;{const c=$(r,t);if(c)return c}{const c=s(t);if(c)return c}const u=n==null?void 0:n(t);if(u===!1)return r.undefined;const a=(c,b)=>o(c,b,u);if(u==="json")return X(r,t,a);const p=c=>O(c,e);return(y=(d=(f=(l=L(r,t,a))!=null?l:Y(r,t,p,a))!=null?f:Q(r,t,p,i,a,e.preApply))!=null?d:V(r,t,p,a))!=null?y:r.undefined}function A(t,e,r,i){t.newFunction("",(n,s)=>{const[o]=i(n);if(typeof o!="string"&&typeof o!="number"&&typeof o!="symbol")return;const u=[["value",!0],["get",!0],["set",!0],["configurable",!1],["enumerable",!1],["writable",!1]].reduce((a,[p,l])=>{const f=t.getProp(s,p),d=t.typeof(f);if(d==="undefined")return a;if(!l&&d==="boolean")return a[p]=t.dump(t.getProp(s,p)),a;const[y,c]=i(f);return c&&f.dispose(),a[p]=y,a},{});Object.defineProperty(r,o,u)}).consume(n=>{m(t,`(o, fn) => {
|
|
30
|
-
const descs = Object.getOwnPropertyDescriptors(o);
|
|
31
|
-
Object.entries(descs).forEach(([k, v]) => fn(k, v));
|
|
32
|
-
Object.getOwnPropertySymbols(descs).forEach(k => fn(k, descs[k]));
|
|
33
|
-
}`,void 0,e,n).dispose()})}function Z(t,e,r,i,n){var u;if(t.typeof(e)!=="function")return;const s=function(...a){return P([r(this),...a.map(p=>r(p))],(p,...l)=>{if(new.target){const[c]=i(m(t,"(Cls, ...args) => new Cls(...args)",p,e,...l));return Object.defineProperties(this,Object.getOwnPropertyDescriptors(c)),this}const f=t.unwrapResult(t.callFunction(e,p,...l)),[d,y]=i(f);return y&&f.dispose(),d})},o=(u=n(s,e))!=null?u:s;return A(t,e,s,i),o}function K(t,e,r,i){var u;if(t.typeof(e)!=="object"||t.unwrapResult(t.evalCode("o => o === null")).consume(a=>t.dump(t.unwrapResult(t.callFunction(a,t.undefined,e)))))return;const n=m(t,"Array.isArray",void 0,e).consume(a=>t.dump(a))?[]:{},s=(u=i(n,e))!=null?u:n,o=m(t,`o => {
|
|
34
|
-
const p = Object.getPrototypeOf(o);
|
|
35
|
-
return !p || p === Object.prototype || p === Array.prototype ? undefined : p;
|
|
36
|
-
}`,void 0,e).consume(a=>{if(t.typeof(a)==="undefined")return;const[p]=r(a);return p});return typeof o=="object"&&Object.setPrototypeOf(s,o),A(t,e,n,r),s}function x(t,e){const r=t.typeof(e);return r==="undefined"||r==="number"||r==="string"||r==="boolean"?[t.dump(e),!0]:r==="object"&&t.unwrapResult(t.evalCode("a => a === null")).consume(n=>t.dump(t.unwrapResult(t.callFunction(n,t.undefined,e))))?[null,!0]:[void 0,!1]}function ee(t,e,r,i){var p;if(!te(t,e))return;const n=I(),[s,o]=r(n.resolve),[u,a]=r(n.reject);return m(t,"(p, res, rej) => { p.then(res, rej); }",void 0,e,s,u),o&&s.dispose(),a&&u.dispose(),(p=i(n.promise,e))!=null?p:n.promise}function te(t,e){return e.owner?t.unwrapResult(t.evalCode("Promise")).consume(r=>e.owner?W(t,e,r):!1):!1}function re(t,e,r){var s;if(t.typeof(e)!=="symbol")return;const i=t.getString(t.getProp(e,"description")),n=Symbol(i);return(s=r(n,e))!=null?s:n}function C(t,e){const[r]=D(t,e);return r}function D(t,e){var a,p,l;const{ctx:r,marshal:i,find:n,pre:s}=e;{const[f,d]=x(r,t);if(d)return[f,!1]}{const f=n(t);if(f)return[f,!0]}const o=f=>D(f,e);return[(l=(p=(a=re(r,t,s))!=null?a:ee(r,t,i,s))!=null?p:Z(r,t,i,o,s))!=null?l:K(r,t,o,s),!1]}function ne(t,e,r,i,n,s){if(!_(e)||e instanceof Promise)return;if(ie(e,r))return e;const o=new Proxy(e,{get(u,a){return a===r?u:Reflect.get(u,a)},set(u,a,p,l){var y;const f=g(p,r),d=(y=s==null?void 0:s(l))!=null?y:"host";return d!=="vm"&&!Reflect.set(u,a,f,l)||d==="host"||!t.alive||P([n(l),n(a),n(f)],(c,b,w)=>{const[J,ue]=S(t,c,i);ue?J.consume(ae=>t.setProp(ae,b,w)):t.setProp(J,b,w)}),!0},deleteProperty(u,a){var l;const p=(l=s==null?void 0:s(o))!=null?l:"host";return P([n(o),n(a)],(f,d)=>{const[y,c]=S(t,f,i);if(p==="vm"||Reflect.deleteProperty(u,a)){if(p==="host"||!t.alive)return!0;c?y.consume(b=>m(t,"(a, b) => delete a[b]",void 0,b,d)):m(t,"(a, b) => delete a[b]",void 0,y,d)}return!0})}});return o}function se(t,e,r,i,n,s){return M(t,e)?B(t,e,i)?[e,!1]:H([t.newFunction("getSyncMode",o=>{const u=s==null?void 0:s(n(o));return typeof u=="string"?t.newString(u):t.undefined}),t.newFunction("setter",(o,u,a)=>{const p=n(o);if(!p)return;const l=n(u);if(l==="__proto__")return;const f=n(a);g(p,r)[l]=f}),t.newFunction("deleter",(o,u)=>{const a=n(o);if(!a)return;const p=n(u);delete g(a,r)[p]})],o=>[m(t,`(target, sym, getSyncMode, setter, deleter) => {
|
|
36
|
+
}`)).consume(i=>this._call(i,void 0));this._mapGet=e.getProp(r,"get"),this._mapSet=e.getProp(r,"set"),this._mapDelete=e.getProp(r,"delete"),this._mapClear=e.getProp(r,"clear"),r.dispose(),this._disposables.add(this._mapGet),this._disposables.add(this._mapSet),this._disposables.add(this._mapDelete),this._disposables.add(this._mapClear)}set(e,r,i,n){var u;if(!r.alive||n&&!n.alive)return!1;const s=(u=this.get(e))!=null?u:this.get(i);if(s)return s===r||s===n;const o=this._counter++;return this._map1.set(e,o),this._map3.set(o,r),this._counterMap.set(o,e),i&&(this._map2.set(i,o),n&&this._map4.set(o,n)),this.ctx.newNumber(o).consume(a=>{this._call(this._mapSet,void 0,r,a,n!=null?n:this.ctx.undefined)}),!0}merge(e){if(!!e)for(const r of e)!r||r[1]&&this.set(r[0],r[1],r[2],r[3])}get(e){var n;const r=(n=this._map1.get(e))!=null?n:this._map2.get(e),i=typeof r=="number"?this._map3.get(r):void 0;if(!!i){if(!i.alive){this.delete(e);return}return i}}getByHandle(e){if(!!e.alive)return this._counterMap.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._map1.keys()}delete(e,r){var o;const i=(o=this._map1.get(e))!=null?o:this._map2.get(e);if(typeof i=="undefined")return;const n=this._map3.get(i),s=this._map4.get(i);this._call(this._mapDelete,void 0,...[n,s].filter(u=>!!(u!=null&&u.alive))),this._map1.delete(e),this._map2.delete(e),this._map3.delete(i),this._map4.delete(i);for(const[u,a]of this._map1)if(a===i){this._map1.delete(u);break}for(const[u,a]of this._map2)if(a===i){this._map2.delete(u);break}for(const[u,a]of this._counterMap)if(a===e){this._counterMap.delete(u);break}r&&(n!=null&&n.alive&&n.dispose(),s!=null&&s.alive&&s.dispose())}deleteByHandle(e,r){const i=this.getByHandle(e);typeof i!="undefined"&&this.delete(i,r)}clear(){this._counter=0,this._map1.clear(),this._map2.clear(),this._map3.clear(),this._map4.clear(),this._counterMap.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._map3.values())e.alive&&e.dispose();for(const e of this._map4.values())e.alive&&e.dispose();this._disposables.clear(),this.clear()}get size(){return this._map1.size}[Symbol.iterator](){const e=this._map1.keys();return{next:()=>{for(;;){const r=e.next();if(r.done)return{value:void 0,done:!0};const i=this._map1.get(r.value);if(typeof i=="undefined")continue;const n=this._map3.get(i),s=this._map4.get(i);if(!n)continue;const o=this._get2(i);return{value:[r.value,n,o,s],done:!1}}}}}_get2(e){for(const[r,i]of this._map2)if(i===e)return r}_call(e,r,...i){return this.ctx.unwrapResult(this.ctx.callFunction(e,typeof r=="undefined"?this.ctx.undefined:r,...i))}}function fe(t,e,r,i,n,s,o){if(!v(e)||e instanceof Promise||e instanceof Date||o&&!o(e))return;if(ce(e,r))return e;const u=new Proxy(e,{get(a,p){return p===r?a:Reflect.get(a,p)},set(a,p,l,f){var y;const c=g(l,r),m=(y=s==null?void 0:s(f))!=null?y:"host";return m!=="vm"&&!Reflect.set(a,p,c,f)||m==="host"||!t.alive||j([n(f),n(p),n(c)],(_,b,T)=>{const[J,he]=E(t,_,i);he?J.consume(me=>t.setProp(me,b,T)):t.setProp(J,b,T)}),!0},deleteProperty(a,p){var f;const l=(f=s==null?void 0:s(u))!=null?f:"host";return j([n(u),n(p)],(c,m)=>{const[y,_]=E(t,c,i);if(l==="vm"||Reflect.deleteProperty(a,p)){if(l==="host"||!t.alive)return!0;_?y.consume(b=>d(t,"(a, b) => delete a[b]",void 0,b,m)):d(t,"(a, b) => delete a[b]",void 0,y,m)}return!0})}});return u}function le(t,e,r,i,n,s,o){return!R(t,e)||o&&!o(e,t)?[void 0,!1]:B(t,e,i)?[e,!1]:H([t.newFunction("getSyncMode",u=>{const a=s==null?void 0:s(n(u));return typeof a=="string"?t.newString(a):t.undefined}),t.newFunction("setter",(u,a,p)=>{const l=n(u);if(!l)return;const f=n(a);if(f==="__proto__")return;const c=n(p);g(l,r)[f]=c}),t.newFunction("deleter",(u,a)=>{const p=n(u);if(!p)return;const l=n(a);delete g(p,r)[l]})],u=>[d(t,`(target, sym, getSyncMode, setter, deleter) => {
|
|
37
37
|
const rec = new Proxy(target, {
|
|
38
38
|
get(obj, key, receiver) {
|
|
39
39
|
return key === sym ? obj : Reflect.get(obj, key, receiver)
|
|
@@ -61,4 +61,4 @@
|
|
|
61
61
|
},
|
|
62
62
|
});
|
|
63
63
|
return rec;
|
|
64
|
-
}`,void 0,e,i,...
|
|
64
|
+
}`,void 0,e,i,...u),!0])}function g(t,e){var r;return v(t)&&(r=t[e])!=null?r:t}function E(t,e,r){return B(t,e,r)?[t.getProp(e,r),!0]:[e,!1]}function ce(t,e){return v(t)&&!!t[e]}function B(t,e,r){return!!t.dump(d(t,'(a, s) => (a instanceof Promise) || (a instanceof Date) || (typeof a === "object" && a !== null || typeof a === "function") && !!a[s]',void 0,e,r))}class de{constructor(e,r){var i;this._registeredMapDispose=new Set,this._sync=new Set,this._temporalSync=new Set,this._symbol=Symbol(),this._isMarshalable=n=>{var o,u;const s=(o=this._options)==null?void 0:o.isMarshalable;return(u=typeof s=="function"?s(this._unwrap(n)):s)!=null?u:"json"},this._marshalFind=n=>{var u,a,p;const s=this._unwrap(n);return(p=(a=(u=this._registeredMap.get(n))!=null?u:s!==n?this._registeredMap.get(s):void 0)!=null?a:this._map.get(n))!=null?p:s!==n?this._map.get(s):void 0},this._marshalPre=(n,s,o)=>{var u;if(o!=="json")return(u=this._register(n,$(s),this._map))==null?void 0:u[1]},this._marshalPreApply=(n,s,o)=>{const u=v(s)?this._unwrap(s):void 0;u&&this._temporalSync.add(u);try{return n.apply(s,o)}finally{u&&this._temporalSync.delete(u)}},this._marshal=n=>{var u,a;const s=this._registeredMap.get(n);if(s)return[s,!1];const o=O((u=this._wrap(n))!=null?u:n,{ctx:this.context,unmarshal:this._unmarshal,isMarshalable:this._isMarshalable,find:this._marshalFind,pre:this._marshalPre,preApply:this._marshalPreApply,custom:(a=this._options)==null?void 0:a.customMarshaller});return[o,!this._map.hasHandle(o)]},this._preUnmarshal=(n,s)=>{var o;return(o=this._register(n,s,void 0,!0))==null?void 0:o[0]},this._unmarshalFind=n=>{var s;return(s=this._registeredMap.getByHandle(n))!=null?s:this._map.getByHandle(n)},this._unmarshal=n=>{var u;const s=this._registeredMap.getByHandle(n);if(typeof s!="undefined")return s;const[o]=this._wrapHandle(n);return A(o!=null?o:n,{ctx:this.context,marshal:this._marshal,find:this._unmarshalFind,pre:this._preUnmarshal,custom:(u=this._options)==null?void 0:u.customUnmarshaller})},this._syncMode=n=>{const s=this._unwrap(n);return this._sync.has(s)||this._temporalSync.has(s)?"both":void 0},this._unwrapIfNotSynced=n=>{const s=this._unwrap(n);return s instanceof Promise||!this._sync.has(s)?s:n},(r==null?void 0:r.compat)&&!("runtime"in e)&&(e.runtime={hasPendingJob:()=>e.hasPendingJob(),executePendingJobs:n=>e.executePendingJobs(n)}),this.context=e,this._options=r,this._symbolHandle=e.unwrapResult(e.evalCode("Symbol()")),this._map=new S(e),this._registeredMap=new S(e),this.registerAll((i=r==null?void 0:r.registeredObjects)!=null?i:w)}dispose(){this._map.dispose(),this._registeredMap.dispose(),this._symbolHandle.dispose()}evalCode(e){const r=this.context.evalCode(e);return this._unwrapResultAndUnmarshal(r)}executePendingJobs(e){const r=this.context.runtime.executePendingJobs(e);if("value"in r)return r.value;throw this._unwrapIfNotSynced(r.error.consume(this._unmarshal))}expose(e){for(const[r,i]of Object.entries(e))W(this._marshal(i),n=>{this.context.setProp(this.context.global,r,n)})}sync(e){const r=this._wrap(e);return typeof r=="undefined"?e:(P(r,i=>{const n=this._unwrap(i);this._sync.add(n)}),r)}register(e,r){if(this._registeredMap.has(e))return;const i=typeof r=="string"?this._unwrapResult(this.context.evalCode(r)):r;M(this.context,i,this.context.undefined)||(typeof r=="string"&&this._registeredMapDispose.add(e),this._registeredMap.set(e,i))}registerAll(e){for(const[r,i]of e)this.register(r,i)}unregister(e,r){this._registeredMap.delete(e,this._registeredMapDispose.has(e)||r),this._registeredMapDispose.delete(e)}unregisterAll(e,r){for(const i of e)this.unregister(i,r)}startSync(e){if(!v(e))return;const r=this._unwrap(e);this._sync.add(r)}endSync(e){this._sync.delete(this._unwrap(e))}_unwrapResult(e){if("value"in e)return e.value;throw this._unwrapIfNotSynced(e.error.consume(this._unmarshal))}_unwrapResultAndUnmarshal(e){if(!!e)return this._unwrapIfNotSynced(this._unwrapResult(e).consume(this._unmarshal))}_register(e,r,i=this._map,n){if(this._registeredMap.has(e)||this._registeredMap.hasHandle(r))return;let s=this._wrap(e);const[o]=this._wrapHandle(r),u=e instanceof Promise;if(!o||!s&&!u)return;u&&(s=e);const a=this._unwrap(e),[p,l]=this._unwrapHandle(r);if(i.set(s,o,a,p))n&&this._sync.add(a);else throw l&&p.dispose(),new Error("already registered");return[s,o]}_wrap(e){var r;return fe(this.context,e,this._symbol,this._symbolHandle,this._marshal,this._syncMode,(r=this._options)==null?void 0:r.isWrappable)}_unwrap(e){return g(e,this._symbol)}_wrapHandle(e){var r;return le(this.context,e,this._symbol,this._symbolHandle,this._unmarshal,this._syncMode,(r=this._options)==null?void 0:r.isHandleWrappable)}_unwrapHandle(e){return E(this.context,e,this._symbolHandle)}}h.Arena=de,h.VMMap=S,h.call=d,h.complexity=L,h.consumeAll=H,h.defaultRegisteredObjects=w,h.eq=M,h.isES2015Class=C,h.isHandleObject=R,h.isObject=v,h.json=k,h.marshal=O,h.unmarshal=A,h.walkObject=P,Object.defineProperties(h,{__esModule:{value:!0},[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.
|
|
4
|
+
"version": "1.5.0",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"source": "./src/index.ts",
|
|
7
7
|
"main": "./dist/quickjs-emscripten-sync.umd.js",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"src"
|
|
21
21
|
],
|
|
22
22
|
"engines": {
|
|
23
|
-
"node": ">=
|
|
23
|
+
"node": ">=12"
|
|
24
24
|
},
|
|
25
25
|
"scripts": {
|
|
26
26
|
"build": "tsc && vite build",
|
|
@@ -30,24 +30,15 @@
|
|
|
30
30
|
"peerDependencies": {
|
|
31
31
|
"quickjs-emscripten": "*"
|
|
32
32
|
},
|
|
33
|
-
"prettier": {
|
|
34
|
-
"printWidth": 80,
|
|
35
|
-
"semi": true,
|
|
36
|
-
"singleQuote": false,
|
|
37
|
-
"trailingComma": "es5"
|
|
38
|
-
},
|
|
39
33
|
"devDependencies": {
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"eslint": "^8.19.0",
|
|
44
|
-
"eslint-config-prettier": "^8.5.0",
|
|
45
|
-
"eslint-plugin-prettier": "^4.2.1",
|
|
34
|
+
"c8": "^7.12.0",
|
|
35
|
+
"eslint": "^8.22.0",
|
|
36
|
+
"eslint-config-reearth": "^0.1.0",
|
|
46
37
|
"prettier": "^2.7.1",
|
|
47
38
|
"quickjs-emscripten": "^0.21.0",
|
|
48
|
-
"typescript": "^4.
|
|
49
|
-
"vite": "^
|
|
50
|
-
"vite-plugin-dts": "^1.
|
|
51
|
-
"vitest": "^0.
|
|
39
|
+
"typescript": "^4.8.2",
|
|
40
|
+
"vite": "^3.0.9",
|
|
41
|
+
"vite-plugin-dts": "^1.4.1",
|
|
42
|
+
"vitest": "^0.22.1"
|
|
52
43
|
}
|
|
53
44
|
}
|
package/src/default.ts
CHANGED
|
@@ -32,6 +32,6 @@ export const defaultRegisteredObjects: [any, string][] = [
|
|
|
32
32
|
[URIError.prototype, "URIError.prototype"],
|
|
33
33
|
// built-in symbols
|
|
34
34
|
...Object.getOwnPropertyNames(Symbol)
|
|
35
|
-
.filter(
|
|
36
|
-
.map<[any, string]>(
|
|
35
|
+
.filter(k => typeof (Symbol as any)[k] === "symbol")
|
|
36
|
+
.map<[any, string]>(k => [(Symbol as any)[k], `Symbol.${k}`]),
|
|
37
37
|
];
|
package/src/index.test.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { getQuickJS } from "quickjs-emscripten";
|
|
2
2
|
import { describe, expect, test, vi } from "vitest";
|
|
3
3
|
|
|
4
|
-
import { Arena } from ".";
|
|
5
4
|
import { isWrapped } from "./wrapper";
|
|
6
5
|
|
|
6
|
+
import { Arena } from ".";
|
|
7
|
+
|
|
7
8
|
describe("readme", () => {
|
|
8
9
|
test("first", async () => {
|
|
9
10
|
class Cls {
|
|
@@ -89,7 +90,7 @@ describe("evalCode", () => {
|
|
|
89
90
|
get e() {
|
|
90
91
|
return { a: 1 };
|
|
91
92
|
}
|
|
92
|
-
})
|
|
93
|
+
})`,
|
|
93
94
|
);
|
|
94
95
|
expect(result).toEqual({
|
|
95
96
|
a: 1,
|
|
@@ -121,6 +122,19 @@ describe("evalCode", () => {
|
|
|
121
122
|
ctx.dispose();
|
|
122
123
|
});
|
|
123
124
|
|
|
125
|
+
test("Date", async () => {
|
|
126
|
+
const ctx = (await getQuickJS()).newContext();
|
|
127
|
+
const arena = new Arena(ctx, { isMarshalable: true });
|
|
128
|
+
|
|
129
|
+
const date = new Date(2022, 7, 26);
|
|
130
|
+
expect(arena.evalCode("new Date(2022, 7, 26)")).toEqual(date);
|
|
131
|
+
expect(arena.evalCode("d => d instanceof Date")(date)).toBe(true);
|
|
132
|
+
expect(arena.evalCode("d => d.getTime()")(date)).toBe(date.getTime());
|
|
133
|
+
|
|
134
|
+
arena.dispose();
|
|
135
|
+
ctx.dispose();
|
|
136
|
+
});
|
|
137
|
+
|
|
124
138
|
test("class", async () => {
|
|
125
139
|
const ctx = (await getQuickJS()).newContext();
|
|
126
140
|
const arena = new Arena(ctx, { isMarshalable: true });
|
|
@@ -167,9 +181,7 @@ describe("evalCode", () => {
|
|
|
167
181
|
const ctx = (await getQuickJS()).newContext();
|
|
168
182
|
const arena = new Arena(ctx, { isMarshalable: true });
|
|
169
183
|
|
|
170
|
-
const [promise, resolve] = arena.evalCode<
|
|
171
|
-
[Promise<string>, (d: string) => void]
|
|
172
|
-
>(`
|
|
184
|
+
const [promise, resolve] = arena.evalCode<[Promise<string>, (d: string) => void]>(`
|
|
173
185
|
let resolve;
|
|
174
186
|
const promise = new Promise(r => {
|
|
175
187
|
resolve = r;
|
|
@@ -177,9 +189,7 @@ describe("evalCode", () => {
|
|
|
177
189
|
[promise, resolve]
|
|
178
190
|
`);
|
|
179
191
|
expect(promise).instanceOf(Promise);
|
|
180
|
-
expect(isWrapped(arena._unwrapIfNotSynced(promise), arena._symbol)).toBe(
|
|
181
|
-
false
|
|
182
|
-
);
|
|
192
|
+
expect(isWrapped(arena._unwrapIfNotSynced(promise), arena._symbol)).toBe(false);
|
|
183
193
|
|
|
184
194
|
resolve("hoge");
|
|
185
195
|
expect(arena.executePendingJobs()).toBe(2);
|
|
@@ -194,7 +204,7 @@ describe("evalCode", () => {
|
|
|
194
204
|
const arena = new Arena(ctx, { isMarshalable: true });
|
|
195
205
|
|
|
196
206
|
const deferred: { resolve?: (s: string) => void } = {};
|
|
197
|
-
const promise = new Promise(
|
|
207
|
+
const promise = new Promise(resolve => {
|
|
198
208
|
deferred.resolve = resolve;
|
|
199
209
|
});
|
|
200
210
|
const res = vi.fn();
|
|
@@ -512,9 +522,7 @@ test("registeredObjects option", async () => {
|
|
|
512
522
|
});
|
|
513
523
|
|
|
514
524
|
expect(arena.evalCode(`Symbol.iterator`)).toBe(Symbol.iterator);
|
|
515
|
-
expect(arena.evalCode(`s => s === Symbol.iterator`)(Symbol.iterator)).toBe(
|
|
516
|
-
true
|
|
517
|
-
);
|
|
525
|
+
expect(arena.evalCode(`s => s === Symbol.iterator`)(Symbol.iterator)).toBe(true);
|
|
518
526
|
|
|
519
527
|
arena.dispose();
|
|
520
528
|
ctx.dispose();
|
|
@@ -554,7 +562,7 @@ describe("isMarshalable option", () => {
|
|
|
554
562
|
test("conditional", async () => {
|
|
555
563
|
const ctx = (await getQuickJS()).newContext();
|
|
556
564
|
const arena = new Arena(ctx, {
|
|
557
|
-
isMarshalable:
|
|
565
|
+
isMarshalable: o => o !== globalThis,
|
|
558
566
|
});
|
|
559
567
|
|
|
560
568
|
const obj = { a: 1 };
|
package/src/index.ts
CHANGED
|
@@ -6,21 +6,13 @@ import type {
|
|
|
6
6
|
VmCallResult,
|
|
7
7
|
} from "quickjs-emscripten";
|
|
8
8
|
|
|
9
|
-
import
|
|
9
|
+
import { defaultRegisteredObjects } from "./default";
|
|
10
10
|
import marshal from "./marshal";
|
|
11
11
|
import unmarshal from "./unmarshal";
|
|
12
|
-
import { wrap, wrapHandle, unwrap, unwrapHandle, Wrapped } from "./wrapper";
|
|
13
12
|
import { complexity, isES2015Class, isObject, walkObject } from "./util";
|
|
14
|
-
import
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
isHandleObject,
|
|
18
|
-
json,
|
|
19
|
-
consumeAll,
|
|
20
|
-
mayConsume,
|
|
21
|
-
handleFrom,
|
|
22
|
-
} from "./vmutil";
|
|
23
|
-
import { defaultRegisteredObjects } from "./default";
|
|
13
|
+
import VMMap from "./vmmap";
|
|
14
|
+
import { call, eq, isHandleObject, json, consumeAll, mayConsume, handleFrom } from "./vmutil";
|
|
15
|
+
import { wrap, wrapHandle, unwrap, unwrapHandle, Wrapped } from "./wrapper";
|
|
24
16
|
|
|
25
17
|
export {
|
|
26
18
|
VMMap,
|
|
@@ -41,11 +33,19 @@ export {
|
|
|
41
33
|
export type Options = {
|
|
42
34
|
/** A callback that returns a boolean value that determines whether an object is marshalled or not. If false, no marshaling will be done and undefined will be passed to the QuickJS VM, otherwise marshaling will be done. By default, all objects will be marshalled. */
|
|
43
35
|
isMarshalable?: boolean | "json" | ((target: any) => boolean | "json");
|
|
44
|
-
/**
|
|
36
|
+
/** Pre-registered pairs of objects that will be considered the same between the host and the QuickJS VM. This will be used automatically during the conversion. By default, it will be registered automatically with `defaultRegisteredObjects`.
|
|
45
37
|
*
|
|
46
38
|
* Instead of a string, you can also pass a QuickJSHandle directly. In that case, however, you have to dispose of them manually when destroying the VM.
|
|
47
39
|
*/
|
|
48
40
|
registeredObjects?: Iterable<[any, QuickJSHandle | string]>;
|
|
41
|
+
/** Register functions to convert an object to a QuickJS handle. */
|
|
42
|
+
customMarshaller?: Iterable<(target: unknown, ctx: QuickJSContext) => QuickJSHandle | undefined>;
|
|
43
|
+
/** Register functions to convert a QuickJS handle to an object. */
|
|
44
|
+
customUnmarshaller?: Iterable<(target: QuickJSHandle, ctx: QuickJSContext) => any>;
|
|
45
|
+
/** A callback that returns a boolean value that determines whether an object is wrappable by proxies. If returns false, note that the object cannot be synchronized between the host and the QuickJS even if arena.sync is used. */
|
|
46
|
+
isWrappable?: (target: any) => boolean;
|
|
47
|
+
/** A callback that returns a boolean value that determines whether an QuickJS handle is wrappable by proxies. If returns false, note that the handle cannot be synchronized between the host and the QuickJS even if arena.sync is used. */
|
|
48
|
+
isHandleWrappable?: (handle: QuickJSHandle, ctx: QuickJSContext) => boolean;
|
|
49
49
|
/** Compatibility with quickjs-emscripten prior to v0.15. Inject code for compatibility into context at Arena class initialization time. */
|
|
50
50
|
compat?: boolean;
|
|
51
51
|
};
|
|
@@ -118,7 +118,7 @@ export class Arena {
|
|
|
118
118
|
*/
|
|
119
119
|
expose(obj: { [k: string]: any }) {
|
|
120
120
|
for (const [key, value] of Object.entries(obj)) {
|
|
121
|
-
mayConsume(this._marshal(value),
|
|
121
|
+
mayConsume(this._marshal(value), handle => {
|
|
122
122
|
this.context.setProp(this.context.global, key, handle);
|
|
123
123
|
});
|
|
124
124
|
}
|
|
@@ -132,7 +132,7 @@ export class Arena {
|
|
|
132
132
|
sync<T>(target: T): T {
|
|
133
133
|
const wrapped = this._wrap(target);
|
|
134
134
|
if (typeof wrapped === "undefined") return target;
|
|
135
|
-
walkObject(wrapped,
|
|
135
|
+
walkObject(wrapped, v => {
|
|
136
136
|
const u = this._unwrap(v);
|
|
137
137
|
this._sync.add(u);
|
|
138
138
|
});
|
|
@@ -170,10 +170,7 @@ export class Arena {
|
|
|
170
170
|
* Unregister a pair of objects that were registered with `registeredObjects` option and `register` method.
|
|
171
171
|
*/
|
|
172
172
|
unregister(target: any, dispose?: boolean) {
|
|
173
|
-
this._registeredMap.delete(
|
|
174
|
-
target,
|
|
175
|
-
this._registeredMapDispose.has(target) || dispose
|
|
176
|
-
);
|
|
173
|
+
this._registeredMap.delete(target, this._registeredMapDispose.has(target) || dispose);
|
|
177
174
|
this._registeredMapDispose.delete(target);
|
|
178
175
|
}
|
|
179
176
|
|
|
@@ -203,13 +200,9 @@ export class Arena {
|
|
|
203
200
|
throw this._unwrapIfNotSynced(result.error.consume(this._unmarshal));
|
|
204
201
|
}
|
|
205
202
|
|
|
206
|
-
_unwrapResultAndUnmarshal(
|
|
207
|
-
result: VmCallResult<QuickJSHandle> | undefined
|
|
208
|
-
): any {
|
|
203
|
+
_unwrapResultAndUnmarshal(result: VmCallResult<QuickJSHandle> | undefined): any {
|
|
209
204
|
if (!result) return;
|
|
210
|
-
return this._unwrapIfNotSynced(
|
|
211
|
-
this._unwrapResult(result).consume(this._unmarshal)
|
|
212
|
-
);
|
|
205
|
+
return this._unwrapIfNotSynced(this._unwrapResult(result).consume(this._unmarshal));
|
|
213
206
|
}
|
|
214
207
|
|
|
215
208
|
_isMarshalable = (t: unknown): boolean | "json" => {
|
|
@@ -230,17 +223,13 @@ export class Arena {
|
|
|
230
223
|
_marshalPre = (
|
|
231
224
|
t: unknown,
|
|
232
225
|
h: QuickJSHandle | QuickJSDeferredPromise,
|
|
233
|
-
mode: true | "json" | undefined
|
|
226
|
+
mode: true | "json" | undefined,
|
|
234
227
|
): Wrapped<QuickJSHandle> | undefined => {
|
|
235
228
|
if (mode === "json") return;
|
|
236
229
|
return this._register(t, handleFrom(h), this._map)?.[1];
|
|
237
230
|
};
|
|
238
231
|
|
|
239
|
-
_marshalPreApply = (
|
|
240
|
-
target: Function,
|
|
241
|
-
that: unknown,
|
|
242
|
-
args: unknown[]
|
|
243
|
-
): void => {
|
|
232
|
+
_marshalPreApply = (target: Function, that: unknown, args: unknown[]): void => {
|
|
244
233
|
const unwrapped = isObject(that) ? this._unwrap(that) : undefined;
|
|
245
234
|
// override sync mode of this object while calling the function
|
|
246
235
|
if (unwrapped) this._temporalSync.add(unwrapped);
|
|
@@ -265,6 +254,7 @@ export class Arena {
|
|
|
265
254
|
find: this._marshalFind,
|
|
266
255
|
pre: this._marshalPre,
|
|
267
256
|
preApply: this._marshalPreApply,
|
|
257
|
+
custom: this._options?.customMarshaller,
|
|
268
258
|
});
|
|
269
259
|
|
|
270
260
|
return [handle, !this._map.hasHandle(handle)];
|
|
@@ -290,6 +280,7 @@ export class Arena {
|
|
|
290
280
|
marshal: this._marshal,
|
|
291
281
|
find: this._unmarshalFind,
|
|
292
282
|
pre: this._preUnmarshal,
|
|
283
|
+
custom: this._options?.customUnmarshaller,
|
|
293
284
|
});
|
|
294
285
|
};
|
|
295
286
|
|
|
@@ -297,7 +288,7 @@ export class Arena {
|
|
|
297
288
|
t: any,
|
|
298
289
|
h: QuickJSHandle,
|
|
299
290
|
map: VMMap = this._map,
|
|
300
|
-
sync?: boolean
|
|
291
|
+
sync?: boolean,
|
|
301
292
|
): [Wrapped<any>, Wrapped<QuickJSHandle>] | undefined {
|
|
302
293
|
if (this._registeredMap.has(t) || this._registeredMap.hasHandle(h)) {
|
|
303
294
|
return;
|
|
@@ -326,9 +317,7 @@ export class Arena {
|
|
|
326
317
|
|
|
327
318
|
_syncMode = (obj: any): "both" | undefined => {
|
|
328
319
|
const obj2 = this._unwrap(obj);
|
|
329
|
-
return this._sync.has(obj2) || this._temporalSync.has(obj2)
|
|
330
|
-
? "both"
|
|
331
|
-
: undefined;
|
|
320
|
+
return this._sync.has(obj2) || this._temporalSync.has(obj2) ? "both" : undefined;
|
|
332
321
|
};
|
|
333
322
|
|
|
334
323
|
_wrap<T>(target: T): Wrapped<T> | undefined {
|
|
@@ -338,7 +327,8 @@ export class Arena {
|
|
|
338
327
|
this._symbol,
|
|
339
328
|
this._symbolHandle,
|
|
340
329
|
this._marshal,
|
|
341
|
-
this._syncMode
|
|
330
|
+
this._syncMode,
|
|
331
|
+
this._options?.isWrappable,
|
|
342
332
|
);
|
|
343
333
|
}
|
|
344
334
|
|
|
@@ -348,21 +338,18 @@ export class Arena {
|
|
|
348
338
|
|
|
349
339
|
_unwrapIfNotSynced = <T>(target: T): T => {
|
|
350
340
|
const unwrapped = this._unwrap(target);
|
|
351
|
-
return unwrapped instanceof Promise || !this._sync.has(unwrapped)
|
|
352
|
-
? unwrapped
|
|
353
|
-
: target;
|
|
341
|
+
return unwrapped instanceof Promise || !this._sync.has(unwrapped) ? unwrapped : target;
|
|
354
342
|
};
|
|
355
343
|
|
|
356
|
-
_wrapHandle(
|
|
357
|
-
handle: QuickJSHandle
|
|
358
|
-
): [Wrapped<QuickJSHandle> | undefined, boolean] {
|
|
344
|
+
_wrapHandle(handle: QuickJSHandle): [Wrapped<QuickJSHandle> | undefined, boolean] {
|
|
359
345
|
return wrapHandle(
|
|
360
346
|
this.context,
|
|
361
347
|
handle,
|
|
362
348
|
this._symbol,
|
|
363
349
|
this._symbolHandle,
|
|
364
350
|
this._unmarshal,
|
|
365
|
-
this._syncMode
|
|
351
|
+
this._syncMode,
|
|
352
|
+
this._options?.isHandleWrappable,
|
|
366
353
|
);
|
|
367
354
|
}
|
|
368
355
|
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { getQuickJS } from "quickjs-emscripten";
|
|
2
|
+
import { expect, test, vi } from "vitest";
|
|
3
|
+
|
|
4
|
+
import { call } from "../vmutil";
|
|
5
|
+
|
|
6
|
+
import marshalCustom, { defaultCustom } from "./custom";
|
|
7
|
+
|
|
8
|
+
test("symbol", async () => {
|
|
9
|
+
const ctx = (await getQuickJS()).newContext();
|
|
10
|
+
const pre = vi.fn();
|
|
11
|
+
const sym = Symbol("foobar");
|
|
12
|
+
|
|
13
|
+
const marshal = (t: unknown) => marshalCustom(ctx, t, pre, defaultCustom);
|
|
14
|
+
|
|
15
|
+
expect(marshal({})).toBe(undefined);
|
|
16
|
+
expect(pre).toBeCalledTimes(0);
|
|
17
|
+
|
|
18
|
+
const handle = marshal(sym);
|
|
19
|
+
if (!handle) throw new Error("handle is undefined");
|
|
20
|
+
expect(ctx.typeof(handle)).toBe("symbol");
|
|
21
|
+
expect(ctx.getString(ctx.getProp(handle, "description"))).toBe("foobar");
|
|
22
|
+
expect(pre).toReturnTimes(1);
|
|
23
|
+
expect(pre.mock.calls[0][0]).toBe(sym);
|
|
24
|
+
expect(pre.mock.calls[0][1] === handle).toBe(true);
|
|
25
|
+
|
|
26
|
+
handle.dispose();
|
|
27
|
+
ctx.dispose();
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test("date", async () => {
|
|
31
|
+
const ctx = (await getQuickJS()).newContext();
|
|
32
|
+
const pre = vi.fn();
|
|
33
|
+
const date = new Date(2022, 7, 26);
|
|
34
|
+
|
|
35
|
+
const marshal = (t: unknown) => marshalCustom(ctx, t, pre, defaultCustom);
|
|
36
|
+
|
|
37
|
+
expect(marshal({})).toBe(undefined);
|
|
38
|
+
expect(pre).toBeCalledTimes(0);
|
|
39
|
+
|
|
40
|
+
const handle = marshal(date);
|
|
41
|
+
if (!handle) throw new Error("handle is undefined");
|
|
42
|
+
expect(ctx.dump(call(ctx, "d => d instanceof Date", undefined, handle))).toBe(true);
|
|
43
|
+
expect(ctx.dump(call(ctx, "d => d.getTime()", undefined, handle))).toBe(date.getTime());
|
|
44
|
+
expect(pre).toReturnTimes(1);
|
|
45
|
+
expect(pre.mock.calls[0][0]).toBe(date);
|
|
46
|
+
expect(pre.mock.calls[0][1] === handle).toBe(true);
|
|
47
|
+
|
|
48
|
+
handle.dispose();
|
|
49
|
+
ctx.dispose();
|
|
50
|
+
});
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { QuickJSContext, QuickJSHandle } from "quickjs-emscripten";
|
|
2
|
+
|
|
3
|
+
import { call } from "../vmutil";
|
|
4
|
+
|
|
5
|
+
export default function marshalCustom(
|
|
6
|
+
ctx: QuickJSContext,
|
|
7
|
+
target: unknown,
|
|
8
|
+
preMarshal: (target: unknown, handle: QuickJSHandle) => QuickJSHandle | undefined,
|
|
9
|
+
custom: Iterable<(target: unknown, ctx: QuickJSContext) => QuickJSHandle | undefined>,
|
|
10
|
+
): QuickJSHandle | undefined {
|
|
11
|
+
let handle: QuickJSHandle | undefined;
|
|
12
|
+
for (const c of custom) {
|
|
13
|
+
handle = c(target, ctx);
|
|
14
|
+
if (handle) break;
|
|
15
|
+
}
|
|
16
|
+
return handle ? preMarshal(target, handle) ?? handle : undefined;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function symbol(target: unknown, ctx: QuickJSContext): QuickJSHandle | undefined {
|
|
20
|
+
if (typeof target !== "symbol") return;
|
|
21
|
+
const handle = call(
|
|
22
|
+
ctx,
|
|
23
|
+
"d => Symbol(d)",
|
|
24
|
+
undefined,
|
|
25
|
+
target.description ? ctx.newString(target.description) : ctx.undefined,
|
|
26
|
+
);
|
|
27
|
+
return handle;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function date(target: unknown, ctx: QuickJSContext): QuickJSHandle | undefined {
|
|
31
|
+
if (!(target instanceof Date)) return;
|
|
32
|
+
const handle = call(ctx, "d => new Date(d)", undefined, ctx.newNumber(target.getTime()));
|
|
33
|
+
return handle;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export const defaultCustom = [symbol, date];
|