Web Inspector: fake value descriptors for promises add a catch handler, preventing...
authordrousso@apple.com <drousso@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 16 Apr 2019 00:02:32 +0000 (00:02 +0000)
committerdrousso@apple.com <drousso@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 16 Apr 2019 00:02:32 +0000 (00:02 +0000)
https://bugs.webkit.org/show_bug.cgi?id=196484
<rdar://problem/49114725>

Reviewed by Joseph Pecoraro.

Source/JavaScriptCore:

Only add a catch handler when the promise is reachable via a native getter and is known to
have rejected. A non-rejected promise doesn't need a catch handler, and any promise that
isn't reachable via a getter won't actually be reached, as `InjectedScript` doesn't call any
functions, instead only getting the function object itself.

* inspector/InjectedScriptSource.js:
(InjectedScript.prototype._propertyDescriptors.createFakeValueDescriptor):

* inspector/JSInjectedScriptHost.h:
* inspector/JSInjectedScriptHost.cpp:
(Inspector::JSInjectedScriptHost::isPromiseRejectedWithNativeGetterTypeError): Added.
* inspector/JSInjectedScriptHostPrototype.cpp:
(Inspector::JSInjectedScriptHostPrototype::finishCreation):
(Inspector::jsInjectedScriptHostPrototypeFunctionIsPromiseRejectedWithNativeGetterTypeError): Added.

* runtime/ErrorInstance.h:
(JSC::ErrorInstance::setNativeGetterTypeError): Added.
(JSC::ErrorInstance::isNativeGetterTypeError const): Added.

* runtime/Error.h:
(JSC::throwVMGetterTypeError): Added.
* runtime/Error.cpp:
(JSC::createGetterTypeError): Added.
(JSC::throwGetterTypeError): Added.
(JSC::throwDOMAttributeGetterTypeError):

Source/WebCore:

Test: inspector/runtime/promise-native-getter.html

Mark errors created from getters as being `isNativeGetterTypeError`.

* bindings/js/JSDOMExceptionHandling.cpp:
(WebCore::throwGetterTypeError):
(WebCore::rejectPromiseWithGetterTypeError):
(WebCore::rejectPromiseWithThisTypeError):

* bindings/js/JSDOMGlobalObject.cpp:
(WebCore::makeGetterTypeErrorForBuiltins):

* bindings/js/JSDOMPromiseDeferred.h:
* bindings/js/JSDOMPromiseDeferred.cpp:
(WebCore::createRejectedPromiseWithTypeError):

* Modules/streams/WritableStream.js:
(getter.closed):
(getter.ready):

LayoutTests:

* inspector/runtime/promise-native-getter.html: Added.
* inspector/runtime/promise-native-getter-expected.txt: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@244312 268f45cc-cd09-0410-ab3c-d52691b4dbfc

17 files changed:
LayoutTests/ChangeLog
LayoutTests/inspector/runtime/promise-native-getter-expected.txt [new file with mode: 0644]
LayoutTests/inspector/runtime/promise-native-getter.html [new file with mode: 0644]
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/inspector/InjectedScriptSource.js
Source/JavaScriptCore/inspector/JSInjectedScriptHost.cpp
Source/JavaScriptCore/inspector/JSInjectedScriptHost.h
Source/JavaScriptCore/inspector/JSInjectedScriptHostPrototype.cpp
Source/JavaScriptCore/runtime/Error.cpp
Source/JavaScriptCore/runtime/Error.h
Source/JavaScriptCore/runtime/ErrorInstance.h
Source/WebCore/ChangeLog
Source/WebCore/Modules/streams/WritableStream.js
Source/WebCore/bindings/js/JSDOMExceptionHandling.cpp
Source/WebCore/bindings/js/JSDOMGlobalObject.cpp
Source/WebCore/bindings/js/JSDOMPromiseDeferred.cpp
Source/WebCore/bindings/js/JSDOMPromiseDeferred.h

