From fb434f1c6cefce932542343ff096719e10d4e8ed Mon Sep 17 00:00:00 2001 From: Camillo Bruni Date: Thu, 13 Dec 2018 16:29:27 +0100 Subject: [PATCH] [runtime] Fix Runtime_InternalSetPrototype Do not set the name property on any function or classes. This is not required as per spec #sec-__proto__-property-names-in-object-initializers. Bug: v8:7773 Change-Id: Iade96573690e5b14b60434c37683f782cf9cb2cb Reviewed-on: https://chromium-review.googlesource.com/c/1375912 Reviewed-by: Igor Sheludko Commit-Queue: Camillo Bruni Cr-Commit-Position: refs/heads/master@{#58239} --- src/runtime/runtime-object.cc | 11 ----- test/mjsunit/es6/classes.js | 35 +++++++++++++- test/mjsunit/regress/regress-7773.js | 71 ++++++++++++++++++++++++++++ 3 files changed, 104 insertions(+), 13 deletions(-) create mode 100644 test/mjsunit/regress/regress-7773.js diff --git a/src/runtime/runtime-object.cc b/src/runtime/runtime-object.cc index f08cb1fdf4..60978b1967 100644 --- a/src/runtime/runtime-object.cc +++ b/src/runtime/runtime-object.cc @@ -378,17 +378,6 @@ RUNTIME_FUNCTION(Runtime_InternalSetPrototype) { DCHECK_EQ(2, args.length()); CONVERT_ARG_HANDLE_CHECKED(JSReceiver, obj, 0); CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1); - if (prototype->IsJSFunction()) { - Handle function = Handle::cast(prototype); - if (!function->shared()->HasSharedName()) { - Handle function_map(function->map(), isolate); - if (!JSFunction::SetName(function, isolate->factory()->proto_string(), - isolate->factory()->empty_string())) { - return ReadOnlyRoots(isolate).exception(); - } - CHECK_EQ(*function_map, function->map()); - } - } MAYBE_RETURN(JSReceiver::SetPrototype(obj, prototype, false, kThrowOnError), ReadOnlyRoots(isolate).exception()); return *obj; diff --git a/test/mjsunit/es6/classes.js b/test/mjsunit/es6/classes.js index fa85faf44e..27121ec007 100644 --- a/test/mjsunit/es6/classes.js +++ b/test/mjsunit/es6/classes.js @@ -23,10 +23,41 @@ assertEquals('D2', D2.name); var E = class {} - assertEquals('E', E.name); // Should be 'E'. + assertEquals('E', E.name); var F = class { constructor() {} }; - assertEquals('F', F.name); // Should be 'F'. + assertEquals('F', F.name); + + var literal = { E: class {} }; + assertEquals('E', literal.E.name); + + literal = { E: class F {} }; + assertEquals('F', literal.E.name); + + literal = { __proto__: class {} }; + assertEquals('', literal.__proto__.name); + assertEquals( + undefined, Object.getOwnPropertyDescriptor(literal.__proto__, 'name')); + + literal = { __proto__: class F {} }; + assertEquals('F', literal.__proto__.name); + assertNotEquals( + undefined, Object.getOwnPropertyDescriptor(literal.__proto__, 'name')); + + class G {}; + literal = { __proto__: G }; + assertEquals('G', literal.__proto__.name); + + var H = class { static name() { return 'A'; } }; + literal = { __proto__ : H }; + assertEquals('A', literal.__proto__.name()); + + literal = { + __proto__: class { + static name() { return 'A'; } + } + }; + assertEquals('A', literal.__proto__.name()); })(); diff --git a/test/mjsunit/regress/regress-7773.js b/test/mjsunit/regress/regress-7773.js new file mode 100644 index 0000000000..7930ae9106 --- /dev/null +++ b/test/mjsunit/regress/regress-7773.js @@ -0,0 +1,71 @@ +// Copyright 2018 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +(function testFunctionNames() { + let descriptor = { + value: '', + writable: false, + enumerable: false, + configurable: true + }; + // Functions have a "name" property by default. + assertEquals( + descriptor, Object.getOwnPropertyDescriptor(function(){}, 'name')); + let a = { fn: function(){} }; + assertSame('fn', a.fn.name); + descriptor.value = 'fn'; + assertEquals(descriptor, Object.getOwnPropertyDescriptor(a.fn, 'name')); + + let b = { __proto__: function(){} }; + assertSame('', b.__proto__.name); + descriptor.value = ''; + assertEquals( + descriptor, Object.getOwnPropertyDescriptor(b.__proto__, 'name')); + + let c = { fn: function F(){} }; + assertSame('F', c.fn.name); + descriptor.value = 'F'; + assertEquals(descriptor, Object.getOwnPropertyDescriptor(c.fn, 'name')); + + let d = { __proto__: function E(){} }; + assertSame('E', d.__proto__.name); + descriptor.value = 'E'; + assertEquals( + descriptor, Object.getOwnPropertyDescriptor(d.__proto__, 'name')); +})(); + +(function testClassNames() { + let descriptor = { + value: '', + writable: false, + enumerable: false, + configurable: true + }; + + // Anonymous classes do not have a "name" property by default. + assertSame(undefined, Object.getOwnPropertyDescriptor(class {}, 'name')); + descriptor.value = 'C'; + assertEquals(descriptor, Object.getOwnPropertyDescriptor(class C {}, 'name')); + + let a = { fn: class {} }; + assertSame('fn', a.fn.name); + descriptor.value = 'fn'; + assertEquals(descriptor, Object.getOwnPropertyDescriptor(a.fn, 'name')); + + let b = { __proto__: class {} }; + assertSame('', b.__proto__.name); + assertSame( + undefined, Object.getOwnPropertyDescriptor(b.__proto__, 'name')); + + let c = { fn: class F {} }; + assertSame('F', c.fn.name); + descriptor.value = 'F'; + assertEquals(descriptor, Object.getOwnPropertyDescriptor(c.fn, 'name')); + + let d = { __proto__: class F {} }; + assertSame('F', d.__proto__.name); + descriptor.value = 'F'; + assertEquals( + descriptor, Object.getOwnPropertyDescriptor(d.__proto__, 'name')); +})();