diff --git a/js/lib.web_assembly.d.ts b/js/lib.web_assembly.d.ts index 1ec6a7943a..e69c4c629b 100644 --- a/js/lib.web_assembly.d.ts +++ b/js/lib.web_assembly.d.ts @@ -165,4 +165,5 @@ declare namespace WebAssembly { // TODO Move ImportMeta intos its own lib.import_meta.d.ts file? interface ImportMeta { url: string; + main: boolean; } diff --git a/libdeno/binding.cc b/libdeno/binding.cc index f7ee977e8e..f640fe83c6 100644 --- a/libdeno/binding.cc +++ b/libdeno/binding.cc @@ -265,7 +265,8 @@ v8::ScriptOrigin ModuleOrigin(v8::Isolate* isolate, v8::True(isolate)); } -deno_mod DenoIsolate::RegisterModule(const char* name, const char* source) { +deno_mod DenoIsolate::RegisterModule(bool main, const char* name, + const char* source) { v8::Isolate::Scope isolate_scope(isolate_); v8::Locker locker(isolate_); v8::HandleScope handle_scope(isolate_); @@ -300,8 +301,9 @@ deno_mod DenoIsolate::RegisterModule(const char* name, const char* source) { import_specifiers.push_back(*specifier_utf8); } - mods_.emplace(std::piecewise_construct, std::make_tuple(id), - std::make_tuple(isolate_, module, name, import_specifiers)); + mods_.emplace( + std::piecewise_construct, std::make_tuple(id), + std::make_tuple(isolate_, module, main, name, import_specifiers)); mods_by_name_[name] = id; return id; @@ -519,8 +521,10 @@ void HostInitializeImportMetaObjectCallback(v8::Local context, auto* info = d->GetModuleInfo(id); const char* url = info->name.c_str(); + const bool main = info->main; meta->CreateDataProperty(context, v8_str("url"), v8_str(url)).ToChecked(); + meta->CreateDataProperty(context, v8_str("main"), v8_bool(main)).ToChecked(); } void DenoIsolate::AddIsolate(v8::Isolate* isolate) { diff --git a/libdeno/deno.h b/libdeno/deno.h index e48dd8cbe1..6be0b56256 100644 --- a/libdeno/deno.h +++ b/libdeno/deno.h @@ -83,7 +83,7 @@ void deno_terminate_execution(Deno* d); typedef int deno_mod; // Returns zero on error - check deno_last_exception(). -deno_mod deno_mod_new(Deno* d, const char* name, const char* source); +deno_mod deno_mod_new(Deno* d, bool main, const char* name, const char* source); size_t deno_mod_imports_len(Deno* d, deno_mod id); diff --git a/libdeno/internal.h b/libdeno/internal.h index a87ec0fdce..7209664079 100644 --- a/libdeno/internal.h +++ b/libdeno/internal.h @@ -13,13 +13,14 @@ namespace deno { struct ModuleInfo { + bool main; std::string name; v8::Persistent handle; std::vector import_specifiers; - ModuleInfo(v8::Isolate* isolate, v8::Local module, + ModuleInfo(v8::Isolate* isolate, v8::Local module, bool main_, const char* name_, std::vector import_specifiers_) - : name(name_), import_specifiers(import_specifiers_) { + : main(main_), name(name_), import_specifiers(import_specifiers_) { handle.Reset(isolate, module); } }; @@ -61,7 +62,7 @@ class DenoIsolate { void AddIsolate(v8::Isolate* isolate); - deno_mod RegisterModule(const char* name, const char* source); + deno_mod RegisterModule(bool main, const char* name, const char* source); v8::Local GetBuiltinModules(); void ClearModules(); diff --git a/libdeno/modules.cc b/libdeno/modules.cc index ca2928e046..d8b2f48d15 100644 --- a/libdeno/modules.cc +++ b/libdeno/modules.cc @@ -88,7 +88,7 @@ v8::MaybeLocal ResolveCallback(Local context, id = it->second; } else { std::string src = BuiltinModuleSrc(context, specifier); - id = d->RegisterModule(req_str.c_str(), src.c_str()); + id = d->RegisterModule(false, req_str.c_str(), src.c_str()); } } else { id = d->resolve_cb_(d->user_data_, req_str.c_str(), referrer_id); @@ -116,10 +116,10 @@ v8::MaybeLocal ResolveCallback(Local context, extern "C" { -deno_mod deno_mod_new(Deno* d_, const char* name_cstr, +deno_mod deno_mod_new(Deno* d_, bool main, const char* name_cstr, const char* source_cstr) { auto* d = unwrap(d_); - return d->RegisterModule(name_cstr, source_cstr); + return d->RegisterModule(main, name_cstr, source_cstr); } const char* deno_mod_name(Deno* d_, deno_mod id) { diff --git a/libdeno/modules_test.cc b/libdeno/modules_test.cc index f637ae0707..d41c38b8e9 100644 --- a/libdeno/modules_test.cc +++ b/libdeno/modules_test.cc @@ -14,7 +14,7 @@ TEST(ModulesTest, Resolution) { Deno* d = deno_new(deno_config{0, empty, empty, recv_cb}); EXPECT_EQ(0, exec_count); - static deno_mod a = deno_mod_new(d, "a.js", + static deno_mod a = deno_mod_new(d, true, "a.js", "import { b } from 'b.js'\n" "if (b() != 'b') throw Error();\n" "libdeno.send(new Uint8Array([4]));"); @@ -22,7 +22,7 @@ TEST(ModulesTest, Resolution) { EXPECT_EQ(nullptr, deno_last_exception(d)); const char* b_src = "export function b() { return 'b' }"; - static deno_mod b = deno_mod_new(d, "b.js", b_src); + static deno_mod b = deno_mod_new(d, false, "b.js", b_src); EXPECT_NE(b, 0); EXPECT_EQ(nullptr, deno_last_exception(d)); @@ -72,7 +72,7 @@ TEST(ModulesTest, BuiltinModules) { EXPECT_EQ(nullptr, deno_last_exception(d)); static deno_mod a = - deno_mod_new(d, "a.js", + deno_mod_new(d, true, "a.js", "import { b } from 'b.js'\n" "import * as deno from 'deno'\n" "if (b() != 'b') throw Error('b');\n" @@ -82,7 +82,7 @@ TEST(ModulesTest, BuiltinModules) { EXPECT_EQ(nullptr, deno_last_exception(d)); const char* b_src = "export function b() { return 'b' }"; - static deno_mod b = deno_mod_new(d, "b.js", b_src); + static deno_mod b = deno_mod_new(d, false, "b.js", b_src); EXPECT_NE(b, 0); EXPECT_EQ(nullptr, deno_last_exception(d)); @@ -134,7 +134,7 @@ TEST(ModulesTest, BuiltinModules2) { EXPECT_EQ(nullptr, deno_last_exception(d)); static deno_mod a = - deno_mod_new(d, "a.js", + deno_mod_new(d, true, "a.js", "import * as b1 from 'builtin1'\n" "import * as b2 from 'builtin2'\n" "if (b1.foo != 'bar') throw Error('bad1');\n" @@ -168,7 +168,7 @@ TEST(ModulesTest, BuiltinModules3) { EXPECT_EQ(nullptr, deno_last_exception(d)); static deno_mod a = - deno_mod_new(d, "a.js", + deno_mod_new(d, true, "a.js", "import * as b1 from 'builtin'\n" "import * as b2 from 'b.js'\n" "if (b1.foo != 'bar') throw Error('bad1');\n" @@ -181,7 +181,7 @@ TEST(ModulesTest, BuiltinModules3) { EXPECT_STREQ("builtin", deno_mod_imports_get(d, a, 0)); EXPECT_STREQ("b.js", deno_mod_imports_get(d, a, 1)); - static deno_mod b = deno_mod_new(d, "b.js", + static deno_mod b = deno_mod_new(d, false, "b.js", "import { foo } from 'builtin';\n" "export function bar() { return foo }\n"); EXPECT_NE(b, 0); @@ -218,7 +218,7 @@ TEST(ModulesTest, ResolutionError) { Deno* d = deno_new(deno_config{0, empty, empty, recv_cb}); EXPECT_EQ(0, exec_count); - static deno_mod a = deno_mod_new(d, "a.js", + static deno_mod a = deno_mod_new(d, true, "a.js", "import 'bad'\n" "libdeno.send(new Uint8Array([4]));"); EXPECT_NE(a, 0); @@ -252,7 +252,7 @@ TEST(ModulesTest, ImportMetaUrl) { EXPECT_EQ(0, exec_count); static deno_mod a = - deno_mod_new(d, "a.js", + deno_mod_new(d, true, "a.js", "if ('a.js' != import.meta.url) throw 'hmm'\n" "libdeno.send(new Uint8Array([4]));"); EXPECT_NE(a, 0); @@ -266,3 +266,32 @@ TEST(ModulesTest, ImportMetaUrl) { EXPECT_EQ(nullptr, deno_last_exception(d)); EXPECT_EQ(1, exec_count); } + +TEST(ModulesTest, ImportMetaMain) { + Deno* d = deno_new(deno_config{0, empty, empty, recv_cb}); + + const char* throw_not_main_src = "if (!import.meta.main) throw 'err'"; + static deno_mod throw_not_main = + deno_mod_new(d, true, "a.js", throw_not_main_src); + EXPECT_NE(throw_not_main, 0); + EXPECT_EQ(nullptr, deno_last_exception(d)); + + deno_mod_instantiate(d, d, throw_not_main, nullptr); + EXPECT_EQ(nullptr, deno_last_exception(d)); + + deno_mod_evaluate(d, d, throw_not_main); + EXPECT_EQ(nullptr, deno_last_exception(d)); + + const char* throw_main_src = "if (import.meta.main) throw 'err'"; + static deno_mod throw_main = deno_mod_new(d, false, "b.js", throw_main_src); + EXPECT_NE(throw_main, 0); + EXPECT_EQ(nullptr, deno_last_exception(d)); + + deno_mod_instantiate(d, d, throw_main, nullptr); + EXPECT_EQ(nullptr, deno_last_exception(d)); + + deno_mod_evaluate(d, d, throw_main); + EXPECT_EQ(nullptr, deno_last_exception(d)); + + deno_delete(d); +} diff --git a/src/isolate.rs b/src/isolate.rs index 63f45b5df5..b723738d71 100644 --- a/src/isolate.rs +++ b/src/isolate.rs @@ -283,6 +283,7 @@ impl Isolate { pub fn mod_new( &mut self, + main: bool, name: String, source: String, ) -> Result { @@ -293,7 +294,7 @@ impl Isolate { let source_ptr = source_.as_ptr() as *const c_char; let id = unsafe { - libdeno::deno_mod_new(self.libdeno_isolate, name_ptr, source_ptr) + libdeno::deno_mod_new(self.libdeno_isolate, main, name_ptr, source_ptr) }; if let Some(js_error) = self.last_exception() { assert_eq!(id, 0); @@ -345,7 +346,7 @@ impl Isolate { &referrer_name, )?; let child_id = - self.mod_new(out.module_name.clone(), out.js_source())?; + self.mod_new(false, out.module_name.clone(), out.js_source())?; self.mod_load_deps(child_id)?; } @@ -391,7 +392,7 @@ impl Isolate { .map_err(RustOrJsError::from)?; let id = self - .mod_new(out.module_name.clone(), out.js_source()) + .mod_new(true, out.module_name.clone(), out.js_source()) .map_err(RustOrJsError::from)?; self.mod_load_deps(id)?; diff --git a/src/libdeno.rs b/src/libdeno.rs index a3a711b651..204f817b5b 100644 --- a/src/libdeno.rs +++ b/src/libdeno.rs @@ -154,6 +154,7 @@ extern "C" { pub fn deno_mod_new( i: *const isolate, + main: bool, name: *const c_char, source: *const c_char, ) -> deno_mod; diff --git a/tests/import_meta.ts b/tests/import_meta.ts index 8f27120680..2f3bec9ed8 100644 --- a/tests/import_meta.ts +++ b/tests/import_meta.ts @@ -1,3 +1,3 @@ -console.log("import_meta", import.meta.url); +console.log("import_meta", import.meta.url, import.meta.main); import "import_meta2.ts"; diff --git a/tests/import_meta.ts.out b/tests/import_meta.ts.out index c43cea6fd6..f38aa98ea1 100644 --- a/tests/import_meta.ts.out +++ b/tests/import_meta.ts.out @@ -1,2 +1,2 @@ -import_meta2 [WILDCARD]import_meta2.ts -import_meta [WILDCARD]import_meta.ts +import_meta2 [WILDCARD]import_meta2.ts false +import_meta [WILDCARD]import_meta.ts true diff --git a/tests/import_meta2.ts b/tests/import_meta2.ts index b64265b5be..7f59a5a462 100644 --- a/tests/import_meta2.ts +++ b/tests/import_meta2.ts @@ -1 +1 @@ -console.log("import_meta2", import.meta.url); +console.log("import_meta2", import.meta.url, import.meta.main);