FunctionObject: Mark name/length property configurable

In ES5, these were not configurable, but ES6 changed the behavior.

For length, refer to:
    9.2.4 (FunctionInitialize)
    17 (ECMAScript Standard Built-in Objects):
        Unless otherwise specified, the length property of a built-in Function
        object has the attributes { [[Writable]]: false, [[Enumerable]]: false,
        [[Configurable]]: true }.
    19.2.2.1 Function.length
    19.2.3.2 (Function.prototype.bind)
    19.2.4.1 (Function instances, length)

For name, refer to:
    9.2.11 (SetFunctionName)

This does regress test262 for ES5 for me a little, but improves our es6 test
coverage a bit (~682 more tests pass, +1.5%).

Change-Id: Icda7c9068dc3e6e4e4aebbb0d359868a30343013
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
This commit is contained in:
Robin Burchell 2017-02-02 18:37:21 +01:00
parent dd31156c6c
commit 6653fdb6bf
5 changed files with 124 additions and 8 deletions

View File

@ -131,7 +131,7 @@ void FunctionObject::init(String *n, bool createProto)
}
if (n)
defineReadonlyProperty(s.engine->id_name(), *n);
defineReadonlyConfigurableProperty(s.engine->id_name(), *n);
}
ReturnedValue FunctionObject::name() const
@ -258,10 +258,10 @@ void FunctionPrototype::init(ExecutionEngine *engine, Object *ctor)
Scope scope(engine);
ScopedObject o(scope);
ctor->defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(1));
ctor->defineReadonlyConfigurableProperty(engine->id_length(), Primitive::fromInt32(1));
ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(0));
defineReadonlyConfigurableProperty(engine->id_length(), Primitive::fromInt32(0));
defineDefaultProperty(QStringLiteral("constructor"), (o = ctor));
defineDefaultProperty(engine->id_toString(), method_toString, 0);
defineDefaultProperty(QStringLiteral("apply"), method_apply, 2);
@ -557,7 +557,7 @@ void Heap::BoundFunction::init(QV4::ExecutionContext *scope, QV4::FunctionObject
len -= boundArgs->size();
if (len < 0)
len = 0;
f->defineReadonlyProperty(s.engine->id_length(), Primitive::fromInt32(len));
f->defineReadonlyConfigurableProperty(s.engine->id_length(), Primitive::fromInt32(len));
ScopedProperty pd(s);
pd->value = s.engine->thrower();

View File

@ -258,6 +258,7 @@ enum PropertyFlag {
Attr_NotEnumerable = 0x4,
Attr_NotConfigurable = 0x8,
Attr_ReadOnly = Attr_NotWritable|Attr_NotEnumerable|Attr_NotConfigurable,
Attr_ReadOnly_ButConfigurable = Attr_NotWritable|Attr_NotEnumerable,
Attr_Invalid = 0xff
};

View File

@ -162,7 +162,7 @@ void Object::defineDefaultProperty(const QString &name, ReturnedValue (*code)(Ca
ScopedString s(scope, e->newIdentifier(name));
ExecutionContext *global = e->rootContext();
ScopedFunctionObject function(scope, BuiltinFunction::create(global, s, code));
function->defineReadonlyProperty(e->id_length(), Primitive::fromInt32(argumentCount));
function->defineReadonlyConfigurableProperty(e->id_length(), Primitive::fromInt32(argumentCount));
defineDefaultProperty(s, function);
}
@ -173,7 +173,7 @@ void Object::defineDefaultProperty(const QString &name, void (*code)(const Built
ScopedString s(scope, e->newIdentifier(name));
ExecutionContext *global = e->rootContext();
ScopedFunctionObject function(scope, BuiltinFunction::create(global, s, code));
function->defineReadonlyProperty(e->id_length(), Primitive::fromInt32(argumentCount));
function->defineReadonlyConfigurableProperty(e->id_length(), Primitive::fromInt32(argumentCount));
defineDefaultProperty(s, function);
}
@ -183,7 +183,7 @@ void Object::defineDefaultProperty(String *name, ReturnedValue (*code)(CallConte
Scope scope(e);
ExecutionContext *global = e->rootContext();
ScopedFunctionObject function(scope, BuiltinFunction::create(global, name, code));
function->defineReadonlyProperty(e->id_length(), Primitive::fromInt32(argumentCount));
function->defineReadonlyConfigurableProperty(e->id_length(), Primitive::fromInt32(argumentCount));
defineDefaultProperty(name, function);
}
@ -193,7 +193,7 @@ void Object::defineDefaultProperty(String *name, void (*code)(const BuiltinFunct
Scope scope(e);
ExecutionContext *global = e->rootContext();
ScopedFunctionObject function(scope, BuiltinFunction::create(global, name, code));
function->defineReadonlyProperty(e->id_length(), Primitive::fromInt32(argumentCount));
function->defineReadonlyConfigurableProperty(e->id_length(), Primitive::fromInt32(argumentCount));
defineDefaultProperty(name, function);
}
@ -250,6 +250,19 @@ void Object::defineReadonlyProperty(String *name, const Value &value)
insertMember(name, value, Attr_ReadOnly);
}
void Object::defineReadonlyConfigurableProperty(const QString &name, const Value &value)
{
QV4::ExecutionEngine *e = engine();
Scope scope(e);
ScopedString s(scope, e->newIdentifier(name));
defineReadonlyConfigurableProperty(s, value);
}
void Object::defineReadonlyConfigurableProperty(String *name, const Value &value)
{
insertMember(name, value, Attr_ReadOnly_ButConfigurable);
}
void Object::markObjects(Heap::Base *that, ExecutionEngine *e)
{
Heap::Object *o = static_cast<Heap::Object *>(that);

View File

@ -253,6 +253,10 @@ struct Q_QML_EXPORT Object: Managed {
void defineReadonlyProperty(const QString &name, const Value &value);
void defineReadonlyProperty(String *name, const Value &value);
/* Fixed: Writable: false, Enumerable: false, Configurable: true */
void defineReadonlyConfigurableProperty(const QString &name, const Value &value);
void defineReadonlyConfigurableProperty(String *name, const Value &value);
void insertMember(String *s, const Value &v, PropertyAttributes attributes = Attr_Data) {
Scope scope(engine());
ScopedProperty p(scope);

View File

@ -29,3 +29,101 @@ Sbp_12.5_A9_T3 failing
Sbp_12.6.1_A13_T3 failing
Sbp_12.6.2_A13_T3 failing
Sbp_12.6.4_A13_T3 failing
# function length attributes are configurable in es6
S15.1.2.2_A9.2 failing
S15.1.3.1_A5.2 failing
S15.1.3.2_A5.2 failing
S15.1.3.3_A5.2 failing
S15.1.2.3_A7.2 failing
S15.1.2.4_A2.2 failing
S15.1.2.5_A2.2 failing
S15.1.3.4_A5.2 failing
15.2.3.3-4-186 failing
S15.2.4.2_A9 failing
S15.2.4.3_A9 failing
S15.2.4.4_A9 failing
S15.2.4.5_A9 failing
S15.2.4.6_A9 failing
S15.2.4.7_A9 failing
15.3.3.2-1 failing
15.4.4.2_A4.2
S15.3.4.2_A9 failing
S15.3.4.3_A9 failing
S15.3.4.4_A9 failing
15.3.4.5-15-2 failing
S15.4.4.2_A4.2 failing
S15.4.4.3_A4.2 failing
S15.4.4.4_A4.2 failing
S15.4.4.5_A6.2 failing
S15.4.4.6_A5.2 failing
S15.4.4.7_A6.2 failing
S15.4.4.8_A5.2 failing
S15.4.4.9_A5.2 failing
S15.4.4.10_A5.2 failing
S15.4.4.11_A7.2 failing
S15.4.4.12_A5.2 failing
S15.4.4.13_A5.2 failing
S15.5.4.10_A9 failing
S15.5.4.11_A9 failing
S15.5.4.12_A9 failing
S15.5.4.13_A9 failing
S15.5.4.14_A9 failing
S15.5.4.15_A9 failing
S15.5.4.16_A9 failing
S15.5.4.17_A9 failing
S15.5.4.18_A9 failing
S15.5.4.19_A9 failing
S15.5.4.4_A9 failing
S15.5.4.5_A9 failing
S15.5.4.6_A9 failing
S15.5.4.7_A9 failing
S15.5.4.8_A9 failing
S15.5.4.9_A9 failing
S15.9.4.2_A3_T2 failing
S15.9.4.3_A3_T2 failing
S15.9.5.2_A3_T2 failing
S15.9.5.3_A3_T2 failing
S15.9.5.4_A3_T2 failing
S15.9.5.5_A3_T2 failing
S15.9.5.10_A3_T2 failing
S15.9.5.11_A3_T2 failing
S15.9.5.12_A3_T2 failing
S15.9.5.13_A3_T2 failing
S15.9.5.14_A3_T2 failing
S15.9.5.15_A3_T2 failing
S15.9.5.16_A3_T2 failing
S15.9.5.17_A3_T2 failing
S15.9.5.18_A3_T2 failing
S15.9.5.19_A3_T2 failing
S15.9.5.20_A3_T2 failing
S15.9.5.21_A3_T2 failing
S15.9.5.22_A3_T2 failing
S15.9.5.23_A3_T2 failing
S15.9.5.24_A3_T2 failing
S15.9.5.25_A3_T2 failing
S15.9.5.26_A3_T2 failing
S15.9.5.27_A3_T2 failing
S15.9.5.28_A3_T2 failing
S15.9.5.29_A3_T2 failing
S15.9.5.30_A3_T2 failing
S15.9.5.31_A3_T2 failing
S15.9.5.32_A3_T2 failing
S15.9.5.33_A3_T2 failing
S15.9.5.34_A3_T2 failing
S15.9.5.35_A3_T2 failing
S15.9.5.36_A3_T2 failing
S15.9.5.37_A3_T2 failing
S15.9.5.38_A3_T2 failing
S15.9.5.39_A3_T2 failing
S15.9.5.40_A3_T2 failing
S15.9.5.41_A3_T2 failing
S15.9.5.42_A3_T2 failing
S15.9.5.6_A3_T2 failing
S15.9.5.7_A3_T2 failing
S15.9.5.8_A3_T2 failing
S15.9.5.9_A3_T2 failing
S15.10.6.2_A9 failing
S15.10.6.3_A9 failing
S15.10.6.4_A9 failing