@@ -35,6 +35,14 @@ const renderResult = {
3535 data : JSON . stringify ( { html : 'Dummy Object' } ) ,
3636} ;
3737
38+ const renderResultFromBothBundles = {
39+ status : 200 ,
40+ headers : { 'Cache-Control' : 'public, max-age=31536000' } ,
41+ data : JSON . stringify ( {
42+ mainBundleResult : { html : 'Dummy Object' } ,
43+ secondaryBundleResult : { html : 'Dummy Object from secondary bundle' } ,
44+ } ) ,
45+ } ;
3846describe ( testName , ( ) => {
3947 beforeEach ( async ( ) => {
4048 await resetForTest ( testName ) ;
@@ -224,4 +232,82 @@ describe(testName, () => {
224232
225233 expect ( result ) . toEqual ( renderResult ) ;
226234 } ) ;
235+
236+ test ( 'rendering request can call runOnOtherBundle' , async ( ) => {
237+ await createVmBundle ( testName ) ;
238+ await createSecondaryVmBundle ( testName ) ;
239+
240+ const renderingRequest = `
241+ runOnOtherBundle(${ SECONDARY_BUNDLE_TIMESTAMP } , 'ReactOnRails.dummy').then((secondaryBundleResult) => ({
242+ mainBundleResult: ReactOnRails.dummy,
243+ secondaryBundleResult: JSON.parse(secondaryBundleResult),
244+ }));
245+ ` ;
246+
247+ const result = await handleRenderRequest ( {
248+ renderingRequest,
249+ bundleTimestamp : BUNDLE_TIMESTAMP ,
250+ dependencyBundleTimestamps : [ SECONDARY_BUNDLE_TIMESTAMP ] ,
251+ } ) ;
252+
253+ expect ( result ) . toEqual ( renderResultFromBothBundles ) ;
254+ // Both bundles should be in the VM context
255+ expect (
256+ hasVMContextForBundle ( path . resolve ( __dirname , `./tmp/${ testName } /1495063024898/1495063024898.js` ) ) ,
257+ ) . toBeTruthy ( ) ;
258+ expect (
259+ hasVMContextForBundle ( path . resolve ( __dirname , `./tmp/${ testName } /1495063024899/1495063024899.js` ) ) ,
260+ ) . toBeTruthy ( ) ;
261+ } ) ;
262+
263+ test ( 'renderingRequest is globally accessible inside the VM' , async ( ) => {
264+ await createVmBundle ( testName ) ;
265+
266+ const renderingRequest = `
267+ renderingRequest;
268+ ` ;
269+
270+ const result = await handleRenderRequest ( {
271+ renderingRequest,
272+ bundleTimestamp : BUNDLE_TIMESTAMP ,
273+ } ) ;
274+
275+ expect ( result ) . toEqual ( {
276+ status : 200 ,
277+ headers : { 'Cache-Control' : 'public, max-age=31536000' } ,
278+ data : renderingRequest ,
279+ } ) ;
280+ } ) ;
281+
282+ // The renderingRequest variable is automatically reset after synchronous execution to prevent data leakage
283+ // between requests in the shared VM context. This means it will be undefined in any async callbacks.
284+ //
285+ // If you need to access renderingRequest in an async context, save it to a local variable first:
286+ //
287+ // const renderingRequest = `
288+ // const savedRequest = renderingRequest; // Save synchronously
289+ // Promise.resolve().then(() => {
290+ // return savedRequest; // Access async
291+ // });
292+ // `;
293+ test ( 'renderingRequest is reset after the sync execution (not accessible from async functions)' , async ( ) => {
294+ await createVmBundle ( testName ) ;
295+
296+ // Since renderingRequest is undefined in async callbacks, we return the string 'undefined'
297+ // to demonstrate this behavior (as undefined cannot be returned from the VM)
298+ const renderingRequest = `
299+ Promise.resolve().then(() => renderingRequest ?? 'undefined');
300+ ` ;
301+
302+ const result = await handleRenderRequest ( {
303+ renderingRequest,
304+ bundleTimestamp : BUNDLE_TIMESTAMP ,
305+ } ) ;
306+
307+ expect ( result ) . toEqual ( {
308+ status : 200 ,
309+ headers : { 'Cache-Control' : 'public, max-age=31536000' } ,
310+ data : JSON . stringify ( 'undefined' ) ,
311+ } ) ;
312+ } ) ;
227313} ) ;
0 commit comments