quickjs-emscripten-sync 1.3.0 → 1.4.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 +36 -34
- package/dist/index.d.ts +17 -15
- package/dist/quickjs-emscripten-sync.es.js +146 -135
- package/dist/quickjs-emscripten-sync.umd.js +6 -6
- package/package.json +3 -3
- package/src/index.test.ts +146 -60
- package/src/index.ts +40 -26
- package/src/marshal/function.test.ts +61 -53
- package/src/marshal/function.ts +7 -6
- package/src/marshal/index.test.ts +73 -65
- package/src/marshal/index.ts +12 -11
- package/src/marshal/json.test.ts +30 -30
- package/src/marshal/json.ts +4 -3
- package/src/marshal/object.test.ts +55 -50
- package/src/marshal/object.ts +6 -5
- package/src/marshal/primitive.test.ts +21 -17
- package/src/marshal/primitive.ts +10 -9
- package/src/marshal/promise.test.ts +14 -14
- package/src/marshal/promise.ts +3 -3
- package/src/marshal/properties.test.ts +17 -15
- package/src/marshal/properties.ts +10 -9
- package/src/marshal/symbol.test.ts +6 -6
- package/src/marshal/symbol.ts +5 -4
- package/src/unmarshal/function.test.ts +45 -43
- package/src/unmarshal/function.ts +9 -8
- package/src/unmarshal/index.test.ts +41 -40
- package/src/unmarshal/index.ts +9 -8
- package/src/unmarshal/object.test.ts +33 -31
- package/src/unmarshal/object.ts +12 -11
- package/src/unmarshal/primitive.test.ts +18 -15
- package/src/unmarshal/primitive.ts +9 -9
- package/src/unmarshal/promise.test.ts +11 -11
- package/src/unmarshal/promise.ts +9 -11
- package/src/unmarshal/properties.test.ts +6 -6
- package/src/unmarshal/properties.ts +47 -44
- package/src/unmarshal/symbol.test.ts +6 -6
- package/src/unmarshal/symbol.ts +4 -4
- package/src/util.test.ts +1 -0
- package/src/vmmap.test.ts +72 -88
- package/src/vmmap.ts +16 -16
- package/src/vmutil.test.ts +71 -73
- package/src/vmutil.ts +22 -18
- package/src/wrapper.test.ts +111 -88
- package/src/wrapper.ts +31 -27
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
(function(h,
|
|
1
|
+
(function(h,v){typeof exports=="object"&&typeof module!="undefined"?v(exports):typeof define=="function"&&define.amd?define(["exports"],v):(h=typeof globalThis!="undefined"?globalThis:h||self,v(h.QuickjsEmscriptenSync={}))})(this,function(h){"use strict";class v{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
2
|
const mapSym = new Map();
|
|
3
3
|
let map = new WeakMap();
|
|
4
4
|
let map2 = new WeakMap();
|
|
@@ -21,19 +21,19 @@
|
|
|
21
21
|
map2 = new WeakMap();
|
|
22
22
|
}
|
|
23
23
|
};
|
|
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.
|
|
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 E(t){return typeof t=="function"&&/^class\s/.test(Function.prototype.toString.call(t))}function _(t){return typeof t=="function"||typeof t=="object"&&t!==null}function j(t,e){const r=new Set,i=n=>{if(!(!_(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 T(t,e){return j(t,e?(r,i)=>i.size<e:void 0).size}function I(){let t=()=>{},e=()=>{};return{promise:new Promise((i,n)=>{t=i,e=n}),resolve:t,reject:e}}function U(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 m(t,e,r,...i){const n=U(t,e);try{return n(r,...i)}finally{n.dispose()}}function R(t,e,r){return t.dump(m(t,"Object.is",void 0,e,r))}function W(t,e,r){return t.dump(m(t,"(a, b) => a instanceof b",void 0,e,r))}function M(t,e){return t.dump(m(t,'a => typeof a === "object" && a !== null || typeof a === "function"',void 0,e))}function k(t,e){const r=JSON.stringify(e);return r?m(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 z([t,e],r){try{return r(t)}finally{e&&t.dispose()}}function P(t,e){try{return e(...t.map(r=>r[0]))}finally{for(const[r,i]of t)i&&r.dispose()}}function G(t){return"handle"in t}function q(t){return G(t)?t.handle:t}function F(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),d=typeof a.set=="undefined"?void 0:i(a.set);t.newObject().consume(y=>{Object.entries(a).forEach(([c,b])=>{const w=c==="value"?l:c==="get"?f:c==="set"?d:b?t.true:t.false;w&&t.setProp(y,c,w)}),t.setProp(n,p,y)})},o=Object.getOwnPropertyDescriptors(e);Object.entries(o).forEach(([u,a])=>s(u,a)),Object.getOwnPropertySymbols(o).forEach(u=>s(u,o[u])),m(t,"Object.defineProperties",void 0,r,n).dispose(),n.dispose()}function Q(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(d=>i(d));if(E(e)&&_(l)){const d=new e(...f);return Object.entries(d).forEach(([y,c])=>{t.setProp(this,y,r(c))}),this}return r(s?s(e,l,f):e.apply(l,f))}).consume(p=>m(t,`Cls => {
|
|
25
25
|
const fn = function(...args) { return Cls.apply(this, args); };
|
|
26
26
|
fn.name = Cls.name;
|
|
27
27
|
fn.length = Cls.length;
|
|
28
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&&
|
|
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
30
|
const descs = Object.getOwnPropertyDescriptors(o);
|
|
31
31
|
Object.entries(descs).forEach(([k, v]) => fn(k, v));
|
|
32
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
|
|
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
34
|
const p = Object.getPrototypeOf(o);
|
|
35
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
|
|
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) => {
|
|
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,...o),!0]):[void 0,!1]}function
|
|
64
|
+
}`,void 0,e,i,...o),!0]):[void 0,!1]}function g(t,e){var r;return _(t)&&(r=t[e])!=null?r:t}function S(t,e,r){return B(t,e,r)?[t.getProp(e,r),!0]:[e,!1]}function ie(t,e){return _(t)&&!!t[e]}function B(t,e,r){return!!t.dump(m(t,'(a, s) => (a instanceof Promise) || (typeof a === "object" && a !== null || typeof a === "function") && !!a[s]',void 0,e,r))}const N=[[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}`])];class oe{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,q(s),this._map))==null?void 0:u[1]},this._marshalPreApply=(n,s,o)=>{const u=_(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;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});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=>{const s=this._registeredMap.getByHandle(n);if(typeof s!="undefined")return s;const[o]=this._wrapHandle(n);return C(o!=null?o:n,{ctx:this.context,marshal:this._marshal,find:this._unmarshalFind,pre:this._preUnmarshal})},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 v(e),this._registeredMap=new v(e),this.registerAll((i=r==null?void 0:r.registeredObjects)!=null?i:N)}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))z(this._marshal(i),n=>{this.context.setProp(this.context.global,r,n)})}sync(e){const r=this._wrap(e);return typeof r=="undefined"?e:(j(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;R(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(!_(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){return ne(this.context,e,this._symbol,this._symbolHandle,this._marshal,this._syncMode)}_unwrap(e){return g(e,this._symbol)}_wrapHandle(e){return se(this.context,e,this._symbol,this._symbolHandle,this._unmarshal,this._syncMode)}_unwrapHandle(e){return S(this.context,e,this._symbolHandle)}}h.Arena=oe,h.VMMap=v,h.call=m,h.complexity=T,h.consumeAll=H,h.defaultRegisteredObjects=N,h.eq=R,h.isES2015Class=E,h.isHandleObject=M,h.isObject=_,h.json=k,h.marshal=O,h.unmarshal=C,h.walkObject=j,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.4.0",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"source": "./src/index.ts",
|
|
7
7
|
"main": "./dist/quickjs-emscripten-sync.umd.js",
|
|
@@ -44,10 +44,10 @@
|
|
|
44
44
|
"eslint-config-prettier": "^8.5.0",
|
|
45
45
|
"eslint-plugin-prettier": "^4.2.1",
|
|
46
46
|
"prettier": "^2.7.1",
|
|
47
|
-
"quickjs-emscripten": "^0.
|
|
47
|
+
"quickjs-emscripten": "^0.21.0",
|
|
48
48
|
"typescript": "^4.7.4",
|
|
49
49
|
"vite": "^2.9.14",
|
|
50
|
-
"vite-plugin-dts": "^1.
|
|
50
|
+
"vite-plugin-dts": "^1.3.0",
|
|
51
51
|
"vitest": "^0.18.0"
|
|
52
52
|
}
|
|
53
53
|
}
|
package/src/index.test.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { getQuickJS } from "quickjs-emscripten";
|
|
|
2
2
|
import { describe, expect, test, vi } from "vitest";
|
|
3
3
|
|
|
4
4
|
import { Arena } from ".";
|
|
5
|
+
import { isWrapped } from "./wrapper";
|
|
5
6
|
|
|
6
7
|
describe("readme", () => {
|
|
7
8
|
test("first", async () => {
|
|
@@ -13,8 +14,8 @@ describe("readme", () => {
|
|
|
13
14
|
}
|
|
14
15
|
}
|
|
15
16
|
|
|
16
|
-
const
|
|
17
|
-
const arena = new Arena(
|
|
17
|
+
const ctx = (await getQuickJS()).newContext();
|
|
18
|
+
const arena = new Arena(ctx, { isMarshalable: true });
|
|
18
19
|
|
|
19
20
|
// We can pass objects to the VM and run code safely
|
|
20
21
|
const exposed = {
|
|
@@ -34,17 +35,17 @@ describe("readme", () => {
|
|
|
34
35
|
expect(arena.evalCode(`syncedCls.field`)).toBe(1);
|
|
35
36
|
|
|
36
37
|
arena.dispose();
|
|
37
|
-
|
|
38
|
+
ctx.dispose();
|
|
38
39
|
});
|
|
39
40
|
|
|
40
41
|
test("usage", async () => {
|
|
41
42
|
const quickjs = await getQuickJS();
|
|
42
|
-
const
|
|
43
|
+
const ctx = quickjs.newContext();
|
|
43
44
|
|
|
44
45
|
// init Arena
|
|
45
46
|
// ⚠️ Marshaling is opt-in for security reasons.
|
|
46
47
|
// ⚠️ Be careful when activating marshalling.
|
|
47
|
-
const arena = new Arena(
|
|
48
|
+
const arena = new Arena(ctx, { isMarshalable: true });
|
|
48
49
|
|
|
49
50
|
// expose objects as global objects in QuickJS VM
|
|
50
51
|
const log = vi.fn();
|
|
@@ -67,14 +68,14 @@ describe("readme", () => {
|
|
|
67
68
|
|
|
68
69
|
// Don't forget calling arena.dispose() before disposing QuickJS VM!
|
|
69
70
|
arena.dispose();
|
|
70
|
-
|
|
71
|
+
ctx.dispose();
|
|
71
72
|
});
|
|
72
73
|
});
|
|
73
74
|
|
|
74
75
|
describe("evalCode", () => {
|
|
75
76
|
test("simple object and function", async () => {
|
|
76
|
-
const
|
|
77
|
-
const arena = new Arena(
|
|
77
|
+
const ctx = (await getQuickJS()).newContext();
|
|
78
|
+
const arena = new Arena(ctx, { isMarshalable: true });
|
|
78
79
|
|
|
79
80
|
const result = arena.evalCode(
|
|
80
81
|
`({
|
|
@@ -106,23 +107,23 @@ describe("evalCode", () => {
|
|
|
106
107
|
expect(result.e).toStrictEqual({ a: 1 });
|
|
107
108
|
|
|
108
109
|
arena.dispose();
|
|
109
|
-
|
|
110
|
+
ctx.dispose();
|
|
110
111
|
});
|
|
111
112
|
|
|
112
113
|
test("Math", async () => {
|
|
113
|
-
const
|
|
114
|
-
const arena = new Arena(
|
|
114
|
+
const ctx = (await getQuickJS()).newContext();
|
|
115
|
+
const arena = new Arena(ctx, { isMarshalable: true });
|
|
115
116
|
|
|
116
117
|
const VMMath = arena.evalCode(`Math`) as Math;
|
|
117
118
|
expect(VMMath.floor(1.1)).toBe(1);
|
|
118
119
|
|
|
119
120
|
arena.dispose();
|
|
120
|
-
|
|
121
|
+
ctx.dispose();
|
|
121
122
|
});
|
|
122
123
|
|
|
123
124
|
test("class", async () => {
|
|
124
|
-
const
|
|
125
|
-
const arena = new Arena(
|
|
125
|
+
const ctx = (await getQuickJS()).newContext();
|
|
126
|
+
const arena = new Arena(ctx, { isMarshalable: true });
|
|
126
127
|
|
|
127
128
|
const instance = arena.evalCode(`{
|
|
128
129
|
globalThis.Cls = class D {
|
|
@@ -143,12 +144,12 @@ describe("evalCode", () => {
|
|
|
143
144
|
expect(instance.a).toBe(102);
|
|
144
145
|
|
|
145
146
|
arena.dispose();
|
|
146
|
-
|
|
147
|
+
ctx.dispose();
|
|
147
148
|
});
|
|
148
149
|
|
|
149
150
|
test("obj", async () => {
|
|
150
|
-
const
|
|
151
|
-
const arena = new Arena(
|
|
151
|
+
const ctx = (await getQuickJS()).newContext();
|
|
152
|
+
const arena = new Arena(ctx, { isMarshalable: true });
|
|
152
153
|
|
|
153
154
|
const obj = arena.evalCode(`globalThis.AAA = { a: 1 }`);
|
|
154
155
|
|
|
@@ -159,14 +160,60 @@ describe("evalCode", () => {
|
|
|
159
160
|
expect(arena.evalCode(`AAA.a`)).toBe(2);
|
|
160
161
|
|
|
161
162
|
arena.dispose();
|
|
162
|
-
|
|
163
|
+
ctx.dispose();
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
test("promise", async () => {
|
|
167
|
+
const ctx = (await getQuickJS()).newContext();
|
|
168
|
+
const arena = new Arena(ctx, { isMarshalable: true });
|
|
169
|
+
|
|
170
|
+
const [promise, resolve] = arena.evalCode<
|
|
171
|
+
[Promise<string>, (d: string) => void]
|
|
172
|
+
>(`
|
|
173
|
+
let resolve;
|
|
174
|
+
const promise = new Promise(r => {
|
|
175
|
+
resolve = r;
|
|
176
|
+
}).then(d => d + "!");
|
|
177
|
+
[promise, resolve]
|
|
178
|
+
`);
|
|
179
|
+
expect(promise).instanceOf(Promise);
|
|
180
|
+
expect(isWrapped(arena._unwrapIfNotSynced(promise), arena._symbol)).toBe(
|
|
181
|
+
false
|
|
182
|
+
);
|
|
183
|
+
|
|
184
|
+
resolve("hoge");
|
|
185
|
+
expect(arena.executePendingJobs()).toBe(2);
|
|
186
|
+
expect(await promise).toBe("hoge!");
|
|
187
|
+
|
|
188
|
+
arena.dispose();
|
|
189
|
+
ctx.dispose();
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
test("promise2", async () => {
|
|
193
|
+
const ctx = (await getQuickJS()).newContext();
|
|
194
|
+
const arena = new Arena(ctx, { isMarshalable: true });
|
|
195
|
+
|
|
196
|
+
const deferred: { resolve?: (s: string) => void } = {};
|
|
197
|
+
const promise = new Promise((resolve) => {
|
|
198
|
+
deferred.resolve = resolve;
|
|
199
|
+
});
|
|
200
|
+
const res = vi.fn();
|
|
201
|
+
arena.evalCode(`(p, r) => { p.then(d => { r(d + "!"); }); }`)(promise, res);
|
|
202
|
+
|
|
203
|
+
deferred.resolve?.("hoge");
|
|
204
|
+
await promise;
|
|
205
|
+
expect(arena.executePendingJobs()).toBe(1);
|
|
206
|
+
expect(res).toBeCalledWith("hoge!");
|
|
207
|
+
|
|
208
|
+
arena.dispose();
|
|
209
|
+
ctx.dispose();
|
|
163
210
|
});
|
|
164
211
|
});
|
|
165
212
|
|
|
166
213
|
describe("expose without sync", () => {
|
|
167
214
|
test("simple object and function", async () => {
|
|
168
|
-
const
|
|
169
|
-
const arena = new Arena(
|
|
215
|
+
const ctx = (await getQuickJS()).newContext();
|
|
216
|
+
const arena = new Arena(ctx, { isMarshalable: true });
|
|
170
217
|
|
|
171
218
|
const obj = {
|
|
172
219
|
a: 1,
|
|
@@ -197,12 +244,12 @@ describe("expose without sync", () => {
|
|
|
197
244
|
expect(arena.evalCode(`obj.e`)).toStrictEqual({ a: 1 });
|
|
198
245
|
|
|
199
246
|
arena.dispose();
|
|
200
|
-
|
|
247
|
+
ctx.dispose();
|
|
201
248
|
});
|
|
202
249
|
|
|
203
250
|
test("Math", async () => {
|
|
204
|
-
const
|
|
205
|
-
const arena = new Arena(
|
|
251
|
+
const ctx = (await getQuickJS()).newContext();
|
|
252
|
+
const arena = new Arena(ctx, { isMarshalable: true });
|
|
206
253
|
|
|
207
254
|
arena.expose({ Math2: Math });
|
|
208
255
|
expect(arena.evalCode(`Math`)).not.toBe(Math);
|
|
@@ -210,12 +257,12 @@ describe("expose without sync", () => {
|
|
|
210
257
|
expect(arena.evalCode(`Math2.floor(1.1)`)).toBe(1);
|
|
211
258
|
|
|
212
259
|
arena.dispose();
|
|
213
|
-
|
|
260
|
+
ctx.dispose();
|
|
214
261
|
});
|
|
215
262
|
|
|
216
263
|
test("class", async () => {
|
|
217
|
-
const
|
|
218
|
-
const arena = new Arena(
|
|
264
|
+
const ctx = (await getQuickJS()).newContext();
|
|
265
|
+
const arena = new Arena(ctx, { isMarshalable: true });
|
|
219
266
|
|
|
220
267
|
class D {
|
|
221
268
|
a: number;
|
|
@@ -239,12 +286,12 @@ describe("expose without sync", () => {
|
|
|
239
286
|
expect(arena.evalCode(`d.a`)).toBe(102);
|
|
240
287
|
|
|
241
288
|
arena.dispose();
|
|
242
|
-
|
|
289
|
+
ctx.dispose();
|
|
243
290
|
});
|
|
244
291
|
|
|
245
292
|
test("object and function", async () => {
|
|
246
|
-
const
|
|
247
|
-
const arena = new Arena(
|
|
293
|
+
const ctx = (await getQuickJS()).newContext();
|
|
294
|
+
const arena = new Arena(ctx, { isMarshalable: true });
|
|
248
295
|
|
|
249
296
|
const obj = {
|
|
250
297
|
a: 1,
|
|
@@ -276,14 +323,14 @@ describe("expose without sync", () => {
|
|
|
276
323
|
expect(arena.evalCode(`obj.a`)).toBe(100);
|
|
277
324
|
|
|
278
325
|
arena.dispose();
|
|
279
|
-
|
|
326
|
+
ctx.dispose();
|
|
280
327
|
});
|
|
281
328
|
});
|
|
282
329
|
|
|
283
330
|
describe("expose with sync", () => {
|
|
284
331
|
test("sync before expose", async () => {
|
|
285
|
-
const
|
|
286
|
-
const arena = new Arena(
|
|
332
|
+
const ctx = (await getQuickJS()).newContext();
|
|
333
|
+
const arena = new Arena(ctx, { isMarshalable: true });
|
|
287
334
|
|
|
288
335
|
const obj = {
|
|
289
336
|
a: 1,
|
|
@@ -322,12 +369,12 @@ describe("expose with sync", () => {
|
|
|
322
369
|
expect(arena.evalCode(`obj.a`)).toBe(100);
|
|
323
370
|
|
|
324
371
|
arena.dispose();
|
|
325
|
-
|
|
372
|
+
ctx.dispose();
|
|
326
373
|
});
|
|
327
374
|
|
|
328
375
|
test("sync after expose", async () => {
|
|
329
|
-
const
|
|
330
|
-
const arena = new Arena(
|
|
376
|
+
const ctx = (await getQuickJS()).newContext();
|
|
377
|
+
const arena = new Arena(ctx, { isMarshalable: true });
|
|
331
378
|
|
|
332
379
|
const obj = {
|
|
333
380
|
a: 1,
|
|
@@ -367,13 +414,13 @@ describe("expose with sync", () => {
|
|
|
367
414
|
expect(arena.evalCode(`obj.a`)).toBe(100);
|
|
368
415
|
|
|
369
416
|
arena.dispose();
|
|
370
|
-
|
|
417
|
+
ctx.dispose();
|
|
371
418
|
});
|
|
372
419
|
});
|
|
373
420
|
|
|
374
421
|
test("evalCode -> expose", async () => {
|
|
375
|
-
const
|
|
376
|
-
const arena = new Arena(
|
|
422
|
+
const ctx = (await getQuickJS()).newContext();
|
|
423
|
+
const arena = new Arena(ctx, { isMarshalable: true });
|
|
377
424
|
|
|
378
425
|
const obj = arena.evalCode(`({ a: 1, b: 1 })`);
|
|
379
426
|
arena.expose({ obj });
|
|
@@ -399,12 +446,12 @@ test("evalCode -> expose", async () => {
|
|
|
399
446
|
expect(arena.evalCode(`obj.b`)).toBe(2);
|
|
400
447
|
|
|
401
448
|
arena.dispose();
|
|
402
|
-
|
|
449
|
+
ctx.dispose();
|
|
403
450
|
});
|
|
404
451
|
|
|
405
452
|
test("expose -> evalCode", async () => {
|
|
406
|
-
const
|
|
407
|
-
const arena = new Arena(
|
|
453
|
+
const ctx = (await getQuickJS()).newContext();
|
|
454
|
+
const arena = new Arena(ctx, { isMarshalable: true });
|
|
408
455
|
|
|
409
456
|
const obj = { a: 1 };
|
|
410
457
|
arena.expose({ obj });
|
|
@@ -421,12 +468,12 @@ test("expose -> evalCode", async () => {
|
|
|
421
468
|
expect(arena.evalCode(`obj.a`)).toBe(3);
|
|
422
469
|
|
|
423
470
|
arena.dispose();
|
|
424
|
-
|
|
471
|
+
ctx.dispose();
|
|
425
472
|
});
|
|
426
473
|
|
|
427
474
|
test("evalCode -> expose -> evalCode", async () => {
|
|
428
|
-
const
|
|
429
|
-
const arena = new Arena(
|
|
475
|
+
const ctx = (await getQuickJS()).newContext();
|
|
476
|
+
const arena = new Arena(ctx, { isMarshalable: true });
|
|
430
477
|
|
|
431
478
|
const obj = [1];
|
|
432
479
|
expect(arena.evalCode("a => a[0] + 10")(obj)).toBe(11);
|
|
@@ -434,12 +481,12 @@ test("evalCode -> expose -> evalCode", async () => {
|
|
|
434
481
|
expect(arena.evalCode("obj")).toBe(obj);
|
|
435
482
|
|
|
436
483
|
arena.dispose();
|
|
437
|
-
|
|
484
|
+
ctx.dispose();
|
|
438
485
|
});
|
|
439
486
|
|
|
440
487
|
test("register and unregister", async () => {
|
|
441
|
-
const
|
|
442
|
-
const arena = new Arena(
|
|
488
|
+
const ctx = (await getQuickJS()).newContext();
|
|
489
|
+
const arena = new Arena(ctx, { isMarshalable: true, registeredObjects: [] });
|
|
443
490
|
|
|
444
491
|
arena.register(Math, `Math`);
|
|
445
492
|
expect(arena.evalCode(`Math`)).toBe(Math);
|
|
@@ -454,12 +501,12 @@ test("register and unregister", async () => {
|
|
|
454
501
|
expect(arena.evalCode(`new Error()`)).toBeInstanceOf(Error);
|
|
455
502
|
|
|
456
503
|
arena.dispose();
|
|
457
|
-
|
|
504
|
+
ctx.dispose();
|
|
458
505
|
});
|
|
459
506
|
|
|
460
507
|
test("registeredObjects option", async () => {
|
|
461
|
-
const
|
|
462
|
-
const arena = new Arena(
|
|
508
|
+
const ctx = (await getQuickJS()).newContext();
|
|
509
|
+
const arena = new Arena(ctx, {
|
|
463
510
|
isMarshalable: true,
|
|
464
511
|
registeredObjects: [[Symbol.iterator, "Symbol.iterator"]],
|
|
465
512
|
});
|
|
@@ -470,13 +517,13 @@ test("registeredObjects option", async () => {
|
|
|
470
517
|
);
|
|
471
518
|
|
|
472
519
|
arena.dispose();
|
|
473
|
-
|
|
520
|
+
ctx.dispose();
|
|
474
521
|
});
|
|
475
522
|
|
|
476
523
|
describe("isMarshalable option", () => {
|
|
477
524
|
test("false", async () => {
|
|
478
|
-
const
|
|
479
|
-
const arena = new Arena(
|
|
525
|
+
const ctx = (await getQuickJS()).newContext();
|
|
526
|
+
const arena = new Arena(ctx, { isMarshalable: false });
|
|
480
527
|
|
|
481
528
|
expect(arena.evalCode(`s => s === undefined`)(globalThis)).toBe(true);
|
|
482
529
|
expect(arena.evalCode(`s => s === undefined`)({})).toBe(true);
|
|
@@ -484,12 +531,12 @@ describe("isMarshalable option", () => {
|
|
|
484
531
|
expect(arena.evalCode(`aaa`)).toBeUndefined();
|
|
485
532
|
|
|
486
533
|
arena.dispose();
|
|
487
|
-
|
|
534
|
+
ctx.dispose();
|
|
488
535
|
});
|
|
489
536
|
|
|
490
537
|
test("json", async () => {
|
|
491
|
-
const
|
|
492
|
-
const arena = new Arena(
|
|
538
|
+
const ctx = (await getQuickJS()).newContext();
|
|
539
|
+
const arena = new Arena(ctx, { isMarshalable: "json" });
|
|
493
540
|
|
|
494
541
|
const obj = { a: () => {}, b: new Date(), c: [() => {}, 1] };
|
|
495
542
|
const objJSON = { b: obj.b.toISOString(), c: [null, 1] };
|
|
@@ -501,12 +548,12 @@ describe("isMarshalable option", () => {
|
|
|
501
548
|
expect(exposedObj).not.toBe(objJSON2);
|
|
502
549
|
|
|
503
550
|
arena.dispose();
|
|
504
|
-
|
|
551
|
+
ctx.dispose();
|
|
505
552
|
});
|
|
506
553
|
|
|
507
554
|
test("conditional", async () => {
|
|
508
|
-
const
|
|
509
|
-
const arena = new Arena(
|
|
555
|
+
const ctx = (await getQuickJS()).newContext();
|
|
556
|
+
const arena = new Arena(ctx, {
|
|
510
557
|
isMarshalable: (o) => o !== globalThis,
|
|
511
558
|
});
|
|
512
559
|
|
|
@@ -518,6 +565,45 @@ describe("isMarshalable option", () => {
|
|
|
518
565
|
expect(arena.evalCode(`bbb`)).toBe(obj);
|
|
519
566
|
|
|
520
567
|
arena.dispose();
|
|
521
|
-
|
|
568
|
+
ctx.dispose();
|
|
569
|
+
});
|
|
570
|
+
});
|
|
571
|
+
|
|
572
|
+
describe("edge cases", () => {
|
|
573
|
+
test("getter", async () => {
|
|
574
|
+
const ctx = (await getQuickJS()).newContext();
|
|
575
|
+
const arena = new Arena(ctx, { isMarshalable: true });
|
|
576
|
+
|
|
577
|
+
const called: string[] = [];
|
|
578
|
+
const obj = { c: 0 };
|
|
579
|
+
const exposed = {
|
|
580
|
+
get a() {
|
|
581
|
+
called.push("a");
|
|
582
|
+
return {
|
|
583
|
+
get b() {
|
|
584
|
+
called.push("b");
|
|
585
|
+
return obj;
|
|
586
|
+
},
|
|
587
|
+
};
|
|
588
|
+
},
|
|
589
|
+
};
|
|
590
|
+
const cb: { current?: () => any } = {};
|
|
591
|
+
const register = (fn: () => any) => {
|
|
592
|
+
cb.current = fn;
|
|
593
|
+
};
|
|
594
|
+
|
|
595
|
+
arena.expose({ exposed, register });
|
|
596
|
+
expect(called).toEqual([]);
|
|
597
|
+
|
|
598
|
+
arena.evalCode(`register(() => exposed.a.b.c);`);
|
|
599
|
+
expect(cb.current?.()).toBe(0);
|
|
600
|
+
expect(called).toEqual(["a", "b"]);
|
|
601
|
+
|
|
602
|
+
obj.c = 1;
|
|
603
|
+
expect(cb.current?.()).toBe(1); // this line causes an error when context is disposed
|
|
604
|
+
expect(called).toEqual(["a", "b", "a", "b"]);
|
|
605
|
+
|
|
606
|
+
arena.dispose();
|
|
607
|
+
// ctx.dispose(); // reports an error
|
|
522
608
|
});
|
|
523
609
|
});
|