2019-04-28 15:31:10 -04:00
|
|
|
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
|
2019-01-30 17:21:31 -05:00
|
|
|
#include "test.h"
|
|
|
|
|
|
|
|
static int exec_count = 0;
|
2019-04-28 15:31:10 -04:00
|
|
|
void recv_cb(void* user_data, deno_buf buf, deno_pinned_buf zero_copy_buf) {
|
2019-01-30 17:21:31 -05:00
|
|
|
// We use this to check that scripts have executed.
|
|
|
|
EXPECT_EQ(1u, buf.data_len);
|
|
|
|
EXPECT_EQ(buf.data_ptr[0], 4);
|
2019-02-26 17:36:05 -05:00
|
|
|
EXPECT_EQ(zero_copy_buf.data_ptr, nullptr);
|
2019-04-28 15:31:10 -04:00
|
|
|
EXPECT_EQ(zero_copy_buf.data_len, 0u);
|
|
|
|
EXPECT_EQ(zero_copy_buf.pin, nullptr);
|
2019-01-30 17:21:31 -05:00
|
|
|
exec_count++;
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(ModulesTest, Resolution) {
|
|
|
|
exec_count = 0; // Reset
|
2019-06-06 19:07:47 -04:00
|
|
|
Deno* d = deno_new(deno_config{0, empty_snapshot, empty, recv_cb, nullptr});
|
2019-01-30 17:21:31 -05:00
|
|
|
EXPECT_EQ(0, exec_count);
|
|
|
|
|
2019-02-26 13:29:45 -05:00
|
|
|
static deno_mod a = deno_mod_new(d, true, "a.js",
|
2019-01-30 17:21:31 -05:00
|
|
|
"import { b } from 'b.js'\n"
|
|
|
|
"if (b() != 'b') throw Error();\n"
|
2019-03-26 08:22:07 -04:00
|
|
|
"Deno.core.send(new Uint8Array([4]));");
|
2019-01-30 17:21:31 -05:00
|
|
|
EXPECT_NE(a, 0);
|
|
|
|
EXPECT_EQ(nullptr, deno_last_exception(d));
|
|
|
|
|
|
|
|
const char* b_src = "export function b() { return 'b' }";
|
2019-02-26 13:29:45 -05:00
|
|
|
static deno_mod b = deno_mod_new(d, false, "b.js", b_src);
|
2019-01-30 17:21:31 -05:00
|
|
|
EXPECT_NE(b, 0);
|
|
|
|
EXPECT_EQ(nullptr, deno_last_exception(d));
|
|
|
|
|
|
|
|
EXPECT_EQ(0, exec_count);
|
|
|
|
|
|
|
|
EXPECT_EQ(1u, deno_mod_imports_len(d, a));
|
|
|
|
EXPECT_EQ(0u, deno_mod_imports_len(d, b));
|
|
|
|
|
|
|
|
EXPECT_STREQ("b.js", deno_mod_imports_get(d, a, 0));
|
|
|
|
EXPECT_EQ(nullptr, deno_mod_imports_get(d, a, 1));
|
|
|
|
EXPECT_EQ(nullptr, deno_mod_imports_get(d, b, 0));
|
|
|
|
|
|
|
|
static int resolve_count = 0;
|
|
|
|
auto resolve_cb = [](void* user_data, const char* specifier,
|
|
|
|
deno_mod referrer) {
|
|
|
|
EXPECT_EQ(referrer, a);
|
|
|
|
EXPECT_STREQ(specifier, "b.js");
|
|
|
|
resolve_count++;
|
|
|
|
return b;
|
|
|
|
};
|
|
|
|
|
|
|
|
deno_mod_instantiate(d, d, b, resolve_cb);
|
|
|
|
EXPECT_EQ(nullptr, deno_last_exception(d));
|
|
|
|
EXPECT_EQ(0, resolve_count);
|
|
|
|
EXPECT_EQ(0, exec_count);
|
|
|
|
|
|
|
|
deno_mod_instantiate(d, d, a, resolve_cb);
|
|
|
|
EXPECT_EQ(nullptr, deno_last_exception(d));
|
|
|
|
EXPECT_EQ(1, resolve_count);
|
|
|
|
EXPECT_EQ(0, exec_count);
|
|
|
|
|
|
|
|
deno_mod_evaluate(d, d, a);
|
|
|
|
EXPECT_EQ(nullptr, deno_last_exception(d));
|
|
|
|
EXPECT_EQ(1, resolve_count);
|
|
|
|
EXPECT_EQ(1, exec_count);
|
|
|
|
|
|
|
|
deno_delete(d);
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(ModulesTest, ResolutionError) {
|
|
|
|
exec_count = 0; // Reset
|
2019-06-06 19:07:47 -04:00
|
|
|
Deno* d = deno_new(deno_config{0, empty_snapshot, empty, recv_cb, nullptr});
|
2019-01-30 17:21:31 -05:00
|
|
|
EXPECT_EQ(0, exec_count);
|
|
|
|
|
2019-02-26 13:29:45 -05:00
|
|
|
static deno_mod a = deno_mod_new(d, true, "a.js",
|
2019-01-30 17:21:31 -05:00
|
|
|
"import 'bad'\n"
|
2019-03-26 08:22:07 -04:00
|
|
|
"Deno.core.send(new Uint8Array([4]));");
|
2019-01-30 17:21:31 -05:00
|
|
|
EXPECT_NE(a, 0);
|
|
|
|
EXPECT_EQ(nullptr, deno_last_exception(d));
|
|
|
|
|
|
|
|
EXPECT_EQ(0, exec_count);
|
|
|
|
|
|
|
|
EXPECT_EQ(1u, deno_mod_imports_len(d, a));
|
|
|
|
EXPECT_STREQ("bad", deno_mod_imports_get(d, a, 0));
|
|
|
|
|
|
|
|
static int resolve_count = 0;
|
|
|
|
auto resolve_cb = [](void* user_data, const char* specifier,
|
|
|
|
deno_mod referrer) {
|
|
|
|
EXPECT_EQ(referrer, a);
|
|
|
|
EXPECT_STREQ(specifier, "bad");
|
|
|
|
resolve_count++;
|
|
|
|
return 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
deno_mod_instantiate(d, d, a, resolve_cb);
|
|
|
|
EXPECT_NE(nullptr, deno_last_exception(d));
|
|
|
|
EXPECT_EQ(1, resolve_count);
|
|
|
|
EXPECT_EQ(0, exec_count);
|
|
|
|
|
|
|
|
deno_delete(d);
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(ModulesTest, ImportMetaUrl) {
|
|
|
|
exec_count = 0; // Reset
|
2019-06-06 19:07:47 -04:00
|
|
|
Deno* d = deno_new(deno_config{0, empty_snapshot, empty, recv_cb, nullptr});
|
2019-01-30 17:21:31 -05:00
|
|
|
EXPECT_EQ(0, exec_count);
|
|
|
|
|
|
|
|
static deno_mod a =
|
2019-02-26 13:29:45 -05:00
|
|
|
deno_mod_new(d, true, "a.js",
|
2019-01-30 17:21:31 -05:00
|
|
|
"if ('a.js' != import.meta.url) throw 'hmm'\n"
|
2019-03-26 08:22:07 -04:00
|
|
|
"Deno.core.send(new Uint8Array([4]));");
|
2019-01-30 17:21:31 -05:00
|
|
|
EXPECT_NE(a, 0);
|
|
|
|
EXPECT_EQ(nullptr, deno_last_exception(d));
|
|
|
|
|
|
|
|
deno_mod_instantiate(d, d, a, nullptr);
|
|
|
|
EXPECT_EQ(nullptr, deno_last_exception(d));
|
|
|
|
EXPECT_EQ(0, exec_count);
|
|
|
|
|
|
|
|
deno_mod_evaluate(d, d, a);
|
|
|
|
EXPECT_EQ(nullptr, deno_last_exception(d));
|
|
|
|
EXPECT_EQ(1, exec_count);
|
|
|
|
}
|
2019-02-26 13:29:45 -05:00
|
|
|
|
|
|
|
TEST(ModulesTest, ImportMetaMain) {
|
2019-06-06 19:07:47 -04:00
|
|
|
Deno* d = deno_new(deno_config{0, empty_snapshot, empty, recv_cb, nullptr});
|
2019-02-26 13:29:45 -05:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
2019-06-06 19:07:47 -04:00
|
|
|
|
|
|
|
TEST(ModulesTest, DynamicImportSuccess) {
|
|
|
|
exec_count = 0;
|
|
|
|
static int dyn_import_count = 0;
|
|
|
|
static deno_mod b = 0;
|
|
|
|
auto dyn_import_cb = [](auto user_data, const char* specifier,
|
|
|
|
const char* referrer, deno_dyn_import_id import_id) {
|
|
|
|
auto d = reinterpret_cast<Deno*>(user_data);
|
|
|
|
dyn_import_count++;
|
|
|
|
EXPECT_STREQ(specifier, "foo");
|
|
|
|
EXPECT_STREQ(referrer, "a.js");
|
2019-06-10 15:27:34 -04:00
|
|
|
deno_dyn_import(d, d, import_id, b);
|
2019-06-06 19:07:47 -04:00
|
|
|
};
|
|
|
|
const char* src =
|
|
|
|
"(async () => { \n"
|
|
|
|
" let mod = await import('foo'); \n"
|
|
|
|
" assert(mod.b() === 'b'); \n"
|
|
|
|
// Send a message to signify that we're done.
|
|
|
|
" Deno.core.send(new Uint8Array([4])); \n"
|
|
|
|
"})(); \n";
|
|
|
|
Deno* d = deno_new(deno_config{0, snapshot, empty, recv_cb, dyn_import_cb});
|
|
|
|
static deno_mod a = deno_mod_new(d, true, "a.js", src);
|
|
|
|
EXPECT_NE(a, 0);
|
|
|
|
EXPECT_EQ(nullptr, deno_last_exception(d));
|
|
|
|
deno_mod_instantiate(d, d, a, nullptr);
|
|
|
|
EXPECT_EQ(nullptr, deno_last_exception(d));
|
|
|
|
const char* b_src = "export function b() { return 'b' }";
|
|
|
|
b = deno_mod_new(d, false, "b.js", b_src);
|
|
|
|
EXPECT_NE(b, 0);
|
|
|
|
EXPECT_EQ(nullptr, deno_last_exception(d));
|
|
|
|
deno_mod_instantiate(d, d, b, nullptr);
|
|
|
|
EXPECT_EQ(nullptr, deno_last_exception(d));
|
|
|
|
deno_mod_evaluate(d, d, a);
|
|
|
|
EXPECT_EQ(nullptr, deno_last_exception(d));
|
|
|
|
deno_check_promise_errors(d);
|
|
|
|
EXPECT_EQ(deno_last_exception(d), nullptr);
|
|
|
|
deno_delete(d);
|
|
|
|
EXPECT_EQ(1, exec_count);
|
|
|
|
EXPECT_EQ(1, dyn_import_count);
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(ModulesTest, DynamicImportError) {
|
|
|
|
exec_count = 0;
|
|
|
|
static int dyn_import_count = 0;
|
|
|
|
auto dyn_import_cb = [](auto user_data, const char* specifier,
|
|
|
|
const char* referrer, deno_dyn_import_id import_id) {
|
|
|
|
auto d = reinterpret_cast<Deno*>(user_data);
|
|
|
|
dyn_import_count++;
|
|
|
|
EXPECT_STREQ(specifier, "foo");
|
|
|
|
EXPECT_STREQ(referrer, "a.js");
|
|
|
|
// We indicate there was an error resolving by returning mod_id 0.
|
2019-06-10 15:27:34 -04:00
|
|
|
deno_dyn_import(d, d, import_id, 0);
|
2019-06-06 19:07:47 -04:00
|
|
|
};
|
|
|
|
const char* src =
|
|
|
|
"(async () => { \n"
|
|
|
|
" let mod = await import('foo'); \n"
|
|
|
|
// The following should be unreachable.
|
|
|
|
" Deno.core.send(new Uint8Array([4])); \n"
|
|
|
|
"})(); \n";
|
|
|
|
Deno* d = deno_new(deno_config{0, snapshot, empty, recv_cb, dyn_import_cb});
|
|
|
|
static deno_mod a = deno_mod_new(d, true, "a.js", src);
|
|
|
|
EXPECT_NE(a, 0);
|
|
|
|
EXPECT_EQ(nullptr, deno_last_exception(d));
|
|
|
|
deno_mod_instantiate(d, d, a, nullptr);
|
|
|
|
EXPECT_EQ(nullptr, deno_last_exception(d));
|
|
|
|
// No error when evaluating, because it's an async error.
|
|
|
|
deno_mod_evaluate(d, d, a);
|
|
|
|
EXPECT_EQ(nullptr, deno_last_exception(d));
|
|
|
|
// Now we should get an error.
|
|
|
|
deno_check_promise_errors(d);
|
|
|
|
EXPECT_NE(deno_last_exception(d), nullptr);
|
|
|
|
deno_delete(d);
|
|
|
|
EXPECT_EQ(0, exec_count);
|
|
|
|
EXPECT_EQ(1, dyn_import_count);
|
|
|
|
}
|
2019-06-10 15:27:34 -04:00
|
|
|
|
|
|
|
TEST(ModulesTest, DynamicImportAsync) {
|
|
|
|
exec_count = 0;
|
|
|
|
static int dyn_import_count = 0;
|
|
|
|
static deno_mod b = 0;
|
|
|
|
static std::vector<deno_dyn_import_id> import_ids = {};
|
|
|
|
auto dyn_import_cb = [](auto user_data, const char* specifier,
|
|
|
|
const char* referrer, deno_dyn_import_id import_id) {
|
|
|
|
// auto d = reinterpret_cast<Deno*>(user_data);
|
|
|
|
dyn_import_count++;
|
|
|
|
EXPECT_STREQ(specifier, "foo");
|
|
|
|
EXPECT_STREQ(referrer, "a.js");
|
|
|
|
// We don't call deno_dyn_import until later.
|
|
|
|
import_ids.push_back(import_id);
|
|
|
|
};
|
|
|
|
const char* src =
|
|
|
|
"(async () => { \n"
|
|
|
|
" let mod = await import('foo'); \n"
|
|
|
|
" assert(mod.b() === 'b'); \n"
|
|
|
|
// AGAIN!
|
|
|
|
" mod = await import('foo'); \n"
|
|
|
|
" assert(mod.b() === 'b'); \n"
|
|
|
|
// Send a message to signify that we're done.
|
|
|
|
" Deno.core.send(new Uint8Array([4])); \n"
|
|
|
|
"})(); \n";
|
|
|
|
Deno* d = deno_new(deno_config{0, snapshot, empty, recv_cb, dyn_import_cb});
|
|
|
|
static deno_mod a = deno_mod_new(d, true, "a.js", src);
|
|
|
|
EXPECT_NE(a, 0);
|
|
|
|
EXPECT_EQ(nullptr, deno_last_exception(d));
|
|
|
|
deno_mod_instantiate(d, d, a, nullptr);
|
|
|
|
EXPECT_EQ(nullptr, deno_last_exception(d));
|
|
|
|
|
|
|
|
// Evaluate. We check that there are no errors, and Deno.core.send has not
|
|
|
|
// been called.
|
|
|
|
deno_mod_evaluate(d, d, a);
|
|
|
|
EXPECT_EQ(nullptr, deno_last_exception(d));
|
|
|
|
deno_check_promise_errors(d);
|
|
|
|
EXPECT_EQ(deno_last_exception(d), nullptr);
|
|
|
|
EXPECT_EQ(0, exec_count);
|
|
|
|
EXPECT_EQ(1, dyn_import_count);
|
|
|
|
|
|
|
|
// Instantiate b.js
|
|
|
|
const char* b_src = "export function b() { return 'b' }";
|
|
|
|
b = deno_mod_new(d, false, "b.js", b_src);
|
|
|
|
EXPECT_NE(b, 0);
|
|
|
|
EXPECT_EQ(nullptr, deno_last_exception(d));
|
|
|
|
deno_mod_instantiate(d, d, b, nullptr);
|
|
|
|
EXPECT_EQ(nullptr, deno_last_exception(d));
|
|
|
|
|
|
|
|
// Now we resolve the import.
|
|
|
|
EXPECT_EQ(1u, import_ids.size());
|
|
|
|
auto import_id = import_ids.back();
|
|
|
|
import_ids.pop_back();
|
|
|
|
|
|
|
|
deno_dyn_import(d, d, import_id, b);
|
|
|
|
|
|
|
|
EXPECT_EQ(nullptr, deno_last_exception(d));
|
|
|
|
deno_check_promise_errors(d);
|
|
|
|
EXPECT_EQ(deno_last_exception(d), nullptr);
|
|
|
|
|
|
|
|
EXPECT_EQ(1u, import_ids.size());
|
|
|
|
EXPECT_EQ(2, dyn_import_count);
|
|
|
|
EXPECT_EQ(0, exec_count);
|
|
|
|
|
|
|
|
import_id = import_ids.back();
|
|
|
|
import_ids.pop_back();
|
|
|
|
deno_dyn_import(d, d, import_id, b);
|
|
|
|
|
|
|
|
EXPECT_EQ(nullptr, deno_last_exception(d));
|
|
|
|
deno_check_promise_errors(d);
|
|
|
|
EXPECT_EQ(deno_last_exception(d), nullptr);
|
|
|
|
|
|
|
|
// We still have to resolve the second one
|
|
|
|
EXPECT_EQ(2, dyn_import_count);
|
|
|
|
EXPECT_EQ(1, exec_count);
|
|
|
|
|
|
|
|
deno_delete(d);
|
|
|
|
}
|