| 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::CreateForTest( | 78 ModuleScript* referrer_module_script = ModuleScript::CreateForTest( |
| 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::CreateForTest(modulator, record, url, "", kParserInserted, | 94 ModuleScript::CreateForTest(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 |