Source/JavaScriptCore/ChangeLog

 12017-02-20 Yusuke Suzuki <utatane.tea@gmail.com>
 2
 3 Support for promise rejection events (unhandledrejection)
 4 https://bugs.webkit.org/show_bug.cgi?id=150358
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 Patch by Joseph Pecoraro and Yusuke Suzuki.
 9
 10 * builtins/BuiltinNames.h:
 11 * builtins/PromiseOperations.js:
 12 (globalPrivate.rejectPromise):
 13 (globalPrivate.initializePromise):
 14 * builtins/PromisePrototype.js:
 15 (then):
 16 * bytecode/BytecodeIntrinsicRegistry.cpp:
 17 (JSC::BytecodeIntrinsicRegistry::BytecodeIntrinsicRegistry):
 18 * bytecode/BytecodeIntrinsicRegistry.h:
 19 * jsc.cpp:
 20 * runtime/JSGlobalObject.cpp:
 21 (JSC::JSGlobalObject::init):
 22 (JSC::JSGlobalObject::visitChildren):
 23 * runtime/JSGlobalObject.h:
 24 (JSC::JSGlobalObject::promiseResolveFunction):
 25 * runtime/JSGlobalObjectFunctions.cpp:
 26 (JSC::globalFuncHostPromiseRejectionTracker):
 27 * runtime/JSGlobalObjectFunctions.h:
 28 * runtime/JSPromise.cpp:
 29 (JSC::JSPromise::isHandled):
 30 * runtime/JSPromise.h:
 31
1322017-02-20 Manuel Rego Casasnovas <rego@igalia.com>
233
334 [css-grid] Remove compilation flag ENABLE_CSS_GRID_LAYOUT

Source/WebCore/ChangeLog

 12017-02-20 Yusuke Suzuki <utatane.tea@gmail.com>
 2
 3 Support for promise rejection events (unhandledrejection)
 4 https://bugs.webkit.org/show_bug.cgi?id=150358
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 Tests: js/dom/unhandled-promise-rejection-basic.html
 9 js/dom/unhandled-promise-rejection-console-report.html
 10 js/dom/unhandled-promise-rejection-handle-during-event.html
 11 js/dom/unhandled-promise-rejection-handle-in-handler.html
 12 js/dom/unhandled-promise-rejection-handle.html
 13 js/dom/unhandled-promise-rejection-order.html
 14
 15 Patch by Joseph Pecoraro and Yusuke Suzuki.
 16
 17 * CMakeLists.txt:
 18 * DerivedSources.cpp:
 19 * DerivedSources.make:
 20 * WebCore.xcodeproj/project.pbxproj:
 21 * bindings/js/JSDOMConvert.h:
 22 * bindings/js/JSDOMConvertPromise.h: Copied from Source/JavaScriptCore/runtime/JSPromise.h.
 23 (WebCore::Converter<IDLPromise<T>>::convert):
 24 (WebCore::JSConverter<IDLPromise<T>>::convert):
 25 * bindings/js/JSDOMWindowBase.cpp:
 26 (WebCore::JSDOMWindowBase::promiseRejectionTracker):
 27 * bindings/js/JSDOMWindowBase.h:
 28 * bindings/js/JSMainThreadExecState.cpp:
 29 (WebCore::JSMainThreadExecState::didLeaveScriptContext):
 30 * bindings/js/JSMainThreadExecState.h:
 31 (WebCore::JSMainThreadExecState::~JSMainThreadExecState):
 32 * bindings/js/JSWorkerGlobalScopeBase.cpp:
 33 * bindings/scripts/CodeGenerator.pm:
 34 (IsPromiseType):
 35 * bindings/scripts/CodeGeneratorJS.pm:
 36 (AddToIncludesForIDLType):
 37 (GetBaseIDLType):
 38 * dom/DOMAllInOne.cpp:
 39 * dom/EventNames.h:
 40 * dom/EventNames.in:
 41 * dom/GlobalEventHandlers.idl:
 42 * dom/PromiseRejectionEvent.cpp: Added.
 43 (WebCore::PromiseRejectionEvent::PromiseRejectionEvent):
 44 (WebCore::PromiseRejectionEvent::~PromiseRejectionEvent):
 45 * dom/PromiseRejectionEvent.h: Added.
 46 * dom/PromiseRejectionEvent.idl: Added.
 47 * dom/RejectedPromiseTracker.cpp: Added.
 48 (WebCore::RejectedPromise::RejectedPromise):
 49 (WebCore::RejectedPromise::globalObject):
 50 (WebCore::RejectedPromise::promise):
 51 (WebCore::UnhandledPromise::UnhandledPromise):
 52 (WebCore::UnhandledPromise::callStack):
 53 (WebCore::RejectedPromiseTracker::RejectedPromiseTracker):
 54 (WebCore::RejectedPromiseTracker::~RejectedPromiseTracker):
 55 (WebCore::createScriptCallStackFromReason):
 56 (WebCore::RejectedPromiseTracker::promiseRejected):
 57 (WebCore::RejectedPromiseTracker::promiseHandled):
 58 (WebCore::RejectedPromiseTracker::processQueueSoon):
 59 (WebCore::RejectedPromiseTracker::reportUnhandledRejection):
 60 (WebCore::RejectedPromiseTracker::reportRejectionHandled):
 61 * dom/RejectedPromiseTracker.h: Added.
 62 * dom/ScriptExecutionContext.cpp:
 63 (WebCore::ScriptExecutionContext::reportUnhandledPromiseRejection):
 64 (WebCore::ScriptExecutionContext::ensureRejectedPromiseTrackerSlow):
 65 * dom/ScriptExecutionContext.h:
 66 (WebCore::ScriptExecutionContext::ensureRejectedPromiseTracker):
 67 * html/HTMLMediaElement.cpp:
 68 (WebCore::HTMLMediaElement::pauseInternal):
 69 * workers/WorkerGlobalScope.idl:
 70
1712017-02-20 Manuel Rego Casasnovas <rego@igalia.com>
272
373 [css-grid] Remove compilation flag ENABLE_CSS_GRID_LAYOUT

Source/JavaScriptCore/builtins/BuiltinNames.h

@@namespace JSC {
8383 macro(getTemplateObject) \
8484 macro(templateRegistryKey) \
8585 macro(enqueueJob) \
 86 macro(hostPromiseRejectionTracker) \
8687 macro(promiseState) \
 88 macro(promiseIsHandled) \
8789 macro(promiseReactions) \
8890 macro(promiseResult) \
8991 macro(onFulfilled) \

Source/JavaScriptCore/builtins/PromiseOperations.js

@@function rejectPromise(promise, reason)
105105
106106 @InspectorInstrumentation.promiseRejected(promise, reason, reactions);
107107
 108 if (!promise.@promiseIsHandled)
 109 @hostPromiseRejectionTracker(promise, @promiseRejectionReject);
 110
108111 @triggerPromiseReactions(@promiseStateRejected, reactions, reason);
109112}
110113

@@function initializePromise(executor)
212215
213216 this.@promiseState = @promiseStatePending;
214217 this.@promiseReactions = [];
 218 this.@promiseIsHandled = false;
215219
216220 var resolvingFunctions = @createResolvingFunctions(this);
217221 try {

Source/JavaScriptCore/builtins/PromisePrototype.js

@@function then(onFulfilled, onRejected)
5252 var state = this.@promiseState;
5353 if (state === @promiseStatePending)
5454 @putByValDirect(this.@promiseReactions, this.@promiseReactions.length, reaction);
55  else
 55 else {
 56 if (state === @promiseStateRejected && !this.@promiseIsHandled)
 57 @hostPromiseRejectionTracker(this, @promiseRejectionHandle);
5658 @enqueueJob(@promiseReactionJob, [state, reaction, this.@promiseResult]);
 59 }
 60
 61 this.@promiseIsHandled = true;
5762
5863 return resultCapability.@promise;
5964}

Source/JavaScriptCore/bytecode/BytecodeIntrinsicRegistry.cpp

3232#include "BytecodeGenerator.h"
3333#include "JSCJSValueInlines.h"
3434#include "JSGeneratorFunction.h"
 35#include "JSGlobalObject.h"
3536#include "JSModuleLoader.h"
3637#include "JSPromise.h"
3738#include "Nodes.h"

@@BytecodeIntrinsicRegistry::BytecodeIntrinsicRegistry(VM& vm)
6162 m_ModuleSatisfy.set(m_vm, jsNumber(static_cast<unsigned>(JSModuleLoader::Status::Satisfy)));
6263 m_ModuleLink.set(m_vm, jsNumber(static_cast<unsigned>(JSModuleLoader::Status::Link)));
6364 m_ModuleReady.set(m_vm, jsNumber(static_cast<unsigned>(JSModuleLoader::Status::Ready)));
 65 m_promiseRejectionReject.set(m_vm, jsNumber(static_cast<unsigned>(JSPromiseRejectionOperation::Reject)));
 66 m_promiseRejectionHandle.set(m_vm, jsNumber(static_cast<unsigned>(JSPromiseRejectionOperation::Handle)));
6467 m_promiseStatePending.set(m_vm, jsNumber(static_cast<unsigned>(JSPromise::Status::Pending)));
6568 m_promiseStateFulfilled.set(m_vm, jsNumber(static_cast<unsigned>(JSPromise::Status::Fulfilled)));
6669 m_promiseStateRejected.set(m_vm, jsNumber(static_cast<unsigned>(JSPromise::Status::Rejected)));

Source/JavaScriptCore/bytecode/BytecodeIntrinsicRegistry.h

@@class Identifier;
7373 macro(ModuleSatisfy) \
7474 macro(ModuleLink) \
7575 macro(ModuleReady) \
 76 macro(promiseRejectionReject) \
 77 macro(promiseRejectionHandle) \
7678 macro(promiseStatePending) \
7779 macro(promiseStateFulfilled) \
7880 macro(promiseStateRejected) \

Source/JavaScriptCore/jsc.cpp

@@const GlobalObjectMethodTable GlobalObject::s_globalObjectMethodTable = {
13951395 &supportsRichSourceInfo,
13961396 &shouldInterruptScript,
13971397 &javaScriptRuntimeFlags,
1398  nullptr,
 1398 nullptr, // queueTaskToEventLoop
13991399 &shouldInterruptScriptBeforeTimeout,
14001400 &moduleLoaderImportModule,
14011401 &moduleLoaderResolve,
14021402 &moduleLoaderFetch,
1403  nullptr,
1404  nullptr,
1405  nullptr
 1403 nullptr, // moduleLoaderInstantiate
 1404 nullptr, // moduleLoaderEvaluate
 1405 nullptr, // promiseRejectionTracker
 1406 nullptr, // defaultLanguage
14061407};
14071408
14081409GlobalObject::GlobalObject(VM& vm, Structure* structure)

Source/JavaScriptCore/runtime/JSGlobalObject.cpp

