9cf8fce74c
Unifies the approaches used for storing the specifier -> module mapping and the module -> directory mapping, using std::unordered_maps for both and storing them per-Context. This requires adding a method to the v8::Module API to get a hash code for a Module, but allows slimming down the API in return: gone are SetEmbedderData/GetEmbedderData, along with the fourth argument to ResolveModuleCallback. Besides a simpler API, this allows d8 to get closer to the HTML loader, which requires each Realm to have a persistent module map (though this capability is not yet exercised by any tests). BUG=v8:1569 Review-Url: https://codereview.chromium.org/2393303002 Cr-Commit-Position: refs/heads/master@{#40133}
94 lines
3.1 KiB
C++
94 lines
3.1 KiB
C++
// Copyright 2016 the V8 project authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include "src/flags.h"
|
|
|
|
#include "test/cctest/cctest.h"
|
|
|
|
namespace {
|
|
|
|
using v8::Context;
|
|
using v8::HandleScope;
|
|
using v8::Isolate;
|
|
using v8::Local;
|
|
using v8::MaybeLocal;
|
|
using v8::Module;
|
|
using v8::ScriptCompiler;
|
|
using v8::ScriptOrigin;
|
|
using v8::String;
|
|
using v8::Value;
|
|
|
|
MaybeLocal<Module> AlwaysEmptyResolveCallback(Local<Context> context,
|
|
Local<String> specifier,
|
|
Local<Module> referrer) {
|
|
return MaybeLocal<Module>();
|
|
}
|
|
|
|
static int g_count = 0;
|
|
MaybeLocal<Module> FailOnSecondCallResolveCallback(Local<Context> context,
|
|
Local<String> specifier,
|
|
Local<Module> referrer) {
|
|
if (g_count++ > 0) return MaybeLocal<Module>();
|
|
Local<String> source_text = v8_str("");
|
|
ScriptOrigin origin(v8_str("module.js"));
|
|
ScriptCompiler::Source source(source_text, origin);
|
|
return ScriptCompiler::CompileModule(CcTest::isolate(), &source)
|
|
.ToLocalChecked();
|
|
}
|
|
|
|
TEST(ModuleInstantiationFailures) {
|
|
Isolate* isolate = CcTest::isolate();
|
|
HandleScope scope(isolate);
|
|
LocalContext env;
|
|
|
|
Local<String> source_text = v8_str(
|
|
"import './foo.js';"
|
|
"export {} from './bar.js';");
|
|
ScriptOrigin origin(v8_str("file.js"));
|
|
ScriptCompiler::Source source(source_text, origin);
|
|
Local<Module> module =
|
|
ScriptCompiler::CompileModule(isolate, &source).ToLocalChecked();
|
|
CHECK_EQ(2, module->GetModuleRequestsLength());
|
|
CHECK(v8_str("./foo.js")->StrictEquals(module->GetModuleRequest(0)));
|
|
CHECK(v8_str("./bar.js")->StrictEquals(module->GetModuleRequest(1)));
|
|
|
|
// Instantiation should fail.
|
|
CHECK(!module->Instantiate(env.local(), AlwaysEmptyResolveCallback));
|
|
|
|
// Start over again...
|
|
module = ScriptCompiler::CompileModule(isolate, &source).ToLocalChecked();
|
|
|
|
// Instantiation should fail if a sub-module fails to resolve.
|
|
g_count = 0;
|
|
CHECK(!module->Instantiate(env.local(), FailOnSecondCallResolveCallback));
|
|
}
|
|
|
|
static MaybeLocal<Module> CompileSpecifierAsModuleResolveCallback(
|
|
Local<Context> context, Local<String> specifier, Local<Module> referrer) {
|
|
ScriptOrigin origin(v8_str("module.js"));
|
|
ScriptCompiler::Source source(specifier, origin);
|
|
return ScriptCompiler::CompileModule(CcTest::isolate(), &source)
|
|
.ToLocalChecked();
|
|
}
|
|
|
|
TEST(ModuleEvaluation) {
|
|
Isolate* isolate = CcTest::isolate();
|
|
HandleScope scope(isolate);
|
|
LocalContext env;
|
|
|
|
Local<String> source_text = v8_str(
|
|
"import 'Object.expando = 5';"
|
|
"import 'Object.expando *= 2';");
|
|
ScriptOrigin origin(v8_str("file.js"));
|
|
ScriptCompiler::Source source(source_text, origin);
|
|
Local<Module> module =
|
|
ScriptCompiler::CompileModule(isolate, &source).ToLocalChecked();
|
|
CHECK(module->Instantiate(env.local(),
|
|
CompileSpecifierAsModuleResolveCallback));
|
|
CHECK(!module->Evaluate(env.local()).IsEmpty());
|
|
ExpectInt32("Object.expando", 10);
|
|
}
|
|
|
|
} // anonymous namespace
|