Changeset 202846 in webkit


Ignore:
Timestamp:
Jul 5, 2016 10:04:05 PM (8 years ago)
Author:
commit-queue@webkit.org
Message:

RELEASE_ASSERT(!thisObject) in ObjCCallbackFunctionImpl::call when calling JSExport ObjC Constructor without operator new
https://bugs.webkit.org/show_bug.cgi?id=159446

Patch by Joseph Pecoraro <Joseph Pecoraro> on 2016-07-05
Reviewed by Mark Lam.

Source/JavaScriptCore:

Treat ObjC JSExport init constructors like ES6 Class Constructors
and throw a TypeError when called without 'new'.

  • API/ObjCCallbackFunction.mm:

(JSC::ObjCCallbackFunctionImpl::type):
(JSC::objCCallbackFunctionCallAsFunction):
When calling an init method as a function instead of construction
throw a TypeError.

  • bytecompiler/BytecodeGenerator.cpp:

(JSC::BytecodeGenerator::BytecodeGenerator):
Improve error message.

  • API/tests/testapi.mm:

(testObjectiveCAPIMain):
Test we get an exception when calling an ObjC constructor without 'new'.

LayoutTests:

  • js/class-syntax-call-expected.txt:
  • js/class-syntax-default-constructor-expected.txt:
  • js/script-tests/class-syntax-call.js:
  • js/script-tests/class-syntax-default-constructor.js:

Improve error message when calling a class constructor without 'new'.

