Changeset 206011 in webkit


Ignore:
Timestamp:
Sep 16, 2016 12:51:37 AM (8 years ago)
Author:
commit-queue@webkit.org
Message:

Custom promise-returning functions should not throw if callee has not the expected type
https://bugs.webkit.org/show_bug.cgi?id=162011

Patch by Youenn Fablet <youenn@apple.com> on 2016-09-16
Reviewed by Sam Weinig.

Source/JavaScriptCore:

  • JavaScriptCore.xcodeproj/project.pbxproj: Making JSPromiseConstructor.h private

Source/WebCore:

Covered by added test.

Updating code generator to handle this case.
Cleaning related getUserMedia implementation.

  • CMakeLists.txt: Removing Modules/mediastream/MediaDevices.js.
  • DerivedSources.make: Removing Modules/mediastream/MediaDevices.js.
  • Modules/mediastream/MediaDevices.idl: Cleaning IDL definition
  • Modules/mediastream/MediaDevices.js: Removing error throwing and so removing file.
  • Modules/mediastream/NavigatorUserMedia.js: getUsermMediaFromJS to getUserMedia.
  • WebCore.xcodeproj/project.pbxproj: Removing Modules/mediastream/MediaDevices.js.
  • bindings/js/JSDOMPromise.cpp:

(WebCore::createRejectedPromiseWithTypeError): Helper routine.

  • bindings/js/JSDOMPromise.h:
  • bindings/js/WebCoreBuiltinNames.h: getUsermMediaFromJS to getUserMedia.
  • bindings/scripts/CodeGeneratorJS.pm:

(GenerateImplementation): Rejecting promise in case of failing castedThis, but only for custom functions since
they are handled differently for non custom methods.
(GenerateFunctionCastedThis):

  • bindings/scripts/test/JS/JSTestObj.cpp:
  • bindings/scripts/test/JS/JSTestObj.h:
  • bindings/scripts/test/TestObj.idl: Adding custom promise test.

LayoutTests:

  • fast/mediastream/MediaDevices-getUserMedia-expected.txt:
  • fast/mediastream/MediaDevices-getUserMedia.html: Enusing calling getUserMedia on something else than MediaDevices does not throw.
  • http/tests/media/media-stream/disconnected-frame-already-expected.txt:
