Closed Bug 1066234 Opened 11 years ago Closed 11 years ago

Support 'extends' in ES6 classes

Categories

(Core :: JavaScript Engine, defect)

x86_64
Linux
defect
Not set
normal

Tracking

()

RESOLVED FIXED
mozilla39
Tracking Status
firefox39 --- fixed

People

(Reporter: jorendorff, Assigned: efaust)

References

Details

(Keywords: dev-doc-complete, Whiteboard: [DocArea=JS])

Attachments

(7 files)

Combined with @@create support, this should be sufficient to test subclassing of builtin classes like Array and Map.
Keywords: dev-doc-needed
Whiteboard: [DocArea=JS]
Assignee: nobody → efaustbmo
Status: NEW → ASSIGNED
Attachment #8539082 - Flags: review?(jorendorff)
Attachment #8539083 - Flags: review?(jorendorff)
Conveniently, because of the used spec here, we can still use nullptr as a sentinel value for %%FunctionPrototype%%
Attachment #8539084 - Flags: review?(jorendorff)
Attachment #8539085 - Flags: review?(jorendorff)
Attachment #8539086 - Flags: review?(jorendorff)
Attachment #8539087 - Flags: review?(jorendorff)
Comment on attachment 8539082 [details] [diff] [review] Parser support for "extends" Review of attachment 8539082 [details] [diff] [review]: ----------------------------------------------------------------- Clearing r? on a bunch of patches that need tests.
Attachment #8539082 - Flags: review?(jorendorff)
Attachment #8539083 - Flags: review?(jorendorff)
Attachment #8539084 - Flags: review?(jorendorff)
Attachment #8539085 - Flags: review?(jorendorff)
Attachment #8539086 - Flags: review?(jorendorff)
Attachment #8539087 - Flags: review?(jorendorff)
If you like this, you'll love the rest ;)
Attachment #8555514 - Flags: review?(jorendorff)
Blocks: 1130744
Comment on attachment 8555514 [details] [diff] [review] Test support for "extends" Review of attachment 8555514 [details] [diff] [review]: ----------------------------------------------------------------- ::: js/src/tests/ecma_6/Class/classHeritage.js @@ +45,5 @@ > +assertEq(overrideCalled, "derived"); > + > +// What about the statics? > +derived.staticMethod(); > +assertEq(staticMethodCalled, true); Check that the 'this' argument passed to the static method in this situation is correct? ::: js/src/tests/js1_8_5/extensions/reflect-parse.js @@ +1277,5 @@ > assertError("class Foo { constructor()", SyntaxError); > assertError("class Foo { constructor()", SyntaxError); > assertError("class Foo { constructor() {", SyntaxError); > assertError("class Foo { constructor() { }", SyntaxError); > + assertError("class Foo extends", SyntaxError); Also "class Foo extends Bar" please.
Attachment #8555514 - Flags: review?(jorendorff) → review+
Attachment #8539082 - Flags: review?(jorendorff)
Attachment #8539083 - Flags: review?(jorendorff)
Attachment #8539084 - Flags: review?(jorendorff)
Attachment #8539085 - Flags: review?(jorendorff)
Attachment #8539086 - Flags: review?(jorendorff)
Please also test this situation. class Foo {} { class Foo extends Foo {} // inner extends outer, or ReferenceError? } I have not attempted to figure out what is supposed to happen.
Please throw this in there too please. // Non-writable, non-configurable base-class methods can be overridden. class Base { x() { return 2; } } Object.freeze(Base.prototype); class Derived extends Base { x() { return 3; } } assertEq(new Derived().x(), 3);
Attachment #8539087 - Flags: review?(jorendorff)
(In reply to Jason Orendorff [:jorendorff] from comment #11) > Please throw this in there too please. > > // Non-writable, non-configurable base-class methods can be overridden. > class Base { > x() { return 2; } > } > Object.freeze(Base.prototype); > > class Derived extends Base { > x() { return 3; } > } > assertEq(new Derived().x(), 3); This is good. It should work, but we should test it.(In reply to Jason Orendorff > Please also test this situation. > > class Foo {} > { > class Foo extends Foo {} // inner extends outer, or ReferenceError? > } > > I have not attempted to figure out what is supposed to happen. Inner should extend outer, as by the time we are able to put the class definition (inside a method), we are in a shadowing block scope.
Attachment #8539082 - Flags: review?(jorendorff) → review+
Comment on attachment 8539083 [details] [diff] [review] Interpreter support for JSOP_CLASSHERITAGE Review of attachment 8539083 [details] [diff] [review]: ----------------------------------------------------------------- ::: js/src/vm/Interpreter.cpp @@ +3465,5 @@ > + RootedObject &funcProto = rootObject2; > + if (val.isNull()) { > + objProto = nullptr; > + if (!GetBuiltinPrototype(cx, JSProto_Function, &funcProto)) > + goto error; Micro-nit: This would be more direct: funcProto = cx->global()->getOrCreateFunctionPrototype(cx); if (!funcProto) goto error; Either way is correct, your call. @@ +3479,5 @@ > + if (!JSObject::getProperty(cx, funcProto, funcProto, cx->names().prototype, &protoProp)) > + goto error; > + > + if (!protoProp.isObjectOrNull()) { > + js_ReportValueError(cx, JSMSG_NOT_OBJORNULL, JSDVG_IGNORE_STACK, protoProp, NullPtr()); This is one of those rare cases where the expression decompiler should be used! Pass -1 instead of JSDVG_IGNORE_STACK, and change the error message like this: >-MSG_DEF(JSMSG_NOT_OBJORNULL, 1, JSEXN_TYPEERR, "{0} is not an object or null") >+MSG_DEF(JSMSG_PROTO_NOT_OBJORNULL, 1, JSEXN_TYPEERR, "{0}.prototype is not an object or null") @@ +3482,5 @@ > + if (!protoProp.isObjectOrNull()) { > + js_ReportValueError(cx, JSMSG_NOT_OBJORNULL, JSDVG_IGNORE_STACK, protoProp, NullPtr()); > + goto error; > + } > + objProto = protoProp.toObjectOrNull(); Seems a little awkward to call toObjectOrNull here and then immediately pass the result to setObjectOrNull. Make objProto a RootedValue & and you can get rid of protoProp. ::: js/src/vm/Opcodes.h @@ +479,5 @@ > * Operands: > * Stack: callee, this, args => rval > */ \ > macro(JSOP_STRICTSPREADEVAL, 50, "strict-spreadeval", NULL, 1, 3, 1, JOF_BYTE|JOF_INVOKE|JOF_TYPESET|JOF_CHECKSTRICT) \ > + macro(JSOP_CLASSHERITAGE, 51, "classheritage", NULL, 1, 1, 2, JOF_BYTE) \ Needs a comment like every other opcode.
Attachment #8539083 - Flags: review?(jorendorff) → review+
Attachment #8539084 - Flags: review?(jorendorff) → review+
Comment on attachment 8539085 [details] [diff] [review] Interpreter support for JSOP_FUNWITHPROTO Review of attachment 8539085 [details] [diff] [review]: ----------------------------------------------------------------- ::: js/src/vm/Opcodes.h @@ +480,5 @@ > * Stack: callee, this, args => rval > */ \ > macro(JSOP_STRICTSPREADEVAL, 50, "strict-spreadeval", NULL, 1, 3, 1, JOF_BYTE|JOF_INVOKE|JOF_TYPESET|JOF_CHECKSTRICT) \ > macro(JSOP_CLASSHERITAGE, 51, "classheritage", NULL, 1, 1, 2, JOF_BYTE) \ > + macro(JSOP_FUNWITHPROTO, 52, "funcwithproto", NULL, 5, 1, 1, JOF_OBJECT) \ Needs a comment.
Attachment #8539085 - Flags: review?(jorendorff) → review+
Comment on attachment 8539086 [details] [diff] [review] Interpreter support for JSOP_OBJWITHPROTO Review of attachment 8539086 [details] [diff] [review]: ----------------------------------------------------------------- ::: js/src/vm/Interpreter.cpp @@ +3511,5 @@ > +{ > + RootedObject &proto = rootObject0; > + proto = REGS.sp[-1].toObjectOrNull(); > + > + JSObject *obj = NewObjectWithGivenProto(cx, &JSObject::class_, proto, cx->global()); It's PlainObject::class_ now (just in case you end up wondering where this went). Do we have tests for cases like function F() {} F.prototype = null; class G extends F {...} And the error case where F.prototype is undefined or a string or something? Add 'em if we don't. No need for a new review. ::: js/src/vm/Opcodes.h @@ +753,5 @@ > * nuses: (argc+2) > */ \ > macro(JSOP_NEW, 82, js_new_str, NULL, 3, -1, 1, JOF_UINT16|JOF_INVOKE|JOF_TYPESET) \ > \ > + macro(JSOP_OBJWITHPROTO, 83, "objwithproto", NULL, 1, 1, 1, JOF_BYTE) \ Needs a comment.
Attachment #8539086 - Flags: review?(jorendorff) → review+
Also don't forget to increment the subtrahend ;)
Comment on attachment 8539087 [details] [diff] [review] Emitter support for "extends" Review of attachment 8539087 [details] [diff] [review]: ----------------------------------------------------------------- woot
Attachment #8539087 - Flags: review?(jorendorff) → review+
Dunno yet whether anything else plans on burning, but SM(e) says "/js/src/frontend/Parser.cpp:5869:16: error: converting 'false' to pointer type 'js::frontend::ParseNode*' [-Werror=conversion-null]" Backed out in https://hg.mozilla.org/integration/mozilla-inbound/rev/b43067fa81e7
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: