Changeset 195070 in webkit


Ignore:
Timestamp:
Jan 14, 2016 12:45:48 PM (8 years ago)
Author:
keith_miller@apple.com
Message:

[ES6] Support subclassing Function.
https://bugs.webkit.org/show_bug.cgi?id=153081

Reviewed by Geoffrey Garen.

Source/JavaScriptCore:

This patch enables subclassing the Function object. It also fixes an existing
bug that prevented users from subclassing functions that have a function in
the superclass's prototype property.

  • bytecompiler/NodesCodegen.cpp:

(JSC::ClassExprNode::emitBytecode):

  • runtime/FunctionConstructor.cpp:

(JSC::constructWithFunctionConstructor):
(JSC::constructFunction):
(JSC::constructFunctionSkippingEvalEnabledCheck):

  • runtime/FunctionConstructor.h:
  • runtime/JSFunction.cpp:

(JSC::JSFunction::create):

  • runtime/JSFunction.h:

(JSC::JSFunction::createImpl):

  • runtime/JSFunctionInlines.h:

(JSC::JSFunction::createWithInvalidatedReallocationWatchpoint):
(JSC::JSFunction::JSFunction): Deleted.

  • tests/stress/class-subclassing-function.js: Added.

LayoutTests:

Rebasline tests with the new clearer error message.

  • js/class-syntax-extends-expected.txt:
  • js/script-tests/class-syntax-extends.js:
Location:
trunk
Files:
1 added
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r195069 r195070  
     12016-01-14  Keith Miller  <keith_miller@apple.com>
     2
     3        [ES6] Support subclassing Function.
     4        https://bugs.webkit.org/show_bug.cgi?id=153081
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        Rebasline tests with the new clearer error message.
     9
     10        * js/class-syntax-extends-expected.txt:
     11        * js/script-tests/class-syntax-extends.js:
     12
    1132016-01-14  Zalan Bujtas  <zalan@apple.com>
    214
  • trunk/LayoutTests/js/class-syntax-extends-expected.txt

    r190847 r195070  
    2727PASS x = class extends "abc" { constructor() { } }; x.__proto__:::TypeError: The superclass is not an object.
    2828PASS baseWithBadPrototype = function () {}; baseWithBadPrototype.prototype = 3; new baseWithBadPrototype
    29 PASS x = class extends baseWithBadPrototype { constructor() { } }:::TypeError: The superclass's prototype is not an object.
     29PASS x = class extends baseWithBadPrototype { constructor() { } }:::TypeError: The value of the superclass's prototype property is not an object.
    3030PASS baseWithBadPrototype.prototype = "abc"
    31 PASS x = class extends baseWithBadPrototype { constructor() { } }:::TypeError: The superclass's prototype is not an object.
     31PASS x = class extends baseWithBadPrototype { constructor() { } }:::TypeError: The value of the superclass's prototype property is not an object.
    3232PASS baseWithBadPrototype.prototype = null; x = class extends baseWithBadPrototype { constructor() { } }
    3333PASS x = 1; c = class extends ++x { constructor() { } };:::SyntaxError: Unexpected token '++'
     
    4949PASS x = 1; namespace = {}; namespace.A = class { constructor() { } }; namespace.B = class extends (x++, namespace.A) { constructor() { } };
    5050PASS x = 1; namespace = {}; namespace.A = class { constructor() { } }; namespace.B = class extends (namespace.A, x++) { constructor() { } };:::TypeError: The superclass is not an object.
    51 PASS namespace = {}; namespace.A = class { constructor() { } }; namespace.B = class extends new namespace.A { constructor() { } }:::TypeError: The superclass's prototype is not an object.
    52 PASS namespace = {}; namespace.A = class { constructor() { } }; namespace.B = class extends new namespace.A() { constructor() { } }:::TypeError: The superclass's prototype is not an object.
     51PASS namespace = {}; namespace.A = class { constructor() { } }; namespace.B = class extends new namespace.A { constructor() { } }:::TypeError: The value of the superclass's prototype property is not an object.
     52PASS namespace = {}; namespace.A = class { constructor() { } }; namespace.B = class extends new namespace.A() { constructor() { } }:::TypeError: The value of the superclass's prototype property is not an object.
    5353PASS x = 1; namespace = {}; namespace.A = class { constructor() { } }; try { namespace.B = class extends (x++, namespace.A) { constructor() { } } } catch (e) { } x:::2
    5454PASS x = 1; namespace = {}; namespace.A = class { constructor() { } }; try { namespace.B = class extends (namespace.A, x++) { constructor() { } } } catch (e) { } x:::2
  • trunk/LayoutTests/js/script-tests/class-syntax-extends.js

    r190847 r195070  
    8282shouldThrow('x = class extends "abc" { constructor() { } }; x.__proto__', '"TypeError: The superclass is not an object."');
    8383shouldNotThrow('baseWithBadPrototype = function () {}; baseWithBadPrototype.prototype = 3; new baseWithBadPrototype');
    84 shouldThrow('x = class extends baseWithBadPrototype { constructor() { } }', '"TypeError: The superclass\'s prototype is not an object."');
     84shouldThrow('x = class extends baseWithBadPrototype { constructor() { } }', '"TypeError: The value of the superclass\'s prototype property is not an object."');
    8585shouldNotThrow('baseWithBadPrototype.prototype = "abc"');
    86 shouldThrow('x = class extends baseWithBadPrototype { constructor() { } }', '"TypeError: The superclass\'s prototype is not an object."');
     86shouldThrow('x = class extends baseWithBadPrototype { constructor() { } }', '"TypeError: The value of the superclass\'s prototype property is not an object."');
    8787shouldNotThrow('baseWithBadPrototype.prototype = null; x = class extends baseWithBadPrototype { constructor() { } }');
    8888
  • trunk/Source/JavaScriptCore/ChangeLog

    r195009 r195070  
     12016-01-14  Keith Miller  <keith_miller@apple.com>
     2
     3        [ES6] Support subclassing Function.
     4        https://bugs.webkit.org/show_bug.cgi?id=153081
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        This patch enables subclassing the Function object. It also fixes an existing
     9        bug that prevented users from subclassing functions that have a function in
     10        the superclass's prototype property.
     11
     12        * bytecompiler/NodesCodegen.cpp:
     13        (JSC::ClassExprNode::emitBytecode):
     14        * runtime/FunctionConstructor.cpp:
     15        (JSC::constructWithFunctionConstructor):
     16        (JSC::constructFunction):
     17        (JSC::constructFunctionSkippingEvalEnabledCheck):
     18        * runtime/FunctionConstructor.h:
     19        * runtime/JSFunction.cpp:
     20        (JSC::JSFunction::create):
     21        * runtime/JSFunction.h:
     22        (JSC::JSFunction::createImpl):
     23        * runtime/JSFunctionInlines.h:
     24        (JSC::JSFunction::createWithInvalidatedReallocationWatchpoint):
     25        (JSC::JSFunction::JSFunction): Deleted.
     26        * tests/stress/class-subclassing-function.js: Added.
     27
    1282016-01-13  Carlos Garcia Campos  <cgarcia@igalia.com>
    229
  • trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp

    r194449 r195070  
    32293229        RefPtr<Label> protoParentIsObjectOrNullLabel = generator.newLabel();
    32303230        generator.emitJumpIfTrue(generator.emitUnaryOp(op_is_object_or_null, tempRegister.get(), protoParent.get()), protoParentIsObjectOrNullLabel.get());
    3231         generator.emitThrowTypeError(ASCIILiteral("The superclass's prototype is not an object."));
     3231        generator.emitJumpIfTrue(generator.emitUnaryOp(op_is_function, tempRegister.get(), protoParent.get()), protoParentIsObjectOrNullLabel.get());
     3232        generator.emitThrowTypeError(ASCIILiteral("The value of the superclass's prototype property is not an object."));
    32323233        generator.emitLabel(protoParentIsObjectOrNullLabel.get());
    32333234
  • trunk/Source/JavaScriptCore/runtime/FunctionConstructor.cpp

    r194310 r195070  
    5757{
    5858    ArgList args(exec);
    59     return JSValue::encode(constructFunction(exec, asInternalFunction(exec->callee())->globalObject(), args));
     59    return JSValue::encode(constructFunction(exec, asInternalFunction(exec->callee())->globalObject(), args, FunctionConstructionMode::Function, exec->newTarget()));
    6060}
    6161
     
    8080
    8181// ECMA 15.3.2 The Function Constructor
    82 JSObject* constructFunction(ExecState* exec, JSGlobalObject* globalObject, const ArgList& args, const Identifier& functionName, const String& sourceURL, const TextPosition& position, FunctionConstructionMode functionConstructionMode)
     82JSObject* constructFunction(ExecState* exec, JSGlobalObject* globalObject, const ArgList& args, const Identifier& functionName, const String& sourceURL, const TextPosition& position, FunctionConstructionMode functionConstructionMode, JSValue newTarget)
    8383{
    8484    if (!globalObject->evalEnabled())
    8585        return exec->vm().throwException(exec, createEvalError(exec, globalObject->evalDisabledErrorMessage()));
    86     return constructFunctionSkippingEvalEnabledCheck(exec, globalObject, args, functionName, sourceURL, position, -1, functionConstructionMode);
     86    return constructFunctionSkippingEvalEnabledCheck(exec, globalObject, args, functionName, sourceURL, position, -1, functionConstructionMode, newTarget);
    8787}
    8888
     
    9090    ExecState* exec, JSGlobalObject* globalObject, const ArgList& args,
    9191    const Identifier& functionName, const String& sourceURL,
    92     const TextPosition& position, int overrideLineNumber, FunctionConstructionMode functionConstructionMode)
     92    const TextPosition& position, int overrideLineNumber, FunctionConstructionMode functionConstructionMode, JSValue newTarget)
    9393{
    9494    // How we stringify functions is sometimes important for web compatibility.
     
    125125    }
    126126
    127     return JSFunction::create(exec->vm(), function, globalObject);
     127
     128    return JSFunction::create(exec->vm(), function, globalObject, InternalFunction::createSubclassStructure(exec, newTarget, globalObject->functionStructure()));
    128129}
    129130
    130131// ECMA 15.3.2 The Function Constructor
    131 JSObject* constructFunction(ExecState* exec, JSGlobalObject* globalObject, const ArgList& args, FunctionConstructionMode functionConstructionMode)
     132JSObject* constructFunction(ExecState* exec, JSGlobalObject* globalObject, const ArgList& args, FunctionConstructionMode functionConstructionMode, JSValue newTarget)
    132133{
    133     return constructFunction(exec, globalObject, args, exec->propertyNames().anonymous, String(), TextPosition::minimumPosition(), functionConstructionMode);
     134    return constructFunction(exec, globalObject, args, exec->propertyNames().anonymous, String(), TextPosition::minimumPosition(), functionConstructionMode, newTarget);
    134135}
    135136
  • trunk/Source/JavaScriptCore/runtime/FunctionConstructor.h

    r192937 r195070  
    6262};
    6363
    64 JSObject* constructFunction(ExecState*, JSGlobalObject*, const ArgList&, const Identifier& functionName, const String& sourceURL, const WTF::TextPosition&, FunctionConstructionMode = FunctionConstructionMode::Function);
    65 JSObject* constructFunction(ExecState*, JSGlobalObject*, const ArgList&, FunctionConstructionMode = FunctionConstructionMode::Function);
     64JSObject* constructFunction(ExecState*, JSGlobalObject*, const ArgList&, const Identifier& functionName, const String& sourceURL, const WTF::TextPosition&, FunctionConstructionMode = FunctionConstructionMode::Function, JSValue newTarget = JSValue());
     65JSObject* constructFunction(ExecState*, JSGlobalObject*, const ArgList&, FunctionConstructionMode = FunctionConstructionMode::Function, JSValue newTarget = JSValue());
    6666
    6767JS_EXPORT_PRIVATE JSObject* constructFunctionSkippingEvalEnabledCheck(
    6868    ExecState*, JSGlobalObject*, const ArgList&, const Identifier&,
    69     const String&, const WTF::TextPosition&, int overrideLineNumber = -1, FunctionConstructionMode = FunctionConstructionMode::Function);
     69    const String&, const WTF::TextPosition&, int overrideLineNumber = -1,
     70    FunctionConstructionMode = FunctionConstructionMode::Function, JSValue newTarget = JSValue());
    7071
    7172} // namespace JSC
  • trunk/Source/JavaScriptCore/runtime/JSFunction.cpp

    r195000 r195070  
    6464JSFunction* JSFunction::create(VM& vm, FunctionExecutable* executable, JSScope* scope)
    6565{
    66     JSFunction* result = createImpl(vm, executable, scope);
     66    return create(vm, executable, scope, scope->globalObject()->functionStructure());
     67}
     68
     69JSFunction* JSFunction::create(VM& vm, FunctionExecutable* executable, JSScope* scope, Structure* structure)
     70{
     71    JSFunction* result = createImpl(vm, executable, scope, structure);
    6772    executable->singletonFunction()->notifyWrite(vm, result, "Allocating a function");
    6873    return result;
  • trunk/Source/JavaScriptCore/runtime/JSFunction.h

    r195000 r195070  
    7474
    7575    static JSFunction* create(VM&, FunctionExecutable*, JSScope*);
     76    static JSFunction* create(VM&, FunctionExecutable*, JSScope*, Structure*);
    7677#if ENABLE(WEBASSEMBLY)
    7778    static JSFunction* create(VM&, WebAssemblyExecutable*, JSScope*);
     
    152153protected:
    153154    JS_EXPORT_PRIVATE JSFunction(VM&, JSGlobalObject*, Structure*);
    154     JSFunction(VM&, FunctionExecutable*, JSScope*);
    155155    JSFunction(VM&, FunctionExecutable*, JSScope*, Structure*);
    156156
     
    180180
    181181private:
    182     static JSFunction* createImpl(VM& vm, FunctionExecutable* executable, JSScope* scope)
    183     {
    184         JSFunction* function = new (NotNull, allocateCell<JSFunction>(vm.heap)) JSFunction(vm, executable, scope);
     182    static JSFunction* createImpl(VM& vm, FunctionExecutable* executable, JSScope* scope, Structure* structure)
     183    {
     184        JSFunction* function = new (NotNull, allocateCell<JSFunction>(vm.heap)) JSFunction(vm, executable, scope, structure);
    185185        ASSERT(function->structure()->globalObject());
    186186        function->finishCreation(vm);
  • trunk/Source/JavaScriptCore/runtime/JSFunctionInlines.h

    r191215 r195070  
    3636{
    3737    ASSERT(executable->singletonFunction()->hasBeenInvalidated());
    38     return createImpl(vm, executable, scope);
     38    return createImpl(vm, executable, scope, scope->globalObject()->functionStructure());
    3939}
    4040
    41 inline JSFunction::JSFunction(VM& vm, FunctionExecutable* executable, JSScope* scope)
    42     : Base(vm, scope, scope->globalObject()->functionStructure())
    43     , m_executable(vm, this, executable)
    44     , m_rareData()
    45 {
    46 }
    47    
    4841inline JSFunction::JSFunction(VM& vm, FunctionExecutable* executable, JSScope* scope, Structure* structure)
    4942    : Base(vm, scope, structure)
Note: See TracChangeset for help on using the changeset viewer.