Location:
trunk
Files:
1 added
1 deleted
19 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r206010 r206011  
     12016-09-16  Youenn Fablet  <youenn@apple.com>
     2
     3        Custom promise-returning functions should not throw if callee has not the expected type
     4        https://bugs.webkit.org/show_bug.cgi?id=162011
     5
     6        Reviewed by Sam Weinig.
     7
     8        * fast/mediastream/MediaDevices-getUserMedia-expected.txt:
     9        * fast/mediastream/MediaDevices-getUserMedia.html: Enusing calling getUserMedia on something else than MediaDevices does not throw.
     10        * http/tests/media/media-stream/disconnected-frame-already-expected.txt:
     11
    1122016-09-16  Youenn Fablet  <youenn@apple.com>
    213
  • trunk/LayoutTests/fast/mediastream/MediaDevices-getUserMedia-expected.txt

    r205953 r206011  
    88PASS navigator.mediaDevices.getUserMedia() rejected with error: TypeError: Not enough arguments
    99PASS navigator.mediaDevices.getUserMedia({}) rejected with error: TypeError: Type error
     10PASS navigator.mediaDevices.getUserMedia.apply(undefined) rejected with error: TypeError: Can only call MediaDevices.getUserMedia on instances of MediaDevices
    1011PASS Stream generated.
    1112PASS stream.getAudioTracks().length is 1
  • trunk/LayoutTests/fast/mediastream/MediaDevices-getUserMedia.html

    r205953 r206011  
    146146            setUserMediaPermission(true);
    147147            shouldNotThrow("navigator.mediaDevices.getUserMedia({audio:true}).then(gotStream1);");
     148            navigator.mediaDevices.getUserMedia.apply(undefined, {audio:true}).then(invalidGotStream, function(error) {
     149                 testPassed("navigator.mediaDevices.getUserMedia.apply(undefined) rejected with error: " + error);
     150            });
    148151
    149152            window.jsTestIsAsync = true;
  • trunk/LayoutTests/http/tests/media/media-stream/disconnected-frame-already-expected.txt

    r191949 r206011  
    1 CONSOLE MESSAGE: line 24: TypeError: The implementation did not support the requested type of object or operation.
     1CONSOLE MESSAGE: line 24: TypeError: Can only call Navigator.webkitGetUserMedia on instances of Navigator
    22Tests that when a getUserMedia request is made after its frame has been disconnected, no callbacks are made and no crash occurs.
    33
  • trunk/Source/JavaScriptCore/ChangeLog

    r205998 r206011  
     12016-09-16  Youenn Fablet  <youenn@apple.com>
     2
     3        Custom promise-returning functions should not throw if callee has not the expected type
     4        https://bugs.webkit.org/show_bug.cgi?id=162011
     5
     6        Reviewed by Sam Weinig.
     7
     8        * JavaScriptCore.xcodeproj/project.pbxproj: Making JSPromiseConstructor.h private
     9
    1102016-09-15  Filip Pizlo  <fpizlo@apple.com>
    211
  • trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r205666 r206011  
    13511351                7C184E1F17BEE22E007CB63A /* JSPromisePrototype.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C184E1D17BEE22E007CB63A /* JSPromisePrototype.h */; };
    13521352                7C184E2217BEE240007CB63A /* JSPromiseConstructor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C184E2017BEE240007CB63A /* JSPromiseConstructor.cpp */; };
    1353                 7C184E2317BEE240007CB63A /* JSPromiseConstructor.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C184E2117BEE240007CB63A /* JSPromiseConstructor.h */; };
     1353                7C184E2317BEE240007CB63A /* JSPromiseConstructor.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C184E2117BEE240007CB63A /* JSPromiseConstructor.h */; settings = {ATTRIBUTES = (Private, ); }; };
    13541354                7E4EE7090EBB7963005934AA /* StructureChain.h in Headers */ = {isa = PBXBuildFile; fileRef = 7E4EE7080EBB7963005934AA /* StructureChain.h */; settings = {ATTRIBUTES = (Private, ); }; };
    13551355                7E4EE70F0EBB7A5B005934AA /* StructureChain.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7E4EE70E0EBB7A5B005934AA /* StructureChain.cpp */; };
  • trunk/Source/WebCore/CMakeLists.txt

    r206007 r206011  
    36593659    ${WEBCORE_DIR}/Modules/fetch/FetchResponse.js
    36603660    ${WEBCORE_DIR}/Modules/fetch/WorkerGlobalScopeFetch.js
    3661     ${WEBCORE_DIR}/Modules/mediastream/MediaDevices.js
    36623661    ${WEBCORE_DIR}/Modules/mediastream/NavigatorUserMedia.js
    36633662    ${WEBCORE_DIR}/Modules/mediastream/RTCPeerConnection.js
  • trunk/Source/WebCore/ChangeLog

    r206010 r206011  
     12016-09-16  Youenn Fablet  <youenn@apple.com>
     2
     3        Custom promise-returning functions should not throw if callee has not the expected type
     4        https://bugs.webkit.org/show_bug.cgi?id=162011
     5
     6        Reviewed by Sam Weinig.
     7
     8        Covered by added test.
     9
     10        Updating code generator to handle this case.
     11        Cleaning related getUserMedia implementation.
     12
     13        * CMakeLists.txt: Removing Modules/mediastream/MediaDevices.js.
     14        * DerivedSources.make: Removing Modules/mediastream/MediaDevices.js.
     15        * Modules/mediastream/MediaDevices.idl: Cleaning IDL definition
     16        * Modules/mediastream/MediaDevices.js: Removing error throwing and so removing file.
     17        * Modules/mediastream/NavigatorUserMedia.js: getUsermMediaFromJS to getUserMedia.
     18        * WebCore.xcodeproj/project.pbxproj: Removing Modules/mediastream/MediaDevices.js.
     19        * bindings/js/JSDOMPromise.cpp:
     20        (WebCore::createRejectedPromiseWithTypeError): Helper routine.
     21        * bindings/js/JSDOMPromise.h:
     22        * bindings/js/WebCoreBuiltinNames.h: getUsermMediaFromJS to getUserMedia.
     23        * bindings/scripts/CodeGeneratorJS.pm:
     24        (GenerateImplementation): Rejecting promise in case of failing castedThis, but only for custom functions since
     25        they are handled differently for non custom methods.
     26        (GenerateFunctionCastedThis):
     27        * bindings/scripts/test/JS/JSTestObj.cpp:
     28        * bindings/scripts/test/JS/JSTestObj.h:
     29        * bindings/scripts/test/TestObj.idl: Adding custom promise test.
     30
    1312016-09-16  Youenn Fablet  <youenn@apple.com>
    232
  • trunk/Source/WebCore/DerivedSources.make

    r205929 r206011  
    12851285    $(WebCore)/Modules/fetch/FetchResponse.js \
    12861286    ${WebCore}/Modules/fetch/WorkerGlobalScopeFetch.js \
    1287     $(WebCore)/Modules/mediastream/MediaDevices.js \
    12881287    $(WebCore)/Modules/mediastream/NavigatorUserMedia.js \
    12891288    $(WebCore)/Modules/mediastream/RTCPeerConnection.js \
  • trunk/Source/WebCore/Modules/mediastream/MediaDevices.idl

    r204516 r206011  
    3535    MediaTrackSupportedConstraints getSupportedConstraints();
    3636
    37     [JSBuiltin] Promise getUserMedia(Dictionary options);
     37    [Custom, PrivateIdentifier, PublicIdentifier] Promise getUserMedia(Dictionary options);
    3838    [RaisesException] Promise enumerateDevices();
    39 
    40     [PrivateIdentifier, RaisesException, ImplementedAs=getUserMedia, Custom] Promise getUserMediaFromJS(Dictionary options);
    4139};
  • trunk/Source/WebCore/Modules/mediastream/NavigatorUserMedia.js

    r196525 r206011  
    3131
    3232    // FIXME: We should raise a DOM unsupported exception if there is no navigator and properly detect whether method is not called on a Navigator object.
    33     if (!(this.mediaDevices && this.mediaDevices.@getUserMediaFromJS))
    34         throw new @TypeError("The implementation did not support the requested type of object or operation.");
     33    if (!(this.mediaDevices && this.mediaDevices.@getUserMedia))
     34        throw @makeThisTypeError("Navigator", "webkitGetUserMedia");
    3535
    3636    if (arguments.length < 3)
     
    4545        throw new @TypeError("Argument 3 ('errorCallback') to Navigator.webkitGetUserMedia must be a function");
    4646
    47     this.mediaDevices.@getUserMediaFromJS(options).@then(successCallback, errorCallback);
     47    this.mediaDevices.@getUserMedia(options).@then(successCallback, errorCallback);
    4848}
  • trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj

    r206007 r206011  
    1082710827                9920398018B95BC600B39AF9 /* UserInputBridge.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UserInputBridge.cpp; sourceTree = "<group>"; };
    1082810828                9920398118B95BC600B39AF9 /* UserInputBridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UserInputBridge.h; sourceTree = "<group>"; };
    10829                 9994E5D81BD843A300F2D835 /* MediaDevices.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = MediaDevices.js; sourceTree = "<group>"; };
    1083010829                99C7CCB218C663E40032E413 /* MemoizedDOMResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MemoizedDOMResult.h; sourceTree = "<group>"; };
    1083110830                99C7CCB418C6B8990032E413 /* MemoizedDOMResult.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MemoizedDOMResult.cpp; sourceTree = "<group>"; };
     
    1447914478                                5EA725CE1ACABCD900EAD17B /* MediaDevices.h */,
    1448014479                                5EA725CF1ACABCD900EAD17B /* MediaDevices.idl */,
    14481                                 9994E5D81BD843A300F2D835 /* MediaDevices.js */,
    1448214480                                07394EC71BAB2CCD00BE99CD /* MediaDevicesRequest.cpp */,
    1448314481                                07394EC91BAB2CD700BE99CD /* MediaDevicesRequest.h */,
  • trunk/Source/WebCore/bindings/js/JSDOMPromise.cpp

    r205569 r206011  
    2929#include "ExceptionCode.h"
    3030#include "JSDOMError.h"
     31#include <builtins/BuiltinNames.h>
    3132#include <runtime/Exception.h>
    3233#include <runtime/JSONObject.h>
     34#include <runtime/JSPromiseConstructor.h>
    3335
    3436using namespace JSC;
     
    113115}
    114116
     117JSC::EncodedJSValue createRejectedPromiseWithTypeError(JSC::ExecState& state, const String& errorMessage)
     118{
     119    ASSERT(state.lexicalGlobalObject());
     120    auto& globalObject = *state.lexicalGlobalObject();
     121
     122    auto promiseConstructor = globalObject.promiseConstructor();
     123    auto rejectFunction = promiseConstructor->get(&state, state.vm().propertyNames->builtinNames().rejectPrivateName());
     124    auto rejectionValue = createTypeError(&state, errorMessage);
     125
     126    CallData callData;
     127    auto callType = getCallData(rejectFunction, callData);
     128    ASSERT(callType != CallType::None);
     129
     130    MarkedArgumentBuffer arguments;
     131    arguments.append(rejectionValue);
     132
     133    return JSValue::encode(call(&state, rejectFunction, callType, callData, promiseConstructor, arguments));
     134}
     135
    115136static inline JSC::JSValue parseAsJSON(JSC::ExecState* state, const String& data)
    116137{
  • trunk/Source/WebCore/bindings/js/JSDOMPromise.h

    r205953 r206011  
    157157void fulfillPromiseWithArrayBuffer(Ref<DeferredWrapper>&&, const void*, size_t);
    158158void rejectPromiseWithExceptionIfAny(JSC::ExecState&, JSDOMGlobalObject&, JSC::JSPromiseDeferred&);
     159JSC::EncodedJSValue createRejectedPromiseWithTypeError(JSC::ExecState&, const String&);
    159160
    160161using PromiseFunction = void(JSC::ExecState&, Ref<DeferredWrapper>&&);
  • trunk/Source/WebCore/bindings/js/WebCoreBuiltinNames.h

    r205348 r206011  
    4949    macro(finishConsumingStream) \
    5050    macro(firstReadCallback) \
    51     macro(getUserMediaFromJS) \
     51    macro(getUserMedia) \
    5252    macro(getRemoteStreams) \
    5353    macro(getSenders) \
  • trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm

    r205953 r206011  
    34193419            my $functionImplementationName = $function->signature->extendedAttributes->{"ImplementedAs"} || $codeGenerator->WK_lcfirst($function->signature->name);
    34203420
     3421            if (IsReturningPromise($function)) {
     3422                AddToImplIncludes("JSDOMPromise.h");
     3423            }
    34213424            if (IsReturningPromise($function) && !$isCustom) {
    3422                 AddToImplIncludes("JSDOMPromise.h");
    34233425
    34243426                my $scope = $interface->extendedAttributes->{"Exposed"} ? "WindowOrWorker" : "WindowOnly";
     
    34713473                }
    34723474            } else {
    3473                 GenerateFunctionCastedThis($interface, $className, $function);
     3475                my $shouldRejectCastedThis = $isCustom && IsReturningPromise($function);
     3476                GenerateFunctionCastedThis($interface, $className, $function, $shouldRejectCastedThis);
    34743477
    34753478                if ($interface->extendedAttributes->{"CheckSecurity"} and !$function->signature->extendedAttributes->{"DoNotCheckSecurity"}) {
     
    37613764sub GenerateFunctionCastedThis
    37623765{
    3763     my ($interface, $className, $function) = @_;
     3766    my ($interface, $className, $function, $shouldRejectPromise) = @_;
    37643767
    37653768    if ($interface->extendedAttributes->{"CustomProxyToJSObject"}) {
     
    37823785        my $domFunctionName = $function->signature->name;
    37833786        push(@implContent, "    if (UNLIKELY(!castedThis))\n");
    3784         push(@implContent, "        return throwThisTypeError(*state, throwScope, \"$visibleInterfaceName\", \"$domFunctionName\");\n");
     3787        if ($shouldRejectPromise) {
     3788            push(@implContent, "        return createRejectedPromiseWithTypeError(*state, makeThisTypeErrorMessage(\"$visibleInterfaceName\", \"$domFunctionName\"));\n");
     3789        } else {
     3790            push(@implContent, "        return throwThisTypeError(*state, throwScope, \"$visibleInterfaceName\", \"$domFunctionName\");\n");
     3791        }
    37853792    }
    37863793
  • trunk/Source/WebCore/bindings/scripts/test/JS/JSTestObj.cpp

    r205964 r206011  
    810810JSC::EncodedJSValue JSC_HOST_CALL jsTestObjConstructorFunctionTestStaticPromiseFunction(JSC::ExecState*);
    811811JSC::EncodedJSValue JSC_HOST_CALL jsTestObjConstructorFunctionTestStaticPromiseFunctionWithException(JSC::ExecState*);
     812JSC::EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionTestCustomPromiseFunction(JSC::ExecState*);
    812813JSC::EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionMethodWithNeedsCustomElementReactionStack(JSC::ExecState*);
    813814#if ENABLE(CONDITION1) || ENABLE(CONDITION2)
     
    14121413    { "testPromiseFunctionWithOptionalIntArgument", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionTestPromiseFunctionWithOptionalIntArgument), (intptr_t) (0) } },
    14131414    { "testPromiseOverloadedFunction", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionTestPromiseOverloadedFunction), (intptr_t) (1) } },
     1415    { "testCustomPromiseFunction", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionTestCustomPromiseFunction), (intptr_t) (0) } },
    14141416    { "methodWithNeedsCustomElementReactionStack", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionMethodWithNeedsCustomElementReactionStack), (intptr_t) (0) } },
    14151417#if ENABLE(CONDITION1) || ENABLE(CONDITION2)
     
    73697371}
    73707372
     7373EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionTestCustomPromiseFunction(ExecState* state)
     7374{
     7375    VM& vm = state->vm();
     7376    auto throwScope = DECLARE_THROW_SCOPE(vm);
     7377    UNUSED_PARAM(throwScope);
     7378    JSValue thisValue = state->thisValue();
     7379    auto castedThis = jsDynamicCast<JSTestObj*>(thisValue);
     7380    if (UNLIKELY(!castedThis))
     7381        return createRejectedPromiseWithTypeError(*state, makeThisTypeErrorMessage("TestObject", "testCustomPromiseFunction"));
     7382    ASSERT_GC_OBJECT_INHERITS(castedThis, JSTestObj::info());
     7383    return JSValue::encode(castedThis->testCustomPromiseFunction(*state));
     7384}
     7385
    73717386EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionMethodWithNeedsCustomElementReactionStack(ExecState* state)
    73727387{
  • trunk/Source/WebCore/bindings/scripts/test/JS/JSTestObj.h

    r205458 r206011  
    6666    JSC::JSValue customMethodWithArgs(JSC::ExecState&);
    6767    static JSC::JSValue classMethod2(JSC::ExecState&);
     68    JSC::JSValue testCustomPromiseFunction(JSC::ExecState&);
    6869public:
    6970    static const unsigned StructureFlags = JSC::HasStaticPropertyTable | JSC::InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero | JSC::OverridesGetOwnPropertySlot | JSC::OverridesGetPropertyNames | Base::StructureFlags;
  • trunk/Source/WebCore/bindings/scripts/test/TestObj.idl

    r205061 r206011  
    389389    static Promise testStaticPromiseFunction();
    390390    [RaisesException] static Promise testStaticPromiseFunctionWithException();
     391    [Custom] Promise testCustomPromiseFunction();
    391392
    392393    // PutForwards
Note: See TracChangeset for help on using the changeset viewer.