@@const GlobalObjectMethodTable JSGlobalObject::s_globalObjectMethodTable = {
250250 &supportsRichSourceInfo,
251251 &shouldInterruptScript,
252252 &javaScriptRuntimeFlags,
253  nullptr,
 253 nullptr, // queueTaskToEventLoop
254254 &shouldInterruptScriptBeforeTimeout,
255  nullptr,
256  nullptr,
257  nullptr,
258  nullptr,
259  nullptr,
260  nullptr
 255 nullptr, // moduleLoaderImportModule
 256 nullptr, // moduleLoaderResolve
 257 nullptr, // moduleLoaderFetch
 258 nullptr, // moduleLoaderInstantiate
 259 nullptr, // moduleLoaderEvaluate
 260 nullptr, // promiseRejectionTracker
 261 nullptr, // defaultLanguage
261262};
262263
263264/* Source for JSGlobalObject.lut.h

@@putDirectWithoutTransition(vm, vm.propertyNames-> jsName, lowerName ## Construct
824825 GlobalPropertyInfo(vm.propertyNames->builtinNames().MapIteratorPrivateName(), JSFunction::create(vm, this, 1, String(), privateFuncMapIterator), DontEnum | DontDelete | ReadOnly),
825826 GlobalPropertyInfo(vm.propertyNames->builtinNames().mapIteratorNextPrivateName(), JSFunction::create(vm, this, 0, String(), privateFuncMapIteratorNext), DontEnum | DontDelete | ReadOnly),
826827
 828 GlobalPropertyInfo(vm.propertyNames->builtinNames().hostPromiseRejectionTrackerPrivateName(), JSFunction::create(vm, this, 2, String(), globalFuncHostPromiseRejectionTracker), DontEnum | DontDelete | ReadOnly),
827829 GlobalPropertyInfo(vm.propertyNames->builtinNames().InspectorInstrumentationPrivateName(), InspectorInstrumentationObject::create(vm, this, InspectorInstrumentationObject::createStructure(vm, this, m_objectPrototype.get())), DontEnum | DontDelete | ReadOnly),
828830 GlobalPropertyInfo(vm.propertyNames->builtinNames().MapPrivateName(), mapConstructor, DontEnum | DontDelete | ReadOnly),
829831 GlobalPropertyInfo(vm.propertyNames->builtinNames().thisTimeValuePrivateName(), privateFuncThisTimeValue, DontEnum | DontDelete | ReadOnly),

@@void JSGlobalObject::visitChildren(JSCell* cell, SlotVisitor& visitor)
11951197 thisObject->m_initializePromiseFunction.visit(visitor);
11961198 thisObject->m_iteratorProtocolFunction.visit(visitor);
11971199 visitor.append(thisObject->m_objectProtoValueOfFunction);
 1200 visitor.append(thisObject->m_promiseResolveFunction);
11981201 visitor.append(thisObject->m_newPromiseCapabilityFunction);
11991202 visitor.append(thisObject->m_functionProtoHasInstanceSymbolFunction);
12001203 thisObject->m_throwTypeErrorGetterSetter.visit(visitor);

Source/JavaScriptCore/runtime/JSGlobalObject.h

@@FOR_EACH_WEBASSEMBLY_CONSTRUCTOR_TYPE(DECLARE_SIMPLE_BUILTIN_TYPE)
161161
162162#undef DECLARE_SIMPLE_BUILTIN_TYPE
163163
164 class JSInternalPromise;
165 class InternalPromisePrototype;
166 class InternalPromiseConstructor;
167 
168 typedef Vector<ExecState*, 16> ExecStateStack;
 164enum class JSPromiseRejectionOperation : unsigned {
 165 Reject, // When a promise is rejected without any handlers.
 166 Handle, // When a handler is added to a rejected promise for the first time.
 167};
169168
170169struct GlobalObjectMethodTable {
171170 typedef bool (*SupportsRichSourceInfoFunctionPtr)(const JSGlobalObject*);

@@struct GlobalObjectMethodTable {
198197 typedef JSValue (*ModuleLoaderEvaluatePtr)(JSGlobalObject*, ExecState*, JSModuleLoader*, JSValue, JSValue, JSValue);
199198 ModuleLoaderEvaluatePtr moduleLoaderEvaluate;
200199
 200 typedef void (*PromiseRejectionTrackerPtr)(JSGlobalObject*, ExecState*, JSPromise*, JSPromiseRejectionOperation);
 201 PromiseRejectionTrackerPtr promiseRejectionTracker;
 202
201203 typedef String (*DefaultLanguageFunctionPtr)();
202204 DefaultLanguageFunctionPtr defaultLanguage;
203205};

@@class JSGlobalObject : public JSSegmentedVariableObject {
262264 LazyProperty<JSGlobalObject, JSFunction> m_initializePromiseFunction;
263265 LazyProperty<JSGlobalObject, JSFunction> m_iteratorProtocolFunction;
264266 WriteBarrier<JSFunction> m_objectProtoValueOfFunction;
 267 WriteBarrier<JSFunction> m_promiseResolveFunction;
265268 WriteBarrier<JSFunction> m_newPromiseCapabilityFunction;
266269 WriteBarrier<JSFunction> m_functionProtoHasInstanceSymbolFunction;
267270 LazyProperty<JSGlobalObject, GetterSetter> m_throwTypeErrorGetterSetter;

@@class JSGlobalObject : public JSSegmentedVariableObject {
510513 JSFunction* initializePromiseFunction() const { return m_initializePromiseFunction.get(this); }
511514 JSFunction* iteratorProtocolFunction() const { return m_iteratorProtocolFunction.get(this); }
512515 JSFunction* objectProtoValueOfFunction() const { return m_objectProtoValueOfFunction.get(); }
 516 JSFunction* promiseResolveFunction() const { return m_promiseResolveFunction.get(); }
513517 JSFunction* newPromiseCapabilityFunction() const { return m_newPromiseCapabilityFunction.get(); }
514518 JSFunction* functionProtoHasInstanceSymbolFunction() const { return m_functionProtoHasInstanceSymbolFunction.get(); }
515519 JSObject* regExpProtoExecFunction() const { return m_regExpProtoExec.get(); }

Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp

3030#include "Exception.h"
3131#include "IndirectEvalExecutable.h"
3232#include "Interpreter.h"
 33#include "JSCInlines.h"
3334#include "JSFunction.h"
3435#include "JSGlobalObject.h"
3536#include "JSInternalPromise.h"
3637#include "JSModuleLoader.h"
 38#include "JSPromise.h"
3739#include "JSPromiseDeferred.h"
3840#include "JSString.h"
3941#include "JSStringBuilder.h"
4042#include "Lexer.h"
4143#include "LiteralParser.h"
4244#include "Nodes.h"
43 #include "JSCInlines.h"
4445#include "Parser.h"
4546#include "StackVisitor.h"
46 #include <wtf/dtoa.h>
4747#include <stdio.h>
4848#include <stdlib.h>
4949#include <wtf/ASCIICType.h>

5151#include <wtf/HexNumber.h>
5252#include <wtf/MathExtras.h>
5353#include <wtf/StringExtras.h>
 54#include <wtf/dtoa.h>
5455#include <wtf/text/StringBuilder.h>
5556#include <wtf/unicode/UTF8.h>
5657

@@EncodedJSValue JSC_HOST_CALL globalFuncProtoSetter(ExecState* exec)
926927 thisObject->setPrototype(vm, exec, value, shouldThrowIfCantSet);
927928 return JSValue::encode(jsUndefined());
928929}
 930
 931EncodedJSValue JSC_HOST_CALL globalFuncHostPromiseRejectionTracker(ExecState* exec)
 932{
 933 JSGlobalObject* globalObject = exec->lexicalGlobalObject();
 934 VM& vm = globalObject->vm();
 935 auto scope = DECLARE_THROW_SCOPE(vm);
 936
 937 if (!globalObject->globalObjectMethodTable()->promiseRejectionTracker)
 938 return JSValue::encode(jsUndefined());
 939
 940 JSPromise* promise = jsCast<JSPromise*>(exec->argument(0));
 941 JSValue operationValue = exec->argument(1);
 942
 943 ASSERT(operationValue.isNumber());
 944 auto operation = static_cast<JSPromiseRejectionOperation>(operationValue.toUInt32(exec));
 945 RETURN_IF_EXCEPTION(scope, encodedJSValue());
 946
 947 globalObject->globalObjectMethodTable()->promiseRejectionTracker(globalObject, exec, promise, operation);
 948 RETURN_IF_EXCEPTION(scope, encodedJSValue());
 949
 950 return JSValue::encode(jsUndefined());
 951}
929952
930953EncodedJSValue JSC_HOST_CALL globalFuncBuiltinLog(ExecState* exec)
931954{

Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.h

@@EncodedJSValue JSC_HOST_CALL globalFuncThrowTypeError(ExecState*);
4949EncodedJSValue JSC_HOST_CALL globalFuncThrowTypeErrorArgumentsCalleeAndCaller(ExecState*);
5050EncodedJSValue JSC_HOST_CALL globalFuncProtoGetter(ExecState*);
5151EncodedJSValue JSC_HOST_CALL globalFuncProtoSetter(ExecState*);
 52EncodedJSValue JSC_HOST_CALL globalFuncHostPromiseRejectionTracker(ExecState*);
5253EncodedJSValue JSC_HOST_CALL globalFuncBuiltinLog(ExecState*);
5354EncodedJSValue JSC_HOST_CALL globalFuncImportModule(ExecState*);
5455

Source/JavaScriptCore/runtime/JSPromise.cpp

@@JSValue JSPromise::result(VM& vm) const
8585 return getDirect(vm, vm.propertyNames->builtinNames().promiseResultPrivateName());
8686}
8787
 88bool JSPromise::isHandled(VM& vm) const
 89{
 90 JSValue value = getDirect(vm, vm.propertyNames->builtinNames().promiseIsHandledPrivateName());
 91 ASSERT(value.isBoolean());
 92 return value.asBoolean();
 93}
 94
8895} // namespace JSC

Source/JavaScriptCore/runtime/JSPromise.h

@@class JSPromise : public JSNonFinalObject {
4545 };
4646
4747 Status status(VM&) const;
48  JSValue result(VM&) const;
 48 JS_EXPORT_PRIVATE JSValue result(VM&) const;
 49 JS_EXPORT_PRIVATE bool isHandled(VM&) const;
4950
5051 // Initialize the promise with the executor.
5152 // This may raise a JS exception.

Source/WebCore/CMakeLists.txt

@@set(WebCore_NON_SVG_IDL_FILES
439439 dom/PopStateEvent.idl
440440 dom/ProcessingInstruction.idl
441441 dom/ProgressEvent.idl
 442 dom/PromiseRejectionEvent.idl
442443 dom/Range.idl
443444 dom/RequestAnimationFrameCallback.idl
444445 dom/SecurityPolicyViolationEvent.idl

@@set(WebCore_SOURCES
14731474 dom/PositionIterator.cpp
14741475 dom/ProcessingInstruction.cpp
14751476 dom/ProgressEvent.cpp
 1477 dom/PromiseRejectionEvent.cpp
14761478 dom/PseudoElement.cpp
14771479 dom/QualifiedName.cpp
14781480 dom/RadioButtonGroups.cpp
14791481 dom/Range.cpp
 1482 dom/RejectedPromiseTracker.cpp
14801483 dom/ScopedEventQueue.cpp
14811484 dom/ScriptElement.cpp
14821485 dom/ScriptElementCachedScriptFetcher.cpp

Source/WebCore/DerivedSources.cpp

382382#include "JSPositionOptions.cpp"
383383#include "JSProcessingInstruction.cpp"
384384#include "JSProgressEvent.cpp"
 385#include "JSPromiseRejectionEvent.cpp"
385386#include "JSRadioNodeList.cpp"
386387#include "JSRange.cpp"
387388#include "JSReadableByteStreamController.cpp"

Source/WebCore/DerivedSources.make

@@JS_BINDING_IDLS = \
373373 $(WebCore)/dom/PopStateEvent.idl \
374374 $(WebCore)/dom/ProcessingInstruction.idl \
375375 $(WebCore)/dom/ProgressEvent.idl \
376  $(WebCore)/dom/ProgressEvent.idl \
 376 $(WebCore)/dom/PromiseRejectionEvent.idl \
377377 $(WebCore)/dom/Range.idl \
378378 $(WebCore)/dom/RequestAnimationFrameCallback.idl \
379379 $(WebCore)/dom/SecurityPolicyViolationEvent.idl \

Source/WebCore/WebCore.xcodeproj/project.pbxproj

40844084 A56C5B9B189F34570082D13C /* WebConsoleAgent.h in Headers */ = {isa = PBXBuildFile; fileRef = A56C5B99189F34570082D13C /* WebConsoleAgent.h */; };
40854085 A5732B0A136A161D005C8D7C /* DateComponents.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A5732B08136A161D005C8D7C /* DateComponents.cpp */; };
40864086 A5732B0B136A161D005C8D7C /* DateComponents.h in Headers */ = {isa = PBXBuildFile; fileRef = A5732B09136A161D005C8D7C /* DateComponents.h */; settings = {ATTRIBUTES = (Private, ); }; };
 4087 A578F4351DE00EEB003DFC6A /* PromiseRejectionEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = A578F4331DE00ED6003DFC6A /* PromiseRejectionEvent.h */; };
 4088 A578F4361DE00EED003DFC6A /* PromiseRejectionEvent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A578F4321DE00ED6003DFC6A /* PromiseRejectionEvent.cpp */; };
 4089 A578F43B1DE01421003DFC6A /* JSPromiseRejectionEvent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A578F4391DE013FB003DFC6A /* JSPromiseRejectionEvent.cpp */; };
 4090 A578F43C1DE01423003DFC6A /* JSPromiseRejectionEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = A578F43A1DE013FB003DFC6A /* JSPromiseRejectionEvent.h */; };
 4091 A578F43F1DE0B630003DFC6A /* RejectedPromiseTracker.h in Headers */ = {isa = PBXBuildFile; fileRef = A578F43E1DE0B62B003DFC6A /* RejectedPromiseTracker.h */; settings = {ATTRIBUTES = (Private, ); }; };
 4092 A578F4401DE0B634003DFC6A /* RejectedPromiseTracker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A578F43D1DE0B62B003DFC6A /* RejectedPromiseTracker.cpp */; };
