Skip to content

Commit 8c63812

Browse files
legendecasV8 LUCI CQ
authored andcommitted
objects: IsGraphAsync should return false for source imports
Fixes a type assumption that elements in `requested_modules` can be a non-Module object when it is a source phase import. Bug: 42204365 Change-Id: If889ee82a72f294a635c90efa459e47f1a830df3 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/6951331 Reviewed-by: Camillo Bruni <[email protected]> Commit-Queue: Chengzhong Wu <[email protected]> Cr-Commit-Position: refs/heads/main@{#102772}
1 parent 5174c35 commit 8c63812

2 files changed

Lines changed: 71 additions & 4 deletions

File tree

src/objects/module.cc

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -488,10 +488,13 @@ bool Module::IsGraphAsync(Isolate* isolate) const {
488488
// Only SourceTextModules may be async.
489489
if (!IsSourceTextModule(*this)) return false;
490490
Tagged<SourceTextModule> root = Cast<SourceTextModule>(*this);
491+
DCHECK(root->status() == kLinked || root->status() == kEvaluated ||
492+
root->status() == kEvaluatingAsync || root->status() == kErrored);
491493

492494
Zone zone(isolate->allocator(), ZONE_NAME);
493495
const size_t bucket_count = 2;
494-
ZoneUnorderedSet<Tagged<Module>, Module::Hash> visited(&zone, bucket_count);
496+
ZoneUnorderedSet<Tagged<SourceTextModule>, Module::Hash> visited(
497+
&zone, bucket_count);
495498
ZoneVector<Tagged<SourceTextModule>> worklist(&zone);
496499
visited.insert(root);
497500
worklist.push_back(root);
@@ -504,10 +507,18 @@ bool Module::IsGraphAsync(Isolate* isolate) const {
504507
if (current->has_toplevel_await()) return true;
505508
Tagged<FixedArray> requested_modules = current->requested_modules();
506509
for (int i = 0, length = requested_modules->length(); i < length; ++i) {
507-
Tagged<Module> descendant = Cast<Module>(requested_modules->get(i));
508-
if (IsSourceTextModule(descendant)) {
510+
Tagged<Object> raw_descendant = requested_modules->get(i);
511+
// The current module must have been linked as the root has been linked.
512+
// If the request is a source phase import, the descendant can be a
513+
// JavaScript object, and it can not be async. Skip it.
514+
// If the request is an evaluation phase import, the descendant can be
515+
// either a SourceTextModule or a SyntheticModule. Visit it if it is a
516+
// SourceTextModule.
517+
if (IsSourceTextModule(raw_descendant)) {
518+
Tagged<SourceTextModule> descendant =
519+
Cast<SourceTextModule>(raw_descendant);
509520
const bool cycle = !visited.insert(descendant).second;
510-
if (!cycle) worklist.push_back(Cast<SourceTextModule>(descendant));
521+
if (!cycle) worklist.push_back(descendant);
511522
}
512523
}
513524
} while (!worklist.empty());

test/unittests/objects/modules-unittest.cc

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
#include "include/v8-function.h"
66
#include "src/flags/flags.h"
7+
#include "test/common/flag-utils.h"
78
#include "test/unittests/test-utils.h"
89
#include "testing/gtest/include/gtest/gtest.h"
910
#if V8_ENABLE_WEBASSEMBLY
@@ -25,6 +26,7 @@ using v8::Location;
2526
using v8::MaybeLocal;
2627
using v8::Module;
2728
using v8::ModuleRequest;
29+
using v8::Object;
2830
using v8::Promise;
2931
using v8::ScriptCompiler;
3032
using v8::ScriptOrigin;
@@ -1213,6 +1215,60 @@ TEST_F(ModuleTest, IsGraphAsyncTopLevelAwait) {
12131215
cycle_two_module_global.Reset();
12141216
}
12151217

1218+
bool resolve_source_return_object_invoked = false;
1219+
MaybeLocal<Object> ResolveSourceReturnObject(
1220+
Local<Context> context, Local<String> specifier,
1221+
Local<FixedArray> import_attributes, Local<Module> referrer) {
1222+
Isolate* isolate = Isolate::GetCurrent();
1223+
1224+
CHECK(!specifier.IsEmpty());
1225+
String::Utf8Value specifier_utf8(isolate, specifier);
1226+
CHECK_EQ(0, strcmp("my-mod", *specifier_utf8));
1227+
1228+
CHECK_EQ(0, import_attributes->Length());
1229+
1230+
resolve_source_return_object_invoked = true;
1231+
1232+
return Object::New(isolate);
1233+
}
1234+
1235+
TEST_F(ModuleTest, IsGraphAsyncImportSource) {
1236+
i::FlagScope<bool> f(&i::v8_flags.js_source_phase_imports, true);
1237+
1238+
HandleScope scope(isolate());
1239+
1240+
// Check that v8::Module::IsGraphAsync() returns false for source
1241+
// phase imports.
1242+
1243+
Local<String> url = NewString("www.google.com");
1244+
Local<String> source_text =
1245+
NewString("import source modSource from 'my-mod';");
1246+
1247+
ScriptOrigin origin(url, 0, 0, false, -1, Local<v8::Value>(), false, false,
1248+
true);
1249+
ScriptCompiler::Source source(source_text, origin);
1250+
1251+
Local<Module> module =
1252+
ScriptCompiler::CompileModule(isolate(), &source).ToLocalChecked();
1253+
1254+
CHECK(!resolve_source_return_object_invoked);
1255+
CHECK(module
1256+
->InstantiateModule(
1257+
context(),
1258+
[](Local<Context> context, Local<String> specifier,
1259+
Local<FixedArray> import_attributes,
1260+
Local<Module> referrer) -> MaybeLocal<Module> {
1261+
// There is no evaluation phase import.
1262+
UNREACHABLE();
1263+
},
1264+
ResolveSourceReturnObject)
1265+
.IsJust());
1266+
CHECK(resolve_source_return_object_invoked);
1267+
1268+
// IsGraphAsync should return false
1269+
CHECK_EQ(module->IsGraphAsync(), false);
1270+
}
1271+
12161272
TEST_F(ModuleTest, HasTopLevelAwait) {
12171273
HandleScope scope(isolate());
12181274
{

0 commit comments

Comments
 (0)