From: Lars Knoll Date: Sat, 8 Dec 2012 07:57:35 +0000 (-0800) Subject: Implement Object.create/defineProperty/defineProperties X-Git-Tag: upstream/5.2.1~669^2~659^2~733 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=13ea451c4fad5925377f51fca1a8bdb35c4bc7f8;p=platform%2Fupstream%2Fqtdeclarative.git Implement Object.create/defineProperty/defineProperties Change-Id: I3a71597d012b5fb7d7a2f482f4a16431c71c1c22 Reviewed-by: Simon Hausmann --- diff --git a/qmljs_engine.cpp b/qmljs_engine.cpp index ea6b32a..b0a964f 100644 --- a/qmljs_engine.cpp +++ b/qmljs_engine.cpp @@ -85,6 +85,12 @@ ExecutionEngine::ExecutionEngine(MemoryManager *memoryManager, EvalISelFactory * id_constructor = identifier(QStringLiteral("constructor")); id_arguments = identifier(QStringLiteral("arguments")); id___proto__ = identifier(QStringLiteral("__proto__")); + id_enumerable = identifier(QStringLiteral("enumerable")); + id_configurable = identifier(QStringLiteral("configurable")); + id_writable = identifier(QStringLiteral("writable")); + id_value = identifier(QStringLiteral("value")); + id_get = identifier(QStringLiteral("get")); + id_set = identifier(QStringLiteral("set")); objectPrototype = new (memoryManager) ObjectPrototype(); stringPrototype = new (memoryManager) StringPrototype(rootContext); diff --git a/qmljs_engine.h b/qmljs_engine.h index 520acab..85a3909 100644 --- a/qmljs_engine.h +++ b/qmljs_engine.h @@ -136,6 +136,12 @@ struct ExecutionEngine String *id_constructor; String *id_arguments; String *id___proto__; + String *id_enumerable; + String *id_configurable; + String *id_writable; + String *id_value; + String *id_get; + String *id_set; struct ExceptionHandler { ExecutionContext *context; diff --git a/qmljs_runtime.cpp b/qmljs_runtime.cpp index aaa5be9..53f313f 100644 --- a/qmljs_runtime.cpp +++ b/qmljs_runtime.cpp @@ -696,8 +696,9 @@ Value __qmljs_call_activation_property(ExecutionContext *context, String *name, return o->call(context, Value::undefinedValue(), args, argc); } -Value __qmljs_call_property(ExecutionContext *context, Value thisObject, String *name, Value *args, int argc) +Value __qmljs_call_property(ExecutionContext *context, Value that, String *name, Value *args, int argc) { + Value thisObject = that; if (!thisObject.isObject()) thisObject = __qmljs_to_object(thisObject, context); @@ -709,7 +710,7 @@ Value __qmljs_call_property(ExecutionContext *context, Value thisObject, String if (!o) context->throwTypeError(); - return o->call(context, thisObject, args, argc); + return o->call(context, that, args, argc); } Value __qmljs_call_value(ExecutionContext *context, Value thisObject, Value func, Value *args, int argc) diff --git a/qmljs_runtime.h b/qmljs_runtime.h index 6675920..e8049d9 100644 --- a/qmljs_runtime.h +++ b/qmljs_runtime.h @@ -91,7 +91,7 @@ extern "C" { // context Value __qmljs_call_activation_property(ExecutionContext *, String *name, Value *args, int argc); -Value __qmljs_call_property(ExecutionContext *context, Value thisObject, String *name, Value *args, int argc); +Value __qmljs_call_property(ExecutionContext *context, Value that, String *name, Value *args, int argc); Value __qmljs_call_value(ExecutionContext *context, Value thisObject, Value func, Value *args, int argc); Value __qmljs_construct_activation_property(ExecutionContext *, String *name, Value *args, int argc); diff --git a/qv4ecmaobjects.cpp b/qv4ecmaobjects.cpp index 5a29c64..88acebf 100644 --- a/qv4ecmaobjects.cpp +++ b/qv4ecmaobjects.cpp @@ -610,18 +610,46 @@ Value ObjectPrototype::method_getOwnPropertyNames(ExecutionContext *ctx) Value ObjectPrototype::method_create(ExecutionContext *ctx) { - ctx->throwUnimplemented(QStringLiteral("Object.create")); - return Value::undefinedValue(); + Value O = ctx->argument(0); + if (!O.isObject()) + ctx->throwTypeError(); + + Object *newObject = ctx->engine->newObject(); + newObject->prototype = O.objectValue(); + + Value objValue = Value::fromObject(newObject); + ctx->arguments[0] = objValue; + method_defineProperties(ctx); + + return objValue; } Value ObjectPrototype::method_defineProperty(ExecutionContext *ctx) { - ctx->throwUnimplemented(QStringLiteral("Object.defineProperty")); - return Value::undefinedValue(); + Value O = ctx->argument(0); + if (!O.isObject()) + ctx->throwTypeError(); + + String *name = ctx->argument(1).toString(ctx); + + Value attributes = ctx->argument(2); + PropertyDescriptor pd; + toPropertyDescriptor(ctx, attributes, &pd); + + bool strict = ctx->strictMode; + ctx->strictMode = true; + O.objectValue()->__defineOwnProperty__(ctx, name, &pd); + ctx->strictMode = strict; + + return O; } Value ObjectPrototype::method_defineProperties(ExecutionContext *ctx) { + Value O = ctx->argument(0); + if (!O.isObject()) + ctx->throwTypeError(); + ctx->throwUnimplemented(QStringLiteral("Object.defineProperties")); return Value::undefinedValue(); } @@ -828,6 +856,63 @@ Value ObjectPrototype::method_defineSetter(ExecutionContext *ctx) return Value::undefinedValue(); } +void ObjectPrototype::toPropertyDescriptor(ExecutionContext *ctx, Value v, PropertyDescriptor *desc) +{ + if (!v.isObject()) + __qmljs_throw_type_error(ctx); + + Object *o = v.objectValue(); + + desc->type = PropertyDescriptor::Generic; + + desc->enumberable = PropertyDescriptor::Undefined; + if (o->__hasProperty__(ctx, ctx->engine->id_enumerable)) + desc->enumberable = __qmljs_to_boolean(o->__get__(ctx, ctx->engine->id_enumerable), ctx) ? PropertyDescriptor::Set : PropertyDescriptor::Unset; + + desc->configurable = PropertyDescriptor::Undefined; + if (o->__hasProperty__(ctx, ctx->engine->id_configurable)) + desc->enumberable = __qmljs_to_boolean(o->__get__(ctx, ctx->engine->id_configurable), ctx) ? PropertyDescriptor::Set : PropertyDescriptor::Unset; + + desc->writable = PropertyDescriptor::Undefined; + if (o->__hasProperty__(ctx, ctx->engine->id_writable)) + desc->enumberable = __qmljs_to_boolean(o->__get__(ctx, ctx->engine->id_writable), ctx) ? PropertyDescriptor::Set : PropertyDescriptor::Unset; + + if (o->__hasProperty__(ctx, ctx->engine->id_value)) { + desc->value = o->__get__(ctx, ctx->engine->id_value); + desc->type = PropertyDescriptor::Data; + } + + if (o->__hasProperty__(ctx, ctx->engine->id_get)) { + Value get = o->__get__(ctx, ctx->engine->id_get); + FunctionObject *f = get.asFunctionObject(); + if (f) { + if (desc->isWritable() || desc->isData()) + __qmljs_throw_type_error(ctx); + desc->get = f; + } else if (!get.isUndefined()) { + __qmljs_throw_type_error(ctx); + } else { + desc->get = 0; + } + desc->type = PropertyDescriptor::Accessor; + } + + if (o->__hasProperty__(ctx, ctx->engine->id_set)) { + Value get = o->__get__(ctx, ctx->engine->id_set); + FunctionObject *f = get.asFunctionObject(); + if (f) { + if (desc->isWritable() || desc->isData()) + __qmljs_throw_type_error(ctx); + desc->set = f; + } else if (!get.isUndefined()) { + __qmljs_throw_type_error(ctx); + } else { + desc->set = 0; + } + desc->type = PropertyDescriptor::Accessor; + } +} + // // String // diff --git a/qv4ecmaobjects_p.h b/qv4ecmaobjects_p.h index 02d7d8c..5803633 100644 --- a/qv4ecmaobjects_p.h +++ b/qv4ecmaobjects_p.h @@ -83,6 +83,8 @@ struct ObjectPrototype: Object static Value method_defineGetter(ExecutionContext *ctx); static Value method_defineSetter(ExecutionContext *ctx); + + static void toPropertyDescriptor(ExecutionContext *ctx, Value v, PropertyDescriptor *desc); }; struct StringCtor: FunctionObject