40874093 A57FD71B1DB9423E006AE24B /* WorkerRuntimeAgent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A57FD7191DB94236006AE24B /* WorkerRuntimeAgent.cpp */; };
40884094 A57FD71C1DB9423E006AE24B /* WorkerRuntimeAgent.h in Headers */ = {isa = PBXBuildFile; fileRef = A57FD71A1DB94236006AE24B /* WorkerRuntimeAgent.h */; };
40894095 A5840E1C187B74D500843B10 /* InspectorInstrumentationCookie.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A5840E1A187B74D500843B10 /* InspectorInstrumentationCookie.cpp */; };

63766382 E3150EA61DA7219000194012 /* JSNodeDOMJIT.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E3AFA9641DA6E908002861BD /* JSNodeDOMJIT.cpp */; };
63776383 E3150EA71DA7219300194012 /* DOMJITHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = E3150EA51DA7218D00194012 /* DOMJITHelpers.h */; };
63786384 E318039D1DC40099009932C2 /* JSDynamicDowncast.h in Headers */ = {isa = PBXBuildFile; fileRef = E3A5872E1DC3F52600F607A6 /* JSDynamicDowncast.h */; settings = {ATTRIBUTES = (Private, ); }; };
 6385 E323CFFA1E5AF6AF00F0B4A0 /* JSDOMConvertPromise.h in Headers */ = {isa = PBXBuildFile; fileRef = E323CFF91E5AF6A500F0B4A0 /* JSDOMConvertPromise.h */; settings = {ATTRIBUTES = (Private, ); }; };
63796386 E3565B7B1DC2D6C900217DBD /* JSEventCustom.h in Headers */ = {isa = PBXBuildFile; fileRef = E34EE49F1DC2D57500EAA9D3 /* JSEventCustom.h */; settings = {ATTRIBUTES = (Private, ); }; };
63806387 E35802B61DC8435D00A9773C /* DOMJITIDLTypeFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = E35802B51DC8435800A9773C /* DOMJITIDLTypeFilter.h */; settings = {ATTRIBUTES = (Private, ); }; };
63816388 E377FE4D1DADE16500CDD025 /* NodeConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = E3D049931DADC04500718F3C /* NodeConstants.h */; settings = {ATTRIBUTES = (Private, ); }; };

1189411901 A56C5B99189F34570082D13C /* WebConsoleAgent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebConsoleAgent.h; sourceTree = "<group>"; };
1189511902 A5732B08136A161D005C8D7C /* DateComponents.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DateComponents.cpp; sourceTree = "<group>"; };
1189611903 A5732B09136A161D005C8D7C /* DateComponents.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DateComponents.h; sourceTree = "<group>"; };
 11904 A578F4321DE00ED6003DFC6A /* PromiseRejectionEvent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PromiseRejectionEvent.cpp; sourceTree = "<group>"; };
 11905 A578F4331DE00ED6003DFC6A /* PromiseRejectionEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PromiseRejectionEvent.h; sourceTree = "<group>"; };
 11906 A578F4341DE00ED6003DFC6A /* PromiseRejectionEvent.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = PromiseRejectionEvent.idl; sourceTree = "<group>"; };
 11907 A578F4391DE013FB003DFC6A /* JSPromiseRejectionEvent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSPromiseRejectionEvent.cpp; sourceTree = "<group>"; };
 11908 A578F43A1DE013FB003DFC6A /* JSPromiseRejectionEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSPromiseRejectionEvent.h; sourceTree = "<group>"; };
 11909 A578F43D1DE0B62B003DFC6A /* RejectedPromiseTracker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RejectedPromiseTracker.cpp; sourceTree = "<group>"; };
 11910 A578F43E1DE0B62B003DFC6A /* RejectedPromiseTracker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RejectedPromiseTracker.h; sourceTree = "<group>"; };
1189711911 A57FD7191DB94236006AE24B /* WorkerRuntimeAgent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WorkerRuntimeAgent.cpp; sourceTree = "<group>"; };
1189811912 A57FD71A1DB94236006AE24B /* WorkerRuntimeAgent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WorkerRuntimeAgent.h; sourceTree = "<group>"; };
1189911913 A5840E1A187B74D500843B10 /* InspectorInstrumentationCookie.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InspectorInstrumentationCookie.cpp; sourceTree = "<group>"; };

1452514539 E307DED21D81E4ED00141CAF /* LoadableModuleScript.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LoadableModuleScript.cpp; sourceTree = "<group>"; };
1452614540 E307DED31D81E4ED00141CAF /* LoadableModuleScript.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LoadableModuleScript.h; sourceTree = "<group>"; };
1452714541 E3150EA51DA7218D00194012 /* DOMJITHelpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMJITHelpers.h; sourceTree = "<group>"; };
 14542 E323CFF91E5AF6A500F0B4A0 /* JSDOMConvertPromise.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSDOMConvertPromise.h; sourceTree = "<group>"; };
1452814543 E334825E1DC93AA0009C9544 /* DOMJITAbstractHeapRepository.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMJITAbstractHeapRepository.h; sourceTree = "<group>"; };
1452914544 E34EE49F1DC2D57500EAA9D3 /* JSEventCustom.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSEventCustom.h; sourceTree = "<group>"; };
1453014545 E35802B51DC8435800A9773C /* DOMJITIDLTypeFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMJITIDLTypeFilter.h; sourceTree = "<group>"; };

1874618761 7C8E34A11E4A338E0054CE23 /* JSDOMConvertNumbers.cpp */,
1874718762 7C8E34A21E4A338E0054CE23 /* JSDOMConvertNumbers.h */,
1874818763 7C8E34A31E4A338E0054CE23 /* JSDOMConvertObject.h */,
 18764 E323CFF91E5AF6A500F0B4A0 /* JSDOMConvertPromise.h */,
1874918765 7C8E34A41E4A338E0054CE23 /* JSDOMConvertRecord.h */,
1875018766 7C8E34A51E4A338E0054CE23 /* JSDOMConvertSequences.h */,
1875118767 7C8E34A61E4A338E0054CE23 /* JSDOMConvertSerializedScriptValue.h */,

2106521081 E1284BAF10449FFA00EAEB52 /* JSPageTransitionEvent.h */,
2106621082 5189F01B10B37BD900F3C739 /* JSPopStateEvent.cpp */,
2106721083 5189F01C10B37BD900F3C739 /* JSPopStateEvent.h */,
 21084 A578F4391DE013FB003DFC6A /* JSPromiseRejectionEvent.cpp */,
 21085 A578F43A1DE013FB003DFC6A /* JSPromiseRejectionEvent.h */,
2106821086 CED06ACE1C77754800FDFAF1 /* JSSecurityPolicyViolationEvent.cpp */,
2106921087 CED06ACF1C77754800FDFAF1 /* JSSecurityPolicyViolationEvent.h */,
2107021088 A86629CE09DA2B47009633A7 /* JSStaticRange.cpp */,

2465624674 E4B41E010CBF8EAA00AF2ECE /* ProgressEvent.cpp */,
2465724675 E4B41E020CBF8EAA00AF2ECE /* ProgressEvent.h */,
2465824676 E4B41E030CBF8EAA00AF2ECE /* ProgressEvent.idl */,
 24677 A578F4321DE00ED6003DFC6A /* PromiseRejectionEvent.cpp */,
 24678 A578F4331DE00ED6003DFC6A /* PromiseRejectionEvent.h */,
 24679 A578F4341DE00ED6003DFC6A /* PromiseRejectionEvent.idl */,
