11import { getRuntimeExposeMutableGlobal } from "../common/global-exposure" ;
2- import { setGlobalValue } from "../common/global-access" ;
32
43const __runtimeExposeMutableGlobal = getRuntimeExposeMutableGlobal ( ) ;
54
@@ -9,15 +8,12 @@ const __initialCwd =
98 typeof __bridgeSetupConfig . initialCwd === "string"
109 ? __bridgeSetupConfig . initialCwd
1110 : "/" ;
12-
13- // Set payload limit defaults on globalThis — read at call time by v8.deserialize,
14- // overridable via __runtimeApplyConfig for context snapshot restore
15- globalThis . __runtimeJsonPayloadLimitBytes =
11+ const __jsonPayloadLimitBytes =
1612 typeof __bridgeSetupConfig . jsonPayloadLimitBytes === "number" &&
1713 Number . isFinite ( __bridgeSetupConfig . jsonPayloadLimitBytes )
1814 ? Math . max ( 0 , Math . floor ( __bridgeSetupConfig . jsonPayloadLimitBytes ) )
1915 : 4 * 1024 * 1024 ;
20- globalThis . __runtimePayloadLimitErrorCode =
16+ const __payloadLimitErrorCode =
2117 typeof __bridgeSetupConfig . payloadLimitErrorCode === "string" &&
2218 __bridgeSetupConfig . payloadLimitErrorCode . length > 0
2319 ? __bridgeSetupConfig . payloadLimitErrorCode
@@ -241,15 +237,12 @@ if (__moduleCache) {
241237 ) ;
242238 } ,
243239 deserialize : function ( buffer : Buffer ) {
244- // Read limits from globals at call time (not captured at setup) for snapshot compatibility
245- const limit = globalThis . __runtimeJsonPayloadLimitBytes ?? 4 * 1024 * 1024 ;
246- const errorCode = globalThis . __runtimePayloadLimitErrorCode ?? "ERR_SANDBOX_PAYLOAD_TOO_LARGE" ;
247240 // Check raw buffer size BEFORE allocating the decoded string
248- if ( buffer . length > limit ) {
241+ if ( buffer . length > __jsonPayloadLimitBytes ) {
249242 throw new Error (
250- errorCode +
243+ __payloadLimitErrorCode +
251244 ": v8.deserialize exceeds " +
252- String ( limit ) +
245+ String ( __jsonPayloadLimitBytes ) +
253246 " bytes" ,
254247 ) ;
255248 }
@@ -276,176 +269,3 @@ if (__moduleCache) {
276269
277270__runtimeExposeMutableGlobal ( "_pendingModules" , { } ) ;
278271__runtimeExposeMutableGlobal ( "_currentModule" , { dirname : __initialCwd } ) ;
279-
280- // Post-restore config application — called after bridge IIFE to apply
281- // per-session config (timing mitigation, payload limits). Enables context
282- // snapshot reuse: the IIFE runs once at snapshot creation, this function
283- // applies session-specific config after restore.
284- globalThis . __runtimeApplyConfig = function ( config : {
285- timingMitigation ?: string ;
286- frozenTimeMs ?: number ;
287- payloadLimitBytes ?: number ;
288- payloadLimitErrorCode ?: string ;
289- } ) {
290- // Apply payload limits
291- if (
292- typeof config . payloadLimitBytes === "number" &&
293- Number . isFinite ( config . payloadLimitBytes )
294- ) {
295- globalThis . __runtimeJsonPayloadLimitBytes = Math . max (
296- 0 ,
297- Math . floor ( config . payloadLimitBytes ) ,
298- ) ;
299- }
300- if (
301- typeof config . payloadLimitErrorCode === "string" &&
302- config . payloadLimitErrorCode . length > 0
303- ) {
304- globalThis . __runtimePayloadLimitErrorCode =
305- config . payloadLimitErrorCode ;
306- }
307-
308- // Apply timing mitigation freeze
309- if ( config . timingMitigation === "freeze" ) {
310- const frozenTimeMs =
311- typeof config . frozenTimeMs === "number" &&
312- Number . isFinite ( config . frozenTimeMs )
313- ? config . frozenTimeMs
314- : Date . now ( ) ;
315- const frozenDateNow = ( ) => frozenTimeMs ;
316-
317- // Freeze Date.now
318- try {
319- Object . defineProperty ( Date , "now" , {
320- value : frozenDateNow ,
321- configurable : false ,
322- writable : false ,
323- } ) ;
324- } catch {
325- Date . now = frozenDateNow ;
326- }
327-
328- // Patch Date constructor so new Date().getTime() returns degraded time
329- const OrigDate = Date ;
330- const FrozenDate = function Date (
331- this : InstanceType < DateConstructor > ,
332- ...args : unknown [ ]
333- ) {
334- if ( new . target ) {
335- if ( args . length === 0 ) {
336- return new OrigDate ( frozenTimeMs ) ;
337- }
338- // @ts -expect-error — spread forwarding to variadic Date constructor
339- return new OrigDate ( ...args ) ;
340- }
341- return OrigDate ( ) ;
342- } as unknown as DateConstructor ;
343- Object . defineProperty ( FrozenDate , "prototype" , {
344- value : OrigDate . prototype ,
345- writable : false ,
346- configurable : false ,
347- } ) ;
348- FrozenDate . now = frozenDateNow ;
349- FrozenDate . parse = OrigDate . parse ;
350- FrozenDate . UTC = OrigDate . UTC ;
351- Object . defineProperty ( FrozenDate , "now" , {
352- value : frozenDateNow ,
353- configurable : false ,
354- writable : false ,
355- } ) ;
356- try {
357- Object . defineProperty ( globalThis , "Date" , {
358- value : FrozenDate ,
359- configurable : false ,
360- writable : false ,
361- } ) ;
362- } catch {
363- ( globalThis as Record < string , unknown > ) . Date = FrozenDate ;
364- }
365-
366- // Freeze performance.now
367- const frozenPerformanceNow = ( ) => 0 ;
368- const origPerf = globalThis . performance ;
369- const frozenPerf = Object . create ( null ) as Record < string , unknown > ;
370- if ( typeof origPerf !== "undefined" && origPerf !== null ) {
371- const src = origPerf as unknown as Record < string , unknown > ;
372- for ( const key of Object . getOwnPropertyNames (
373- Object . getPrototypeOf ( origPerf ) ?? origPerf ,
374- ) ) {
375- if ( key !== "now" ) {
376- try {
377- const val = src [ key ] ;
378- if ( typeof val === "function" ) {
379- frozenPerf [ key ] = val . bind ( origPerf ) ;
380- } else {
381- frozenPerf [ key ] = val ;
382- }
383- } catch {
384- /* skip inaccessible properties */
385- }
386- }
387- }
388- }
389- Object . defineProperty ( frozenPerf , "now" , {
390- value : frozenPerformanceNow ,
391- configurable : false ,
392- writable : false ,
393- } ) ;
394- Object . freeze ( frozenPerf ) ;
395- try {
396- Object . defineProperty ( globalThis , "performance" , {
397- value : frozenPerf ,
398- configurable : false ,
399- writable : false ,
400- } ) ;
401- } catch {
402- ( globalThis as Record < string , unknown > ) . performance = frozenPerf ;
403- }
404-
405- // Harden SharedArrayBuffer removal
406- const OrigSAB = globalThis . SharedArrayBuffer ;
407- if ( typeof OrigSAB === "function" ) {
408- try {
409- const proto = OrigSAB . prototype ;
410- if ( proto ) {
411- for ( const key of [
412- "byteLength" ,
413- "slice" ,
414- "grow" ,
415- "maxByteLength" ,
416- "growable" ,
417- ] ) {
418- try {
419- Object . defineProperty ( proto , key , {
420- get ( ) {
421- throw new TypeError (
422- "SharedArrayBuffer is not available in sandbox" ,
423- ) ;
424- } ,
425- configurable : false ,
426- } ) ;
427- } catch {
428- /* property may not exist or be non-configurable */
429- }
430- }
431- }
432- } catch {
433- /* best-effort prototype neutering */
434- }
435- }
436- try {
437- Object . defineProperty ( globalThis , "SharedArrayBuffer" , {
438- value : undefined ,
439- configurable : false ,
440- writable : false ,
441- enumerable : false ,
442- } ) ;
443- } catch {
444- Reflect . deleteProperty ( globalThis , "SharedArrayBuffer" ) ;
445- setGlobalValue ( "SharedArrayBuffer" , undefined ) ;
446- }
447- }
448-
449- // Clean up — one-shot function
450- delete globalThis . __runtimeApplyConfig ;
451- } ;
0 commit comments