Location:
trunk
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r202845 r202846  
     12016-07-05  Joseph Pecoraro  <pecoraro@apple.com>
     2
     3        RELEASE_ASSERT(!thisObject) in ObjCCallbackFunctionImpl::call when calling JSExport ObjC Constructor without operator new
     4        https://bugs.webkit.org/show_bug.cgi?id=159446
     5
     6        Reviewed by Mark Lam.
     7
     8        * js/class-syntax-call-expected.txt:
     9        * js/class-syntax-default-constructor-expected.txt:
     10        * js/script-tests/class-syntax-call.js:
     11        * js/script-tests/class-syntax-default-constructor.js:
     12        Improve error message when calling a class constructor without 'new'.
     13
    1142016-07-05  David Kilzer  <ddkilzer@apple.com>
    215
  • trunk/LayoutTests/js/class-syntax-call-expected.txt

    r190847 r202846  
    55
    66PASS new A
    7 PASS A():::"TypeError: Cannot call a class constructor"
     7PASS A():::"TypeError: Cannot call a class constructor without |new|"
    88PASS new B
    9 PASS B():::"TypeError: Cannot call a class constructor"
     9PASS B():::"TypeError: Cannot call a class constructor without |new|"
    1010PASS new (class { constructor() {} })()
    11 PASS (class { constructor() {} })():::"TypeError: Cannot call a class constructor"
     11PASS (class { constructor() {} })():::"TypeError: Cannot call a class constructor without |new|"
    1212PASS new (class extends null { constructor() { super() } })():::"TypeError: function is not a constructor (evaluating 'super()')"
    13 PASS (class extends null { constructor() { super() } })():::"TypeError: Cannot call a class constructor"
     13PASS (class extends null { constructor() { super() } })():::"TypeError: Cannot call a class constructor without |new|"
    1414PASS successfullyParsed is true
    1515
  • trunk/LayoutTests/js/class-syntax-default-constructor-expected.txt

    r187680 r202846  
    55
    66PASS new A instanceof A
    7 PASS A():::TypeError: Cannot call a class constructor
     7PASS A():::TypeError: Cannot call a class constructor without |new|
    88PASS A.prototype.constructor instanceof Function
    99PASS A.prototype.constructor.name:::"A"
    1010PASS new B instanceof A; new B instanceof A
    11 PASS B():::TypeError: Cannot call a class constructor
     11PASS B():::TypeError: Cannot call a class constructor without |new|
    1212PASS B.prototype.constructor.name:::"B"
    1313PASS A !== B
  • trunk/LayoutTests/js/script-tests/class-syntax-call.js

    r190847 r202846  
    3333
    3434shouldNotThrow('new A');
    35 shouldThrow('A()', '"TypeError: Cannot call a class constructor"');
     35shouldThrow('A()', '"TypeError: Cannot call a class constructor without |new|"');
    3636shouldNotThrow('new B');
    37 shouldThrow('B()', '"TypeError: Cannot call a class constructor"');
     37shouldThrow('B()', '"TypeError: Cannot call a class constructor without |new|"');
    3838shouldNotThrow('new (class { constructor() {} })()');
    39 shouldThrow('(class { constructor() {} })()', '"TypeError: Cannot call a class constructor"');
     39shouldThrow('(class { constructor() {} })()', '"TypeError: Cannot call a class constructor without |new|"');
    4040shouldThrow('new (class extends null { constructor() { super() } })()', '"TypeError: function is not a constructor (evaluating \'super()\')"');
    41 shouldThrow('(class extends null { constructor() { super() } })()', '"TypeError: Cannot call a class constructor"');
     41shouldThrow('(class extends null { constructor() { super() } })()', '"TypeError: Cannot call a class constructor without |new|"');
    4242
    4343var successfullyParsed = true;
  • trunk/LayoutTests/js/script-tests/class-syntax-default-constructor.js

    r187680 r202846  
    4444
    4545shouldBeTrue('new A instanceof A');
    46 shouldThrow('A()', '"TypeError: Cannot call a class constructor"');
     46shouldThrow('A()', '"TypeError: Cannot call a class constructor without |new|"');
    4747shouldBeTrue('A.prototype.constructor instanceof Function');
    4848shouldBe('A.prototype.constructor.name', '"A"');
    4949shouldBeTrue('new B instanceof A; new B instanceof A');
    50 shouldThrow('B()', '"TypeError: Cannot call a class constructor"');
     50shouldThrow('B()', '"TypeError: Cannot call a class constructor without |new|"');
    5151shouldBe('B.prototype.constructor.name', '"B"');
    5252shouldBeTrue('A !== B');
  • trunk/Source/JavaScriptCore/API/ObjCCallbackFunction.mm

    r200430 r202846  
    429429    }
    430430
     431    CallbackType type() const { return m_type; }
     432
    431433    bool isConstructible()
    432434    {
     
    455457    ObjCCallbackFunctionImpl* impl = callback->impl();
    456458    JSContext *context = [JSContext contextWithJSGlobalContextRef:toGlobalRef(callback->globalObject()->globalExec())];
     459
     460    if (impl->type() == CallbackInitMethod) {
     461        JSGlobalContextRef contextRef = [context JSGlobalContextRef];
     462        *exception = toRef(JSC::createTypeError(toJS(contextRef), ASCIILiteral("Cannot call a class constructor without |new|")));
     463        return JSValueMakeUndefined(contextRef);
     464    }
    457465
    458466    CallbackData callbackData;
  • trunk/Source/JavaScriptCore/API/tests/testapi.mm

    r190267 r202846  
    13351335        })()"];
    13361336        checkResult(@"shouldn't be able to construct ClassC", ![canConstructClassC toBool]);
     1337
    13371338        JSValue *canConstructClassCPrime = [context evaluateScript:@"(function() { \
    13381339            try { \
     
    13441345        })()"];
    13451346        checkResult(@"shouldn't be able to construct ClassCPrime", ![canConstructClassCPrime toBool]);
     1347    }
     1348
     1349    @autoreleasepool {
     1350        JSContext *context = [[JSContext alloc] init];
     1351        context[@"ClassA"] = [ClassA class];
     1352        context.exceptionHandler = ^(JSContext *context, JSValue *exception) {
     1353            NSLog(@"%@", [exception toString]);
     1354            context.exception = exception;
     1355        };
     1356
     1357        checkResult(@"ObjC Constructor without 'new' pre", !context.exception);
     1358        [context evaluateScript:@"ClassA(42)"];
     1359        checkResult(@"ObjC Constructor without 'new' post", context.exception);
    13461360    }
    13471361
  • trunk/Source/JavaScriptCore/ChangeLog

    r202844 r202846  
     12016-07-05  Joseph Pecoraro  <pecoraro@apple.com>
     2
     3        RELEASE_ASSERT(!thisObject) in ObjCCallbackFunctionImpl::call when calling JSExport ObjC Constructor without operator new
     4        https://bugs.webkit.org/show_bug.cgi?id=159446
     5
     6        Reviewed by Mark Lam.
     7
     8        Treat ObjC JSExport init constructors like ES6 Class Constructors
     9        and throw a TypeError when called without 'new'.
     10
     11        * API/ObjCCallbackFunction.mm:
     12        (JSC::ObjCCallbackFunctionImpl::type):
     13        (JSC::objCCallbackFunctionCallAsFunction):
     14        When calling an init method as a function instead of construction
     15        throw a TypeError.
     16
     17        * bytecompiler/BytecodeGenerator.cpp:
     18        (JSC::BytecodeGenerator::BytecodeGenerator):
     19        Improve error message.
     20
     21        * API/tests/testapi.mm:
     22        (testObjectiveCAPIMain):
     23        Test we get an exception when calling an ObjC constructor without 'new'.
     24
    1252016-07-05  Mark Lam  <mark.lam@apple.com>
    226
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp

    r202795 r202846  
    565565                    emitCreateThis(&m_thisRegister);
    566566            } else if (constructorKind() != ConstructorKind::None)
    567                 emitThrowTypeError("Cannot call a class constructor");
     567                emitThrowTypeError("Cannot call a class constructor without |new|");
    568568            else {
    569569                bool shouldEmitToThis = false;
Note: See TracChangeset for help on using the changeset viewer.