2465924680 FF945EC9161F7F3600971BC8 /* PseudoElement.cpp */,
2466024681 FF945ECA161F7F3600971BC8 /* PseudoElement.h */,
2466124682 550A0BC7085F6039007353D6 /* QualifiedName.cpp */,

2466824689 93D9D53B0DA27E180077216C /* RangeBoundaryPoint.h */,
2466924690 A84D827B11D333ED00972990 /* RawDataDocumentParser.h */,
2467024691 85031B360A44EFC700F992E0 /* RegisteredEventListener.h */,
 24692 A578F43D1DE0B62B003DFC6A /* RejectedPromiseTracker.cpp */,
 24693 A578F43E1DE0B62B003DFC6A /* RejectedPromiseTracker.h */,
2467124694 A76E5F7E135E0DCF00A69837 /* RenderedDocumentMarker.h */,
2467224695 4998AEC413F9D0EA0090B1AA /* RequestAnimationFrameCallback.h */,
2467324696 4998AEC513F9D0EA0090B1AA /* RequestAnimationFrameCallback.idl */,

2568225705 BC772B3C0C4EA91E0083285F /* CSSHelper.h in Headers */,
2568325706 BC23EE920DAED2BC009FDC91 /* CSSImageGeneratorValue.h in Headers */,
2568425707 9393E600151A99F200066F06 /* CSSImageSetValue.h in Headers */,
 25708 A578F4351DE00EEB003DFC6A /* PromiseRejectionEvent.h in Headers */,
2568525709 A80E6CFA0A1989CA007FB8C5 /* CSSImageValue.h in Headers */,
2568625710 A80E6CF60A1989CA007FB8C5 /* CSSImportRule.h in Headers */,
2568725711 A80E6D010A1989CA007FB8C5 /* CSSInheritedValue.h in Headers */,

2586425888 86D982F7125C154000AD9E3D /* DocumentTiming.h in Headers */,
2586525889 A8185F3909765766005826D9 /* DocumentType.h in Headers */,
2586625890 973889A1116EA9DC00ADF313 /* DocumentWriter.h in Headers */,
 25891 A578F43C1DE01423003DFC6A /* JSPromiseRejectionEvent.h in Headers */,
2586725892 1A8F6BC30DB55CDC001DB794 /* DOMApplicationCache.h in Headers */,
2586825893 BC60D6E90D28D83400B9918F /* DOMCoreException.h in Headers */,
2586925894 FC9A0F75164094CF003D6B8D /* DOMCSSNamespace.h in Headers */,

2758327608 499B3EC5128CCC4700E726C2 /* PlatformCALayer.h in Headers */,
2758427609 493E5E0912D6420500020081 /* PlatformCALayerClient.h in Headers */,
2758527610 2D70BA1318074DDF0001908A /* PlatformCALayerCocoa.h in Headers */,
 27611 A578F43F1DE0B630003DFC6A /* RejectedPromiseTracker.h in Headers */,
2758627612 A14978711ABAF3A500CEF7E4 /* PlatformContentFilter.h in Headers */,
2758727613 E1424C8A164B3B4E00F32D40 /* PlatformCookieJar.h in Headers */,
2758827614 BC5C762B1497FE1400BC4775 /* PlatformEvent.h in Headers */,

2834628372 83C1D427178D5AB400141E68 /* SVGPathSegCurvetoCubicAbs.h in Headers */,
2834728373 83C1D428178D5AB400141E68 /* SVGPathSegCurvetoCubicRel.h in Headers */,
2834828374 B2227A690D00BF220071B782 /* SVGPathSegCurvetoCubicSmooth.h in Headers */,
 28375 E323CFFA1E5AF6AF00F0B4A0 /* JSDOMConvertPromise.h in Headers */,
2834928376 83C1D429178D5AB400141E68 /* SVGPathSegCurvetoCubicSmoothAbs.h in Headers */,
2835028377 83C1D42A178D5AB400141E68 /* SVGPathSegCurvetoCubicSmoothRel.h in Headers */,
2835128378 B2227A6D0D00BF220071B782 /* SVGPathSegCurvetoQuadratic.h in Headers */,

3029130318 BC946346107A934B00857193 /* JSBeforeLoadEvent.cpp in Sources */,
3029230319 70F546E8B8B5D7DC54EE144E /* JSBeforeUnloadEvent.cpp in Sources */,
3029330320 FDF09DC81399B62200688E5B /* JSBiquadFilterNode.cpp in Sources */,
 30321 A578F43B1DE01421003DFC6A /* JSPromiseRejectionEvent.cpp in Sources */,
3029430322 2E2D99CD10E2BBDA00496337 /* JSBlob.cpp in Sources */,
3029530323 8931DE5B14C44C44000DC9D2 /* JSBlobCustom.cpp in Sources */,
3029630324 7C77C3DB1DEF86D700A50BFA /* JSBlobLineEndings.cpp in Sources */,

3112631154 2D9BF7471DBFDC49007A7D99 /* MediaKeyMessageEvent.cpp in Sources */,
3112731155 2D9BF7461DBFDC47007A7D99 /* MediaKeys.cpp in Sources */,
3112831156 2D9BF7451DBFDC44007A7D99 /* MediaKeySession.cpp in Sources */,
 31157 A578F4401DE0B634003DFC6A /* RejectedPromiseTracker.cpp in Sources */,
3112931158 2D9BF7441DBFDC41007A7D99 /* MediaKeyStatusMap.cpp in Sources */,
3113031159 2D9BF7431DBFDC3E007A7D99 /* MediaKeySystemAccess.cpp in Sources */,
3113131160 A8EA80090A19516E00A8EF5F /* MediaList.cpp in Sources */,

3235232381 93309E23099E64920056E581 /* WrapContentsInDummySpanCommand.cpp in Sources */,
3235332382 A833C7CC0A2CF07400D57664 /* XLinkNames.cpp in Sources */,
3235432383 00B9318713BA8DB30035A948 /* XMLDocumentParser.cpp in Sources */,
 32384 A578F4361DE00EED003DFC6A /* PromiseRejectionEvent.cpp in Sources */,
3235532385 00B9318913BA8DBC0035A948 /* XMLDocumentParserLibxml2.cpp in Sources */,
3235632386 00B9318B13BA8DC90035A948 /* XMLDocumentParserScope.cpp in Sources */,
3235732387 59C28045138DC2410079B7E2 /* XMLErrors.cpp in Sources */,

Source/WebCore/bindings/js/JSDOMConvert.h

4040#include "JSDOMConvertNullable.h"
4141#include "JSDOMConvertNumbers.h"
4242#include "JSDOMConvertObject.h"
 43#include "JSDOMConvertPromise.h"
4344#include "JSDOMConvertRecord.h"
4445#include "JSDOMConvertSequences.h"
4546#include "JSDOMConvertSerializedScriptValue.h"

