Changeset 223744 in webkit
- Timestamp:
- Oct 20, 2017 12:19:02 AM (7 years ago)
- Location:
- trunk
- Files:
-
- 18 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r223718 r223744 1 2017-10-20 Yusuke Suzuki <utatane.tea@gmail.com> 2 3 [JSC] ScriptFetcher should be notified directly from module pipeline 4 https://bugs.webkit.org/show_bug.cgi?id=178340 5 6 Reviewed by Sam Weinig. 7 8 * http/tests/security/contentSecurityPolicy/1.1/module-scriptnonce-redirect-expected.txt: 9 * http/tests/security/module-no-mime-type-expected.txt: 10 * js/dom/modules/module-execution-error-should-be-propagated-to-onerror-expected.txt: 11 1 12 2017-10-19 Youenn Fablet <youenn@apple.com> 2 13 -
trunk/LayoutTests/http/tests/security/contentSecurityPolicy/1.1/module-scriptnonce-redirect-expected.txt
r208788 r223744 1 1 CONSOLE MESSAGE: Origin http://127.0.0.1:8000 is not allowed by Access-Control-Allow-Origin. 2 CONSOLE MESSAGE: line 1 : TypeError: Cross-origin script load denied by Cross-Origin Resource Sharing policy.2 CONSOLE MESSAGE: line 11: TypeError: Cross-origin script load denied by Cross-Origin Resource Sharing policy. 3 3 This tests whether a deferred script load caused by a redirect is properly allowed by a nonce. -
trunk/LayoutTests/http/tests/security/module-no-mime-type-expected.txt
r208788 r223744 1 CONSOLE MESSAGE: line 1 : TypeError: 'application/octet-stream' is not a valid JavaScript MIME type.1 CONSOLE MESSAGE: line 11: TypeError: 'application/octet-stream' is not a valid JavaScript MIME type. 2 2 Test module rejects scripts with no mime type. 3 3 -
trunk/LayoutTests/js/dom/modules/module-execution-error-should-be-propagated-to-onerror-expected.txt
r208788 r223744 1 CONSOLE MESSAGE: line 19: Error: module is executed. 1 2 Test window.onerror will be fired when the inlined module throws an error. 2 3 -
trunk/Source/JavaScriptCore/ChangeLog
r223738 r223744 1 2017-10-20 Yusuke Suzuki <utatane.tea@gmail.com> 2 3 [JSC] ScriptFetcher should be notified directly from module pipeline 4 https://bugs.webkit.org/show_bug.cgi?id=178340 5 6 Reviewed by Sam Weinig. 7 8 Previously, we use JSStdFunction to let WebCore inform the module pipeline results. 9 We setup JSStdFunction to the resulted promise of the module pipeline. It is super 10 ad-hoc since JSStdFunction's lambda need extra-careful to make it non-cyclic-referenced. 11 JSStdFunction's lambda can capture variables, but they are not able to be marked by GC. 12 13 But now, we have ScriptFetcher. It is introduced after we implemented the module pipeline 14 notification mechanism by using JSStdFunction. But it is appropriate one to receive notification 15 from the module pipeline by observer style. 16 17 This patch removes the above ad-hoc JSStdFunction use. And now ScriptFetcher receives 18 completion/failure notifications from the module pipeline. 19 20 * builtins/ModuleLoaderPrototype.js: 21 (loadModule): 22 (loadAndEvaluateModule): 23 * runtime/Completion.cpp: 24 (JSC::loadModule): 25 * runtime/Completion.h: 26 * runtime/JSModuleLoader.cpp: 27 (JSC::jsValueToModuleKey): 28 (JSC::JSModuleLoader::notifyCompleted): 29 (JSC::JSModuleLoader::notifyFailed): 30 * runtime/JSModuleLoader.h: 31 * runtime/ModuleLoaderPrototype.cpp: 32 (JSC::moduleLoaderPrototypeNotifyCompleted): 33 (JSC::moduleLoaderPrototypeNotifyFailed): 34 * runtime/ScriptFetcher.h: 35 (JSC::ScriptFetcher::notifyLoadCompleted): 36 (JSC::ScriptFetcher::notifyLoadFailed): 37 1 38 2017-10-19 JF Bastien <jfbastien@apple.com> 2 39 -
trunk/Source/JavaScriptCore/builtins/ModuleLoaderPrototype.js
r223331 r223744 321 321 return this.resolve(moduleName, @undefined, fetcher).then((key) => { 322 322 return this.requestSatisfy(this.ensureRegistered(key), parameters, fetcher); 323 }).then((entry) => { 324 return entry.key; 325 }); 323 }).then( 324 (entry) => { 325 this.notifyCompleted(fetcher, entry.key); 326 return entry; 327 }, 328 (error) => { 329 this.notifyFailed(fetcher, error); 330 throw error; 331 }); 326 332 } 327 333 … … 342 348 "use strict"; 343 349 344 return this.loadModule(moduleName, parameters, fetcher).then(( key) => {345 return this.linkAndEvaluateModule( key, fetcher);350 return this.loadModule(moduleName, parameters, fetcher).then((entry) => { 351 return this.linkAndEvaluateModule(entry.key, fetcher); 346 352 }); 347 353 } -
trunk/Source/JavaScriptCore/runtime/Completion.cpp
r223237 r223744 184 184 } 185 185 186 JSInternalPromise*loadModule(ExecState* exec, const String& moduleName, JSValue parameters, JSValue scriptFetcher)187 { 188 VM& vm = exec->vm(); 189 JSLockHolder lock(vm); 190 RELEASE_ASSERT(vm.atomicStringTable() == Thread::current().atomicStringTable()); 191 RELEASE_ASSERT(!vm.isCollectorBusyOnCurrentThread()); 192 193 returnexec->vmEntryGlobalObject()->moduleLoader()->loadModule(exec, identifierToJSValue(vm, Identifier::fromString(exec, moduleName)), parameters, scriptFetcher);194 } 195 196 JSInternalPromise*loadModule(ExecState* exec, const SourceCode& source, JSValue scriptFetcher)186 void loadModule(ExecState* exec, const String& moduleName, JSValue parameters, JSValue scriptFetcher) 187 { 188 VM& vm = exec->vm(); 189 JSLockHolder lock(vm); 190 RELEASE_ASSERT(vm.atomicStringTable() == Thread::current().atomicStringTable()); 191 RELEASE_ASSERT(!vm.isCollectorBusyOnCurrentThread()); 192 193 exec->vmEntryGlobalObject()->moduleLoader()->loadModule(exec, identifierToJSValue(vm, Identifier::fromString(exec, moduleName)), parameters, scriptFetcher); 194 } 195 196 void loadModule(ExecState* exec, const SourceCode& source, JSValue scriptFetcher) 197 197 { 198 198 VM& vm = exec->vm(); … … 209 209 // FIXME: Introduce JSSourceCode object to wrap around this source. 210 210 globalObject->moduleLoader()->provideFetch(exec, key, source); 211 RETURN_IF_EXCEPTION(scope, rejectPromise(exec, globalObject));212 213 returnglobalObject->moduleLoader()->loadModule(exec, key, jsUndefined(), scriptFetcher);211 RETURN_IF_EXCEPTION(scope, void()); 212 213 globalObject->moduleLoader()->loadModule(exec, key, jsUndefined(), scriptFetcher); 214 214 } 215 215 -
trunk/Source/JavaScriptCore/runtime/Completion.h
r223237 r223744 62 62 63 63 // Fetch the module source, and instantiate the module record. 64 JS_EXPORT_PRIVATE JSInternalPromise*loadModule(ExecState*, const String& moduleName, JSValue parameters, JSValue scriptFetcher);65 JS_EXPORT_PRIVATE JSInternalPromise*loadModule(ExecState*, const SourceCode&, JSValue scriptFetcher);64 JS_EXPORT_PRIVATE void loadModule(ExecState*, const String& moduleName, JSValue parameters, JSValue scriptFetcher); 65 JS_EXPORT_PRIVATE void loadModule(ExecState*, const SourceCode&, JSValue scriptFetcher); 66 66 67 67 // Link and evaluate the already linked module. This function is called in a sync manner. -
trunk/Source/JavaScriptCore/runtime/JSModuleLoader.cpp
r223331 r223744 40 40 #include "JSModuleEnvironment.h" 41 41 #include "JSModuleRecord.h" 42 #include "JSScriptFetcher.h" 42 43 #include "JSSourceCode.h" 43 44 #include "ModuleAnalyzer.h" … … 292 293 } 293 294 295 static Identifier jsValueToModuleKey(ExecState* exec, JSValue value) 296 { 297 if (value.isSymbol()) 298 return Identifier::fromUid(jsCast<Symbol*>(value)->privateName()); 299 ASSERT(value.isString()); 300 return asString(value)->toIdentifier(exec); 301 } 302 303 JSValue JSModuleLoader::notifyCompleted(ExecState* exec, JSValue scriptFetcher, JSValue key) 304 { 305 auto* fetcherWrapper = jsDynamicCast<JSScriptFetcher*>(exec->vm(), scriptFetcher); 306 if (!fetcherWrapper) 307 return jsUndefined(); 308 auto* fetcher = fetcherWrapper->fetcher(); 309 if (!fetcher) 310 return jsUndefined(); 311 312 Identifier moduleKey = jsValueToModuleKey(exec, key); 313 fetcher->notifyLoadCompleted(*moduleKey.impl()); 314 return jsUndefined(); 315 } 316 317 JSValue JSModuleLoader::notifyFailed(ExecState* exec, JSValue scriptFetcher, JSValue errorValue) 318 { 319 auto* fetcherWrapper = jsDynamicCast<JSScriptFetcher*>(exec->vm(), scriptFetcher); 320 if (!fetcherWrapper) 321 return jsUndefined(); 322 auto* fetcher = fetcherWrapper->fetcher(); 323 if (!fetcher) 324 return jsUndefined(); 325 fetcher->notifyLoadFailed(exec, errorValue); 326 return jsUndefined(); 327 } 328 294 329 } // namespace JSC -
trunk/Source/JavaScriptCore/runtime/JSModuleLoader.h
r223331 r223744 69 69 JSValue linkAndEvaluateModule(ExecState*, JSValue moduleKey, JSValue scriptFetcher); 70 70 JSInternalPromise* requestImportModule(ExecState*, const Identifier&, JSValue parameters, JSValue scriptFetcher); 71 JSValue notifyCompleted(ExecState*, JSValue scriptFetcher, JSValue key); 72 JSValue notifyFailed(ExecState*, JSValue scriptFetcher, JSValue error); 71 73 72 74 // Platform dependent hooked APIs. -
trunk/Source/JavaScriptCore/runtime/ModuleLoaderPrototype.cpp
r223331 r223744 57 57 static EncodedJSValue JSC_HOST_CALL moduleLoaderPrototypeFetch(ExecState*); 58 58 static EncodedJSValue JSC_HOST_CALL moduleLoaderPrototypeGetModuleNamespaceObject(ExecState*); 59 static EncodedJSValue JSC_HOST_CALL moduleLoaderPrototypeNotifyCompleted(ExecState*); 60 static EncodedJSValue JSC_HOST_CALL moduleLoaderPrototypeNotifyFailed(ExecState*); 59 61 60 62 } … … 91 93 resolveSync moduleLoaderPrototypeResolveSync DontEnum|Function 2 92 94 fetch moduleLoaderPrototypeFetch DontEnum|Function 3 95 notifyCompleted moduleLoaderPrototypeNotifyCompleted DontEnum|Function 2 96 notifyFailed moduleLoaderPrototypeNotifyFailed DontEnum|Function 2 93 97 @end 94 98 */ … … 171 175 } 172 176 177 EncodedJSValue JSC_HOST_CALL moduleLoaderPrototypeNotifyCompleted(ExecState* exec) 178 { 179 VM& vm = exec->vm(); 180 JSModuleLoader* loader = jsDynamicCast<JSModuleLoader*>(vm, exec->thisValue()); 181 if (!loader) 182 return JSValue::encode(jsUndefined()); 183 return JSValue::encode(loader->notifyCompleted(exec, exec->argument(0), exec->argument(1))); 184 } 185 186 EncodedJSValue JSC_HOST_CALL moduleLoaderPrototypeNotifyFailed(ExecState* exec) 187 { 188 VM& vm = exec->vm(); 189 JSModuleLoader* loader = jsDynamicCast<JSModuleLoader*>(vm, exec->thisValue()); 190 if (!loader) 191 return JSValue::encode(jsUndefined()); 192 return JSValue::encode(loader->notifyFailed(exec, exec->argument(0), exec->argument(1))); 193 } 194 173 195 // ------------------------------ Hook Functions --------------------------- 174 196 -
trunk/Source/JavaScriptCore/runtime/ScriptFetcher.h
r210585 r223744 26 26 #pragma once 27 27 28 #include "JSCJSValue.h" 28 29 #include <wtf/RefCounted.h> 29 30 30 31 namespace JSC { 31 32 33 class ExecState; 34 32 35 class ScriptFetcher : public RefCounted<ScriptFetcher> { 33 36 public: 34 37 virtual ~ScriptFetcher() { } 38 39 virtual void notifyLoadCompleted(UniquedStringImpl&) { } 40 virtual void notifyLoadFailed(ExecState*, JSValue) { } 35 41 }; 36 42 -
trunk/Source/WebCore/ChangeLog
r223743 r223744 1 2017-10-20 Yusuke Suzuki <utatane.tea@gmail.com> 2 3 [JSC] ScriptFetcher should be notified directly from module pipeline 4 https://bugs.webkit.org/show_bug.cgi?id=178340 5 6 Reviewed by Sam Weinig. 7 8 No behavior change. 9 10 * bindings/js/JSMainThreadExecState.h: 11 (WebCore::JSMainThreadExecState::loadModule): 12 * bindings/js/ScriptController.cpp: 13 (WebCore::ScriptController::loadModuleScriptInWorld): 14 (WebCore::jsValueToModuleKey): Deleted. 15 (WebCore::ScriptController::setupModuleScriptHandlers): Deleted. 16 * bindings/js/ScriptController.h: 17 * dom/LoadableModuleScript.cpp: 18 (WebCore::LoadableModuleScript::notifyLoadFailed): 19 * dom/LoadableModuleScript.h: 20 1 21 2017-10-19 Ms2ger <Ms2ger@igalia.com> 2 22 -
trunk/Source/WebCore/bindings/js/JSMainThreadExecState.h
r223237 r223744 91 91 } 92 92 93 static JSC::JSInternalPromise&loadModule(JSC::ExecState& state, const String& moduleName, JSC::JSValue parameters, JSC::JSValue scriptFetcher)93 static void loadModule(JSC::ExecState& state, const String& moduleName, JSC::JSValue parameters, JSC::JSValue scriptFetcher) 94 94 { 95 95 JSMainThreadExecState currentState(&state); 96 return *JSC::loadModule(&state, moduleName, parameters, scriptFetcher);96 JSC::loadModule(&state, moduleName, parameters, scriptFetcher); 97 97 } 98 98 99 static JSC::JSInternalPromise&loadModule(JSC::ExecState& state, const JSC::SourceCode& sourceCode, JSC::JSValue scriptFetcher)99 static void loadModule(JSC::ExecState& state, const JSC::SourceCode& sourceCode, JSC::JSValue scriptFetcher) 100 100 { 101 101 JSMainThreadExecState currentState(&state); 102 return *JSC::loadModule(&state, sourceCode, scriptFetcher);102 JSC::loadModule(&state, sourceCode, scriptFetcher); 103 103 } 104 104 -
trunk/Source/WebCore/bindings/js/ScriptController.cpp
r223476 r223744 41 41 #include "LoadableModuleScript.h" 42 42 #include "MainFrame.h" 43 #include "ModuleFetchFailureKind.h"44 43 #include "ModuleFetchParameters.h" 45 44 #include "NP_jsobject.h" … … 63 62 #include <runtime/JSLock.h> 64 63 #include <runtime/JSModuleRecord.h> 65 #include <runtime/JSNativeStdFunction.h>66 64 #include <runtime/JSScriptFetchParameters.h> 67 65 #include <runtime/JSScriptFetcher.h> … … 200 198 auto& state = *proxy.window()->globalExec(); 201 199 202 auto& promise = JSMainThreadExecState::loadModule(state, moduleName, JSC::JSScriptFetchParameters::create(state.vm(), WTFMove(topLevelFetchParameters)), JSC::JSScriptFetcher::create(state.vm(), { &moduleScript })); 203 setupModuleScriptHandlers(moduleScript, promise, world); 200 JSMainThreadExecState::loadModule(state, moduleName, JSC::JSScriptFetchParameters::create(state.vm(), WTFMove(topLevelFetchParameters)), JSC::JSScriptFetcher::create(state.vm(), { &moduleScript })); 204 201 } 205 202 … … 216 213 auto& state = *proxy.window()->globalExec(); 217 214 218 auto& promise = JSMainThreadExecState::loadModule(state, sourceCode.jsSourceCode(), JSC::JSScriptFetcher::create(state.vm(), { &moduleScript })); 219 setupModuleScriptHandlers(moduleScript, promise, world); 215 JSMainThreadExecState::loadModule(state, sourceCode.jsSourceCode(), JSC::JSScriptFetcher::create(state.vm(), { &moduleScript })); 220 216 } 221 217 … … 363 359 364 360 return &windowProxy; 365 }366 367 static Identifier jsValueToModuleKey(ExecState* exec, JSValue value)368 {369 if (value.isSymbol())370 return Identifier::fromUid(jsCast<Symbol*>(value)->privateName());371 ASSERT(value.isString());372 return asString(value)->toIdentifier(exec);373 }374 375 void ScriptController::setupModuleScriptHandlers(LoadableModuleScript& moduleScriptRef, JSInternalPromise& promise, DOMWrapperWorld& world)376 {377 auto& proxy = *windowProxy(world);378 auto& state = *proxy.window()->globalExec();379 380 // It is not guaranteed that either fulfillHandler or rejectHandler is eventually called.381 // For example, if the page load is canceled, the DeferredPromise used in the module loader pipeline will stop executing JS code.382 // Thus the promise returned from this function could remain unresolved.383 384 RefPtr<LoadableModuleScript> moduleScript(&moduleScriptRef);385 386 auto& fulfillHandler = *JSNativeStdFunction::create(state.vm(), proxy.window(), 1, String(), [moduleScript](ExecState* exec) {387 Identifier moduleKey = jsValueToModuleKey(exec, exec->argument(0));388 moduleScript->notifyLoadCompleted(*moduleKey.impl());389 return JSValue::encode(jsUndefined());390 });391 392 auto& rejectHandler = *JSNativeStdFunction::create(state.vm(), proxy.window(), 1, String(), [moduleScript](ExecState* exec) {393 VM& vm = exec->vm();394 JSValue errorValue = exec->argument(0);395 if (errorValue.isObject()) {396 auto* object = JSC::asObject(errorValue);397 if (JSValue failureKindValue = object->getDirect(vm, static_cast<JSVMClientData&>(*vm.clientData).builtinNames().failureKindPrivateName())) {398 // This is host propagated error in the module loader pipeline.399 switch (static_cast<ModuleFetchFailureKind>(failureKindValue.asInt32())) {400 case ModuleFetchFailureKind::WasErrored:401 moduleScript->notifyLoadFailed(LoadableScript::Error {402 LoadableScript::ErrorType::CachedScript,403 std::nullopt404 });405 break;406 case ModuleFetchFailureKind::WasCanceled:407 moduleScript->notifyLoadWasCanceled();408 break;409 }410 return JSValue::encode(jsUndefined());411 }412 }413 414 auto scope = DECLARE_CATCH_SCOPE(vm);415 moduleScript->notifyLoadFailed(LoadableScript::Error {416 LoadableScript::ErrorType::CachedScript,417 LoadableScript::ConsoleMessage {418 MessageSource::JS,419 MessageLevel::Error,420 retrieveErrorMessage(*exec, vm, errorValue, scope),421 }422 });423 return JSValue::encode(jsUndefined());424 });425 426 promise.then(&state, &fulfillHandler, &rejectHandler);427 361 } 428 362 -
trunk/Source/WebCore/bindings/js/ScriptController.h
r223237 r223744 183 183 private: 184 184 WEBCORE_EXPORT JSDOMWindowProxy* initScript(DOMWrapperWorld&); 185 void setupModuleScriptHandlers(LoadableModuleScript&, JSC::JSInternalPromise&, DOMWrapperWorld&);186 185 187 186 void disconnectPlatformScriptObjects(); -
trunk/Source/WebCore/dom/LoadableModuleScript.cpp
r223728 r223744 29 29 #include "Document.h" 30 30 #include "Frame.h" 31 #include "JSDOMExceptionHandling.h" 32 #include "ModuleFetchFailureKind.h" 31 33 #include "ModuleFetchParameters.h" 32 34 #include "ScriptController.h" 33 35 #include "ScriptElement.h" 36 #include "WebCoreJSClientData.h" 37 #include <heap/StrongInlines.h> 38 #include <runtime/CatchScope.h> 34 39 35 40 namespace WebCore { … … 70 75 } 71 76 77 void LoadableModuleScript::notifyLoadFailed(JSC::ExecState* exec, JSC::JSValue errorValue) 78 { 79 JSC::VM& vm = exec->vm(); 80 if (errorValue.isObject()) { 81 auto* object = JSC::asObject(errorValue); 82 if (JSC::JSValue failureKindValue = object->getDirect(vm, static_cast<JSVMClientData&>(*vm.clientData).builtinNames().failureKindPrivateName())) { 83 // This is host propagated error in the module loader pipeline. 84 switch (static_cast<ModuleFetchFailureKind>(failureKindValue.asInt32())) { 85 case ModuleFetchFailureKind::WasErrored: 86 notifyLoadFailed(LoadableScript::Error { 87 LoadableScript::ErrorType::CachedScript, 88 std::nullopt 89 }); 90 break; 91 case ModuleFetchFailureKind::WasCanceled: 92 notifyLoadWasCanceled(); 93 break; 94 } 95 return; 96 } 97 } 98 99 auto scope = DECLARE_CATCH_SCOPE(vm); 100 notifyLoadFailed(LoadableScript::Error { 101 LoadableScript::ErrorType::CachedScript, 102 LoadableScript::ConsoleMessage { 103 MessageSource::JS, 104 MessageLevel::Error, 105 retrieveErrorMessage(*exec, vm, errorValue, scope), 106 } 107 }); 108 } 109 72 110 void LoadableModuleScript::notifyLoadFailed(LoadableScript::Error&& error) 73 111 { -
trunk/Source/WebCore/dom/LoadableModuleScript.h
r223237 r223744 54 54 void load(Document&, const ScriptSourceCode&); 55 55 56 void notifyLoadCompleted(UniquedStringImpl&); 57 void notifyLoadFailed(LoadableScript::Error&&); 58 void notifyLoadWasCanceled(); 56 UniquedStringImpl* moduleKey() const { return m_moduleKey.get(); } 59 57 60 UniquedStringImpl* moduleKey() const { return m_moduleKey.get(); } 58 void notifyLoadCompleted(UniquedStringImpl&) final; 59 void notifyLoadFailed(JSC::ExecState*, JSC::JSValue) final; 61 60 62 61 private: 63 62 LoadableModuleScript(const String& nonce, const String& integrity, const String& crossOriginMode, const String& charset, const AtomicString& initiatorName, bool isInUserAgentShadowTree); 63 64 void notifyLoadFailed(LoadableScript::Error&&); 65 void notifyLoadWasCanceled(); 64 66 65 67 Ref<ModuleFetchParameters> m_parameters;
Note: See TracChangeset
for help on using the changeset viewer.