diff --git a/changes/scope-default-import.polish.md b/changes/scope-default-import.polish.md new file mode 100644 index 00000000000..0ecb1e43925 --- /dev/null +++ b/changes/scope-default-import.polish.md @@ -0,0 +1 @@ +- Import the default export, instead of the module namespace, for `@module` externals whose `@scope` starts with `"default"`. diff --git a/compiler/core/lam_compile_external_call.ml b/compiler/core/lam_compile_external_call.ml index d0449bd32c9..b2f01a8fc29 100644 --- a/compiler/core/lam_compile_external_call.ml +++ b/compiler/core/lam_compile_external_call.ml @@ -223,8 +223,9 @@ let translate_scoped_module_val E.external_var_field ?import_attributes ~external_name:bundle ~field:fn ~default id | x :: rest -> - (* TODO: what happens when scope contains "default" ?*) - let default = false in + (* A leading "default" scope is the module's default export: import + it as such, like [external x: t = "default"] *) + let default = x = "default" in let id = Lam_compile_env.add_js_module ?import_attributes module_bind_name bundle default ~dynamic_import:false diff --git a/tests/commonjs_tests/src/scope_default_import.js b/tests/commonjs_tests/src/scope_default_import.js new file mode 100644 index 00000000000..890f7060a77 --- /dev/null +++ b/tests/commonjs_tests/src/scope_default_import.js @@ -0,0 +1,18 @@ +// Generated by ReScript, PLEASE EDIT WITH CARE +'use strict'; + +let Mod1 = require("mod1"); +let Mod1$1 = require("mod1").default; +let Mod2 = require("mod2").default; + +function f() { + Mod1$1.x.fn((Mod1$1.value + Mod1.other.other | 0) + Mod2.default | 0); +} + +function g() { + return new (Mod1$1.Klass)(); +} + +exports.f = f; +exports.g = g; +/* mod1 Not a pure module */ diff --git a/tests/commonjs_tests/src/scope_default_import.res b/tests/commonjs_tests/src/scope_default_import.res new file mode 100644 index 00000000000..43de8427618 --- /dev/null +++ b/tests/commonjs_tests/src/scope_default_import.res @@ -0,0 +1,11 @@ +// A leading "default" scope imports the module's default export + +@module("mod1") @scope(("default", "x")) external fn: int => unit = "fn" +@module("mod1") @scope("default") external value: int = "value" +@module("mod1") @new @scope("default") external make: unit => {"a": int} = "Klass" +@module("mod1") @scope("other") external other: int = "other" + +@module("mod2") @scope("default") external defaultOfDefault: int = "default" + +let f = () => fn(value + other + defaultOfDefault) +let g = () => make() diff --git a/tests/tests/src/scope_default_import.mjs b/tests/tests/src/scope_default_import.mjs new file mode 100644 index 00000000000..593b7936410 --- /dev/null +++ b/tests/tests/src/scope_default_import.mjs @@ -0,0 +1,19 @@ +// Generated by ReScript, PLEASE EDIT WITH CARE + +import * as Mod1 from "mod1"; +import Mod1$1 from "mod1"; +import Mod2 from "mod2"; + +function f() { + Mod1$1.x.fn((Mod1$1.value + Mod1.other.other | 0) + Mod2.default | 0); +} + +function g() { + return new (Mod1$1.Klass)(); +} + +export { + f, + g, +} +/* mod1 Not a pure module */ diff --git a/tests/tests/src/scope_default_import.res b/tests/tests/src/scope_default_import.res new file mode 100644 index 00000000000..43de8427618 --- /dev/null +++ b/tests/tests/src/scope_default_import.res @@ -0,0 +1,11 @@ +// A leading "default" scope imports the module's default export + +@module("mod1") @scope(("default", "x")) external fn: int => unit = "fn" +@module("mod1") @scope("default") external value: int = "value" +@module("mod1") @new @scope("default") external make: unit => {"a": int} = "Klass" +@module("mod1") @scope("other") external other: int = "other" + +@module("mod2") @scope("default") external defaultOfDefault: int = "default" + +let f = () => fn(value + other + defaultOfDefault) +let g = () => make()