Source/WebCore/bindings/js/JSDOMConvertPromise.h

 1/*
 2 * Copyright (C) 2017 Yusuke Suzuki <utatane.tea@gmail.com>
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 23 * THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#pragma once
 27
 28#include "IDLTypes.h"
 29#include "JSDOMConvertBase.h"
 30
 31namespace WebCore {
 32
 33// FIXME: Implement IDLPromise<> conversions.
 34// https://bugs.webkit.org/show_bug.cgi?id=166752
 35template<typename T>
 36struct Converter<IDLPromise<T>> : DefaultConverter<IDLPromise<T>> {
 37 using ReturnType = JSC::JSValue;
 38
 39 static JSC::JSValue convert(JSC::ExecState&, JSC::JSValue value)
 40 {
 41 return value;
 42 }
 43};
 44
 45template<typename T>
 46struct JSConverter<IDLPromise<T>> {
 47 using Type = JSC::JSValue;
 48 static constexpr bool needsState = false;
 49 static constexpr bool needsGlobalObject = false;
 50
 51 static JSC::JSValue convert(JSC::JSValue value)
 52 {
 53 return value;
 54 }
 55};
 56
 57} // namespace WebCore

Source/WebCore/bindings/js/JSDOMWindowBase.cpp

3838#include "Language.h"
3939#include "Logging.h"
4040#include "Page.h"
 41#include "RejectedPromiseTracker.h"
4142#include "RuntimeApplicationChecks.h"
4243#include "ScriptController.h"
4344#include "ScriptModuleLoader.h"

4647#include "WebCoreJSClientData.h"
4748#include <bytecode/CodeBlock.h>
4849#include <heap/StrongInlines.h>
 50#include <runtime/JSInternalPromise.h>
4951#include <runtime/JSInternalPromiseDeferred.h>
5052#include <runtime/Microtask.h>
5153#include <wtf/MainThread.h>

@@const GlobalObjectMethodTable JSDOMWindowBase::s_globalObjectMethodTable = {
6971 &moduleLoaderImportModule,
7072 &moduleLoaderResolve,
7173 &moduleLoaderFetch,
72  nullptr,
 74 nullptr, // moduleLoaderInstantiate
7375 &moduleLoaderEvaluate,
 76 &promiseRejectionTracker,
7477 &defaultLanguage
7578};
7679

@@void JSDOMWindowBase::fireFrameClearedWatchpointsForWindow(DOMWindow* window)
355358 }
356359}
357360
358 
359361JSC::JSInternalPromise* JSDOMWindowBase::moduleLoaderResolve(JSC::JSGlobalObject* globalObject, JSC::ExecState* exec, JSC::JSModuleLoader* moduleLoader, JSC::JSValue moduleName, JSC::JSValue importerModuleKey, JSC::JSValue scriptFetcher)
360362{
361363 JSDOMWindowBase* thisObject = JSC::jsCast<JSDOMWindowBase*>(globalObject);

@@JSC::JSInternalPromise* JSDOMWindowBase::moduleLoaderImportModule(JSC::JSGlobalO
391393 return deferred->reject(exec, jsUndefined());
392394}
393395
 396void JSDOMWindowBase::promiseRejectionTracker(JSGlobalObject* jsGlobalObject, ExecState* exec, JSPromise* promise, JSPromiseRejectionOperation operation)
 397{
 398 VM& vm = exec->vm();
 399 auto& globalObject = *JSC::jsCast<JSDOMWindowBase*>(jsGlobalObject);
 400 auto* context = globalObject.scriptExecutionContext();
 401 if (!context)
 402 return;
 403
 404 // The state of InternalPromise is hidden in the browser side.
 405 if (JSC::jsDynamicCast<JSC::JSInternalPromise*>(vm, promise))
 406 return;
 407
 408 // FIXME: Cross origin check.
 409 auto sourceOrigin = exec->callerSourceOrigin();
 410 UNUSED_PARAM(sourceOrigin);
 411
 412 switch (operation) {
 413 case JSPromiseRejectionOperation::Reject:
 414 context->ensureRejectedPromiseTracker().promiseRejected(*exec, globalObject, *promise);
 415 break;
 416 case JSPromiseRejectionOperation::Handle:
 417 context->ensureRejectedPromiseTracker().promiseHandled(*exec, globalObject, *promise);
 418 break;
 419 }
 420}
 421
394422} // namespace WebCore

Source/WebCore/bindings/js/JSDOMWindowBase.h

@@namespace WebCore {
8080 static JSC::JSInternalPromise* moduleLoaderFetch(JSC::JSGlobalObject*, JSC::ExecState*, JSC::JSModuleLoader*, JSC::JSValue, JSC::JSValue);
8181 static JSC::JSValue moduleLoaderEvaluate(JSC::JSGlobalObject*, JSC::ExecState*, JSC::JSModuleLoader*, JSC::JSValue, JSC::JSValue, JSC::JSValue);
8282 static JSC::JSInternalPromise* moduleLoaderImportModule(JSC::JSGlobalObject*, JSC::ExecState*, JSC::JSModuleLoader*, JSC::JSString*, const JSC::SourceOrigin&);
 83 static void promiseRejectionTracker(JSC::JSGlobalObject*, JSC::ExecState*, JSC::JSPromise*, JSC::JSPromiseRejectionOperation);
8384
8485 RefPtr<DOMWindow> m_wrapped;
8586 JSDOMWindowShell* m_shell;

Source/WebCore/bindings/js/JSMainThreadExecState.cpp

2828
2929#include "Microtasks.h"
3030#include "MutationObserver.h"
 31#include "RejectedPromiseTracker.h"
 32#include "ScriptExecutionContext.h"
 33#include "ScriptState.h"
3134
3235namespace WebCore {
3336
3437JSC::ExecState* JSMainThreadExecState::s_mainThreadState = 0;
3538
36 void JSMainThreadExecState::didLeaveScriptContext()
 39void JSMainThreadExecState::didLeaveScriptContext(JSC::ExecState* exec)
3740{
3841 MicrotaskQueue::mainThreadQueue().performMicrotaskCheckpoint();
 42 scriptExecutionContextFromExecState(exec)->ensureRejectedPromiseTracker().processQueueSoon();
3943}
4044
4145JSC::JSValue functionCallHandlerFromAnyThread(JSC::ExecState* exec, JSC::JSValue functionObject, JSC::CallType callType, const JSC::CallData& callData, JSC::JSValue thisValue, const JSC::ArgList& args, NakedPtr<JSC::Exception>& returnedException)

Source/WebCore/bindings/js/JSMainThreadExecState.h

@@class JSMainThreadExecState {
139139 ASSERT(isMainThread());
140140 ASSERT_UNUSED(scope, !scope.exception());
141141
 142 JSC::ExecState* state = s_mainThreadState;
142143 bool didExitJavaScript = s_mainThreadState && !m_previousState;
143144
144145 s_mainThreadState = m_previousState;
145146
146147 if (didExitJavaScript)
147  didLeaveScriptContext();
 148 didLeaveScriptContext(state);
148149 }
149150
150151 template<typename Type, Type jsType, typename DataType> static InspectorInstrumentationCookie instrumentFunctionInternal(ScriptExecutionContext*, Type, const DataType&);

@@class JSMainThreadExecState {
153154 JSC::ExecState* m_previousState;
154155 JSC::JSLockHolder m_lock;
155156
156  static void didLeaveScriptContext();
 157 static void didLeaveScriptContext(JSC::ExecState*);
157158};
158159
159160// Null state prevents origin security checks.

Source/WebCore/bindings/js/JSWorkerGlobalScopeBase.cpp

@@const GlobalObjectMethodTable JSWorkerGlobalScopeBase::s_globalObjectMethodTable
5252 &javaScriptRuntimeFlags,
5353 &queueTaskToEventLoop,
5454 &shouldInterruptScriptBeforeTimeout,
55  nullptr,
56  nullptr,
57  nullptr,
58  nullptr,
59  nullptr,
 55 nullptr, // moduleLoaderImportModule
 56 nullptr, // moduleLoaderResolve
 57 nullptr, // moduleLoaderFetch
 58 nullptr, // moduleLoaderInstantiate
 59 nullptr, // moduleLoaderEvaluate
 60 nullptr, // promiseRejectionTracker
6061 &defaultLanguage
6162};
6263

Source/WebCore/bindings/scripts/CodeGenerator.pm

@@sub IsRecordType
686686 return $type->name eq "record";
687687}
688688
 689sub IsPromiseType
 690{
 691 my ($object, $type) = @_;
 692
 693 assert("Not a type") if ref($type) ne "IDLType";
 694
 695 return $type->name eq "Promise";
 696}
 697
689698# These match WK_lcfirst and WK_ucfirst defined in builtins_generator.py.
690699# Uppercase the first letter while respecting WebKit style guidelines.
691700# E.g., xmlEncoding becomes XMLEncoding, but xmlllang becomes Xmllang.

Source/WebCore/bindings/scripts/CodeGeneratorJS.pm

@@sub AddToIncludesForIDLType
303303 return;
304304 }
305305
 306 if ($codeGenerator->IsPromiseType($type)) {
 307 AddToIncludes("JSDOMPromise.h", $includesRef, $conditional);
 308 AddToIncludesForIDLType(@{$type->subtypes}[0], $includesRef, $conditional);
 309 return;
 310 }
 311
306312 if ($codeGenerator->IsWrapperType($type) || $codeGenerator->IsExternalDictionaryType($type) || $codeGenerator->IsExternalEnumType($type) || $type->name eq "EventListener") {
307313 AddToIncludes("JS" . $type->name . ".h", $includesRef, $conditional);
308314 return;

@@sub GetBaseIDLType
53645370 return "IDLSequence<" . GetIDLType($interface, @{$type->subtypes}[0]) . ">" if $codeGenerator->IsSequenceType($type);
53655371 return "IDLFrozenArray<" . GetIDLType($interface, @{$type->subtypes}[0]) . ">" if $codeGenerator->IsFrozenArrayType($type);
53665372 return "IDLRecord<" . GetIDLType($interface, @{$type->subtypes}[0]) . ", " . GetIDLType($interface, @{$type->subtypes}[1]) . ">" if $codeGenerator->IsRecordType($type);
 5373 return "IDLPromise<" . GetIDLType($interface, @{$type->subtypes}[0]) . ">" if $codeGenerator->IsPromiseType($type);
53675374 return "IDLUnion<" . join(", ", GetIDLUnionMemberTypes($interface, $type)) . ">" if $type->isUnion;
53685375 return "IDLCallbackFunction<" . GetCallbackClassName($type->name) . ">" if $codeGenerator->IsCallbackFunction($type);
53695376 return "IDLCallbackInterface<" . GetCallbackClassName($type->name) . ">" if $codeGenerator->IsCallbackInterface($type);

Source/WebCore/dom/DOMAllInOne.cpp

126126// #include "QualifiedName.cpp"
127127#include "RadioButtonGroups.cpp"
128128#include "Range.cpp"
 129#include "RejectedPromiseTracker.cpp"
129130#include "ScopedEventQueue.cpp"
130131#include "ScriptElement.cpp"
131132#include "ScriptExecutionContext.cpp"

Source/WebCore/dom/EventNames.h

@@namespace WebCore {
181181 macro(progress) \
182182 macro(ratechange) \
183183 macro(readystatechange) \
 184 macro(rejectionhandled) \
184185 macro(removesourcebuffer) \
185186 macro(removestream) \
186187 macro(removetrack) \

@@namespace WebCore {
229230 macro(touchstart) \
230231 macro(track) \
231232 macro(transitionend) \
 233 macro(unhandledrejection) \
232234 macro(unload) \
233235 macro(unmute) \
234236 macro(update) \

Source/WebCore/dom/EventNames.in

@@OverflowEvent
2626PageTransitionEvent
2727PopStateEvent
2828ProgressEvent
 29PromiseRejectionEvent
2930TextEvent
3031TransitionEvent
3132UIEvent

Source/WebCore/dom/GlobalEventHandlers.idl

7979 attribute EventHandler onplaying;
8080 attribute EventHandler onprogress;
8181 attribute EventHandler onratechange;
 82 attribute EventHandler onrejectionhandled;
8283 attribute EventHandler onreset;
8384 attribute EventHandler onresize;
8485 attribute EventHandler onscroll;

9293 attribute EventHandler onsuspend;
9394 attribute EventHandler ontimeupdate;
9495 attribute EventHandler ontoggle;
 96 attribute EventHandler onunhandledrejection;
9597 attribute EventHandler onvolumechange;
9698 attribute EventHandler onwaiting;
9799

Source/WebCore/dom/PromiseRejectionEvent.cpp

 1/*
 2* Copyright (C) 2016 Apple Inc. All rights reserved.
 3*
 4* Redistribution and use in source and binary forms, with or without
 5* modification, are permitted provided that the following conditions
 6* are met:
 7* 1. Redistributions of source code must retain the above copyright
 8* notice, this list of conditions and the following disclaimer.
 9* 2. Redistributions in binary form must reproduce the above copyright
 10* notice, this list of conditions and the following disclaimer in the
 11* documentation and/or other materials provided with the distribution.
 12*
 13* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 14* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
 17* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 24*/
 25
 26#include "config.h"
 27#include "PromiseRejectionEvent.h"
 28
 29#include "DOMWrapperWorld.h"
 30#include <heap/HeapInlines.h>
 31#include <heap/StrongInlines.h>
 32
 33using namespace JSC;
 34
 35namespace WebCore {
 36
 37PromiseRejectionEvent::PromiseRejectionEvent(ExecState& state, const AtomicString& type, const Init& initializer, IsTrusted isTrusted)
 38 : Event(type, initializer, isTrusted)
 39 , m_promise(state.vm(), initializer.promise)
 40 , m_reason(state.vm(), initializer.reason)
 41{
 42}
 43
 44PromiseRejectionEvent::~PromiseRejectionEvent()
 45{
 46}
 47
 48} // namespace WebCore

Source/WebCore/dom/PromiseRejectionEvent.h

 1/*
 2* Copyright (C) 2016 Apple Inc. All rights reserved.
 3*
 4* Redistribution and use in source and binary forms, with or without
 5* modification, are permitted provided that the following conditions
 6* are met:
 7* 1. Redistributions of source code must retain the above copyright
 8* notice, this list of conditions and the following disclaimer.
 9* 2. Redistributions in binary form must reproduce the above copyright
 10* notice, this list of conditions and the following disclaimer in the
 11* documentation and/or other materials provided with the distribution.
 12*
 13* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 14* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
 17* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 24*/
 25
 26#pragma once
 27
 28#include "Event.h"
 29#include <heap/Strong.h>
 30
 31namespace WebCore {
 32
 33class PromiseRejectionEvent final : public Event {
 34public:
 35 struct Init : EventInit {
 36 JSC::JSValue promise;
 37 JSC::JSValue reason;
 38 };
 39
 40 static Ref<PromiseRejectionEvent> create(JSC::ExecState& state, const AtomicString& type, const Init& initializer, IsTrusted isTrusted = IsTrusted::No)
 41 {
 42 return adoptRef(*new PromiseRejectionEvent(state, type, initializer, isTrusted));
 43 }
 44
 45 virtual ~PromiseRejectionEvent();
 46
 47 JSC::JSValue promise() const { return m_promise.get(); }
 48 JSC::JSValue reason() const { return m_reason.get(); }
 49
 50 EventInterface eventInterface() const override { return PromiseRejectionEventInterfaceType; }
 51
 52private:
 53 PromiseRejectionEvent(JSC::ExecState&, const AtomicString&, const Init&, IsTrusted);
 54
 55 JSC::Strong<JSC::Unknown> m_promise;
 56 JSC::Strong<JSC::Unknown> m_reason;
 57};
 58
 59} // namespace WebCore

