Skip to content

Commit

Permalink
handle error case of dynamic import/require
Browse files Browse the repository at this point in the history
  • Loading branch information
sokra committed Feb 6, 2024
1 parent 058769b commit db59a1a
Show file tree
Hide file tree
Showing 7 changed files with 60 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ function instantiateModule(id: ModuleId, source: SourceInfo): Module {
i: esmImport.bind(null, module),
s: esmExport.bind(null, module, module.exports),
j: dynamicExport.bind(null, module, module.exports),
p: moduleLookup,
v: exportValue.bind(null, module),
n: exportNamespace.bind(null, module),
m: module,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,7 @@ function instantiateModule(id: ModuleId, source: SourceInfo): Module {
i: esmImport.bind(null, module),
s: esmExport.bind(null, module, module.exports),
j: dynamicExport.bind(null, module, module.exports),
p: moduleLookup,
v: exportValue.bind(null, module),
n: exportNamespace.bind(null, module),
m: module,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ type EsmExport = (exportGetters: Record<string, () => any>) => void;
type ExportValue = (value: any) => void;
type ExportNamespace = (namespace: any) => void;
type DynamicExport = (object: Record<string, any>) => void;
type ModuleLookup = (
object: Record<string, any>,
name: string,
flags?: number
) => any;

type LoadChunk = (chunkPath: ChunkPath) => Promise<any> | undefined;
type LoadWebAssembly = (
Expand Down Expand Up @@ -61,6 +66,7 @@ interface TurbopackBaseContext {
i: EsmImport;
s: EsmExport;
j: DynamicExport;
p: ModuleLookup;
v: ExportValue;
n: ExportNamespace;
m: Module;
Expand Down
24 changes: 24 additions & 0 deletions crates/turbopack-ecmascript-runtime/js/src/shared/runtime-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,30 @@ function dynamicExport(
}
}

/**
* Access one entry from a mapping from name to functor.
* flags:
* * 1: Error as rejected promise
*/
function moduleLookup(
map: Record<string, () => any>,
name: string,
flags: number = 0
) {
if (hasOwnProperty.call(map, name)) {
return map[name]();
}
const e = new Error(`Cannot find module '${name}'`);
(e as any).code = "MODULE_NOT_FOUND";
if (flags & 1) {
return Promise.resolve().then(() => {
throw e;
});
} else {
throw e;
}
}

function exportValue(module: Module, value: any) {
module.exports = value;
}
Expand Down
1 change: 1 addition & 0 deletions crates/turbopack-ecmascript/src/chunk/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ impl EcmascriptChunkItemContent {
"M: __turbopack_modules__",
"l: __turbopack_load__",
"j: __turbopack_dynamic__",
"p: __turbopack_lookup__",
"p: __turbopack_resolve_absolute_path__",
"U: __turbopack_relative_url__",
"R: __turbopack_resolve_module_id_path__",
Expand Down
44 changes: 20 additions & 24 deletions crates/turbopack-ecmascript/src/references/pattern_mapping.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ use serde::{Deserialize, Serialize};
use swc_core::{
common::DUMMY_SP,
ecma::ast::{
CallExpr, Callee, ComputedPropName, Expr, ExprOrSpread, KeyValueProp, Lit, MemberExpr,
MemberProp, ObjectLit, Prop, PropName, PropOrSpread,
CallExpr, Callee, Expr, ExprOrSpread, KeyValueProp, Lit, ObjectLit, Prop, PropName,
PropOrSpread,
},
quote, quote_expr,
};
Expand Down Expand Up @@ -211,52 +211,48 @@ impl PatternMapping {
pub fn create_require(&self, key_expr: Expr) -> Expr {
match self {
PatternMapping::Single(pm) => pm.create_require(Cow::Owned(key_expr)),
PatternMapping::Map(map) => Expr::Member(MemberExpr {
obj: Box::new(Expr::Object(ObjectLit {
PatternMapping::Map(map) => {
let map = Expr::Object(ObjectLit {
span: DUMMY_SP,
props: map
.iter()
.map(|(k, v)| {
PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp {
key: PropName::Str(k.as_str().into()),
value: Box::new(v.create_require(Cow::Borrowed(&key_expr))),
value: quote_expr!("() => $expr", expr: Expr = v.create_require(Cow::Borrowed(&key_expr))),
})))
})
.collect(),
})),
prop: MemberProp::Computed(ComputedPropName {
span: DUMMY_SP,
expr: Box::new(key_expr),
}),
span: DUMMY_SP,
}),
});
quote!("__turbopack_lookup__($map, $key)" as Expr,
map: Expr = map,
key: Expr = key_expr
)
}
}
}

pub fn create_import(&self, key_expr: Expr, import_externals: bool) -> Expr {
match self {
PatternMapping::Single(pm) => pm.create_import(Cow::Owned(key_expr), import_externals),
PatternMapping::Map(map) => Expr::Member(MemberExpr {
obj: Box::new(Expr::Object(ObjectLit {
PatternMapping::Map(map) => {
let map = Expr::Object(ObjectLit {
span: DUMMY_SP,
props: map
.iter()
.map(|(k, v)| {
PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp {
key: PropName::Str(k.as_str().into()),
value: Box::new(
v.create_import(Cow::Borrowed(&key_expr), import_externals),
),
value: quote_expr!("() => $expr", expr: Expr = v.create_import(Cow::Borrowed(&key_expr), import_externals)),
})))
})
.collect(),
})),
prop: MemberProp::Computed(ComputedPropName {
span: DUMMY_SP,
expr: Box::new(key_expr),
}),
span: DUMMY_SP,
}),
});
quote!("__turbopack_lookup__($map, $key, 1)" as Expr,
map: Expr = map,
key: Expr = key_expr
)
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,10 @@ it("should support dynamic requests in import with concatenation and suffix", as
await expect(importConcatSuffix("a")).resolves.toBe(a);
await expect(importConcatSuffix("d")).resolves.toHaveProperty("default", "d");
});

it("should throw an error when requesting a non-existent file", async () => {
expect(() => requireTemplate("e.js")).toThrowError();
expect(() => requireConcat("e.js")).toThrowError();
await expect(importTemplate("e.js")).rejects.toThrowError();
await expect(importConcat("e.js")).rejects.toThrowError();
});

0 comments on commit db59a1a

Please sign in to comment.