quickjs-emscripten-sync 1.5.2 → 1.6.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/dist/index.d.ts +120 -5
- package/dist/quickjs-emscripten-sync.mjs +404 -329
- package/dist/quickjs-emscripten-sync.umd.js +7 -7
- package/package.json +7 -7
- package/src/index.test.ts +299 -0
- package/src/index.ts +136 -0
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
(function(m,v){typeof exports=="object"&&typeof module!="undefined"?v(exports):typeof define=="function"&&define.amd?define(["exports"],v):(m=typeof globalThis!="undefined"?globalThis:m||self,v(m.QuickjsEmscriptenSync={}))})(this,function(m){"use strict";var ve=Object.defineProperty;var we=(m,v,j)=>v in m?ve(m,v,{enumerable:!0,configurable:!0,writable:!0,value:j}):m[v]=j;var c=(m,v,j)=>
|
|
1
|
+
(function(m,v){typeof exports=="object"&&typeof module!="undefined"?v(exports):typeof define=="function"&&define.amd?define(["exports"],v):(m=typeof globalThis!="undefined"?globalThis:m||self,v(m.QuickjsEmscriptenSync={}))})(this,(function(m){"use strict";var ve=Object.defineProperty;var we=(m,v,j)=>v in m?ve(m,v,{enumerable:!0,configurable:!0,writable:!0,value:j}):m[v]=j;var c=(m,v,j)=>we(m,typeof v!="symbol"?v+"":v,j);const v=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){c(this,"context");c(this,"fn");c(this,"fnGenerator");c(this,"fnCounter",Number.MIN_SAFE_INTEGER);c(this,"fnMap",new Map);c(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 o=e.getNumber(r),i=t.get(o);if(!i)throw new Error("function is not registered");return i.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 k=[[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
|
|
8
|
+
})`))}disposeEx(){this.fnGenerator.dispose(),this.fn.dispose()}}const k=[[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 J(n,e){const t=n.unwrapResult(n.evalCode(e)),r=(s,...o)=>n.unwrapResult(n.callFunction(t,s!=null?s:n.undefined,...o));return r.dispose=()=>t.dispose(),r.alive=!0,Object.defineProperty(r,"alive",{get:()=>t.alive}),r}function _(n,e,t,...r){const s=J(n,e);try{return s(t,...r)}finally{s.dispose()}}function C(n,e,t){return n.dump(_(n,"Object.is",void 0,e,t))}function W(n,e,t){return n.dump(_(n,"(a, b) => a instanceof b",void 0,e,t))}function F(n,e){return n.dump(_(n,'a => typeof a === "object" && a !== null || typeof a === "function"',void 0,e))}function H(n,e){const t=JSON.stringify(e);return t?_(n,"JSON.parse",void 0,n.newString(t)):n.undefined}function z(n,e){try{return e(n)}finally{for(const t of n)t.alive&&t.dispose()}}function $([n,e],t){try{return t(n)}finally{e&&n.dispose()}}function S(n,e){try{return e(...n.map(t=>t[0]))}finally{for(const[t,r]of n)r&&t.dispose()}}function q(n){return"handle"in n}function L(n){return q(n)?n.handle:n}function Q(n,e,t,r){var o;let s;for(const i of r)if(s=i(e,n),s)break;return s?(o=t(e,s))!=null?o:s:void 0}function V(n,e){return typeof n!="symbol"?void 0:_(e,"d => Symbol(d)",void 0,n.description?e.newString(n.description):e.undefined)}function X(n,e){return n instanceof Date?_(e,"d => new Date(d)",void 0,e.newNumber(n.getTime())):void 0}const Y=[V,X];function N(n){return typeof n=="function"&&/^class\s/.test(Function.prototype.toString.call(n))}function g(n){return typeof n=="function"||typeof n=="object"&&n!==null}function O(n,e){const t=new Set,r=s=>{if(!(!g(s)||t.has(s)||(e==null?void 0:e(s,t))===!1)){if(t.add(s),Array.isArray(s)){for(const o of s)r(o);return}if(typeof s=="object"){const o=Object.getPrototypeOf(s);o&&o!==Object.prototype&&r(o)}for(const o of Object.values(Object.getOwnPropertyDescriptors(s)))"value"in o&&r(o.value),"get"in o&&r(o.get),"set"in o&&r(o.set)}};return r(n),t}function Z(n,e){return O(n,e?(t,r)=>r.size<e:void 0).size}function K(){let n=()=>{},e=()=>{};return{promise:new Promise((r,s)=>{n=r,e=s}),resolve:n,reject:e}}function A(n,e,t,r){const s=n.newObject(),o=(a,u)=>{const p=r(a),l=typeof u.value=="undefined"?void 0:r(u.value),f=typeof u.get=="undefined"?void 0:r(u.get),d=typeof u.set=="undefined"?void 0:r(u.set);n.newObject().consume(h=>{Object.entries(u).forEach(([y,b])=>{const w=y==="value"?l:y==="get"?f:y==="set"?d:b?n.true:n.false;w&&n.setProp(h,y,w)}),n.setProp(s,p,h)})},i=Object.getOwnPropertyDescriptors(e);Object.entries(i).forEach(([a,u])=>o(a,u)),Object.getOwnPropertySymbols(i).forEach(a=>o(a,i[a])),_(n,"Object.defineProperties",void 0,t,s).dispose(),s.dispose()}function x(n,e,t,r,s,o){var u;if(typeof e!="function")return;const i=n.newFunction(e.name,function(...p){const l=r(this),f=p.map(d=>r(d));if(N(e)&&g(l)){const d=new e(...f);return Object.entries(d).forEach(([h,y])=>{n.setProp(this,h,t(y))}),this}return t(o?o(e,l,f):e.apply(l,f))}).consume(p=>_(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,p)),a=(u=
|
|
13
|
+
}`,void 0,p)),a=(u=s(e,i))!=null?u:i;return A(n,e,i,t),a}function ee(n,e,t){var o;const r=H(n,e);return(o=t(e,r))!=null?o:r}function te(n,e,t,r){var u;if(typeof e!="object"||e===null)return;const s=Array.isArray(e)?n.newArray():n.newObject(),o=(u=r(e,s))!=null?u:s,i=Object.getPrototypeOf(e),a=i&&i!==Object.prototype&&i!==Array.prototype?t(i):void 0;return a&&_(n,"Object.setPrototypeOf",void 0,o,a).dispose(),A(n,e,s,t),o}function ne(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"object":return e===null?n.null:void 0}}function re(n,e,t,r){var o;if(!(e instanceof Promise))return;const s=n.newPromise();return e.then(i=>s.resolve(t(i)),i=>s.reject(t(i))),(o=r(e,s))!=null?o:s.handle}function E(n,e){var l,f,d,h,y;const{ctx:t,unmarshal:r,isMarshalable:s,find:o,pre:i}=e;{const b=ne(t,n);if(b)return b}{const b=o(n);if(b)return b}const a=s==null?void 0:s(n);if(a===!1)return t.undefined;const u=(b,w)=>i(b,w,a);if(a==="json")return ee(t,n,u);const p=b=>E(b,e);return(y=(h=(d=(f=Q(t,n,u,[...Y,...(l=e.custom)!=null?l:[]]))!=null?f:re(t,n,p,u))!=null?d:x(t,n,p,r,u,e.preApply))!=null?h:te(t,n,p,u))!=null?y:t.undefined}function se(n,e,t,r){var o;let s;for(const i of r)if(s=i(e,n),s)break;return s?(o=t(s,e))!=null?o:s:void 0}function oe(n,e){if(e.typeof(n)!=="symbol")return;const t=e.getString(e.getProp(n,"description"));return Symbol(t)}function ie(n,e){if(!e.dump(_(e,"a => a instanceof Date",void 0,n)))return;const t=e.getNumber(_(e,"a => a.getTime()",void 0,n));return new Date(t)}const ue=[oe,ie];function D(n,e,t,r){n.newFunction("",(s,o)=>{const[i]=r(s);if(typeof i!="string"&&typeof i!="number"&&typeof i!="symbol")return;const a=[["value",!0],["get",!0],["set",!0],["configurable",!1],["enumerable",!1],["writable",!1]].reduce((u,[p,l])=>{const f=n.getProp(o,p),d=n.typeof(f);if(d==="undefined")return u;if(!l&&d==="boolean")return u[p]=n.dump(n.getProp(o,p)),u;const[h,y]=r(f);return y&&f.dispose(),u[p]=h,u},{});Object.defineProperty(t,i,a)}).consume(s=>{_(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,
|
|
17
|
+
}`,void 0,e,s).dispose()})}function ae(n,e,t,r,s){var a;if(n.typeof(e)!=="function")return;const o=function(...u){return S([t(this),...u.map(p=>t(p))],(p,...l)=>{if(new.target){const[y]=r(_(n,"(Cls, ...args) => new Cls(...args)",p,e,...l));return Object.defineProperties(this,Object.getOwnPropertyDescriptors(y)),this}const f=n.unwrapResult(n.callFunction(e,p,...l)),[d,h]=r(f);return h&&f.dispose(),d})},i=(a=s(o,e))!=null?a:o;return D(n,e,o,r),i}function pe(n,e,t,r){var a;if(n.typeof(e)!=="object"||n.unwrapResult(n.evalCode("o => o === null")).consume(u=>n.dump(n.unwrapResult(n.callFunction(u,n.undefined,e)))))return;const s=_(n,"Array.isArray",void 0,e).consume(u=>n.dump(u))?[]:{},o=(a=r(s,e))!=null?a:s,i=_(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).consume(u=>{if(n.typeof(u)==="undefined")return;const[p]=t(u);return p});return typeof i=="object"&&Object.setPrototypeOf(o,i),D(n,e,
|
|
20
|
+
}`,void 0,e).consume(u=>{if(n.typeof(u)==="undefined")return;const[p]=t(u);return p});return typeof i=="object"&&Object.setPrototypeOf(o,i),D(n,e,s,t),o}function fe(n,e){const t=n.typeof(e);return t==="undefined"||t==="number"||t==="string"||t==="boolean"?[n.dump(e),!0]:t==="object"&&n.unwrapResult(n.evalCode("a => a === null")).consume(s=>n.dump(n.unwrapResult(n.callFunction(s,n.undefined,e))))?[null,!0]:[void 0,!1]}function ce(n,e,t,r){var p;if(!le(n,e))return;const s=K(),[o,i]=t(s.resolve),[a,u]=t(s.reject);return _(n,"(p, res, rej) => { p.then(res, rej); }",void 0,e,o,a),i&&o.dispose(),u&&a.dispose(),(p=r(s.promise,e))!=null?p:s.promise}function le(n,e){return e.owner?n.unwrapResult(n.evalCode("Promise")).consume(t=>e.owner?W(n,e,t):!1):!1}function B(n,e){const[t]=T(n,e);return t}function T(n,e){var u,p,l,f;const{ctx:t,marshal:r,find:s,pre:o}=e;{const[d,h]=fe(t,n);if(h)return[d,!1]}{const d=s(n);if(d)return[d,!0]}const i=d=>T(d,e);return[(f=(l=(p=se(t,n,o,[...ue,...(u=e.custom)!=null?u:[]]))!=null?p:ce(t,n,r,o))!=null?l:ae(t,n,r,i,o))!=null?f:pe(t,n,i,o),!1]}class M{constructor(e){c(this,"ctx");c(this,"_map1",new Map);c(this,"_map2",new Map);c(this,"_map3",new Map);c(this,"_map4",new Map);c(this,"_counterMap",new Map);c(this,"_disposables",new Set);c(this,"_mapGet");c(this,"_mapSet");c(this,"_mapDelete");c(this,"_mapClear");c(this,"_counter",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(
|
|
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 a;if(!t.alive||s&&!s.alive)return!1;const o=(a=this.get(e))!=null?a:this.get(r);if(o)return o===t||o===s;const i=this._counter++;return this._map1.set(e,i),this._map3.set(i,t),this._counterMap.set(i,e),r&&(this._map2.set(r,i),s&&this._map4.set(i,s)),this.ctx.newNumber(i).consume(u=>{this._call(this._mapSet,void 0,t,u,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._map1.get(e))!=null?s:this._map2.get(e),r=typeof t=="number"?this._map3.get(t):void 0;if(r){if(!r.alive){this.delete(e);return}return r}}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,t){var i;const r=(i=this._map1.get(e))!=null?i:this._map2.get(e);if(typeof r=="undefined")return;const s=this._map3.get(r),o=this._map4.get(r);this._call(this._mapDelete,void 0,...[s,o].filter(a=>!!(a!=null&&a.alive))),this._map1.delete(e),this._map2.delete(e),this._map3.delete(r),this._map4.delete(r);for(const[a,u]of this._map1)if(u===r){this._map1.delete(a);break}for(const[a,u]of this._map2)if(u===r){this._map2.delete(a);break}for(const[a,u]of this._counterMap)if(u===e){this._counterMap.delete(a);break}t&&(s!=null&&s.alive&&s.dispose(),o!=null&&o.alive&&o.dispose())}deleteByHandle(e,t){const r=this.getByHandle(e);typeof r!="undefined"&&this.delete(r,t)}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 t=e.next();if(t.done)return{value:void 0,done:!0};const r=this._map1.get(t.value);if(typeof r=="undefined")continue;const s=this._map3.get(r),o=this._map4.get(r);if(!s)continue;const i=this._get2(r);return{value:[t.value,s,i,o],done:!1}}}}}_get2(e){for(const[t,r]of this._map2)if(r===e)return t}_call(e,t,...r){return this.ctx.unwrapResult(this.ctx.callFunction(e,typeof t=="undefined"?this.ctx.undefined:t,...r))}}function de(n,e,t,r,s,o,i){if(!g(e)||e instanceof Promise||e instanceof Date||i&&!i(e))return;if(he(e,t))return e;const a=new Proxy(e,{get(u,p){return p===t?u:Reflect.get(u,p)},set(u,p,l,f){var y;const d=P(l,t),h=(y=o==null?void 0:o(f))!=null?y:"host";return h!=="vm"&&!Reflect.set(u,p,d,f)||h==="host"||!n.alive||S([s(f),s(p),s(d)],(b,w,I)=>{const[G,_e]=R(n,b,r);_e?G.consume(be=>n.setProp(be,w,I)):n.setProp(G,w,I)}),!0},deleteProperty(u,p){var f;const l=(f=o==null?void 0:o(a))!=null?f:"host";return S([s(a),s(p)],(d,h)=>{const[y,b]=R(n,d,r);if(l==="vm"||Reflect.deleteProperty(u,p)){if(l==="host"||!n.alive)return!0;b?y.consume(w=>_(n,"(a, b) => delete a[b]",void 0,w,h)):_(n,"(a, b) => delete a[b]",void 0,y,h)}return!0})}});return a}function me(n,e,t,r,s,o,i){if(!F(n,e)||i&&!i(e,n))return[void 0,!1];if(U(n,e,r))return[e,!1];const a=l=>{const f=o==null?void 0:o(s(l));return typeof f=="string"?n.newString(f):n.undefined},u=(l,f,d)=>{const h=s(l);if(!h)return;const y=s(f);if(y==="__proto__")return;const b=s(d);P(h,t)[y]=b},p=(l,f)=>{const d=s(l);if(!d)return;const h=s(f);delete P(d,t)[h]};return n.newFunction("proxyFuncs",(l,...f)=>{switch(n.getNumber(l)){case 1:return a(f[0]);case 2:return u(f[0],f[1],f[2]);case 3:return p(f[0],f[1])}return n.undefined}).consume(l=>[_(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)
|
|
@@ -68,4 +68,4 @@
|
|
|
68
68
|
},
|
|
69
69
|
});
|
|
70
70
|
return rec;
|
|
71
|
-
}`,void 0,e,
|
|
71
|
+
}`,void 0,e,r,l),!0])}function P(n,e){var t;return g(n)&&(t=n[e])!=null?t:n}function R(n,e,t){return U(n,e,t)?[n.getProp(e,t),!0]:[e,!1]}function he(n,e){return g(n)&&!!n[e]}function U(n,e,t){return!!n.dump(_(n,'(a, s) => (a instanceof Promise) || (a instanceof Date) || (typeof a === "object" && a !== null || typeof a === "function") && !!a[s]',void 0,e,t))}class ye{constructor(e,t){c(this,"context");c(this,"_map");c(this,"_registeredMap");c(this,"_registeredMapDispose",new Set);c(this,"_sync",new Set);c(this,"_temporalSync",new Set);c(this,"_symbol",Symbol());c(this,"_symbolHandle");c(this,"_options");c(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"});c(this,"_marshalFind",e=>{var s,o,i;const t=this._unwrap(e);return(i=(o=(s=this._registeredMap.get(e))!=null?s:t!==e?this._registeredMap.get(t):void 0)!=null?o:this._map.get(e))!=null?i:t!==e?this._map.get(t):void 0});c(this,"_marshalPre",(e,t,r)=>{var s;if(r!=="json")return(s=this._register(e,L(t),this._map))==null?void 0:s[1]});c(this,"_marshalPreApply",(e,t,r)=>{const s=g(t)?this._unwrap(t):void 0;s&&this._temporalSync.add(s);try{return e.apply(t,r)}finally{s&&this._temporalSync.delete(s)}});c(this,"_marshal",e=>{var s,o;const t=this._registeredMap.get(e);if(t)return[t,!1];const r=E((s=this._wrap(e))!=null?s:e,{ctx:this.context,unmarshal:this._unmarshal,isMarshalable:this._isMarshalable,find:this._marshalFind,pre:this._marshalPre,preApply:this._marshalPreApply,custom:(o=this._options)==null?void 0:o.customMarshaller});return[r,!this._map.hasHandle(r)]});c(this,"_preUnmarshal",(e,t)=>{var r;return(r=this._register(e,t,void 0,!0))==null?void 0:r[0]});c(this,"_unmarshalFind",e=>{var t;return(t=this._registeredMap.getByHandle(e))!=null?t:this._map.getByHandle(e)});c(this,"_unmarshal",e=>{var s;const t=this._registeredMap.getByHandle(e);if(typeof t!="undefined")return t;const[r]=this._wrapHandle(e);return B(r!=null?r:e,{ctx:this.context,marshal:this._marshal,find:this._unmarshalFind,pre:this._preUnmarshal,custom:(s=this._options)==null?void 0:s.customUnmarshaller})});c(this,"_syncMode",e=>{const t=this._unwrap(e);return this._sync.has(t)||this._temporalSync.has(t)?"both":void 0});c(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?v(e):e,this._options=t,this._symbolHandle=e.unwrapResult(e.evalCode("Symbol()")),this._map=new M(e),this._registeredMap=new M(e),this.registerAll((r=t==null?void 0:t.registeredObjects)!=null?r:k)}dispose(){var e,t;this._map.dispose(),this._registeredMap.dispose(),this._symbolHandle.dispose(),(t=(e=this.context).disposeEx)==null||t.call(e)}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"});this._unwrapResultAndUnmarshal(r)}executePendingJobs(e){const t=this.context.runtime.executePendingJobs(e);if("value"in t)return t.value;throw this._unwrapIfNotSynced(t.error.consume(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))$(this._marshal(r),s=>{this.context.setProp(this.context.global,t,s)})}sync(e){const t=this._wrap(e);return typeof t=="undefined"?e:(O(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;C(this.context,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(!g(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(e.error.consume(this._unmarshal))}_unwrapResultAndUnmarshal(e){if(e)return this._unwrapIfNotSynced(this._unwrapResult(e).consume(this._unmarshal))}_register(e,t,r=this._map,s){if(this._registeredMap.has(e)||this._registeredMap.hasHandle(t))return;let o=this._wrap(e);const[i]=this._wrapHandle(t),a=e instanceof Promise;if(!i||!o&&!a)return;a&&(o=e);const u=this._unwrap(e),[p,l]=this._unwrapHandle(t);if(r.set(o,i,u,p))s&&this._sync.add(u);else throw l&&p.dispose(),new Error("already registered");return[o,i]}_wrap(e){var t;return de(this.context,e,this._symbol,this._symbolHandle,this._marshal,this._syncMode,(t=this._options)==null?void 0:t.isWrappable)}_unwrap(e){return P(e,this._symbol)}_wrapHandle(e){var t;return me(this.context,e,this._symbol,this._symbolHandle,this._unmarshal,this._syncMode,(t=this._options)==null?void 0:t.isHandleWrappable)}_unwrapHandle(e){return R(this.context,e,this._symbolHandle)}}m.Arena=ye,m.VMMap=M,m.call=_,m.complexity=Z,m.consumeAll=z,m.defaultRegisteredObjects=k,m.eq=C,m.isES2015Class=N,m.isHandleObject=F,m.isObject=g,m.json=H,m.marshal=E,m.unmarshal=B,m.walkObject=O,Object.defineProperty(m,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.6.0",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"source": "./src/index.ts",
|
|
7
7
|
"main": "./dist/quickjs-emscripten-sync.umd.js",
|
|
@@ -32,13 +32,13 @@
|
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"@vitest/coverage-c8": "^0.28.5",
|
|
35
|
-
"eslint": "^8.
|
|
35
|
+
"eslint": "^8.57.1",
|
|
36
36
|
"eslint-config-reearth": "^0.2.1",
|
|
37
|
-
"prettier": "^2.
|
|
38
|
-
"quickjs-emscripten": "^0.
|
|
39
|
-
"typescript": "^
|
|
40
|
-
"vite": "^
|
|
41
|
-
"vite-plugin-dts": "^
|
|
37
|
+
"prettier": "^2.8.8",
|
|
38
|
+
"quickjs-emscripten": "^0.25.0",
|
|
39
|
+
"typescript": "^5.7.2",
|
|
40
|
+
"vite": "^6.0.3",
|
|
41
|
+
"vite-plugin-dts": "^4.3.0",
|
|
42
42
|
"vitest": "^0.28.5"
|
|
43
43
|
}
|
|
44
44
|
}
|
package/src/index.test.ts
CHANGED
|
@@ -612,3 +612,302 @@ describe("isMarshalable option", () => {
|
|
|
612
612
|
ctx.dispose();
|
|
613
613
|
});
|
|
614
614
|
});
|
|
615
|
+
|
|
616
|
+
describe("evalModule", () => {
|
|
617
|
+
test("module can modify exposed globals", async () => {
|
|
618
|
+
const ctx = (await getQuickJS()).newContext();
|
|
619
|
+
const arena = new Arena(ctx, { isMarshalable: true });
|
|
620
|
+
|
|
621
|
+
const data = arena.sync({ count: 0, message: "" });
|
|
622
|
+
arena.expose({ data });
|
|
623
|
+
|
|
624
|
+
// Module code can have side effects on exposed globals
|
|
625
|
+
arena.evalModule(`
|
|
626
|
+
data.count = 42;
|
|
627
|
+
data.message = "Hello from module";
|
|
628
|
+
`);
|
|
629
|
+
|
|
630
|
+
expect(data.count).toBe(42);
|
|
631
|
+
expect(data.message).toBe("Hello from module");
|
|
632
|
+
|
|
633
|
+
arena.dispose();
|
|
634
|
+
ctx.dispose();
|
|
635
|
+
});
|
|
636
|
+
|
|
637
|
+
test("module with function side effects", async () => {
|
|
638
|
+
const ctx = (await getQuickJS()).newContext();
|
|
639
|
+
const arena = new Arena(ctx, { isMarshalable: true });
|
|
640
|
+
|
|
641
|
+
const results: number[] = [];
|
|
642
|
+
arena.expose({
|
|
643
|
+
results,
|
|
644
|
+
push: (value: number) => results.push(value),
|
|
645
|
+
});
|
|
646
|
+
|
|
647
|
+
arena.evalModule(`
|
|
648
|
+
push(1);
|
|
649
|
+
push(2);
|
|
650
|
+
push(3);
|
|
651
|
+
`);
|
|
652
|
+
|
|
653
|
+
expect(results).toEqual([1, 2, 3]);
|
|
654
|
+
|
|
655
|
+
arena.dispose();
|
|
656
|
+
ctx.dispose();
|
|
657
|
+
});
|
|
658
|
+
|
|
659
|
+
test("module can define and use internal exports", async () => {
|
|
660
|
+
const ctx = (await getQuickJS()).newContext();
|
|
661
|
+
const arena = new Arena(ctx, { isMarshalable: true });
|
|
662
|
+
|
|
663
|
+
const output = arena.sync({ value: 0 });
|
|
664
|
+
arena.expose({ output });
|
|
665
|
+
|
|
666
|
+
// Module can export and use its own exports internally
|
|
667
|
+
arena.evalModule(`
|
|
668
|
+
export function double(x) {
|
|
669
|
+
return x * 2;
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
export const value = 21;
|
|
673
|
+
|
|
674
|
+
// Use the exports internally
|
|
675
|
+
output.value = double(value);
|
|
676
|
+
`);
|
|
677
|
+
|
|
678
|
+
expect(output.value).toBe(42);
|
|
679
|
+
|
|
680
|
+
arena.dispose();
|
|
681
|
+
ctx.dispose();
|
|
682
|
+
});
|
|
683
|
+
|
|
684
|
+
test("module with custom filename", async () => {
|
|
685
|
+
const ctx = (await getQuickJS()).newContext();
|
|
686
|
+
const arena = new Arena(ctx, { isMarshalable: true });
|
|
687
|
+
|
|
688
|
+
const state = arena.sync({ executed: false });
|
|
689
|
+
arena.expose({ state });
|
|
690
|
+
|
|
691
|
+
// Test that custom filename doesn't break functionality
|
|
692
|
+
arena.evalModule(`state.executed = true;`, "custom-module.js");
|
|
693
|
+
|
|
694
|
+
expect(state.executed).toBe(true);
|
|
695
|
+
|
|
696
|
+
arena.dispose();
|
|
697
|
+
ctx.dispose();
|
|
698
|
+
});
|
|
699
|
+
|
|
700
|
+
test("module with strict mode", async () => {
|
|
701
|
+
const ctx = (await getQuickJS()).newContext();
|
|
702
|
+
const arena = new Arena(ctx, { isMarshalable: true });
|
|
703
|
+
|
|
704
|
+
const result = arena.sync({ ok: false });
|
|
705
|
+
arena.expose({ result });
|
|
706
|
+
|
|
707
|
+
// Modules are strict by default
|
|
708
|
+
arena.evalModule(`
|
|
709
|
+
// This would fail in strict mode if we tried: undeclaredVariable = 1;
|
|
710
|
+
result.ok = true;
|
|
711
|
+
`);
|
|
712
|
+
|
|
713
|
+
expect(result.ok).toBe(true);
|
|
714
|
+
|
|
715
|
+
arena.dispose();
|
|
716
|
+
ctx.dispose();
|
|
717
|
+
});
|
|
718
|
+
});
|
|
719
|
+
|
|
720
|
+
describe("memory management", () => {
|
|
721
|
+
test("getMemoryUsage returns statistics", async () => {
|
|
722
|
+
const ctx = (await getQuickJS()).newContext();
|
|
723
|
+
const arena = new Arena(ctx, { isMarshalable: true });
|
|
724
|
+
|
|
725
|
+
const stats = arena.getMemoryUsage();
|
|
726
|
+
|
|
727
|
+
// Check that key properties exist
|
|
728
|
+
expect(stats).toHaveProperty("memory_used_size");
|
|
729
|
+
expect(stats).toHaveProperty("malloc_limit");
|
|
730
|
+
expect(stats).toHaveProperty("obj_count");
|
|
731
|
+
expect(stats).toHaveProperty("malloc_count");
|
|
732
|
+
|
|
733
|
+
// Memory should be used
|
|
734
|
+
expect(stats.memory_used_size).toBeGreaterThan(0);
|
|
735
|
+
expect(stats.malloc_count).toBeGreaterThan(0);
|
|
736
|
+
|
|
737
|
+
arena.dispose();
|
|
738
|
+
ctx.dispose();
|
|
739
|
+
});
|
|
740
|
+
|
|
741
|
+
test("getMemoryUsage tracks allocations", async () => {
|
|
742
|
+
const ctx = (await getQuickJS()).newContext();
|
|
743
|
+
const arena = new Arena(ctx, { isMarshalable: true });
|
|
744
|
+
|
|
745
|
+
const before = arena.getMemoryUsage();
|
|
746
|
+
|
|
747
|
+
// Allocate some objects
|
|
748
|
+
arena.evalCode(`
|
|
749
|
+
const arr = [];
|
|
750
|
+
for (let i = 0; i < 100; i++) {
|
|
751
|
+
arr.push({ id: i, data: "test".repeat(10) });
|
|
752
|
+
}
|
|
753
|
+
`);
|
|
754
|
+
|
|
755
|
+
const after = arena.getMemoryUsage();
|
|
756
|
+
|
|
757
|
+
// Memory usage should increase
|
|
758
|
+
expect(after.memory_used_size).toBeGreaterThan(before.memory_used_size);
|
|
759
|
+
expect(after.obj_count).toBeGreaterThan(before.obj_count);
|
|
760
|
+
|
|
761
|
+
arena.dispose();
|
|
762
|
+
ctx.dispose();
|
|
763
|
+
});
|
|
764
|
+
|
|
765
|
+
test("dumpMemoryUsage returns formatted string", async () => {
|
|
766
|
+
const ctx = (await getQuickJS()).newContext();
|
|
767
|
+
const arena = new Arena(ctx, { isMarshalable: true });
|
|
768
|
+
|
|
769
|
+
const dump = arena.dumpMemoryUsage();
|
|
770
|
+
|
|
771
|
+
// Should be a non-empty string
|
|
772
|
+
expect(typeof dump).toBe("string");
|
|
773
|
+
expect(dump.length).toBeGreaterThan(0);
|
|
774
|
+
|
|
775
|
+
// Should contain key memory metrics (the format varies)
|
|
776
|
+
expect(dump).toMatch(/memory|malloc/i);
|
|
777
|
+
|
|
778
|
+
arena.dispose();
|
|
779
|
+
ctx.dispose();
|
|
780
|
+
});
|
|
781
|
+
|
|
782
|
+
test("setMemoryLimit enforces memory constraints", async () => {
|
|
783
|
+
const ctx = (await getQuickJS()).newContext();
|
|
784
|
+
const arena = new Arena(ctx, { isMarshalable: true });
|
|
785
|
+
|
|
786
|
+
// Set a low memory limit (100KB)
|
|
787
|
+
arena.setMemoryLimit(100 * 1024);
|
|
788
|
+
|
|
789
|
+
// Verify limit is set
|
|
790
|
+
const stats = arena.getMemoryUsage();
|
|
791
|
+
expect(stats.malloc_limit).toBe(100 * 1024);
|
|
792
|
+
|
|
793
|
+
// Try to allocate too much memory
|
|
794
|
+
expect(() => {
|
|
795
|
+
arena.evalCode(`
|
|
796
|
+
const huge = [];
|
|
797
|
+
for (let i = 0; i < 1000000; i++) {
|
|
798
|
+
huge.push({ data: "x".repeat(1000) });
|
|
799
|
+
}
|
|
800
|
+
`);
|
|
801
|
+
}).toThrow();
|
|
802
|
+
|
|
803
|
+
arena.dispose();
|
|
804
|
+
ctx.dispose();
|
|
805
|
+
});
|
|
806
|
+
|
|
807
|
+
test("setMemoryLimit can be removed with -1", async () => {
|
|
808
|
+
const ctx = (await getQuickJS()).newContext();
|
|
809
|
+
const arena = new Arena(ctx, { isMarshalable: true });
|
|
810
|
+
|
|
811
|
+
// Set a limit
|
|
812
|
+
arena.setMemoryLimit(100 * 1024);
|
|
813
|
+
expect(arena.getMemoryUsage().malloc_limit).toBe(100 * 1024);
|
|
814
|
+
|
|
815
|
+
// Remove the limit
|
|
816
|
+
arena.setMemoryLimit(-1);
|
|
817
|
+
const stats = arena.getMemoryUsage();
|
|
818
|
+
expect(stats.malloc_limit).toBeGreaterThan(100 * 1024);
|
|
819
|
+
|
|
820
|
+
arena.dispose();
|
|
821
|
+
ctx.dispose();
|
|
822
|
+
});
|
|
823
|
+
|
|
824
|
+
test("setMaxStackSize prevents stack overflow", async () => {
|
|
825
|
+
const ctx = (await getQuickJS()).newContext();
|
|
826
|
+
const arena = new Arena(ctx, { isMarshalable: true });
|
|
827
|
+
|
|
828
|
+
// Set a small stack size (256KB)
|
|
829
|
+
arena.setMaxStackSize(256 * 1024);
|
|
830
|
+
|
|
831
|
+
// Try to cause stack overflow with deep recursion
|
|
832
|
+
expect(() => {
|
|
833
|
+
arena.evalCode(`
|
|
834
|
+
function recurse(n) {
|
|
835
|
+
if (n > 0) return recurse(n - 1);
|
|
836
|
+
return n;
|
|
837
|
+
}
|
|
838
|
+
recurse(100000);
|
|
839
|
+
`);
|
|
840
|
+
}).toThrow();
|
|
841
|
+
|
|
842
|
+
arena.dispose();
|
|
843
|
+
ctx.dispose();
|
|
844
|
+
});
|
|
845
|
+
|
|
846
|
+
test("setMaxStackSize can be removed with 0", async () => {
|
|
847
|
+
const ctx = (await getQuickJS()).newContext();
|
|
848
|
+
const arena = new Arena(ctx, { isMarshalable: true });
|
|
849
|
+
|
|
850
|
+
// Set a very small stack
|
|
851
|
+
arena.setMaxStackSize(128 * 1024);
|
|
852
|
+
|
|
853
|
+
// This should fail with small stack
|
|
854
|
+
expect(() => {
|
|
855
|
+
arena.evalCode(`
|
|
856
|
+
function recurse(n) {
|
|
857
|
+
if (n > 0) return recurse(n - 1);
|
|
858
|
+
return n;
|
|
859
|
+
}
|
|
860
|
+
recurse(10000);
|
|
861
|
+
`);
|
|
862
|
+
}).toThrow();
|
|
863
|
+
|
|
864
|
+
// Remove the limit
|
|
865
|
+
arena.setMaxStackSize(0);
|
|
866
|
+
|
|
867
|
+
// Now it should work (or at least get further)
|
|
868
|
+
const result = arena.evalCode(`
|
|
869
|
+
function recurse(n) {
|
|
870
|
+
if (n > 0) return recurse(n - 1);
|
|
871
|
+
return n;
|
|
872
|
+
}
|
|
873
|
+
recurse(1000);
|
|
874
|
+
`);
|
|
875
|
+
|
|
876
|
+
expect(result).toBe(0);
|
|
877
|
+
|
|
878
|
+
arena.dispose();
|
|
879
|
+
ctx.dispose();
|
|
880
|
+
});
|
|
881
|
+
|
|
882
|
+
test("memory limits work with marshaling", async () => {
|
|
883
|
+
const ctx = (await getQuickJS()).newContext();
|
|
884
|
+
const arena = new Arena(ctx, { isMarshalable: true });
|
|
885
|
+
|
|
886
|
+
// Set limit
|
|
887
|
+
arena.setMemoryLimit(200 * 1024);
|
|
888
|
+
|
|
889
|
+
const data = arena.sync({ items: [] as any[] });
|
|
890
|
+
arena.expose({ data });
|
|
891
|
+
|
|
892
|
+
// Should be able to add reasonable data
|
|
893
|
+
arena.evalCode(`
|
|
894
|
+
for (let i = 0; i < 10; i++) {
|
|
895
|
+
data.items.push({ id: i });
|
|
896
|
+
}
|
|
897
|
+
`);
|
|
898
|
+
|
|
899
|
+
expect(data.items.length).toBe(10);
|
|
900
|
+
|
|
901
|
+
// But not unlimited data
|
|
902
|
+
expect(() => {
|
|
903
|
+
arena.evalCode(`
|
|
904
|
+
for (let i = 0; i < 100000; i++) {
|
|
905
|
+
data.items.push({ id: i, data: "x".repeat(1000) });
|
|
906
|
+
}
|
|
907
|
+
`);
|
|
908
|
+
}).toThrow();
|
|
909
|
+
|
|
910
|
+
arena.dispose();
|
|
911
|
+
ctx.dispose();
|
|
912
|
+
});
|
|
913
|
+
});
|
package/src/index.ts
CHANGED
|
@@ -103,6 +103,27 @@ export class Arena {
|
|
|
103
103
|
return this._unwrapResultAndUnmarshal(handle);
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
+
/**
|
|
107
|
+
* Evaluate ES module code in the VM. The module can import/export, but the return value
|
|
108
|
+
* depends on whether the module exports are accessible (implementation varies by quickjs-emscripten version).
|
|
109
|
+
* Use this for side effects or when you don't need access to exports.
|
|
110
|
+
*
|
|
111
|
+
* @param code - The ES module code to evaluate
|
|
112
|
+
* @param filename - Optional filename for debugging purposes (default: "module.js")
|
|
113
|
+
* @returns Undefined in most cases (module side effects are applied)
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* ```js
|
|
117
|
+
* // Execute module code with side effects
|
|
118
|
+
* arena.expose({ data: { count: 0 } });
|
|
119
|
+
* arena.evalModule('import { data } from "globals"; data.count = 42;'); // undefined, but data.count is now 42
|
|
120
|
+
* ```
|
|
121
|
+
*/
|
|
122
|
+
evalModule(code: string, filename = "module.js"): void {
|
|
123
|
+
const handle = this.context.evalCode(code, filename, { type: "module" });
|
|
124
|
+
this._unwrapResultAndUnmarshal(handle);
|
|
125
|
+
}
|
|
126
|
+
|
|
106
127
|
/**
|
|
107
128
|
* Almost same as `vm.executePendingJobs()`, but it converts and re-throws error objects when an error is thrown during evaluation.
|
|
108
129
|
*/
|
|
@@ -114,6 +135,121 @@ export class Arena {
|
|
|
114
135
|
throw this._unwrapIfNotSynced(result.error.consume(this._unmarshal));
|
|
115
136
|
}
|
|
116
137
|
|
|
138
|
+
/**
|
|
139
|
+
* Set the max memory this runtime can allocate.
|
|
140
|
+
* To remove the limit, set to `-1`.
|
|
141
|
+
*
|
|
142
|
+
* This is useful for preventing runaway memory usage in untrusted code.
|
|
143
|
+
*
|
|
144
|
+
* @param limitBytes - Maximum memory in bytes, or -1 to remove limit
|
|
145
|
+
*
|
|
146
|
+
* @example
|
|
147
|
+
* ```js
|
|
148
|
+
* // Limit sandbox to 10MB
|
|
149
|
+
* arena.setMemoryLimit(10 * 1024 * 1024);
|
|
150
|
+
*
|
|
151
|
+
* try {
|
|
152
|
+
* arena.evalCode(`const huge = new Array(1000000000);`);
|
|
153
|
+
* } catch (e) {
|
|
154
|
+
* console.log("Memory limit exceeded");
|
|
155
|
+
* }
|
|
156
|
+
* ```
|
|
157
|
+
*/
|
|
158
|
+
setMemoryLimit(limitBytes: number): void {
|
|
159
|
+
this.context.runtime.setMemoryLimit(limitBytes);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Set the max stack size for this runtime, in bytes.
|
|
164
|
+
* To remove the limit, set to `0`.
|
|
165
|
+
*
|
|
166
|
+
* This is useful for preventing stack overflow from deeply nested calls or recursion.
|
|
167
|
+
*
|
|
168
|
+
* @param stackSize - Maximum stack size in bytes, or 0 to remove limit
|
|
169
|
+
*
|
|
170
|
+
* @example
|
|
171
|
+
* ```js
|
|
172
|
+
* // Limit stack to 512KB
|
|
173
|
+
* arena.setMaxStackSize(512 * 1024);
|
|
174
|
+
*
|
|
175
|
+
* try {
|
|
176
|
+
* arena.evalCode(`function recurse() { recurse(); } recurse();`);
|
|
177
|
+
* } catch (e) {
|
|
178
|
+
* console.log("Stack overflow prevented");
|
|
179
|
+
* }
|
|
180
|
+
* ```
|
|
181
|
+
*/
|
|
182
|
+
setMaxStackSize(stackSize: number): void {
|
|
183
|
+
this.context.runtime.setMaxStackSize(stackSize);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Get detailed memory usage statistics for this runtime.
|
|
188
|
+
*
|
|
189
|
+
* @returns An object containing detailed memory allocation information
|
|
190
|
+
*
|
|
191
|
+
* @example
|
|
192
|
+
* ```js
|
|
193
|
+
* const stats = arena.getMemoryUsage();
|
|
194
|
+
* console.log(`Memory used: ${stats.memory_used_size} bytes`);
|
|
195
|
+
* console.log(`Object count: ${stats.obj_count}`);
|
|
196
|
+
* console.log(`Memory limit: ${stats.malloc_limit}`);
|
|
197
|
+
* ```
|
|
198
|
+
*/
|
|
199
|
+
getMemoryUsage(): {
|
|
200
|
+
malloc_limit: number;
|
|
201
|
+
memory_used_size: number;
|
|
202
|
+
malloc_count: number;
|
|
203
|
+
memory_used_count: number;
|
|
204
|
+
atom_count: number;
|
|
205
|
+
atom_size: number;
|
|
206
|
+
str_count: number;
|
|
207
|
+
str_size: number;
|
|
208
|
+
obj_count: number;
|
|
209
|
+
obj_size: number;
|
|
210
|
+
prop_count: number;
|
|
211
|
+
prop_size: number;
|
|
212
|
+
shape_count: number;
|
|
213
|
+
shape_size: number;
|
|
214
|
+
js_func_count: number;
|
|
215
|
+
js_func_size: number;
|
|
216
|
+
js_func_code_size: number;
|
|
217
|
+
js_func_pc2line_count: number;
|
|
218
|
+
js_func_pc2line_size: number;
|
|
219
|
+
c_func_count: number;
|
|
220
|
+
array_count: number;
|
|
221
|
+
fast_array_count: number;
|
|
222
|
+
fast_array_elements: number;
|
|
223
|
+
binary_object_count: number;
|
|
224
|
+
binary_object_size: number;
|
|
225
|
+
} {
|
|
226
|
+
const handle = this.context.runtime.computeMemoryUsage();
|
|
227
|
+
try {
|
|
228
|
+
return this.context.dump(handle);
|
|
229
|
+
} finally {
|
|
230
|
+
handle.dispose();
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Get a human-readable description of memory usage in this runtime.
|
|
236
|
+
*
|
|
237
|
+
* @returns A formatted string showing memory statistics
|
|
238
|
+
*
|
|
239
|
+
* @example
|
|
240
|
+
* ```js
|
|
241
|
+
* console.log(arena.dumpMemoryUsage());
|
|
242
|
+
* // Output:
|
|
243
|
+
* // QuickJS memory usage:
|
|
244
|
+
* // malloc_limit: 4294967295
|
|
245
|
+
* // memory_used_size: 67078
|
|
246
|
+
* // ...
|
|
247
|
+
* ```
|
|
248
|
+
*/
|
|
249
|
+
dumpMemoryUsage(): string {
|
|
250
|
+
return this.context.runtime.dumpMemoryUsage();
|
|
251
|
+
}
|
|
252
|
+
|
|
117
253
|
/**
|
|
118
254
|
* Expose objects as global objects in the VM.
|
|
119
255
|
*
|