Source/WebCore/dom/PromiseRejectionEvent.idl

 1/*
 2* Copyright (C) 2016 Apple Inc. All rights reserved.
 3*
 4* Redistribution and use in source and binary forms, with or without
 5* modification, are permitted provided that the following conditions
 6* are met:
 7* 1. Redistributions of source code must retain the above copyright
 8* notice, this list of conditions and the following disclaimer.
 9* 2. Redistributions in binary form must reproduce the above copyright
 10* notice, this list of conditions and the following disclaimer in the
 11* documentation and/or other materials provided with the distribution.
 12*
 13* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 14* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
 17* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 24*/
 25
 26[
 27 Constructor(DOMString type, PromiseRejectionEventInit eventInitDict),
 28 ConstructorCallWith=ScriptState,
 29 Exposed=(Window,Worker),
 30] interface PromiseRejectionEvent : Event {
 31 readonly attribute Promise<any> promise;
 32 readonly attribute any reason;
 33};
 34
 35dictionary PromiseRejectionEventInit : EventInit {
 36 required Promise<any> promise;
 37 any reason;
 38};

Source/WebCore/dom/RejectedPromiseTracker.cpp

 1/*
 2 * Copyright (C) 2016 Apple Inc. All rights reserved.
 3 * Copyright (C) 2017 Yusuke Suzuki <utatane.tea@gmail.com>
 4 *
 5 * Redistribution and use in source and binary forms, with or without
 6 * modification, are permitted provided that the following conditions
 7 * are met:
 8 * 1. Redistributions of source code must retain the above copyright
 9 * notice, this list of conditions and the following disclaimer.
 10 * 2. Redistributions in binary form must reproduce the above copyright
 11 * notice, this list of conditions and the following disclaimer in the
 12 * documentation and/or other materials provided with the distribution.
 13 *
 14 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
 18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 25 */
 26
 27#include "config.h"
 28#include "RejectedPromiseTracker.h"
 29
 30#include "EventNames.h"
 31#include "EventTarget.h"
 32#include "JSDOMGlobalObject.h"
 33#include "PromiseRejectionEvent.h"
 34#include "ScriptExecutionContext.h"
 35#include <heap/HeapInlines.h>
 36#include <heap/Strong.h>
 37#include <heap/StrongInlines.h>
 38#include <heap/Weak.h>
 39#include <heap/WeakInlines.h>
 40#include <inspector/ScriptCallStack.h>
 41#include <inspector/ScriptCallStackFactory.h>
 42#include <runtime/Exception.h>
 43#include <runtime/JSCJSValueInlines.h>
 44#include <runtime/JSGlobalObject.h>
 45#include <runtime/JSPromise.h>
 46#include <runtime/WeakGCMapInlines.h>
 47
 48using namespace JSC;
 49using namespace Inspector;
 50
 51namespace WebCore {
 52
 53class RejectedPromise {
 54 WTF_MAKE_NONCOPYABLE(RejectedPromise);
 55public:
 56 RejectedPromise(VM& vm, JSDOMGlobalObject& globalObject, JSPromise& promise)
 57 : m_globalObject(vm, &globalObject)
 58 , m_promise(vm, &promise)
 59 {
 60 }
 61
 62 RejectedPromise(RejectedPromise&&) = default;
 63
 64 JSDOMGlobalObject& globalObject()
 65 {
 66 return *m_globalObject.get();
 67 }
 68
 69 JSPromise& promise()
 70 {
 71 return *m_promise.get();
 72 }
 73
 74private:
 75 Strong<JSDOMGlobalObject> m_globalObject;
 76 Strong<JSPromise> m_promise;
 77};
 78
 79class UnhandledPromise : public RejectedPromise {
 80public:
 81 UnhandledPromise(VM& vm, JSDOMGlobalObject& globalObject, JSPromise& promise, Ref<ScriptCallStack>&& stack)
 82 : RejectedPromise(vm, globalObject, promise)
 83 , m_stack(WTFMove(stack))
 84 {
 85 }
 86
 87 ScriptCallStack& callStack()
 88 {
 89 return m_stack.get();
 90 }
 91
 92private:
 93 Ref<ScriptCallStack> m_stack;
 94};
 95
 96
 97RejectedPromiseTracker::RejectedPromiseTracker(ScriptExecutionContext& context, JSC::VM& vm)
 98 : m_context(context)
 99 , m_outstandingRejectedPromises(vm)
 100{
 101}
 102
 103RejectedPromiseTracker::~RejectedPromiseTracker()
 104{
 105}
 106
 107static Ref<ScriptCallStack> createScriptCallStackFromReason(ExecState& state, JSValue reason)
 108{
 109 VM& vm = state.vm();
 110 if (auto* exception = jsDynamicCast<JSC::Exception*>(vm, reason))
 111 return createScriptCallStackFromException(&state, exception, ScriptCallStack::maxCallStackSizeToCapture);
 112 return createScriptCallStack(&state, ScriptCallStack::maxCallStackSizeToCapture);
 113}
 114
 115void RejectedPromiseTracker::promiseRejected(ExecState& state, JSDOMGlobalObject& globalObject, JSPromise& promise)
 116{
 117 // https://html.spec.whatwg.org/multipage/webappapis.html#the-hostpromiserejectiontracker-implementation
 118
 119 VM& vm = state.vm();
 120 JSValue reason = promise.result(vm);
 121 m_aboutToBeNotifiedRejectedPromises.append(UnhandledPromise { vm, globalObject, promise, createScriptCallStackFromReason(state, reason) });
 122}
 123
 124void RejectedPromiseTracker::promiseHandled(ExecState& state, JSDOMGlobalObject& globalObject, JSPromise& promise)
 125{
 126 // https://html.spec.whatwg.org/multipage/webappapis.html#the-hostpromiserejectiontracker-implementation
 127
 128 bool removed = m_aboutToBeNotifiedRejectedPromises.removeFirstMatching([&] (UnhandledPromise& unhandledPromise) {
 129 return &unhandledPromise.promise() == &promise;
 130 });
 131 if (removed)
 132 return;
 133
 134 if (!m_outstandingRejectedPromises.remove(&promise))
 135 return;
 136
 137 VM& vm = state.vm();
 138
 139 m_context.postTask([this, rejectedPromise = RejectedPromise { vm, globalObject, promise }] (ScriptExecutionContext&) mutable {
 140 reportRejectionHandled(WTFMove(rejectedPromise));
 141 });
 142}
 143
 144void RejectedPromiseTracker::processQueueSoon()
 145{
 146 // https://html.spec.whatwg.org/multipage/webappapis.html#unhandled-promise-rejections
 147
 148 if (m_aboutToBeNotifiedRejectedPromises.isEmpty())
 149 return;
 150
 151 Vector<UnhandledPromise> items;
 152 items.swap(m_aboutToBeNotifiedRejectedPromises);
 153
 154 m_context.postTask([this, items = WTFMove(items)] (ScriptExecutionContext&) mutable {
 155 reportUnhandledRejection(WTFMove(items));
 156 });
 157}
 158
 159void RejectedPromiseTracker::reportUnhandledRejection(Vector<UnhandledPromise>&& unhandledPromises)
 160{
 161 // https://html.spec.whatwg.org/multipage/webappapis.html#unhandled-promise-rejections
 162
 163 VM& vm = m_context.vm();
 164 JSC::JSLockHolder lock(vm);
 165
 166 for (auto& unhandledPromise : unhandledPromises) {
 167 ExecState& state = *unhandledPromise.globalObject().globalExec();
 168 auto& promise = unhandledPromise.promise();
 169
 170 if (promise.isHandled(vm))
 171 continue;
 172
 173 PromiseRejectionEvent::Init initializer;
 174 initializer.cancelable = true;
 175 initializer.promise = &promise;
 176 initializer.reason = promise.result(vm);
 177
 178 auto event = PromiseRejectionEvent::create(state, eventNames().unhandledrejectionEvent, initializer);
 179 auto target = m_context.errorEventTarget();
 180 bool needsDefaultAction = target->dispatchEvent(event);
 181
 182 if (needsDefaultAction)
 183 m_context.reportUnhandledPromiseRejection(state, unhandledPromise.promise(), unhandledPromise.callStack());
 184
 185 if (!promise.isHandled(vm))
 186 m_outstandingRejectedPromises.set(&promise, &promise);
 187 }
 188}
 189
 190void RejectedPromiseTracker::reportRejectionHandled(RejectedPromise&& rejectedPromise)
 191{
 192 // https://html.spec.whatwg.org/multipage/webappapis.html#the-hostpromiserejectiontracker-implementation
 193
 194 VM& vm = m_context.vm();
 195 JSC::JSLockHolder lock(vm);
 196
 197 ExecState& state = *rejectedPromise.globalObject().globalExec();
 198
 199 PromiseRejectionEvent::Init initializer;
 200 initializer.cancelable = false;
 201 initializer.promise = &rejectedPromise.promise();
 202 initializer.reason = rejectedPromise.promise().result(state.vm());
 203
 204 auto event = PromiseRejectionEvent::create(state, eventNames().rejectionhandledEvent, initializer);
 205 auto target = m_context.errorEventTarget();
 206 target->dispatchEvent(event);
 207}
 208
 209} // namespace WebCore