index af6fce5..08060ca 100644 (file)
@@ -1,3 +1,14 @@
+2019-04-15  Devin Rousso  <drousso@apple.com>
+
+        Web Inspector: fake value descriptors for promises add a catch handler, preventing "rejectionhandled" events from being fired
+        https://bugs.webkit.org/show_bug.cgi?id=196484
+        <rdar://problem/49114725>
+
+        Reviewed by Joseph Pecoraro.
+
+        * inspector/runtime/promise-native-getter.html: Added.
+        * inspector/runtime/promise-native-getter-expected.txt: Added.
+
 2019-04-15  Shawn Roberts  <sroberts@apple.com>
 
         storage/indexeddb/modern/gc-closes-database-private.html is a flaky timeout
diff --git a/LayoutTests/inspector/runtime/promise-native-getter-expected.txt b/LayoutTests/inspector/runtime/promise-native-getter-expected.txt
new file mode 100644 (file)
index 0000000..4cfe2dd
--- /dev/null
@@ -0,0 +1,5 @@
+CONSOLE MESSAGE: line 8: unhandledrejection - "test"
+CONSOLE MESSAGE: Unhandled Promise Rejection: test
+CONSOLE MESSAGE: line 20: caught - "test"
+CONSOLE MESSAGE: line 12: rejectionhandled - "test"
+Tests that the injected script only `.then()`s promises if they are returned by native getters.
diff --git a/LayoutTests/inspector/runtime/promise-native-getter.html b/LayoutTests/inspector/runtime/promise-native-getter.html
new file mode 100644 (file)
index 0000000..8e39bc0
--- /dev/null
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="../../http/tests/inspector/resources/protocol-test.js"></script>
+<script>
+function createUnhandledPromise() {
+    window.addEventListener("unhandledrejection", (event) => {
+        console.log("unhandledrejection - " + JSON.stringify(event.reason));
+    });
+
+    window.addEventListener("rejectionhandled", (event) => {
+        console.log("rejectionhandled - " + JSON.stringify(event.reason));
+        TestPage.dispatchEventToFrontend("rejectionhandled");
+    });
+
+    let promise = Promise.reject("test");
+
+    setTimeout(() => {
+        promise.catch((value) => {
+            console.log("caught - " + JSON.stringify(value));
+        });
+    }, 5);
+}
+
+function test()
+{
+    ProtocolTest.awaitEvent("rejectionhandled")
+    .then(() => {
+        ProtocolTest.completeTest();
+    });
+
+    ProtocolTest.evaluateInPage(`createUnhandledPromise()`)
+    .catch((e) => {
+        ProtocolTest.fail(e);
+    });
+}
+</script>
+</head>
+<body onload="runTest()">
+    <p>Tests that the injected script only `.then()`s promises if they are returned by native getters.</p>
+</body>
+</html>
index 888287c..b6ba2be 100644 (file)
@@ -1,3 +1,37 @@
+2019-04-15  Devin Rousso  <drousso@apple.com>
+
+        Web Inspector: fake value descriptors for promises add a catch handler, preventing "rejectionhandled" events from being fired
+        https://bugs.webkit.org/show_bug.cgi?id=196484
+        <rdar://problem/49114725>
+
+        Reviewed by Joseph Pecoraro.
+
+        Only add a catch handler when the promise is reachable via a native getter and is known to
+        have rejected. A non-rejected promise doesn't need a catch handler, and any promise that
+        isn't reachable via a getter won't actually be reached, as `InjectedScript` doesn't call any
+        functions, instead only getting the function object itself.
+
+        * inspector/InjectedScriptSource.js:
+        (InjectedScript.prototype._propertyDescriptors.createFakeValueDescriptor):
+
+        * inspector/JSInjectedScriptHost.h:
+        * inspector/JSInjectedScriptHost.cpp:
+        (Inspector::JSInjectedScriptHost::isPromiseRejectedWithNativeGetterTypeError): Added.
+        * inspector/JSInjectedScriptHostPrototype.cpp:
+        (Inspector::JSInjectedScriptHostPrototype::finishCreation):
+        (Inspector::jsInjectedScriptHostPrototypeFunctionIsPromiseRejectedWithNativeGetterTypeError): Added.
+
+        * runtime/ErrorInstance.h:
+        (JSC::ErrorInstance::setNativeGetterTypeError): Added.
+        (JSC::ErrorInstance::isNativeGetterTypeError const): Added.
+
+        * runtime/Error.h:
+        (JSC::throwVMGetterTypeError): Added.
+        * runtime/Error.cpp:
+        (JSC::createGetterTypeError): Added.
+        (JSC::throwGetterTypeError): Added.
+        (JSC::throwDOMAttributeGetterTypeError):
+
 2019-04-15  Robin Morisset  <rmorisset@apple.com>
 
         B3::Value should have different kinds of adjacency lists
