Bug 1166950 - Only give constructor functions a prototype. r=efaust
authorTom Schuster <evilpies@gmail.com>
Mon, 25 May 2015 19:31:46 +0200
changeset 245498 f3bf2b462632
parent 245497 0adc0764b127
child 245499 8911b21aa87c
push id60192
push userevilpies@gmail.com
push dateMon, 25 May 2015 17:32:02 +0000
treeherdermozilla-inbound@f3bf2b462632 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersefaust
bugs1166950
milestone41.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1166950 - Only give constructor functions a prototype. r=efaust
js/src/jsfun.cpp
js/src/tests/ecma_6/Class/methDefn.js
js/src/tests/ecma_6/Class/methDefnGen.js
js/src/tests/ecma_6/Class/methodsPrototype.js
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -438,26 +438,29 @@ fun_resolve(JSContext* cx, HandleObject 
     RootedFunction fun(cx, &obj->as<JSFunction>());
 
     if (JSID_IS_ATOM(id, cx->names().prototype)) {
         /*
          * Built-in functions do not have a .prototype property per ECMA-262,
          * or (Object.prototype, Function.prototype, etc.) have that property
          * created eagerly.
          *
-         * ES5 15.3.4: the non-native function object named Function.prototype
-         * does not have a .prototype property.
-         *
          * ES5 15.3.4.5: bound functions don't have a prototype property. The
          * isBuiltin() test covers this case because bound functions are native
          * (and thus built-in) functions by definition/construction.
          *
-         * ES6 19.2.4.3: arrow functions also don't have a prototype property.
+         * In ES6 9.2.8 MakeConstructor the .prototype property is only assigned
+         * to constructors.
+         *
+         * Thus all of the following don't get a .prototype property:
+         * - Methods (that are not class-constructors or generators)
+         * - Arrow functions
+         * - Function.prototype
          */
-        if (fun->isBuiltin() || fun->isArrow() || fun->isFunctionPrototype())
+        if (fun->isBuiltin() || !fun->isConstructor())
             return true;
 
         if (!ResolveInterpretedFunctionPrototype(cx, fun))
             return false;
 
         *resolvedp = true;
         return true;
     }
--- a/js/src/tests/ecma_6/Class/methDefn.js
+++ b/js/src/tests/ecma_6/Class/methDefn.js
@@ -113,16 +113,20 @@ assertEq(a[registered_sym](), 3);
 // Method characteristics.
 a = { b(){ return 4;} };
 b = Object.getOwnPropertyDescriptor(a, "b");
 assertEq(b.configurable, true);
 assertEq(b.enumerable, true);
 assertEq(b.writable, true);
 assertEq(b.value(), 4);
 
+// prototype property
+assertEq(a.b.prototype, undefined);
+assertEq(a.b.hasOwnProperty("prototype"), false);
+
 // Defining several methods using eval.
 var code = "({";
 for (i = 0; i < 1000; i++)
     code += "['foo' + " + i + "]() {return 'ok';}, "
 code += "['bar']() {return 'all ok'}});";
 var obj = eval(code);
 for (i = 0; i < 1000; i++)
     assertEq(obj["foo" + i](), "ok");
--- a/js/src/tests/ecma_6/Class/methDefnGen.js
+++ b/js/src/tests/ecma_6/Class/methDefnGen.js
@@ -61,16 +61,19 @@ assertEq(next.value, 1);
 next = it.next("hello");
 assertEq(next.done, false);
 assertEq(next.value, 2);
 next = it.next("world");
 assertEq(next.done, true);
 assertEq(next.value.hello, 2);
 assertEq(next.value.world, 3);
 
+// prototype property
+assertEq(b.g.hasOwnProperty("prototype"), true);
+
 // Strict mode
 a = {*b(c){"use strict";yield c;}};
 assertEq(a.b(1).next().value, 1);
 a = {*["b"](c){"use strict";return c;}};
 assertEq(a.b(1).next().value, 1);
 
 // Constructing
 a = {*g() { yield 1; }}
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_6/Class/methodsPrototype.js
@@ -0,0 +1,45 @@
+var test = `
+class TestClass {
+    constructor() { }
+    method() { }
+    get getter() { }
+    set setter(x) { }
+    *generator() { }
+    static staticMethod() { }
+    static get staticGetter() { }
+    static set staticSetter(x) { }
+    static *staticGenerator() { }
+}
+
+var test = new TestClass();
+
+var hasPrototype = [
+    test.constructor,
+    test.generator,
+    TestClass.staticGenerator
+]
+
+for (var fun of hasPrototype) {
+    assertEq(fun.hasOwnProperty('prototype'), true);
+}
+
+var hasNoPrototype = [
+    test.method,
+    Object.getOwnPropertyDescriptor(test.__proto__, 'getter').get,
+    Object.getOwnPropertyDescriptor(test.__proto__, 'setter').set,
+    TestClass.staticMethod,
+    Object.getOwnPropertyDescriptor(TestClass, 'staticGetter').get,
+    Object.getOwnPropertyDescriptor(TestClass, 'staticSetter').set,
+]
+
+for (var fun of hasNoPrototype) {
+    assertEq(fun.hasOwnProperty('prototype'), false);
+}
+
+`;
+
+if (classesEnabled())
+    eval(test);
+
+if (typeof reportCompare === "function")
+    reportCompare(0, 0, "OK");