Source/WebCore/dom/RejectedPromiseTracker.h

 1/*
 2 * Copyright (C) 2016 Apple Inc. All rights reserved.
 3 * Copyright (C) 2017 Yusuke Suzuki <utatane.tea@gmail.com>
 4 *
 5 * Redistribution and use in source and binary forms, with or without
 6 * modification, are permitted provided that the following conditions
 7 * are met:
 8 * 1. Redistributions of source code must retain the above copyright
 9 * notice, this list of conditions and the following disclaimer.
 10 * 2. Redistributions in binary form must reproduce the above copyright
 11 * notice, this list of conditions and the following disclaimer in the
 12 * documentation and/or other materials provided with the distribution.
 13 *
 14 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
 18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 25 */
 26
 27#pragma once
 28
 29#include <runtime/JSPromise.h>
 30#include <runtime/WeakGCMap.h>
 31#include <wtf/Forward.h>
 32#include <wtf/Noncopyable.h>
 33#include <wtf/Vector.h>
 34
 35namespace JSC {
 36class VM;
 37}
 38
 39namespace WebCore {
 40
 41class JSDOMGlobalObject;
 42class RejectedPromise;
 43class ScriptExecutionContext;
 44class UnhandledPromise;
 45
 46class RejectedPromiseTracker {
 47 WTF_MAKE_NONCOPYABLE(RejectedPromiseTracker);
 48public:
 49 explicit RejectedPromiseTracker(ScriptExecutionContext&, JSC::VM&);
 50 ~RejectedPromiseTracker();
 51
 52 void promiseRejected(JSC::ExecState&, JSDOMGlobalObject&, JSC::JSPromise&);
 53 void promiseHandled(JSC::ExecState&, JSDOMGlobalObject&, JSC::JSPromise&);
 54
 55 void processQueueSoon();
 56
 57private:
 58 void reportUnhandledRejection(Vector<UnhandledPromise>&&);
 59 void reportRejectionHandled(RejectedPromise&&);
 60
 61 ScriptExecutionContext& m_context;
 62 Vector<UnhandledPromise> m_aboutToBeNotifiedRejectedPromises;
 63 JSC::WeakGCMap<JSC::JSPromise*, JSC::JSPromise> m_outstandingRejectedPromises;
 64};
 65
 66} // namespace WebCore

Source/WebCore/dom/ScriptExecutionContext.cpp

3434#include "DatabaseContext.h"
3535#include "Document.h"
3636#include "ErrorEvent.h"
 37#include "JSDOMExceptionHandling.h"
3738#include "JSDOMWindow.h"
3839#include "MessagePort.h"
3940#include "NoEventDispatchAssertion.h"
4041#include "PublicURLManager.h"
 42#include "RejectedPromiseTracker.h"
4143#include "ResourceRequest.h"
4244#include "ScriptState.h"
4345#include "Settings.h"

4648#include <heap/StrongInlines.h>
4749#include <inspector/ScriptCallStack.h>
4850#include <runtime/Exception.h>
 51#include <runtime/JSPromise.h>
4952#include <wtf/MainThread.h>
5053#include <wtf/Ref.h>
5154

@@void ScriptExecutionContext::reportException(const String& errorMessage, int lin
379382 logExceptionToConsole(exception->m_errorMessage, exception->m_sourceURL, exception->m_lineNumber, exception->m_columnNumber, WTFMove(exception->m_callStack));
380383}
381384
 385void ScriptExecutionContext::reportUnhandledPromiseRejection(JSC::ExecState& state, JSC::JSPromise& promise, Inspector::ScriptCallStack& callStack)
 386{
 387 JSC::VM& vm = state.vm();
 388 auto scope = DECLARE_CATCH_SCOPE(vm);
 389
 390 int lineNumber = 0;
 391 int columnNumber = 0;
 392 String sourceURL;
 393
 394 JSC::JSValue result = promise.result(vm);
 395 String resultMessage = retrieveErrorMessage(state, vm, result, scope);
 396 String errorMessage = makeString("Unhandled Promise Rejection: ", resultMessage);
 397 if (const ScriptCallFrame* callFrame = callStack.firstNonNativeCallFrame()) {
 398 lineNumber = callFrame->lineNumber();
 399 columnNumber = callFrame->columnNumber();
 400 sourceURL = callFrame->sourceURL();
 401 }
 402
 403 logExceptionToConsole(errorMessage, sourceURL, lineNumber, columnNumber, &callStack);
 404}
 405
382406void ScriptExecutionContext::addConsoleMessage(MessageSource source, MessageLevel level, const String& message, const String& sourceURL, unsigned lineNumber, unsigned columnNumber, JSC::ExecState* state, unsigned long requestIdentifier)
383407{
384408 addMessage(source, level, message, sourceURL, lineNumber, columnNumber, 0, state, requestIdentifier);

@@JSC::VM& ScriptExecutionContext::vm()
464488 return downcast<WorkerGlobalScope>(*this).script()->vm();
465489}
466490
 491RejectedPromiseTracker& ScriptExecutionContext::ensureRejectedPromiseTrackerSlow()
 492{
 493 // ScriptExecutionContext::vm() in Worker is only available after WorkerGlobalScope initialization is done.
 494 // When initializing ScriptExecutionContext, vm() is not ready.
 495
 496 ASSERT(!m_rejectedPromiseTracker);
 497 m_rejectedPromiseTracker = std::make_unique<RejectedPromiseTracker>(*this, vm());
 498 return *m_rejectedPromiseTracker.get();
 499}
 500
