@secure-exec/core 0.1.1-rc.1 → 0.1.1-rc.3

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.
@@ -40,8 +40,8 @@ function getNowMs() {
40
40
  ? performance.now()
41
41
  : Date.now();
42
42
  }
43
- // Start time for uptime calculation (mutable for snapshot restore)
44
- let _processStartTime = getNowMs();
43
+ // Start time for uptime calculation
44
+ const _processStartTime = getNowMs();
45
45
  const BUFFER_MAX_LENGTH = typeof BufferPolyfill.kMaxLength ===
46
46
  "number"
47
47
  ? BufferPolyfill.kMaxLength
@@ -71,18 +71,6 @@ if (typeof bufferPolyfillMutable.constants !== "object" ||
71
71
  // Exit code tracking
72
72
  let _exitCode = 0;
73
73
  let _exited = false;
74
- // Expose reset function for snapshot restore — resets mutable state
75
- // captured in this closure so each restored context starts fresh.
76
- globalThis.__runtimeResetProcessState =
77
- function () {
78
- _processStartTime =
79
- typeof performance !== "undefined" && performance.now
80
- ? performance.now()
81
- : Date.now();
82
- _exitCode = 0;
83
- _exited = false;
84
- delete globalThis.__runtimeResetProcessState;
85
- };
86
74
  /**
87
75
  * Thrown by `process.exit()` to unwind the sandbox call stack. The host
88
76
  * catches this to extract the exit code without killing the isolate.
@@ -134,7 +122,7 @@ function _addListener(event, listener, once = false) {
134
122
  const warning = `MaxListenersExceededWarning: Possible EventEmitter memory leak detected. ${total} ${event} listeners added to [process]. MaxListeners is ${_processMaxListeners}. Use emitter.setMaxListeners() to increase limit`;
135
123
  // Use console.error to emit warning without recursion risk
136
124
  if (typeof _error !== "undefined") {
137
- _error(warning);
125
+ _error.applySync(undefined, [warning]);
138
126
  }
139
127
  }
140
128
  }
@@ -181,7 +169,7 @@ const _stderrIsTTY = (typeof _processConfig !== "undefined" && _processConfig.st
181
169
  const _stdout = {
182
170
  write(data) {
183
171
  if (typeof _log !== "undefined") {
184
- _log(String(data).replace(/\n$/, ""));
172
+ _log.applySync(undefined, [String(data).replace(/\n$/, "")]);
185
173
  }
186
174
  return true;
187
175
  },
@@ -206,7 +194,7 @@ const _stdout = {
206
194
  const _stderr = {
207
195
  write(data) {
208
196
  if (typeof _error !== "undefined") {
209
- _error(String(data).replace(/\n$/, ""));
197
+ _error.applySync(undefined, [String(data).replace(/\n$/, "")]);
210
198
  }
211
199
  return true;
212
200
  },
@@ -340,7 +328,7 @@ const _stdin = {
340
328
  throw new Error("setRawMode is not supported when stdin is not a TTY");
341
329
  }
342
330
  if (typeof _ptySetRawMode !== "undefined") {
343
- _ptySetRawMode(mode);
331
+ _ptySetRawMode.applySync(undefined, [mode]);
344
332
  }
345
333
  return this;
346
334
  },
@@ -444,9 +432,9 @@ const process = {
444
432
  },
445
433
  chdir(dir) {
446
434
  // Validate directory exists in VFS before setting cwd
447
- let stat;
435
+ let statJson;
448
436
  try {
449
- stat = _fs.stat(dir);
437
+ statJson = _fs.stat.applySyncPromise(undefined, [dir]);
450
438
  }
451
439
  catch {
452
440
  const err = new Error(`ENOENT: no such file or directory, chdir '${dir}'`);
@@ -456,7 +444,8 @@ const process = {
456
444
  err.path = dir;
457
445
  throw err;
458
446
  }
459
- if (!stat.isDirectory) {
447
+ const parsed = JSON.parse(statJson);
448
+ if (!parsed.isDirectory) {
460
449
  const err = new Error(`ENOTDIR: not a directory, chdir '${dir}'`);
461
450
  err.code = "ENOTDIR";
462
451
  err.errno = -20;
@@ -714,6 +703,13 @@ process.memoryUsage.rss =
714
703
  function () {
715
704
  return 50 * 1024 * 1024;
716
705
  };
706
+ // Match Node.js Object.prototype.toString.call(process) === '[object process]'
707
+ Object.defineProperty(process, Symbol.toStringTag, {
708
+ value: "process",
709
+ writable: false,
710
+ configurable: true,
711
+ enumerable: false,
712
+ });
717
713
  export default process;
718
714
  // ============================================================================
719
715
  // Global polyfills
@@ -770,7 +766,11 @@ export function setTimeout(callback, delay, ...args) {
770
766
  const actualDelay = delay ?? 0;
771
767
  // Use host timer for actual delays if available and delay > 0
772
768
  if (typeof _scheduleTimer !== "undefined" && actualDelay > 0) {
773
- _scheduleTimer(actualDelay)
769
+ // _scheduleTimer.apply() returns a Promise that resolves after the delay
770
+ // Using { result: { promise: true } } tells isolated-vm to wait for the
771
+ // host Promise to resolve before resolving the apply() Promise
772
+ _scheduleTimer
773
+ .apply(undefined, [actualDelay], { result: { promise: true } })
774
774
  .then(() => {
775
775
  if (_timers.has(id)) {
776
776
  _timers.delete(id);
@@ -818,7 +818,8 @@ export function setInterval(callback, delay, ...args) {
818
818
  return; // Interval was cleared
819
819
  if (typeof _scheduleTimer !== "undefined" && actualDelay > 0) {
820
820
  // Use host timer for actual delays
821
- _scheduleTimer(actualDelay)
821
+ _scheduleTimer
822
+ .apply(undefined, [actualDelay], { result: { promise: true } })
822
823
  .then(() => {
823
824
  if (_intervals.has(id)) {
824
825
  try {
@@ -871,6 +872,25 @@ export const URLSearchParams = WhatwgURLSearchParams;
871
872
  export { TextEncoder, TextDecoder };
872
873
  // Buffer - use buffer package polyfill
873
874
  export const Buffer = BufferPolyfill;
875
+ // Patch internal V8 Buffer slice/write methods used by native-protocol libraries
876
+ // (ssh2, msgpack, protobuf, etc.). The polyfill supports these encodings through
877
+ // toString()/write() but doesn't expose the fast-path internal methods.
878
+ const bp = BufferPolyfill.prototype;
879
+ const sliceEncodings = ["utf8", "ascii", "latin1", "binary", "hex", "base64", "ucs2", "utf16le"];
880
+ for (const enc of sliceEncodings) {
881
+ const sliceKey = `${enc}Slice`;
882
+ if (typeof bp[sliceKey] !== "function") {
883
+ bp[sliceKey] = function (start, end) {
884
+ return this.toString(enc, start, end);
885
+ };
886
+ }
887
+ const writeKey = `${enc}Write`;
888
+ if (typeof bp[writeKey] !== "function") {
889
+ bp[writeKey] = function (str, offset, length) {
890
+ return this.write(str, offset, length, enc);
891
+ };
892
+ }
893
+ }
874
894
  function throwUnsupportedCryptoApi(api) {
875
895
  throw new Error(`crypto.${api} is not supported in sandbox`);
876
896
  }
@@ -890,7 +910,8 @@ export const cryptoPolyfill = {
890
910
  }
891
911
  const bytes = new Uint8Array(array.buffer, array.byteOffset, array.byteLength);
892
912
  try {
893
- const hostBytes = _cryptoRandomFill(bytes.byteLength);
913
+ const base64 = _cryptoRandomFill.applySync(undefined, [bytes.byteLength]);
914
+ const hostBytes = BufferPolyfill.from(base64, "base64");
894
915
  if (hostBytes.byteLength !== bytes.byteLength) {
895
916
  throw new Error("invalid host entropy size");
896
917
  }
@@ -906,7 +927,7 @@ export const cryptoPolyfill = {
906
927
  throwUnsupportedCryptoApi("randomUUID");
907
928
  }
908
929
  try {
909
- const uuid = _cryptoRandomUUID();
930
+ const uuid = _cryptoRandomUUID.applySync(undefined, []);
910
931
  if (typeof uuid !== "string") {
911
932
  throw new Error("invalid host uuid");
912
933
  }