index c440c62..630e5dc 100644 (file)
@@ -653,7 +653,7 @@ let InjectedScript = class InjectedScript
                 if (symbol)
                     fakeDescriptor.symbol = symbol;
                 // Silence any possible unhandledrejection exceptions created from accessing a native accessor with a wrong this object.
-                if (fakeDescriptor.value instanceof Promise)
+                if (fakeDescriptor.value instanceof Promise && InjectedScriptHost.isPromiseRejectedWithNativeGetterTypeError(fakeDescriptor.value))
                     fakeDescriptor.value.catch(function(){});
                 return fakeDescriptor;
             } catch (e) {
index 241f5db..d9725c0 100644 (file)
@@ -142,6 +142,21 @@ JSValue JSInjectedScriptHost::isHTMLAllCollection(ExecState* exec)
     return jsBoolean(impl().isHTMLAllCollection(vm, value));
 }
 
+JSValue JSInjectedScriptHost::isPromiseRejectedWithNativeGetterTypeError(ExecState* exec)
+{
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
+    auto* promise = jsDynamicCast<JSPromise*>(vm, exec->argument(0));
+    if (!promise || promise->status(vm) != JSPromise::Status::Rejected)
+        return throwTypeError(exec, scope, "InjectedScriptHost.isPromiseRejectedWithNativeGetterTypeError first argument must be a rejected Promise."_s);
+
+    bool result = false;
+    if (auto* errorInstance = jsDynamicCast<ErrorInstance*>(vm, promise->result(vm)))
+        result = errorInstance->isNativeGetterTypeError();
+    return jsBoolean(result);
+}
+
 JSValue JSInjectedScriptHost::subtype(ExecState* exec)
 {
     VM& vm = exec->vm();
index bacc37a..8d920f5 100644 (file)
@@ -62,6 +62,7 @@ public:
     JSC::JSValue evaluateWithScopeExtension(JSC::ExecState*);
     JSC::JSValue internalConstructorName(JSC::ExecState*);
     JSC::JSValue isHTMLAllCollection(JSC::ExecState*);
+    JSC::JSValue isPromiseRejectedWithNativeGetterTypeError(JSC::ExecState*);
     JSC::JSValue subtype(JSC::ExecState*);
     JSC::JSValue functionDetails(JSC::ExecState*);
     JSC::JSValue getInternalProperties(JSC::ExecState*);
index 01f61f4..df00bfa 100644 (file)
@@ -43,6 +43,7 @@ static EncodedJSValue JSC_HOST_CALL jsInjectedScriptHostPrototypeFunctionFunctio
 static EncodedJSValue JSC_HOST_CALL jsInjectedScriptHostPrototypeFunctionGetInternalProperties(ExecState*);
 static EncodedJSValue JSC_HOST_CALL jsInjectedScriptHostPrototypeFunctionInternalConstructorName(ExecState*);
 static EncodedJSValue JSC_HOST_CALL jsInjectedScriptHostPrototypeFunctionIsHTMLAllCollection(ExecState*);
+static EncodedJSValue JSC_HOST_CALL jsInjectedScriptHostPrototypeFunctionIsPromiseRejectedWithNativeGetterTypeError(ExecState*);
 static EncodedJSValue JSC_HOST_CALL jsInjectedScriptHostPrototypeFunctionProxyTargetValue(ExecState*);
 static EncodedJSValue JSC_HOST_CALL jsInjectedScriptHostPrototypeFunctionWeakMapSize(ExecState*);
 static EncodedJSValue JSC_HOST_CALL jsInjectedScriptHostPrototypeFunctionWeakMapEntries(ExecState*);
@@ -67,6 +68,7 @@ void JSInjectedScriptHostPrototype::finishCreation(VM& vm, JSGlobalObject* globa
     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("getInternalProperties", jsInjectedScriptHostPrototypeFunctionGetInternalProperties, static_cast<unsigned>(PropertyAttribute::DontEnum), 1);
     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("internalConstructorName", jsInjectedScriptHostPrototypeFunctionInternalConstructorName, static_cast<unsigned>(PropertyAttribute::DontEnum), 1);
     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("isHTMLAllCollection", jsInjectedScriptHostPrototypeFunctionIsHTMLAllCollection, static_cast<unsigned>(PropertyAttribute::DontEnum), 1);
+    JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("isPromiseRejectedWithNativeGetterTypeError", jsInjectedScriptHostPrototypeFunctionIsPromiseRejectedWithNativeGetterTypeError, static_cast<unsigned>(PropertyAttribute::DontEnum), 1);
     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("proxyTargetValue", jsInjectedScriptHostPrototypeFunctionProxyTargetValue, static_cast<unsigned>(PropertyAttribute::DontEnum), 1);
     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("weakMapSize", jsInjectedScriptHostPrototypeFunctionWeakMapSize, static_cast<unsigned>(PropertyAttribute::DontEnum), 1);
     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("weakMapEntries", jsInjectedScriptHostPrototypeFunctionWeakMapEntries, static_cast<unsigned>(PropertyAttribute::DontEnum), 1);
@@ -118,6 +120,19 @@ EncodedJSValue JSC_HOST_CALL jsInjectedScriptHostPrototypeFunctionIsHTMLAllColle
     return JSValue::encode(castedThis->isHTMLAllCollection(exec));
 }
 
+EncodedJSValue JSC_HOST_CALL jsInjectedScriptHostPrototypeFunctionIsPromiseRejectedWithNativeGetterTypeError(ExecState* exec)
+{
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
+    JSValue thisValue = exec->thisValue();
+    JSInjectedScriptHost* castedThis = jsDynamicCast<JSInjectedScriptHost*>(vm, thisValue);
+    if (!castedThis)
+        return throwVMTypeError(exec, scope);
+
+    return JSValue::encode(castedThis->isPromiseRejectedWithNativeGetterTypeError(exec));
+}
+
 EncodedJSValue JSC_HOST_CALL jsInjectedScriptHostPrototypeFunctionProxyTargetValue(ExecState* exec)
 {
     VM& vm = exec->vm();
index 09ba627..70c7147 100644 (file)
@@ -123,6 +123,15 @@ JSObject* createError(ExecState* exec, ErrorType errorType, const String& messag
     return nullptr;
 }
 
+JSObject* createGetterTypeError(ExecState* exec, const String& message)
+{
+    ASSERT(!message.isEmpty());
+    JSGlobalObject* globalObject = exec->lexicalGlobalObject();
+    auto* error = ErrorInstance::create(exec, globalObject->vm(), globalObject->errorStructure(ErrorType::TypeError), message);
+    error->setNativeGetterTypeError();
+    return error;
+}
+
 class FindFirstCallerFrameWithCodeblockFunctor {
 public:
     FindFirstCallerFrameWithCodeblockFunctor(CallFrame* startCallFrame)
@@ -290,9 +299,14 @@ Exception* throwSyntaxError(ExecState* exec, ThrowScope& scope, const String& me
     return throwException(exec, scope, createSyntaxError(exec, message));
 }
 
+Exception* throwGetterTypeError(ExecState* exec, ThrowScope& scope, const String& message)
+{
+    return throwException(exec, scope, createGetterTypeError(exec, message));
+}
+
 JSValue throwDOMAttributeGetterTypeError(ExecState* exec, ThrowScope& scope, const ClassInfo* classInfo, PropertyName propertyName)
 {
-    return throwTypeError(exec, scope, makeString("The ", classInfo->className, '.', String(propertyName.uid()), " getter can only be used on instances of ", classInfo->className));
+    return throwGetterTypeError(exec, scope, makeString("The ", classInfo->className, '.', String(propertyName.uid()), " getter can only be used on instances of ", classInfo->className));
 }
 
 JSObject* createError(ExecState* exec, const String& message)
index f1f9d85..c04bc55 100644 (file)
@@ -67,6 +67,8 @@ JS_EXPORT_PRIVATE JSObject* createOutOfMemoryError(ExecState*, const String&);
 
 JS_EXPORT_PRIVATE JSObject* createError(ExecState*, ErrorType, const String&);
 
+JSObject* createGetterTypeError(ExecState*, const String&);
+
 std::unique_ptr<Vector<StackFrame>> getStackTrace(ExecState*, VM&, JSObject*, bool useCurrentFrame);
 void getBytecodeOffset(ExecState*, VM&, Vector<StackFrame>*, CallFrame*&, unsigned& bytecodeOffset);
 bool getLineColumnAndSource(Vector<StackFrame>* stackTrace, unsigned& line, unsigned& column, String& sourceURL);
@@ -84,6 +86,8 @@ JS_EXPORT_PRIVATE Exception* throwTypeError(ExecState*, ThrowScope&, const Strin
 JS_EXPORT_PRIVATE Exception* throwSyntaxError(ExecState*, ThrowScope&);
 JS_EXPORT_PRIVATE Exception* throwSyntaxError(ExecState*, ThrowScope&, const String& errorMessage);
 inline Exception* throwRangeError(ExecState* state, ThrowScope& scope, const String& errorMessage) { return throwException(state, scope, createRangeError(state, errorMessage)); }
+
+JS_EXPORT_PRIVATE Exception* throwGetterTypeError(ExecState*, ThrowScope&, const String& errorMessage);
 JS_EXPORT_PRIVATE JSValue throwDOMAttributeGetterTypeError(ExecState*, ThrowScope&, const ClassInfo*, PropertyName);
 
 // Convenience wrappers, wrap result as an EncodedJSValue.
@@ -94,6 +98,7 @@ inline EncodedJSValue throwVMTypeError(ExecState* exec, ThrowScope& scope) { ret
 inline EncodedJSValue throwVMTypeError(ExecState* exec, ThrowScope& scope, ASCIILiteral errorMessage) { return JSValue::encode(throwTypeError(exec, scope, errorMessage)); }
 inline EncodedJSValue throwVMTypeError(ExecState* exec, ThrowScope& scope, const String& errorMessage) { return JSValue::encode(throwTypeError(exec, scope, errorMessage)); }
 inline EncodedJSValue throwVMRangeError(ExecState* state, ThrowScope& scope, const String& errorMessage) { return JSValue::encode(throwRangeError(state, scope, errorMessage)); }
+inline EncodedJSValue throwVMGetterTypeError(ExecState* exec, ThrowScope& scope, const String& errorMessage) { return JSValue::encode(throwGetterTypeError(exec, scope, errorMessage)); }
 inline EncodedJSValue throwVMDOMAttributeGetterTypeError(ExecState* state, ThrowScope& scope, const ClassInfo* classInfo, PropertyName propertyName) { return JSValue::encode(throwDOMAttributeGetterTypeError(state, scope, classInfo, propertyName)); }
 
 } // namespace JSC
index fbc6f25..97a89da 100644 (file)
@@ -65,6 +65,9 @@ public:
     void setOutOfMemoryError() { m_outOfMemoryError = true; }
     bool isOutOfMemoryError() const { return m_outOfMemoryError; }
 
+    void setNativeGetterTypeError() { m_nativeGetterTypeError = true; }
+    bool isNativeGetterTypeError() const { return m_nativeGetterTypeError; }
+
     JS_EXPORT_PRIVATE String sanitizedToString(ExecState*);
     
     Vector<StackFrame>* stackTrace() { return m_stackTrace.get(); }
@@ -105,6 +108,7 @@ protected:
     bool m_stackOverflowError { false };
     bool m_outOfMemoryError { false };
     bool m_errorInfoMaterialized { false };
+    bool m_nativeGetterTypeError { false };
 };
 
 } // namespace JSC
index 2197aac..77d250c 100644 (file)
@@ -1,3 +1,31 @@
+2019-04-15  Devin Rousso  <drousso@apple.com>
+
+        Web Inspector: fake value descriptors for promises add a catch handler, preventing "rejectionhandled" events from being fired
+        https://bugs.webkit.org/show_bug.cgi?id=196484
+        <rdar://problem/49114725>
+
+        Reviewed by Joseph Pecoraro.
+
+        Test: inspector/runtime/promise-native-getter.html
+
+        Mark errors created from getters as being `isNativeGetterTypeError`.
+
+        * bindings/js/JSDOMExceptionHandling.cpp:
+        (WebCore::throwGetterTypeError):
+        (WebCore::rejectPromiseWithGetterTypeError):
+        (WebCore::rejectPromiseWithThisTypeError):
+
+        * bindings/js/JSDOMGlobalObject.cpp:
+        (WebCore::makeGetterTypeErrorForBuiltins):
+
+        * bindings/js/JSDOMPromiseDeferred.h:
+        * bindings/js/JSDOMPromiseDeferred.cpp:
+        (WebCore::createRejectedPromiseWithTypeError):
+
+        * Modules/streams/WritableStream.js:
+        (getter.closed):
+        (getter.ready):
+
 2019-04-15  Jer Noble  <jer.noble@apple.com>
 
         Add a DiagnosticLogging method taking an arbitrary dictionary of values.
index f68adfb..04acf81 100644 (file)
@@ -154,7 +154,7 @@ function closed()
     "use strict";
 
     if (!@isWritableStream(this))
-        return @Promise.@reject(@makeTypeError("The WritableStream.closed getter can only be used on instances of WritableStream"));
+        return @Promise.@reject(@makeGetterTypeError("WritableStream", "closed"));
 
     return @getByIdDirectPrivate(this, "closedPromiseCapability").@promise;
 }
@@ -165,7 +165,7 @@ function ready()
     "use strict";
 
     if (!@isWritableStream(this))
-        return @Promise.@reject(@makeTypeError("The WritableStream.ready getter can only be used on instances of WritableStream"));
+        return @Promise.@reject(@makeGetterTypeError("WritableStream", "ready"));
 
     return @getByIdDirectPrivate(this, "readyPromiseCapability").@promise;
 }
