-
Notifications
You must be signed in to change notification settings - Fork 27.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Currently we ship dev runtimes (with things like HMR logic) along with code for loading chunks. This separates them and allows us to include a minimal runtime for builds. Test Plan: `TURBOPACK=1 TURBOPACK_BUILD=1 pnpm build` on an app with a `middleware.ts` and verified it loads when started.
- Loading branch information
1 parent
74d2136
commit 3473b85
Showing
27 changed files
with
898 additions
and
590 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
6 changes: 3 additions & 3 deletions
6
turbopack/crates/turbopack-ecmascript-runtime/js/src/browser/dev/hmr-client/hmr-client.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
155 changes: 155 additions & 0 deletions
155
turbopack/crates/turbopack-ecmascript-runtime/js/src/browser/runtime/base/build-base.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
/// <reference path="./runtime-base.ts" /> | ||
|
||
const moduleCache: ModuleCache<BaseModule> = {}; | ||
|
||
/** | ||
* Gets or instantiates a runtime module. | ||
*/ | ||
// @ts-ignore | ||
// eslint-disable-next-line @typescript-eslint/no-unused-vars | ||
function getOrInstantiateRuntimeModule( | ||
moduleId: ModuleId, | ||
chunkPath: ChunkPath, | ||
): BaseModule { | ||
const module = moduleCache[moduleId]; | ||
if (module) { | ||
if (module.error) { | ||
throw module.error; | ||
} | ||
return module; | ||
} | ||
|
||
return instantiateModule(moduleId, { type: SourceType.Runtime, chunkPath }); | ||
} | ||
|
||
/** | ||
* Retrieves a module from the cache, or instantiate it if it is not cached. | ||
*/ | ||
// Used by the backend | ||
// @ts-ignore | ||
// eslint-disable-next-line @typescript-eslint/no-unused-vars | ||
const getOrInstantiateModuleFromParent: GetOrInstantiateModuleFromParent<BaseModule> = ( | ||
id, | ||
sourceModule | ||
) => { | ||
const module = moduleCache[id]; | ||
|
||
if (sourceModule.children.indexOf(id) === -1) { | ||
sourceModule.children.push(id); | ||
} | ||
|
||
if (module) { | ||
if (module.parents.indexOf(sourceModule.id) === -1) { | ||
module.parents.push(sourceModule.id); | ||
} | ||
|
||
return module; | ||
} | ||
|
||
return instantiateModule(id, { | ||
type: SourceType.Parent, | ||
parentId: sourceModule.id, | ||
}); | ||
}; | ||
|
||
function instantiateModule(id: ModuleId, source: SourceInfo): BaseModule { | ||
const moduleFactory = moduleFactories[id]; | ||
if (typeof moduleFactory !== "function") { | ||
// This can happen if modules incorrectly handle HMR disposes/updates, | ||
// e.g. when they keep a `setTimeout` around which still executes old code | ||
// and contains e.g. a `require("something")` call. | ||
let instantiationReason; | ||
switch (source.type) { | ||
case SourceType.Runtime: | ||
instantiationReason = `as a runtime entry of chunk ${source.chunkPath}`; | ||
break; | ||
case SourceType.Parent: | ||
instantiationReason = `because it was required from module ${source.parentId}`; | ||
break; | ||
case SourceType.Update: | ||
instantiationReason = "because of an HMR update"; | ||
break; | ||
default: | ||
invariant(source, (source) => `Unknown source type: ${source?.type}`); | ||
} | ||
throw new Error( | ||
`Module ${id} was instantiated ${instantiationReason}, but the module factory is not available. It might have been deleted in an HMR update.` | ||
); | ||
} | ||
|
||
let parents: ModuleId[]; | ||
switch (source.type) { | ||
case SourceType.Runtime: | ||
runtimeModules.add(id); | ||
parents = []; | ||
break; | ||
case SourceType.Parent: | ||
// No need to add this module as a child of the parent module here, this | ||
// has already been taken care of in `getOrInstantiateModuleFromParent`. | ||
parents = [source.parentId]; | ||
break; | ||
case SourceType.Update: | ||
parents = source.parents || []; | ||
break; | ||
default: | ||
invariant(source, (source) => `Unknown source type: ${source?.type}`); | ||
} | ||
|
||
const module: BaseModule = { | ||
exports: {}, | ||
error: undefined, | ||
loaded: false, | ||
id, | ||
parents, | ||
children: [], | ||
namespaceObject: undefined, | ||
}; | ||
|
||
moduleCache[id] = module; | ||
|
||
// NOTE(alexkirsz) This can fail when the module encounters a runtime error. | ||
try { | ||
const sourceInfo: SourceInfo = { type: SourceType.Parent, parentId: id }; | ||
|
||
const r = commonJsRequire.bind(null, module); | ||
moduleFactory.call( | ||
module.exports, | ||
{ | ||
a: asyncModule.bind(null, module), | ||
e: module.exports, | ||
r: commonJsRequire.bind(null, module), | ||
t: runtimeRequire, | ||
f: moduleContext, | ||
i: esmImport.bind(null, module), | ||
s: esmExport.bind(null, module, module.exports), | ||
j: dynamicExport.bind(null, module, module.exports), | ||
v: exportValue.bind(null, module), | ||
n: exportNamespace.bind(null, module), | ||
m: module, | ||
c: moduleCache, | ||
M: moduleFactories, | ||
l: loadChunk.bind(null, sourceInfo), | ||
w: loadWebAssembly.bind(null, sourceInfo), | ||
u: loadWebAssemblyModule.bind(null, sourceInfo), | ||
g: globalThis, | ||
P: resolveAbsolutePath, | ||
U: relativeURL, | ||
R: createResolvePathFromModule(r), | ||
b: getWorkerBlobURL, | ||
__dirname: typeof module.id === "string" ? module.id.replace(/(^|\/)\/+$/, "") : module.id | ||
} | ||
); | ||
} catch (error) { | ||
module.error = error as any; | ||
throw error; | ||
} | ||
|
||
module.loaded = true; | ||
if (module.namespaceObject && module.exports !== module.namespaceObject) { | ||
// in case of a circular dependency: cjs1 -> esm2 -> cjs1 | ||
interopEsm(module.exports, module.namespaceObject); | ||
} | ||
|
||
return module; | ||
} | ||
|
Oops, something went wrong.