Skip to content

Commit 638b12d

Browse files
committed
Fix memory leak in react-static packager
1 parent 67e4fe0 commit 638b12d

File tree

1 file changed

+36
-13
lines changed

1 file changed

+36
-13
lines changed

packages/packagers/react-static/src/ReactStaticPackager.js

Lines changed: 36 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,15 @@ let serverResolver: ResolverBase;
4444
let packagingBundles = new Map<NamedBundle, Async<{|contents: Blob|}>>();
4545
let moduleCache = new Map<string, ParcelModule>();
4646
let loadedBundles = new Map<NamedBundle, any>();
47+
let context: any = vm.createContext();
4748

4849
export default (new Packager({
4950
async loadConfig({options, config}) {
5051
config.invalidateOnBuild();
5152
packagingBundles.clear();
5253
moduleCache.clear();
5354
loadedBundles.clear();
55+
context = createContext(options);
5456
clientResolver = new ResolverBase(options.projectRoot, {
5557
mode: 2,
5658
packageExports: true,
@@ -76,28 +78,17 @@ export default (new Packager({
7678
parcelRequireName: 'parcelRequire' + hashString(name).slice(-4),
7779
};
7880
},
79-
async package({
80-
bundle,
81-
bundleGraph,
82-
getInlineBundleContents,
83-
config,
84-
options,
85-
}) {
81+
async package({bundle, bundleGraph, getInlineBundleContents, config}) {
8682
if (bundle.env.shouldScopeHoist) {
8783
throw new Error('Scope hoisting is not supported with SSG');
8884
}
8985

90-
// $FlowFixMe
91-
globalThis.AsyncLocalStorage ??= AsyncLocalStorage;
92-
9386
let {load, loadModule} = await loadBundle(
9487
bundle,
9588
bundleGraph,
9689
getInlineBundleContents,
9790
);
9891

99-
let env = process.env.NODE_ENV;
100-
process.env.NODE_ENV = options.env.NODE_ENV;
10192
let Component = load(nullthrows(bundle.getMainEntry()).id).default;
10293
let {renderToReadableStream} = loadModule(
10394
'react-server-dom-parcel/server.edge',
@@ -115,7 +106,6 @@ export default (new Packager({
115106
__filename,
116107
'react-client',
117108
);
118-
process.env.NODE_ENV = env;
119109
let {injectRSCPayload} = await import('rsc-html-stream/server');
120110

121111
let pages: Page[] = [];
@@ -474,6 +464,38 @@ async function loadBundleUncached(
474464
return {load: loadAsset, loadModule, assets};
475465
}
476466

467+
function createContext(options) {
468+
// Create a fresh global context to execute code in on each build to avoid memory leaks.
469+
// $FlowFixMe
470+
let context: any = vm.createContext(vm.constants.DONT_CONTEXTIFY);
471+
context.global = context;
472+
context.AsyncLocalStorage = AsyncLocalStorage;
473+
context.process = new Proxy(process, {
474+
get(target, prop, receiver) {
475+
// Expose the provided environment variables from Parcel instead of the global ones.
476+
if (prop === 'env') {
477+
return options.env;
478+
}
479+
480+
return Reflect.get(target, prop, receiver);
481+
},
482+
});
483+
484+
// $FlowFixMe
485+
for (let key of Object.getOwnPropertyNames(globalThis)) {
486+
if (!context.hasOwnProperty(key)) {
487+
Object.defineProperty(
488+
context,
489+
key,
490+
// $FlowFixMe
491+
Object.getOwnPropertyDescriptor(globalThis, key),
492+
);
493+
}
494+
}
495+
496+
return context;
497+
}
498+
477499
function runModule(
478500
code: string,
479501
filename: string,
@@ -493,6 +515,7 @@ function runModule(
493515
],
494516
{
495517
filename,
518+
parsingContext: context,
496519
},
497520
);
498521

0 commit comments

Comments
 (0)