467501void ScriptExecutionContext::setDatabaseContext(DatabaseContext* databaseContext)
468502{
469503 m_databaseContext = databaseContext;

Source/WebCore/dom/ScriptExecutionContext.h

4040namespace JSC {
4141class Exception;
4242class ExecState;
 43class JSPromise;
4344class VM;
4445template<typename> class Strong;
4546}

@@class EventQueue;
5657class EventTarget;
5758class MessagePort;
5859class PublicURLManager;
 60class RejectedPromiseTracker;
5961class ResourceRequest;
6062class SecurityOrigin;
6163class SocketProvider;

@@class ScriptExecutionContext : public SecurityContext {
9496
9597 bool sanitizeScriptError(String& errorMessage, int& lineNumber, int& columnNumber, String& sourceURL, JSC::Strong<JSC::Unknown>& error, CachedScript* = nullptr);
9698 void reportException(const String& errorMessage, int lineNumber, int columnNumber, const String& sourceURL, JSC::Exception*, RefPtr<Inspector::ScriptCallStack>&&, CachedScript* = nullptr);
 99 void reportUnhandledPromiseRejection(JSC::ExecState&, JSC::JSPromise&, Inspector::ScriptCallStack&);
97100
98101 void addConsoleMessage(MessageSource, MessageLevel, const String& message, const String& sourceURL, unsigned lineNumber, unsigned columnNumber, JSC::ExecState* = nullptr, unsigned long requestIdentifier = 0);
99102 virtual void addConsoleMessage(MessageSource, MessageLevel, const String& message, unsigned long requestIdentifier = 0) = 0;

@@class ScriptExecutionContext : public SecurityContext {
187190 void removeTimeout(int timeoutId) { m_timeouts.remove(timeoutId); }
188191 DOMTimer* findTimeout(int timeoutId) { return m_timeouts.get(timeoutId); }
189192
190  WEBCORE_EXPORT JSC::VM& vm();
191 
192193 // Interval is in seconds.
193194 void adjustMinimumTimerInterval(std::chrono::milliseconds oldMinimumTimerInterval);
194195 virtual std::chrono::milliseconds minimumTimerInterval() const;

@@class ScriptExecutionContext : public SecurityContext {
197198 virtual std::chrono::milliseconds timerAlignmentInterval(bool hasReachedMaxNestingLevel) const;
198199
199200 virtual EventQueue& eventQueue() const = 0;
 201 virtual EventTarget* errorEventTarget() = 0;
200202
201203 DatabaseContext* databaseContext() { return m_databaseContext.get(); }
202204 void setDatabaseContext(DatabaseContext*);

@@class ScriptExecutionContext : public SecurityContext {
209211 int timerNestingLevel() const { return m_timerNestingLevel; }
210212 void setTimerNestingLevel(int timerNestingLevel) { m_timerNestingLevel = timerNestingLevel; }
211213
 214 RejectedPromiseTracker& ensureRejectedPromiseTracker()
 215 {
 216 if (m_rejectedPromiseTracker)
 217 return *m_rejectedPromiseTracker.get();
 218 return ensureRejectedPromiseTrackerSlow();
 219 }
 220
 221 WEBCORE_EXPORT JSC::VM& vm();
212222 JSC::ExecState* execState();
213223
214224protected:

@@class ScriptExecutionContext : public SecurityContext {
228238
229239private:
230240 virtual void addMessage(MessageSource, MessageLevel, const String& message, const String& sourceURL, unsigned lineNumber, unsigned columnNumber, RefPtr<Inspector::ScriptCallStack>&&, JSC::ExecState* = nullptr, unsigned long requestIdentifier = 0) = 0;
231  virtual EventTarget* errorEventTarget() = 0;
232241 virtual void logExceptionToConsole(const String& errorMessage, const String& sourceURL, int lineNumber, int columnNumber, RefPtr<Inspector::ScriptCallStack>&&) = 0;
233242 bool dispatchErrorEvent(const String& errorMessage, int lineNumber, int columnNumber, const String& sourceURL, JSC::Exception*, CachedScript*);
234243
235244 virtual void refScriptExecutionContext() = 0;
236245 virtual void derefScriptExecutionContext() = 0;
237246
 247 RejectedPromiseTracker& ensureRejectedPromiseTrackerSlow();
 248
238249 void checkConsistency() const;
239250
240251 HashSet<MessagePort*> m_messagePorts;

@@class ScriptExecutionContext : public SecurityContext {
248259 struct PendingException;
249260 std::unique_ptr<Vector<std::unique_ptr<PendingException>>> m_pendingExceptions;
250261
 262 std::unique_ptr<RejectedPromiseTracker> m_rejectedPromiseTracker;
 263
251264 bool m_activeDOMObjectsAreSuspended { false };
252265 ActiveDOMObject::ReasonForSuspension m_reasonForSuspendingActiveDOMObjects { static_cast<ActiveDOMObject::ReasonForSuspension>(-1) };
253266 bool m_activeDOMObjectsAreStopped { false };

Source/WebCore/html/HTMLMediaElement.cpp

@@void HTMLMediaElement::pauseInternal()
32433243
32443244 if (!m_paused) {
32453245 m_paused = true;
3246  scheduleTimeupdateEvent(false);
3247  scheduleEvent(eventNames().pauseEvent);
3248  rejectPendingPlayPromises(DOMError::create("AbortError", "The operation was aborted."));
3249 
 3246 m_promiseTaskQueue.enqueueTask([this]() {
 3247 scheduleTimeupdateEvent(false);
 3248 scheduleEvent(eventNames().pauseEvent);
 3249 rejectPendingPlayPromises(DOMError::create("AbortError", "The operation was aborted."));
 3250 });
32503251 if (MemoryPressureHandler::singleton().isUnderMemoryPressure())
32513252 purgeBufferedDataIfPossible();
32523253 }

Source/WebCore/workers/WorkerGlobalScope.idl

3737 attribute EventHandler onerror;
3838 attribute EventHandler onoffline;
3939 attribute EventHandler ononline;
 40 attribute EventHandler onrejectionhandled;
 41 attribute EventHandler onunhandledrejection;
4042
4143 // WorkerUtils
4244

LayoutTests/ChangeLog

 12017-02-20 Yusuke Suzuki <utatane.tea@gmail.com>
 2
 3 Support for promise rejection events (unhandledrejection)
 4 https://bugs.webkit.org/show_bug.cgi?id=150358
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 * js/dom/unhandled-promise-rejection-basic-expected.txt: Added.
 9 * js/dom/unhandled-promise-rejection-basic.html: Added.
 10 * js/dom/unhandled-promise-rejection-console-report-expected.txt: Added.
 11 * js/dom/unhandled-promise-rejection-console-report.html: Added.
 12 * js/dom/unhandled-promise-rejection-handle-during-event-expected.txt: Added.
 13 * js/dom/unhandled-promise-rejection-handle-during-event.html: Added.
 14 * js/dom/unhandled-promise-rejection-handle-expected.txt: Added.
 15 * js/dom/unhandled-promise-rejection-handle-in-handler-expected.txt: Added.
 16 * js/dom/unhandled-promise-rejection-handle-in-handler.html: Added.
 17 * js/dom/unhandled-promise-rejection-handle.html: Added.
 18 * js/dom/unhandled-promise-rejection-order-expected.txt: Added.
 19 * js/dom/unhandled-promise-rejection-order.html: Added.
 20
1212017-02-20 Carlos Garcia Campos <cgarcia@igalia.com>
222
323 Unreviewed GTK+ gardening. Mark fast/events/message-port-postMessage-recursive.html as timing out.

LayoutTests/js/dom/unhandled-promise-rejection-basic-expected.txt

 1Test unhandled promise rejection event.
 2
 3On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 4
 5PASS error.type is "unhandledrejection"
 6PASS error.cancelable is true
 7PASS error.promise is promise
 8PASS error.reason is "ERROR"
 9PASS successfullyParsed is true
 10
 11TEST COMPLETE
 12

LayoutTests/js/dom/unhandled-promise-rejection-basic.html

 1<!DOCTYPE html>
 2<html>
 3<head>
 4<script src="../../resources/js-test-pre.js"></script>
 5</head>
 6<body>
 7<div id="description"></div>
 8<div id="console"></div>
 9<script>
 10description('Test unhandled promise rejection event.');
 11
 12window.jsTestIsAsync = true;
 13
 14window.error = null;
 15window.promise = null;
 16window.onunhandledrejection = function (e) {
 17 error = e;
 18 shouldBe(`error.type`, `"unhandledrejection"`);
 19 shouldBe(`error.cancelable`, `true`);
 20 shouldBe(`error.promise`, `promise`);
 21 shouldBe(`error.reason`, `"ERROR"`);
 22 finishJSTest();
 23 return false;
 24};
 25
 26window.promise = Promise.reject("ERROR");
 27
 28</script>
 29<script src="../../resources/js-test-post.js"></script>
 30</body>
 31</html>

LayoutTests/js/dom/unhandled-promise-rejection-console-report-expected.txt

 1CONSOLE MESSAGE: line 1: Unhandled Promise Rejection: 0
 2CONSOLE MESSAGE: line 1: Unhandled Promise Rejection: 1
 3CONSOLE MESSAGE: line 1: Unhandled Promise Rejection: 2
 4Test unhandled promise rejection event.
 5
 6On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 7
 8PASS successfullyParsed is true
 9
 10TEST COMPLETE
 11

LayoutTests/js/dom/unhandled-promise-rejection-console-report.html

 1<!DOCTYPE html>
 2<html>
 3<head>
 4<script src="../../resources/js-test-pre.js"></script>
 5</head>
 6<body>
 7<div id="description"></div>
 8<div id="console"></div>
 9<script>
 10description('Test unhandled promise rejection event.');
 11
 12window.jsTestIsAsync = true;
 13
 14window.promise = [];
 15for (var i = 0; i < 3; ++i)
 16 window.promise[i] = Promise.reject(i);
 17
 18window.onunhandledrejection = function (e) { return true; };
 19setTimeout(function () { finishJSTest(); }, 100);
 20
 21</script>
 22<script src="../../resources/js-test-post.js"></script>
 23</body>
 24</html>

LayoutTests/js/dom/unhandled-promise-rejection-handle-during-event-expected.txt

 1Test unhandled promise rejection event.
 2
 3On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 4
 5PASS error.type is "unhandledrejection"
 6PASS error.cancelable is true
 7PASS error.promise is promise[0]
 8PASS error.reason is 0
 9PASS successfullyParsed is true
 10
 11TEST COMPLETE
 12

LayoutTests/js/dom/unhandled-promise-rejection-handle-during-event.html

 1<!DOCTYPE html>
 2<html>
 3<head>
 4<script src="../../resources/js-test-pre.js"></script>
 5</head>
 6<body>
 7<div id="description"></div>
 8<div id="console"></div>
 9<script>
 10description('Test unhandled promise rejection event.');
 11
 12window.jsTestIsAsync = true;
 13
 14window.error = null;
 15window.promise = [];
 16window.onunhandledrejection = function (e) {
 17 error = e;
 18
 19 shouldBe(`error.type`, `"unhandledrejection"`);
 20 shouldBe(`error.cancelable`, `true`);
 21 shouldBe(`error.promise`, `promise[0]`);
 22 shouldBe(`error.reason`, `0`);
 23
 24 promise[1].catch(function () { });
 25 promise[2].catch(function () { });
 26 setTimeout(function () { finishJSTest(); });
 27 return false;
 28};
 29
 30for (var i = 0; i < 3; ++i)
 31 window.promise[i] = Promise.reject(i);
 32
 33</script>
 34<script src="../../resources/js-test-post.js"></script>
 35</body>
 36</html>

LayoutTests/js/dom/unhandled-promise-rejection-handle-expected.txt

 1Test rejection handled event.
 2
 3On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 4
 5PASS error.type is "unhandledrejection"
 6PASS error.cancelable is true
 7PASS error.promise is promise
 8PASS error.reason is "ERROR"
 9PASS reason is "ERROR"
 10PASS handled.type is "rejectionhandled"
 11PASS handled.cancelable is false
 12PASS handled.promise is promise
 13PASS handled.reason is "ERROR"
 14PASS successfullyParsed is true
 15
 16TEST COMPLETE
 17

LayoutTests/js/dom/unhandled-promise-rejection-handle-in-handler-expected.txt

 1Test rejection handled event.
 2
 3On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 4
 5PASS error.type is "unhandledrejection"
 6PASS error.cancelable is true
 7PASS error.promise is promise
 8PASS error.reason is "ERROR"
 9PASS reason is "ERROR"
 10PASS successfullyParsed is true
 11
 12TEST COMPLETE
 13

LayoutTests/js/dom/unhandled-promise-rejection-handle-in-handler.html

 1<!DOCTYPE html>
 2<html>
 3<head>
 4<script src="../../resources/js-test-pre.js"></script>
 5</head>
 6<body>
 7<div id="description"></div>
 8<div id="console"></div>
 9<script>
 10description('Test rejection handled event.');
 11
 12window.jsTestIsAsync = true;
 13
 14window.error = null;
 15window.promise = null;
 16window.reason = null;
 17
 18window.onunhandledrejection = function (e) {
 19 error = e;
 20 shouldBe(`error.type`, `"unhandledrejection"`);
 21 shouldBe(`error.cancelable`, `true`);
 22 shouldBe(`error.promise`, `promise`);
 23 shouldBe(`error.reason`, `"ERROR"`);
 24 promise.catch(function (r) {
 25 window.reason = r;
 26 shouldBe(`reason`, `"ERROR"`);
 27 });
 28
 29 setTimeout(function () {
 30 finishJSTest();
 31 }, 100);
 32 return false;
 33};
 34
 35window.onrejectionhandled = function (e) {
 36 testFailed(`rejectionhandled is fired.`);
 37};
 38
 39window.promise = Promise.reject("ERROR");
 40
 41</script>
 42<script src="../../resources/js-test-post.js"></script>
 43</body>
 44</html>

LayoutTests/js/dom/unhandled-promise-rejection-handle.html

 1<!DOCTYPE html>
 2<html>
 3<head>
 4<script src="../../resources/js-test-pre.js"></script>
 5</head>
 6<body>
 7<div id="description"></div>
 8<div id="console"></div>
 9<script>
 10description('Test rejection handled event.');
 11
 12window.jsTestIsAsync = true;
 13
 14window.error = null;
 15window.handled = null;
 16window.promise = null;
 17window.reason = null;
 18
 19window.onunhandledrejection = function (e) {
 20 error = e;
 21 shouldBe(`error.type`, `"unhandledrejection"`);
 22 shouldBe(`error.cancelable`, `true`);
 23 shouldBe(`error.promise`, `promise`);
 24 shouldBe(`error.reason`, `"ERROR"`);
 25 setTimeout(function () {
 26 promise.catch(function (r) {
 27 window.reason = r;
 28 shouldBe(`reason`, `"ERROR"`);
 29 });
 30 }, 0);
 31 return false;
 32};
 33
 34window.onrejectionhandled = function (e) {
 35 window.handled = e;
 36 shouldBe(`handled.type`, `"rejectionhandled"`);
 37 shouldBe(`handled.cancelable`, `false`);
 38 shouldBe(`handled.promise`, `promise`);
 39 shouldBe(`handled.reason`, `"ERROR"`);
 40 finishJSTest();
 41};
 42
 43window.promise = Promise.reject("ERROR");
 44
 45</script>
 46<script src="../../resources/js-test-post.js"></script>
 47</body>
 48</html>

LayoutTests/js/dom/unhandled-promise-rejection-order-expected.txt

 1Test unhandled promise rejection event.
 2
 3On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 4
 5PASS error.type is "unhandledrejection"
 6PASS error.cancelable is true
 7PASS error.promise is promise[0]
 8PASS error.reason is 0
 9PASS error.type is "unhandledrejection"
 10PASS error.cancelable is true
 11PASS error.promise is promise[1]
 12PASS error.reason is 1
 13PASS error.type is "unhandledrejection"
 14PASS error.cancelable is true
 15PASS error.promise is promise[2]
 16PASS error.reason is 2
 17PASS successfullyParsed is true
 18
 19TEST COMPLETE
 20

LayoutTests/js/dom/unhandled-promise-rejection-order.html

 1<!DOCTYPE html>
 2<html>
 3<head>
 4<script src="../../resources/js-test-pre.js"></script>
 5</head>
 6<body>
 7<div id="description"></div>
 8<div id="console"></div>
 9<script>
 10description('Test unhandled promise rejection event.');
 11
 12window.jsTestIsAsync = true;
 13
 14window.error = null;
 15window.promise = [];
 16window.count = 0;
 17window.index = 0;
 18window.onunhandledrejection = function (e) {
 19 error = e;
 20 index = count++;
 21
 22 shouldBe(`error.type`, `"unhandledrejection"`);
 23 shouldBe(`error.cancelable`, `true`);
 24 shouldBe(`error.promise`, `promise[${index}]`);
 25 shouldBe(`error.reason`, `${index}`);
 26
 27 if (count === 3)
 28 finishJSTest();
 29 return false;
 30};
 31
 32for (var i = 0; i < 3; ++i)
 33 window.promise[i] = Promise.reject(i);
 34
 35</script>
 36<script src="../../resources/js-test-post.js"></script>
 37</body>
 38</html>