Install "name" property on anonymous classes
This is a normative PR that reached consensus at the June 2019 TC39: https://github.com/tc39/test262/pull/2299 Bug: v8:9646 Change-Id: I8cb927b9e9231dfb71ebf47171205a096350e38b Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2360905 Reviewed-by: Marja Hölttä <marja@chromium.org> Commit-Queue: Shu-yu Guo <syg@chromium.org> Cr-Commit-Position: refs/heads/master@{#69460}
This commit is contained in:
parent
65d28a7fe4
commit
048761aa0f
@ -95,14 +95,8 @@ void ObjectBoilerplateDescription::set_backing_store_size(
|
||||
OBJECT_CONSTRUCTORS_IMPL(ClassBoilerplate, FixedArray)
|
||||
CAST_ACCESSOR(ClassBoilerplate)
|
||||
|
||||
BIT_FIELD_ACCESSORS(ClassBoilerplate, flags, install_class_name_accessor,
|
||||
ClassBoilerplate::Flags::InstallClassNameAccessorBit)
|
||||
|
||||
BIT_FIELD_ACCESSORS(ClassBoilerplate, flags, arguments_count,
|
||||
ClassBoilerplate::Flags::ArgumentsCountBits)
|
||||
|
||||
SMI_ACCESSORS(ClassBoilerplate, flags,
|
||||
FixedArray::OffsetOfElementAt(kFlagsIndex))
|
||||
SMI_ACCESSORS(ClassBoilerplate, arguments_count,
|
||||
FixedArray::OffsetOfElementAt(kArgumentsCountIndex))
|
||||
|
||||
ACCESSORS(ClassBoilerplate, static_properties_template, Object,
|
||||
FixedArray::OffsetOfElementAt(kClassPropertiesTemplateIndex))
|
||||
|
@ -551,32 +551,24 @@ Handle<ClassBoilerplate> ClassBoilerplate::BuildClassBoilerplate(
|
||||
}
|
||||
}
|
||||
|
||||
// Add name accessor to the class object if necessary.
|
||||
bool install_class_name_accessor = false;
|
||||
// All classes, even anonymous ones, have a name accessor. If static_desc is
|
||||
// in dictionary mode, the name accessor is installed at runtime in
|
||||
// DefineClass.
|
||||
if (!expr->has_name_static_property() &&
|
||||
expr->constructor()->has_shared_name()) {
|
||||
if (static_desc.HasDictionaryProperties()) {
|
||||
// Install class name accessor if necessary during class literal
|
||||
// instantiation.
|
||||
install_class_name_accessor = true;
|
||||
} else {
|
||||
// Set class name accessor if the "name" method was not added yet.
|
||||
PropertyAttributes attribs =
|
||||
static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY);
|
||||
static_desc.AddConstant(isolate, factory->name_string(),
|
||||
factory->function_name_accessor(), attribs);
|
||||
}
|
||||
!static_desc.HasDictionaryProperties()) {
|
||||
// Set class name accessor if the "name" method was not added yet.
|
||||
PropertyAttributes attribs =
|
||||
static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY);
|
||||
static_desc.AddConstant(isolate, factory->name_string(),
|
||||
factory->function_name_accessor(), attribs);
|
||||
}
|
||||
|
||||
static_desc.Finalize(isolate);
|
||||
instance_desc.Finalize(isolate);
|
||||
|
||||
Handle<ClassBoilerplate> class_boilerplate = Handle<ClassBoilerplate>::cast(
|
||||
factory->NewFixedArray(kBoileplateLength, AllocationType::kOld));
|
||||
factory->NewFixedArray(kBoilerplateLength, AllocationType::kOld));
|
||||
|
||||
class_boilerplate->set_flags(0);
|
||||
class_boilerplate->set_install_class_name_accessor(
|
||||
install_class_name_accessor);
|
||||
class_boilerplate->set_arguments_count(dynamic_argument_index);
|
||||
|
||||
class_boilerplate->set_static_properties_template(
|
||||
|
@ -77,14 +77,6 @@ class ClassBoilerplate : public FixedArray {
|
||||
public:
|
||||
enum ValueKind { kData, kGetter, kSetter };
|
||||
|
||||
struct Flags {
|
||||
#define FLAGS_BIT_FIELDS(V, _) \
|
||||
V(InstallClassNameAccessorBit, bool, 1, _) \
|
||||
V(ArgumentsCountBits, int, 30, _)
|
||||
DEFINE_BIT_FIELDS(FLAGS_BIT_FIELDS)
|
||||
#undef FLAGS_BIT_FIELDS
|
||||
};
|
||||
|
||||
struct ComputedEntryFlags {
|
||||
#define COMPUTED_ENTRY_BIT_FIELDS(V, _) \
|
||||
V(ValueKindBits, ValueKind, 2, _) \
|
||||
@ -133,14 +125,14 @@ class ClassBoilerplate : public FixedArray {
|
||||
ClassLiteral* expr);
|
||||
|
||||
enum {
|
||||
kFlagsIndex,
|
||||
kArgumentsCountIndex,
|
||||
kClassPropertiesTemplateIndex,
|
||||
kClassElementsTemplateIndex,
|
||||
kClassComputedPropertiesIndex,
|
||||
kPrototypePropertiesTemplateIndex,
|
||||
kPrototypeElementsTemplateIndex,
|
||||
kPrototypeComputedPropertiesIndex,
|
||||
kBoileplateLength // last element
|
||||
kBoilerplateLength // last element
|
||||
};
|
||||
|
||||
private:
|
||||
|
@ -537,7 +537,7 @@ bool InitClassPrototype(Isolate* isolate,
|
||||
map->set_may_have_interesting_symbols(true);
|
||||
map->set_construction_counter(Map::kNoSlackTracking);
|
||||
|
||||
// We care about name property only for class constructor.
|
||||
// Class prototypes do not have a name accessor.
|
||||
const bool install_name_accessor = false;
|
||||
|
||||
return AddDescriptorsByTemplate(
|
||||
@ -592,8 +592,8 @@ bool InitClassConstructor(
|
||||
map->set_may_have_interesting_symbols(true);
|
||||
map->set_construction_counter(Map::kNoSlackTracking);
|
||||
|
||||
bool install_name_accessor =
|
||||
class_boilerplate->install_class_name_accessor() != 0;
|
||||
// All class constructors have a name accessor.
|
||||
const bool install_name_accessor = true;
|
||||
|
||||
return AddDescriptorsByTemplate(
|
||||
isolate, map, properties_dictionary_template,
|
||||
|
@ -36,8 +36,11 @@
|
||||
|
||||
literal = { __proto__: class {} };
|
||||
assertEquals('', literal.__proto__.name);
|
||||
assertEquals(
|
||||
undefined, Object.getOwnPropertyDescriptor(literal.__proto__, 'name'));
|
||||
var nameDescr = Object.getOwnPropertyDescriptor(literal.__proto__, 'name');
|
||||
assertEquals('', nameDescr.value);
|
||||
assertFalse(nameDescr.writable);
|
||||
assertFalse(nameDescr.enumerable);
|
||||
assertTrue(nameDescr.configurable);
|
||||
|
||||
literal = { __proto__: class F {} };
|
||||
assertEquals('F', literal.__proto__.name);
|
||||
|
@ -394,7 +394,7 @@
|
||||
})();
|
||||
|
||||
(function testClassNameOrder() {
|
||||
assertEquals(['length', 'prototype'], Object.getOwnPropertyNames(class {}));
|
||||
assertEquals(['length', 'prototype', 'name'], Object.getOwnPropertyNames(class {}));
|
||||
|
||||
var tmp = {'': class {}};
|
||||
var Tmp = tmp[''];
|
||||
|
@ -44,7 +44,8 @@
|
||||
};
|
||||
|
||||
// Anonymous classes do not have a "name" property by default.
|
||||
assertSame(undefined, Object.getOwnPropertyDescriptor(class {}, 'name'));
|
||||
descriptor.value = '';
|
||||
assertEquals(descriptor, Object.getOwnPropertyDescriptor(class {}, 'name'));
|
||||
descriptor.value = 'C';
|
||||
assertEquals(descriptor, Object.getOwnPropertyDescriptor(class C {}, 'name'));
|
||||
|
||||
@ -55,8 +56,9 @@
|
||||
|
||||
let b = { __proto__: class {} };
|
||||
assertSame('', b.__proto__.name);
|
||||
assertSame(
|
||||
undefined, Object.getOwnPropertyDescriptor(b.__proto__, 'name'));
|
||||
descriptor.value = '';
|
||||
assertEquals(
|
||||
descriptor, Object.getOwnPropertyDescriptor(b.__proto__, 'name'));
|
||||
|
||||
let c = { fn: class F {} };
|
||||
assertSame('F', c.fn.name);
|
||||
|
@ -504,7 +504,6 @@
|
||||
|
||||
# https://bugs.chromium.org/p/v8/issues/detail?id=9646
|
||||
'built-ins/ThrowTypeError/name': [FAIL],
|
||||
'language/expressions/class/name': [FAIL],
|
||||
|
||||
# https://bugs.chromium.org/p/v8/issues/detail?id=9742
|
||||
'intl402/Locale/getters': [FAIL],
|
||||
|
Loading…
Reference in New Issue
Block a user