OLD | NEW |
1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "core/dom/ScriptModuleResolverImpl.h" | 5 #include "core/dom/ScriptModuleResolverImpl.h" |
6 | 6 |
| 7 #include "bindings/core/v8/ScriptState.h" |
7 #include "bindings/core/v8/V8BindingForTesting.h" | 8 #include "bindings/core/v8/V8BindingForTesting.h" |
| 9 #include "bindings/core/v8/V8ThrowException.h" |
8 #include "core/dom/ExceptionCode.h" | 10 #include "core/dom/ExceptionCode.h" |
9 #include "core/dom/Modulator.h" | 11 #include "core/dom/Modulator.h" |
10 #include "core/dom/ModuleScript.h" | 12 #include "core/dom/ModuleScript.h" |
11 #include "core/testing/DummyModulator.h" | 13 #include "core/testing/DummyModulator.h" |
12 #include "platform/heap/Handle.h" | 14 #include "platform/heap/Handle.h" |
13 #include "platform/testing/TestingPlatformSupport.h" | 15 #include "platform/testing/TestingPlatformSupport.h" |
14 #include "public/platform/Platform.h" | 16 #include "public/platform/Platform.h" |
15 #include "testing/gtest/include/gtest/gtest.h" | 17 #include "testing/gtest/include/gtest/gtest.h" |
16 #include "v8/include/v8.h" | 18 #include "v8/include/v8.h" |
17 | 19 |
18 namespace blink { | 20 namespace blink { |
19 | 21 |
20 namespace { | 22 namespace { |
21 | 23 |
22 class ScriptModuleResolverImplTestModulator final : public DummyModulator { | 24 class ScriptModuleResolverImplTestModulator final : public DummyModulator { |
23 public: | 25 public: |
24 ScriptModuleResolverImplTestModulator() {} | 26 ScriptModuleResolverImplTestModulator() {} |
25 virtual ~ScriptModuleResolverImplTestModulator() {} | 27 virtual ~ScriptModuleResolverImplTestModulator() {} |
26 | 28 |
27 DECLARE_TRACE(); | 29 DECLARE_TRACE(); |
28 | 30 |
| 31 void SetScriptState(ScriptState* script_state) { |
| 32 script_state_ = script_state; |
| 33 } |
| 34 |
29 int GetFetchedModuleScriptCalled() const { | 35 int GetFetchedModuleScriptCalled() const { |
30 return get_fetched_module_script_called_; | 36 return get_fetched_module_script_called_; |
31 } | 37 } |
32 void SetModuleScript(ModuleScript* module_script) { | 38 void SetModuleScript(ModuleScript* module_script) { |
33 module_script_ = module_script; | 39 module_script_ = module_script; |
34 } | 40 } |
35 const KURL& FetchedUrl() const { return fetched_url_; } | 41 const KURL& FetchedUrl() const { return fetched_url_; } |
36 | 42 |
37 private: | 43 private: |
38 // Implements Modulator: | 44 // Implements Modulator: |
39 ModuleScript* GetFetchedModuleScript(const KURL&) override; | 45 ModuleScript* GetFetchedModuleScript(const KURL&) override; |
40 | 46 |
| 47 ScriptValue GetInstantiationError(const ModuleScript* module_script) { |
| 48 ScriptState::Scope scope(script_state_.Get()); |
| 49 return ScriptValue( |
| 50 script_state_.Get(), |
| 51 module_script->CreateInstantiationError(script_state_->GetIsolate())); |
| 52 } |
| 53 |
| 54 RefPtr<ScriptState> script_state_; |
41 int get_fetched_module_script_called_ = 0; | 55 int get_fetched_module_script_called_ = 0; |
42 KURL fetched_url_; | 56 KURL fetched_url_; |
43 Member<ModuleScript> module_script_; | 57 Member<ModuleScript> module_script_; |
44 }; | 58 }; |
45 | 59 |
46 DEFINE_TRACE(ScriptModuleResolverImplTestModulator) { | 60 DEFINE_TRACE(ScriptModuleResolverImplTestModulator) { |
47 visitor->Trace(module_script_); | 61 visitor->Trace(module_script_); |
48 DummyModulator::Trace(visitor); | 62 DummyModulator::Trace(visitor); |
49 } | 63 } |
50 | 64 |
51 ModuleScript* ScriptModuleResolverImplTestModulator::GetFetchedModuleScript( | 65 ModuleScript* ScriptModuleResolverImplTestModulator::GetFetchedModuleScript( |
52 const KURL& url) { | 66 const KURL& url) { |
53 get_fetched_module_script_called_++; | 67 get_fetched_module_script_called_++; |
54 fetched_url_ = url; | 68 fetched_url_ = url; |
55 return module_script_.Get(); | 69 return module_script_.Get(); |
56 } | 70 } |
57 | 71 |
58 ModuleScript* CreateReferrerModuleScript(Modulator* modulator, | 72 ModuleScript* CreateReferrerModuleScript(Modulator* modulator, |
59 V8TestingScope& scope) { | 73 V8TestingScope& scope) { |
60 ScriptModule referrer_record = ScriptModule::Compile( | 74 ScriptModule referrer_record = ScriptModule::Compile( |
61 scope.GetIsolate(), "import './target.js'; export const a = 42;", | 75 scope.GetIsolate(), "import './target.js'; export const a = 42;", |
62 "referrer.js", kSharableCrossOrigin); | 76 "referrer.js", kSharableCrossOrigin); |
63 KURL referrer_url(kParsedURLString, "https://example.com/referrer.js"); | 77 KURL referrer_url(kParsedURLString, "https://example.com/referrer.js"); |
64 ModuleScript* referrer_module_script = ModuleScript::Create( | 78 ModuleScript* referrer_module_script = ModuleScript::Create( |
65 modulator, referrer_record, referrer_url, "", kParserInserted, | 79 modulator, referrer_record, referrer_url, "", kParserInserted, |
66 WebURLRequest::kFetchCredentialsModeOmit); | 80 WebURLRequest::kFetchCredentialsModeOmit); |
67 // TODO(kouhei): moduleScript->setInstantiateSuccess(); once | 81 referrer_module_script->SetInstantiationSuccess(); |
68 // https://codereview.chromium.org/2782403002/ landed. | |
69 return referrer_module_script; | 82 return referrer_module_script; |
70 } | 83 } |
71 | 84 |
72 ModuleScript* CreateTargetModuleScript(Modulator* modulator, | 85 ModuleScript* CreateTargetModuleScript( |
73 V8TestingScope& scope) { | 86 Modulator* modulator, |
| 87 V8TestingScope& scope, |
| 88 ModuleInstantiationState state = ModuleInstantiationState::kInstantiated) { |
74 ScriptModule record = | 89 ScriptModule record = |
75 ScriptModule::Compile(scope.GetIsolate(), "export const pi = 3.14;", | 90 ScriptModule::Compile(scope.GetIsolate(), "export const pi = 3.14;", |
76 "target.js", kSharableCrossOrigin); | 91 "target.js", kSharableCrossOrigin); |
77 KURL url(kParsedURLString, "https://example.com/target.js"); | 92 KURL url(kParsedURLString, "https://example.com/target.js"); |
78 ModuleScript* module_script = | 93 ModuleScript* module_script = |
79 ModuleScript::Create(modulator, record, url, "", kParserInserted, | 94 ModuleScript::Create(modulator, record, url, "", kParserInserted, |
80 WebURLRequest::kFetchCredentialsModeOmit); | 95 WebURLRequest::kFetchCredentialsModeOmit); |
81 // TODO(kouhei): moduleScript->setInstantiateSuccess(); once | 96 if (state == ModuleInstantiationState::kInstantiated) { |
82 // https://codereview.chromium.org/2782403002/ landed. | 97 module_script->SetInstantiationSuccess(); |
| 98 } else { |
| 99 EXPECT_EQ(ModuleInstantiationState::kErrored, state); |
| 100 v8::Local<v8::Value> error = |
| 101 V8ThrowException::CreateError(scope.GetIsolate(), "hoge"); |
| 102 module_script->SetInstantiationErrorAndClearRecord( |
| 103 ScriptValue(scope.GetScriptState(), error)); |
| 104 } |
83 return module_script; | 105 return module_script; |
84 } | 106 } |
85 | 107 |
86 } // namespace | 108 } // namespace |
87 | 109 |
88 class ScriptModuleResolverImplTest : public testing::Test { | 110 class ScriptModuleResolverImplTest : public testing::Test { |
89 public: | 111 public: |
90 void SetUp() override; | 112 void SetUp() override; |
91 | 113 |
92 ScriptModuleResolverImplTestModulator* Modulator() { | 114 ScriptModuleResolverImplTestModulator* Modulator() { |
93 return modulator_.Get(); | 115 return modulator_.Get(); |
94 } | 116 } |
95 | 117 |
96 protected: | 118 protected: |
97 ScopedTestingPlatformSupport<TestingPlatformSupportWithMockScheduler> | 119 ScopedTestingPlatformSupport<TestingPlatformSupportWithMockScheduler> |
98 platform_; | 120 platform_; |
99 Persistent<ScriptModuleResolverImplTestModulator> modulator_; | 121 Persistent<ScriptModuleResolverImplTestModulator> modulator_; |
100 }; | 122 }; |
101 | 123 |
102 void ScriptModuleResolverImplTest::SetUp() { | 124 void ScriptModuleResolverImplTest::SetUp() { |
103 platform_->AdvanceClockSeconds(1.); // For non-zero DocumentParserTimings | 125 platform_->AdvanceClockSeconds(1.); // For non-zero DocumentParserTimings |
104 modulator_ = new ScriptModuleResolverImplTestModulator(); | 126 modulator_ = new ScriptModuleResolverImplTestModulator(); |
105 } | 127 } |
106 | 128 |
107 TEST_F(ScriptModuleResolverImplTest, registerResolveSuccess) { | 129 TEST_F(ScriptModuleResolverImplTest, RegisterResolveSuccess) { |
108 ScriptModuleResolverImpl* resolver = | 130 ScriptModuleResolverImpl* resolver = |
109 ScriptModuleResolverImpl::Create(Modulator()); | 131 ScriptModuleResolverImpl::Create(Modulator()); |
110 V8TestingScope scope; | 132 V8TestingScope scope; |
111 | 133 |
112 ModuleScript* referrer_module_script = | 134 ModuleScript* referrer_module_script = |
113 CreateReferrerModuleScript(modulator_, scope); | 135 CreateReferrerModuleScript(modulator_, scope); |
114 resolver->RegisterModuleScript(referrer_module_script); | 136 resolver->RegisterModuleScript(referrer_module_script); |
115 | 137 |
116 ModuleScript* target_module_script = | 138 ModuleScript* target_module_script = |
117 CreateTargetModuleScript(modulator_, scope); | 139 CreateTargetModuleScript(modulator_, scope); |
118 Modulator()->SetModuleScript(target_module_script); | 140 Modulator()->SetModuleScript(target_module_script); |
119 | 141 |
120 ScriptModule resolved = | 142 ScriptModule resolved = |
121 resolver->Resolve("./target.js", referrer_module_script->Record(), | 143 resolver->Resolve("./target.js", referrer_module_script->Record(), |
122 scope.GetExceptionState()); | 144 scope.GetExceptionState()); |
123 EXPECT_FALSE(scope.GetExceptionState().HadException()); | 145 EXPECT_FALSE(scope.GetExceptionState().HadException()); |
124 EXPECT_EQ(resolved, target_module_script->Record()); | 146 EXPECT_EQ(resolved, target_module_script->Record()); |
125 EXPECT_EQ(1, modulator_->GetFetchedModuleScriptCalled()); | 147 EXPECT_EQ(1, modulator_->GetFetchedModuleScriptCalled()); |
126 EXPECT_EQ(modulator_->FetchedUrl(), target_module_script->BaseURL()) | 148 EXPECT_EQ(modulator_->FetchedUrl(), target_module_script->BaseURL()) |
127 << "Unexpectedly fetched URL: " << modulator_->FetchedUrl().GetString(); | 149 << "Unexpectedly fetched URL: " << modulator_->FetchedUrl().GetString(); |
128 } | 150 } |
129 | 151 |
130 TEST_F(ScriptModuleResolverImplTest, resolveInvalidModuleSpecifier) { | 152 TEST_F(ScriptModuleResolverImplTest, ResolveInvalidModuleSpecifier) { |
131 ScriptModuleResolverImpl* resolver = | 153 ScriptModuleResolverImpl* resolver = |
132 ScriptModuleResolverImpl::Create(Modulator()); | 154 ScriptModuleResolverImpl::Create(Modulator()); |
133 V8TestingScope scope; | 155 V8TestingScope scope; |
134 | 156 |
135 ModuleScript* referrer_module_script = | 157 ModuleScript* referrer_module_script = |
136 CreateReferrerModuleScript(modulator_, scope); | 158 CreateReferrerModuleScript(modulator_, scope); |
137 resolver->RegisterModuleScript(referrer_module_script); | 159 resolver->RegisterModuleScript(referrer_module_script); |
138 | 160 |
139 ModuleScript* target_module_script = | 161 ModuleScript* target_module_script = |
140 CreateTargetModuleScript(modulator_, scope); | 162 CreateTargetModuleScript(modulator_, scope); |
141 Modulator()->SetModuleScript(target_module_script); | 163 Modulator()->SetModuleScript(target_module_script); |
142 | 164 |
143 ScriptModule resolved = resolver->Resolve( | 165 ScriptModule resolved = resolver->Resolve( |
144 "invalid", referrer_module_script->Record(), scope.GetExceptionState()); | 166 "invalid", referrer_module_script->Record(), scope.GetExceptionState()); |
145 EXPECT_TRUE(scope.GetExceptionState().HadException()); | 167 EXPECT_TRUE(scope.GetExceptionState().HadException()); |
146 EXPECT_EQ(kV8TypeError, scope.GetExceptionState().Code()); | 168 EXPECT_EQ(kV8TypeError, scope.GetExceptionState().Code()); |
147 EXPECT_TRUE(resolved.IsNull()); | 169 EXPECT_TRUE(resolved.IsNull()); |
148 EXPECT_EQ(0, modulator_->GetFetchedModuleScriptCalled()); | 170 EXPECT_EQ(0, modulator_->GetFetchedModuleScriptCalled()); |
149 } | 171 } |
150 | 172 |
151 TEST_F(ScriptModuleResolverImplTest, resolveLoadFailedModule) { | 173 TEST_F(ScriptModuleResolverImplTest, ResolveLoadFailedModule) { |
152 ScriptModuleResolverImpl* resolver = | 174 ScriptModuleResolverImpl* resolver = |
153 ScriptModuleResolverImpl::Create(Modulator()); | 175 ScriptModuleResolverImpl::Create(Modulator()); |
154 V8TestingScope scope; | 176 V8TestingScope scope; |
155 | 177 |
156 ModuleScript* referrer_module_script = | 178 ModuleScript* referrer_module_script = |
157 CreateReferrerModuleScript(modulator_, scope); | 179 CreateReferrerModuleScript(modulator_, scope); |
158 resolver->RegisterModuleScript(referrer_module_script); | 180 resolver->RegisterModuleScript(referrer_module_script); |
159 | 181 |
160 ModuleScript* target_module_script = | 182 ModuleScript* target_module_script = |
161 CreateTargetModuleScript(modulator_, scope); | 183 CreateTargetModuleScript(modulator_, scope); |
162 // Set Modulator::getFetchedModuleScript to return nullptr, which represents | 184 // Set Modulator::getFetchedModuleScript to return nullptr, which represents |
163 // that the target module failed to load. | 185 // that the target module failed to load. |
164 Modulator()->SetModuleScript(nullptr); | 186 Modulator()->SetModuleScript(nullptr); |
165 | 187 |
166 ScriptModule resolved = | 188 ScriptModule resolved = |
167 resolver->Resolve("./target.js", referrer_module_script->Record(), | 189 resolver->Resolve("./target.js", referrer_module_script->Record(), |
168 scope.GetExceptionState()); | 190 scope.GetExceptionState()); |
169 EXPECT_TRUE(scope.GetExceptionState().HadException()); | 191 EXPECT_TRUE(scope.GetExceptionState().HadException()); |
170 EXPECT_EQ(kV8TypeError, scope.GetExceptionState().Code()); | 192 EXPECT_EQ(kV8TypeError, scope.GetExceptionState().Code()); |
171 EXPECT_TRUE(resolved.IsNull()); | 193 EXPECT_TRUE(resolved.IsNull()); |
172 EXPECT_EQ(1, modulator_->GetFetchedModuleScriptCalled()); | 194 EXPECT_EQ(1, modulator_->GetFetchedModuleScriptCalled()); |
173 EXPECT_EQ(modulator_->FetchedUrl(), target_module_script->BaseURL()) | 195 EXPECT_EQ(modulator_->FetchedUrl(), target_module_script->BaseURL()) |
174 << "Unexpectedly fetched URL: " << modulator_->FetchedUrl().GetString(); | 196 << "Unexpectedly fetched URL: " << modulator_->FetchedUrl().GetString(); |
175 } | 197 } |
176 | 198 |
| 199 TEST_F(ScriptModuleResolverImplTest, ResolveInstantiationFailedModule) { |
| 200 ScriptModuleResolverImpl* resolver = |
| 201 ScriptModuleResolverImpl::Create(Modulator()); |
| 202 V8TestingScope scope; |
| 203 Modulator()->SetScriptState(scope.GetScriptState()); |
| 204 |
| 205 ModuleScript* referrer_module_script = |
| 206 CreateReferrerModuleScript(modulator_, scope); |
| 207 resolver->RegisterModuleScript(referrer_module_script); |
| 208 |
| 209 ModuleScript* target_module_script = CreateTargetModuleScript( |
| 210 modulator_, scope, ModuleInstantiationState::kErrored); |
| 211 Modulator()->SetModuleScript(target_module_script); |
| 212 |
| 213 ScriptModule resolved = |
| 214 resolver->Resolve("./target.js", referrer_module_script->Record(), |
| 215 scope.GetExceptionState()); |
| 216 EXPECT_TRUE(scope.GetExceptionState().HadException()); |
| 217 EXPECT_EQ(kUnknownError, scope.GetExceptionState().Code()); |
| 218 EXPECT_TRUE(resolved.IsNull()); |
| 219 EXPECT_EQ(1, modulator_->GetFetchedModuleScriptCalled()); |
| 220 EXPECT_EQ(modulator_->FetchedUrl(), target_module_script->BaseURL()) |
| 221 << "Unexpectedly fetched URL: " << modulator_->FetchedUrl().GetString(); |
| 222 } |
| 223 |
177 } // namespace blink | 224 } // namespace blink |
OLD | NEW |