559 lines
19 KiB
C++
559 lines
19 KiB
C++
/****************************************************************************
|
|
**
|
|
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
|
|
** Contact: http://www.qt-project.org/legal
|
|
**
|
|
** This file is part of the V4VM module of the Qt Toolkit.
|
|
**
|
|
** $QT_BEGIN_LICENSE:LGPL$
|
|
** Commercial License Usage
|
|
** Licensees holding valid commercial Qt licenses may use this file in
|
|
** accordance with the commercial license agreement provided with the
|
|
** Software or, alternatively, in accordance with the terms contained in
|
|
** a written agreement between you and Digia. For licensing terms and
|
|
** conditions see http://qt.digia.com/licensing. For further information
|
|
** use the contact form at http://qt.digia.com/contact-us.
|
|
**
|
|
** GNU Lesser General Public License Usage
|
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
|
** General Public License version 2.1 as published by the Free Software
|
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
|
** packaging of this file. Please review the following information to
|
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
**
|
|
** In addition, as a special exception, Digia gives you certain additional
|
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
**
|
|
** GNU General Public License Usage
|
|
** Alternatively, this file may be used under the terms of the GNU
|
|
** General Public License version 3.0 as published by the Free Software
|
|
** Foundation and appearing in the file LICENSE.GPL included in the
|
|
** packaging of this file. Please review the following information to
|
|
** ensure the GNU General Public License version 3.0 requirements will be
|
|
** met: http://www.gnu.org/copyleft/gpl.html.
|
|
**
|
|
**
|
|
** $QT_END_LICENSE$
|
|
**
|
|
****************************************************************************/
|
|
|
|
|
|
#include "qv4objectproto.h"
|
|
#include "qv4mm.h"
|
|
#include <QtCore/qnumeric.h>
|
|
#include <QtCore/qmath.h>
|
|
#include <QtCore/QDateTime>
|
|
#include <QtCore/QStringList>
|
|
#include <QtCore/QDebug>
|
|
#include <cassert>
|
|
|
|
#include <private/qqmljsengine_p.h>
|
|
#include <private/qqmljslexer_p.h>
|
|
#include <private/qqmljsparser_p.h>
|
|
#include <private/qqmljsast_p.h>
|
|
#include <qv4ir_p.h>
|
|
#include <qv4codegen_p.h>
|
|
#include <qv4isel_masm_p.h>
|
|
|
|
#ifndef Q_WS_WIN
|
|
# include <time.h>
|
|
# ifndef Q_OS_VXWORKS
|
|
# include <sys/time.h>
|
|
# else
|
|
# include "qplatformdefs.h"
|
|
# endif
|
|
#else
|
|
# include <windows.h>
|
|
#endif
|
|
|
|
using namespace QQmlJS::VM;
|
|
|
|
|
|
//
|
|
// Object
|
|
//
|
|
ObjectCtor::ObjectCtor(ExecutionContext *scope)
|
|
: FunctionObject(scope)
|
|
{
|
|
}
|
|
|
|
Value ObjectCtor::construct(ExecutionContext *ctx)
|
|
{
|
|
if (!ctx->argumentCount || ctx->argument(0).isUndefined() || ctx->argument(0).isNull())
|
|
return ctx->thisObject;
|
|
return __qmljs_to_object(ctx->argument(0), ctx);
|
|
}
|
|
|
|
Value ObjectCtor::call(ExecutionContext *ctx)
|
|
{
|
|
if (!ctx->argumentCount || ctx->argument(0).isUndefined() || ctx->argument(0).isNull())
|
|
return Value::fromObject(ctx->engine->newObject());
|
|
return __qmljs_to_object(ctx->argument(0), ctx);
|
|
}
|
|
|
|
void ObjectPrototype::init(ExecutionContext *ctx, const Value &ctor)
|
|
{
|
|
ctor.objectValue()->defineReadonlyProperty(ctx->engine->id_prototype, Value::fromObject(this));
|
|
ctor.objectValue()->defineReadonlyProperty(ctx->engine->id_length, Value::fromInt32(1));
|
|
ctor.objectValue()->defineDefaultProperty(ctx, QStringLiteral("getPrototypeOf"), method_getPrototypeOf, 1);
|
|
ctor.objectValue()->defineDefaultProperty(ctx, QStringLiteral("getOwnPropertyDescriptor"), method_getOwnPropertyDescriptor, 2);
|
|
ctor.objectValue()->defineDefaultProperty(ctx, QStringLiteral("getOwnPropertyNames"), method_getOwnPropertyNames, 1);
|
|
ctor.objectValue()->defineDefaultProperty(ctx, QStringLiteral("create"), method_create, 2);
|
|
ctor.objectValue()->defineDefaultProperty(ctx, QStringLiteral("defineProperty"), method_defineProperty, 3);
|
|
ctor.objectValue()->defineDefaultProperty(ctx, QStringLiteral("defineProperties"), method_defineProperties, 2);
|
|
ctor.objectValue()->defineDefaultProperty(ctx, QStringLiteral("seal"), method_seal, 1);
|
|
ctor.objectValue()->defineDefaultProperty(ctx, QStringLiteral("freeze"), method_freeze, 1);
|
|
ctor.objectValue()->defineDefaultProperty(ctx, QStringLiteral("preventExtensions"), method_preventExtensions, 1);
|
|
ctor.objectValue()->defineDefaultProperty(ctx, QStringLiteral("isSealed"), method_isSealed, 1);
|
|
ctor.objectValue()->defineDefaultProperty(ctx, QStringLiteral("isFrozen"), method_isFrozen, 1);
|
|
ctor.objectValue()->defineDefaultProperty(ctx, QStringLiteral("isExtensible"), method_isExtensible, 1);
|
|
ctor.objectValue()->defineDefaultProperty(ctx, QStringLiteral("keys"), method_keys, 1);
|
|
|
|
defineDefaultProperty(ctx, QStringLiteral("constructor"), ctor);
|
|
defineDefaultProperty(ctx, QStringLiteral("toString"), method_toString, 0);
|
|
defineDefaultProperty(ctx, QStringLiteral("toLocaleString"), method_toLocaleString, 0);
|
|
defineDefaultProperty(ctx, QStringLiteral("valueOf"), method_valueOf, 0);
|
|
defineDefaultProperty(ctx, QStringLiteral("hasOwnProperty"), method_hasOwnProperty, 1);
|
|
defineDefaultProperty(ctx, QStringLiteral("isPrototypeOf"), method_isPrototypeOf, 1);
|
|
defineDefaultProperty(ctx, QStringLiteral("propertyIsEnumerable"), method_propertyIsEnumerable, 1);
|
|
defineDefaultProperty(ctx, QStringLiteral("__defineGetter__"), method_defineGetter, 0);
|
|
defineDefaultProperty(ctx, QStringLiteral("__defineSetter__"), method_defineSetter, 0);
|
|
}
|
|
|
|
Value ObjectPrototype::method_getPrototypeOf(ExecutionContext *ctx)
|
|
{
|
|
Value o = ctx->argument(0);
|
|
if (! o.isObject())
|
|
ctx->throwTypeError();
|
|
|
|
Object *p = o.objectValue()->prototype;
|
|
return p ? Value::fromObject(p) : Value::nullValue();
|
|
}
|
|
|
|
Value ObjectPrototype::method_getOwnPropertyDescriptor(ExecutionContext *ctx)
|
|
{
|
|
Value O = ctx->argument(0);
|
|
if (!O.isObject())
|
|
ctx->throwTypeError();
|
|
|
|
String *name = ctx->argument(1).toString(ctx);
|
|
PropertyDescriptor *desc = O.objectValue()->__getOwnProperty__(ctx, name);
|
|
return fromPropertyDescriptor(ctx, desc);
|
|
}
|
|
|
|
Value ObjectPrototype::method_getOwnPropertyNames(ExecutionContext *ctx)
|
|
{
|
|
Object *O = ctx->argument(0).asObject();
|
|
if (!O)
|
|
ctx->throwTypeError();
|
|
|
|
ArrayObject *array = ctx->engine->newArrayObject(ctx)->asArrayObject();
|
|
Array &a = array->array;
|
|
ObjectIterator it(ctx, O, ObjectIterator::NoFlags);
|
|
while (1) {
|
|
Value v = it.nextPropertyNameAsString();
|
|
if (v.isNull())
|
|
break;
|
|
a.push_back(v);
|
|
}
|
|
return Value::fromObject(array);
|
|
}
|
|
|
|
Value ObjectPrototype::method_create(ExecutionContext *ctx)
|
|
{
|
|
Value O = ctx->argument(0);
|
|
if (!O.isObject() && !O.isNull())
|
|
ctx->throwTypeError();
|
|
|
|
Object *newObject = ctx->engine->newObject();
|
|
newObject->prototype = O.objectValue();
|
|
|
|
Value objValue = Value::fromObject(newObject);
|
|
if (ctx->argumentCount > 1 && !ctx->argument(1).isUndefined()) {
|
|
ctx->arguments[0] = objValue;
|
|
method_defineProperties(ctx);
|
|
}
|
|
|
|
return objValue;
|
|
}
|
|
|
|
Value ObjectPrototype::method_defineProperty(ExecutionContext *ctx)
|
|
{
|
|
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);
|
|
|
|
if (!O.objectValue()->__defineOwnProperty__(ctx, name, &pd))
|
|
__qmljs_throw_type_error(ctx);
|
|
|
|
return O;
|
|
}
|
|
|
|
Value ObjectPrototype::method_defineProperties(ExecutionContext *ctx)
|
|
{
|
|
Value O = ctx->argument(0);
|
|
if (!O.isObject())
|
|
ctx->throwTypeError();
|
|
|
|
Object *o = ctx->argument(1).toObject(ctx).objectValue();
|
|
|
|
ObjectIterator it(ctx, o, ObjectIterator::EnumberableOnly);
|
|
while (1) {
|
|
uint index;
|
|
String *name;
|
|
PropertyDescriptor *pd = it.next(&name, &index);
|
|
if (!pd)
|
|
break;
|
|
PropertyDescriptor n;
|
|
toPropertyDescriptor(ctx, o->getValue(ctx, pd), &n);
|
|
bool ok;
|
|
if (name)
|
|
ok = O.objectValue()->__defineOwnProperty__(ctx, name, &n);
|
|
else
|
|
ok = O.objectValue()->__defineOwnProperty__(ctx, index, &n);
|
|
if (!ok)
|
|
__qmljs_throw_type_error(ctx);
|
|
}
|
|
|
|
return O;
|
|
}
|
|
|
|
Value ObjectPrototype::method_seal(ExecutionContext *ctx)
|
|
{
|
|
if (!ctx->argument(0).isObject())
|
|
__qmljs_throw_type_error(ctx);
|
|
|
|
Object *o = ctx->argument(0).objectValue();
|
|
o->extensible = false;
|
|
|
|
ObjectIterator it(ctx, o, ObjectIterator::NoFlags);
|
|
while (1) {
|
|
uint index;
|
|
String *name;
|
|
PropertyDescriptor *pd = it.next(&name, &index);
|
|
if (!pd)
|
|
break;
|
|
pd->configurable = PropertyDescriptor::Disabled;
|
|
}
|
|
return ctx->argument(0);
|
|
}
|
|
|
|
Value ObjectPrototype::method_freeze(ExecutionContext *ctx)
|
|
{
|
|
if (!ctx->argument(0).isObject())
|
|
__qmljs_throw_type_error(ctx);
|
|
|
|
Object *o = ctx->argument(0).objectValue();
|
|
o->extensible = false;
|
|
|
|
ObjectIterator it(ctx, o, ObjectIterator::NoFlags);
|
|
while (1) {
|
|
uint index;
|
|
String *name;
|
|
PropertyDescriptor *pd = it.next(&name, &index);
|
|
if (!pd)
|
|
break;
|
|
if (pd->type == PropertyDescriptor::Data)
|
|
pd->writable = PropertyDescriptor::Disabled;
|
|
pd->configurable = PropertyDescriptor::Disabled;
|
|
}
|
|
return ctx->argument(0);
|
|
}
|
|
|
|
Value ObjectPrototype::method_preventExtensions(ExecutionContext *ctx)
|
|
{
|
|
if (!ctx->argument(0).isObject())
|
|
__qmljs_throw_type_error(ctx);
|
|
|
|
Object *o = ctx->argument(0).objectValue();
|
|
o->extensible = false;
|
|
return ctx->argument(0);
|
|
}
|
|
|
|
Value ObjectPrototype::method_isSealed(ExecutionContext *ctx)
|
|
{
|
|
if (!ctx->argument(0).isObject())
|
|
__qmljs_throw_type_error(ctx);
|
|
|
|
Object *o = ctx->argument(0).objectValue();
|
|
if (o->extensible)
|
|
return Value::fromBoolean(false);
|
|
|
|
ObjectIterator it(ctx, o, ObjectIterator::NoFlags);
|
|
while (1) {
|
|
uint index;
|
|
String *name;
|
|
PropertyDescriptor *pd = it.next(&name, &index);
|
|
if (!pd)
|
|
break;
|
|
if (pd->configurable != PropertyDescriptor::Disabled)
|
|
return Value::fromBoolean(false);
|
|
}
|
|
return Value::fromBoolean(true);
|
|
}
|
|
|
|
Value ObjectPrototype::method_isFrozen(ExecutionContext *ctx)
|
|
{
|
|
if (!ctx->argument(0).isObject())
|
|
__qmljs_throw_type_error(ctx);
|
|
|
|
Object *o = ctx->argument(0).objectValue();
|
|
if (o->extensible)
|
|
return Value::fromBoolean(false);
|
|
|
|
ObjectIterator it(ctx, o, ObjectIterator::NoFlags);
|
|
while (1) {
|
|
uint index;
|
|
String *name;
|
|
PropertyDescriptor *pd = it.next(&name, &index);
|
|
if (!pd)
|
|
break;
|
|
if (pd->isWritable() || pd->isConfigurable())
|
|
return Value::fromBoolean(false);
|
|
}
|
|
return Value::fromBoolean(true);
|
|
}
|
|
|
|
Value ObjectPrototype::method_isExtensible(ExecutionContext *ctx)
|
|
{
|
|
if (!ctx->argument(0).isObject())
|
|
__qmljs_throw_type_error(ctx);
|
|
|
|
Object *o = ctx->argument(0).objectValue();
|
|
return Value::fromBoolean(o->extensible);
|
|
}
|
|
|
|
Value ObjectPrototype::method_keys(ExecutionContext *ctx)
|
|
{
|
|
if (!ctx->argument(0).isObject())
|
|
__qmljs_throw_type_error(ctx);
|
|
|
|
Object *o = ctx->argument(0).objectValue();
|
|
|
|
ArrayObject *a = ctx->engine->newArrayObject(ctx);
|
|
|
|
ObjectIterator it(ctx, o, ObjectIterator::EnumberableOnly);
|
|
while (1) {
|
|
uint index;
|
|
String *name;
|
|
PropertyDescriptor *pd = it.next(&name, &index);
|
|
if (!pd)
|
|
break;
|
|
Value key;
|
|
if (name) {
|
|
key = Value::fromString(name);
|
|
} else {
|
|
key = Value::fromDouble(index);
|
|
key = __qmljs_to_string(key, ctx);
|
|
}
|
|
a->array.push_back(key);
|
|
}
|
|
|
|
return Value::fromObject(a);
|
|
}
|
|
|
|
Value ObjectPrototype::method_toString(ExecutionContext *ctx)
|
|
{
|
|
if (ctx->thisObject.isUndefined()) {
|
|
return Value::fromString(ctx, QStringLiteral("[object Undefined]"));
|
|
} else if (ctx->thisObject.isNull()) {
|
|
return Value::fromString(ctx, QStringLiteral("[object Null]"));
|
|
} else {
|
|
Value obj = __qmljs_to_object(ctx->thisObject, ctx);
|
|
QString className = obj.objectValue()->className();
|
|
return Value::fromString(ctx, QString::fromUtf8("[object %1]").arg(className));
|
|
}
|
|
}
|
|
|
|
Value ObjectPrototype::method_toLocaleString(ExecutionContext *ctx)
|
|
{
|
|
Object *o = __qmljs_to_object(ctx->thisObject, ctx).objectValue();
|
|
Value ts = o->__get__(ctx, ctx->engine->identifier(QStringLiteral("toString")));
|
|
FunctionObject *f = ts.asFunctionObject();
|
|
if (!f)
|
|
__qmljs_throw_type_error(ctx);
|
|
return f->call(ctx, Value::fromObject(o), 0, 0);
|
|
}
|
|
|
|
Value ObjectPrototype::method_valueOf(ExecutionContext *ctx)
|
|
{
|
|
return ctx->thisObject.toObject(ctx);
|
|
}
|
|
|
|
Value ObjectPrototype::method_hasOwnProperty(ExecutionContext *ctx)
|
|
{
|
|
String *P = ctx->argument(0).toString(ctx);
|
|
Value O = ctx->thisObject.toObject(ctx);
|
|
bool r = O.objectValue()->__getOwnProperty__(ctx, P) != 0;
|
|
return Value::fromBoolean(r);
|
|
}
|
|
|
|
Value ObjectPrototype::method_isPrototypeOf(ExecutionContext *ctx)
|
|
{
|
|
Value V = ctx->argument(0);
|
|
if (! V.isObject())
|
|
return Value::fromBoolean(false);
|
|
|
|
Object *O = ctx->thisObject.toObject(ctx).objectValue();
|
|
Object *proto = V.objectValue()->prototype;
|
|
while (proto) {
|
|
if (O == proto)
|
|
return Value::fromBoolean(true);
|
|
proto = proto->prototype;
|
|
}
|
|
return Value::fromBoolean(false);
|
|
}
|
|
|
|
Value ObjectPrototype::method_propertyIsEnumerable(ExecutionContext *ctx)
|
|
{
|
|
String *p = ctx->argument(0).toString(ctx);
|
|
|
|
Object *o = ctx->thisObject.toObject(ctx).objectValue();
|
|
PropertyDescriptor *pd = o->__getOwnProperty__(ctx, p);
|
|
return Value::fromBoolean(pd && pd->isEnumerable());
|
|
}
|
|
|
|
Value ObjectPrototype::method_defineGetter(ExecutionContext *ctx)
|
|
{
|
|
if (ctx->argumentCount < 2)
|
|
__qmljs_throw_type_error(ctx);
|
|
String *prop = ctx->argument(0).toString(ctx);
|
|
|
|
FunctionObject *f = ctx->argument(1).asFunctionObject();
|
|
if (!f)
|
|
__qmljs_throw_type_error(ctx);
|
|
|
|
Object *o = ctx->thisObject.toObject(ctx).objectValue();
|
|
|
|
PropertyDescriptor pd = PropertyDescriptor::fromAccessor(f, 0);
|
|
pd.configurable = PropertyDescriptor::Enabled;
|
|
pd.enumberable = PropertyDescriptor::Enabled;
|
|
o->__defineOwnProperty__(ctx, prop, &pd);
|
|
return Value::undefinedValue();
|
|
}
|
|
|
|
Value ObjectPrototype::method_defineSetter(ExecutionContext *ctx)
|
|
{
|
|
if (ctx->argumentCount < 2)
|
|
__qmljs_throw_type_error(ctx);
|
|
String *prop = ctx->argument(0).toString(ctx);
|
|
|
|
FunctionObject *f = ctx->argument(1).asFunctionObject();
|
|
if (!f)
|
|
__qmljs_throw_type_error(ctx);
|
|
|
|
Object *o = ctx->thisObject.toObject(ctx).objectValue();
|
|
|
|
PropertyDescriptor pd = PropertyDescriptor::fromAccessor(0, f);
|
|
pd.configurable = PropertyDescriptor::Enabled;
|
|
pd.enumberable = PropertyDescriptor::Enabled;
|
|
o->__defineOwnProperty__(ctx, prop, &pd);
|
|
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::Enabled : PropertyDescriptor::Disabled;
|
|
|
|
desc->configurable = PropertyDescriptor::Undefined;
|
|
if (o->__hasProperty__(ctx, ctx->engine->id_configurable))
|
|
desc->configurable = __qmljs_to_boolean(o->__get__(ctx, ctx->engine->id_configurable), ctx) ? PropertyDescriptor::Enabled : PropertyDescriptor::Disabled;
|
|
|
|
desc->get = 0;
|
|
if (o->__hasProperty__(ctx, ctx->engine->id_get)) {
|
|
Value get = o->__get__(ctx, ctx->engine->id_get);
|
|
FunctionObject *f = get.asFunctionObject();
|
|
if (f) {
|
|
desc->get = f;
|
|
} else if (get.isUndefined()) {
|
|
desc->get = (FunctionObject *)0x1;
|
|
} else {
|
|
__qmljs_throw_type_error(ctx);
|
|
}
|
|
desc->type = PropertyDescriptor::Accessor;
|
|
}
|
|
|
|
desc->set = 0;
|
|
if (o->__hasProperty__(ctx, ctx->engine->id_set)) {
|
|
Value set = o->__get__(ctx, ctx->engine->id_set);
|
|
FunctionObject *f = set.asFunctionObject();
|
|
if (f) {
|
|
desc->set = f;
|
|
} else if (set.isUndefined()) {
|
|
desc->set = (FunctionObject *)0x1;
|
|
} else {
|
|
__qmljs_throw_type_error(ctx);
|
|
}
|
|
desc->type = PropertyDescriptor::Accessor;
|
|
}
|
|
|
|
desc->writable = PropertyDescriptor::Undefined;
|
|
if (o->__hasProperty__(ctx, ctx->engine->id_writable)) {
|
|
if (desc->isAccessor())
|
|
__qmljs_throw_type_error(ctx);
|
|
desc->writable = __qmljs_to_boolean(o->__get__(ctx, ctx->engine->id_writable), ctx) ? PropertyDescriptor::Enabled : PropertyDescriptor::Disabled;
|
|
// writable forces it to be a data descriptor
|
|
desc->value = Value::undefinedValue();
|
|
}
|
|
|
|
if (o->__hasProperty__(ctx, ctx->engine->id_value)) {
|
|
if (desc->isAccessor())
|
|
__qmljs_throw_type_error(ctx);
|
|
desc->value = o->__get__(ctx, ctx->engine->id_value);
|
|
desc->type = PropertyDescriptor::Data;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
Value ObjectPrototype::fromPropertyDescriptor(ExecutionContext *ctx, const PropertyDescriptor *desc)
|
|
{
|
|
if (!desc)
|
|
return Value::undefinedValue();
|
|
|
|
ExecutionEngine *engine = ctx->engine;
|
|
// Let obj be the result of creating a new object as if by the expression new Object() where Object is the standard built-in constructor with that name.
|
|
Object *o = engine->newObject();
|
|
|
|
PropertyDescriptor pd;
|
|
pd.type = PropertyDescriptor::Data;
|
|
pd.writable = PropertyDescriptor::Enabled;
|
|
pd.enumberable = PropertyDescriptor::Enabled;
|
|
pd.configurable = PropertyDescriptor::Enabled;
|
|
|
|
if (desc->isData()) {
|
|
pd.value = desc->value;
|
|
o->__defineOwnProperty__(ctx, engine->identifier(QStringLiteral("value")), &pd);
|
|
pd.value = Value::fromBoolean(desc->writable == PropertyDescriptor::Enabled ? true : false);
|
|
o->__defineOwnProperty__(ctx, engine->identifier(QStringLiteral("writable")), &pd);
|
|
} else {
|
|
pd.value = desc->get ? Value::fromObject(desc->get) : Value::undefinedValue();
|
|
o->__defineOwnProperty__(ctx, engine->identifier(QStringLiteral("get")), &pd);
|
|
pd.value = desc->set ? Value::fromObject(desc->set) : Value::undefinedValue();
|
|
o->__defineOwnProperty__(ctx, engine->identifier(QStringLiteral("set")), &pd);
|
|
}
|
|
pd.value = Value::fromBoolean(desc->enumberable == PropertyDescriptor::Enabled ? true : false);
|
|
o->__defineOwnProperty__(ctx, engine->identifier(QStringLiteral("enumerable")), &pd);
|
|
pd.value = Value::fromBoolean(desc->configurable == PropertyDescriptor::Enabled ? true : false);
|
|
o->__defineOwnProperty__(ctx, engine->identifier(QStringLiteral("configurable")), &pd);
|
|
|
|
return Value::fromObject(o);
|
|
}
|