index 1311c9d..7002453 100644 (file)
@@ -270,12 +270,12 @@ String makeGetterTypeErrorMessage(const char* interfaceName, const char* attribu
 
 JSC::EncodedJSValue throwGetterTypeError(JSC::ExecState& state, JSC::ThrowScope& scope, const char* interfaceName, const char* attributeName)
 {
-    return throwVMTypeError(&state, scope, makeGetterTypeErrorMessage(interfaceName, attributeName));
+    return throwVMGetterTypeError(&state, scope, makeGetterTypeErrorMessage(interfaceName, attributeName));
 }
 
 JSC::EncodedJSValue rejectPromiseWithGetterTypeError(JSC::ExecState& state, const char* interfaceName, const char* attributeName)
 {
-    return createRejectedPromiseWithTypeError(state, makeGetterTypeErrorMessage(interfaceName, attributeName));
+    return createRejectedPromiseWithTypeError(state, makeGetterTypeErrorMessage(interfaceName, attributeName), RejectedPromiseWithTypeErrorCause::NativeGetter);
 }
 
 bool throwSetterTypeError(JSC::ExecState& state, JSC::ThrowScope& scope, const char* interfaceName, const char* attributeName)
@@ -302,7 +302,7 @@ JSC::EncodedJSValue rejectPromiseWithThisTypeError(DeferredPromise& promise, con
 
 JSC::EncodedJSValue rejectPromiseWithThisTypeError(JSC::ExecState& state, const char* interfaceName, const char* methodName)
 {
-    return createRejectedPromiseWithTypeError(state, makeThisTypeErrorMessage(interfaceName, methodName));
+    return createRejectedPromiseWithTypeError(state, makeThisTypeErrorMessage(interfaceName, methodName), RejectedPromiseWithTypeErrorCause::InvalidThis);
 }
 
 void throwDOMSyntaxError(JSC::ExecState& state, JSC::ThrowScope& scope, ASCIILiteral message)
index d144091..788e2e6 100644 (file)
@@ -100,7 +100,10 @@ EncodedJSValue JSC_HOST_CALL makeGetterTypeErrorForBuiltins(ExecState* execState
     scope.assertNoException();
     auto attributeName = execState->uncheckedArgument(1).getString(execState);
     scope.assertNoException();
-    return JSValue::encode(createTypeError(execState, makeGetterTypeErrorMessage(interfaceName.utf8().data(), attributeName.utf8().data())));
+
+    auto error = static_cast<ErrorInstance*>(createTypeError(execState, makeGetterTypeErrorMessage(interfaceName.utf8().data(), attributeName.utf8().data())));
+    error->setNativeGetterTypeError();
+    return JSValue::encode(error);
 }
 
 #if ENABLE(STREAMS_API)
index 20f9737..98abb5f 100644 (file)
@@ -197,14 +197,16 @@ Ref<DeferredPromise> createDeferredPromise(JSC::ExecState& state, JSDOMWindow& d
     return DeferredPromise::create(domWindow, *deferred);
 }
 
-JSC::EncodedJSValue createRejectedPromiseWithTypeError(JSC::ExecState& state, const String& errorMessage)
+JSC::EncodedJSValue createRejectedPromiseWithTypeError(JSC::ExecState& state, const String& errorMessage, RejectedPromiseWithTypeErrorCause cause)
 {
     ASSERT(state.lexicalGlobalObject());
     auto& globalObject = *state.lexicalGlobalObject();
 
     auto promiseConstructor = globalObject.promiseConstructor();
     auto rejectFunction = promiseConstructor->get(&state, state.vm().propertyNames->builtinNames().rejectPrivateName());
-    auto rejectionValue = createTypeError(&state, errorMessage);
+    auto* rejectionValue = static_cast<ErrorInstance*>(createTypeError(&state, errorMessage));
+    if (cause == RejectedPromiseWithTypeErrorCause::NativeGetter)
+        rejectionValue->setNativeGetterTypeError();
 
     CallData callData;
     auto callType = getCallData(state.vm(), rejectFunction, callData);
index 4318c9f..b4aab78 100644 (file)
@@ -257,7 +257,9 @@ void fulfillPromiseWithJSON(Ref<DeferredPromise>&&, const String&);
 void fulfillPromiseWithArrayBuffer(Ref<DeferredPromise>&&, ArrayBuffer*);
 void fulfillPromiseWithArrayBuffer(Ref<DeferredPromise>&&, const void*, size_t);
 WEBCORE_EXPORT void rejectPromiseWithExceptionIfAny(JSC::ExecState&, JSDOMGlobalObject&, JSC::JSPromiseDeferred&);
-JSC::EncodedJSValue createRejectedPromiseWithTypeError(JSC::ExecState&, const String&);
+
+enum class RejectedPromiseWithTypeErrorCause { NativeGetter, InvalidThis };
+JSC::EncodedJSValue createRejectedPromiseWithTypeError(JSC::ExecState&, const String&, RejectedPromiseWithTypeErrorCause);
 
 using PromiseFunction = void(JSC::ExecState&, Ref<DeferredPromise>&&);