Commit 41c899bb authored by oliver@apple.com's avatar oliver@apple.com

Implement ES5 Object.defineProperties function

https://bugs.webkit.org/show_bug.cgi?id=29522

Reviewed by Sam Weinig

Implement Object.defineProperties.  Fairly simple patch, simply makes use of
existing functionality used for defineProperty.

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@48565 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent b13df214
......@@ -22,6 +22,22 @@
(JSC::Heap::freeBlock):
* runtime/Collector.h:
2009-09-19 Oliver Hunt <oliver@apple.com>
Reviewed by Sam Weinig.
Implement ES5 Object.defineProperties function
https://bugs.webkit.org/show_bug.cgi?id=29522
Implement Object.defineProperties. Fairly simple patch, simply makes use of
existing functionality used for defineProperty.
* runtime/CommonIdentifiers.h:
* runtime/ObjectConstructor.cpp:
(JSC::ObjectConstructor::ObjectConstructor):
(JSC::defineProperties):
(JSC::objectConstructorDefineProperties):
2009-09-19 Oliver Hunt <oliver@apple.com>
Reviewed by NOBODY (Build fix).
......
......@@ -40,6 +40,7 @@
macro(configurable) \
macro(constructor) \
macro(defineProperty) \
macro(defineProperties) \
macro(enumerable) \
macro(eval) \
macro(exec) \
......
......@@ -38,6 +38,7 @@ static JSValue JSC_HOST_CALL objectConstructorGetPrototypeOf(ExecState*, JSObjec
static JSValue JSC_HOST_CALL objectConstructorGetOwnPropertyDescriptor(ExecState*, JSObject*, JSValue, const ArgList&);
static JSValue JSC_HOST_CALL objectConstructorKeys(ExecState*, JSObject*, JSValue, const ArgList&);
static JSValue JSC_HOST_CALL objectConstructorDefineProperty(ExecState*, JSObject*, JSValue, const ArgList&);
static JSValue JSC_HOST_CALL objectConstructorDefineProperties(ExecState*, JSObject*, JSValue, const ArgList&);
ObjectConstructor::ObjectConstructor(ExecState* exec, PassRefPtr<Structure> structure, ObjectPrototype* objectPrototype, Structure* prototypeFunctionStructure)
: InternalFunction(&exec->globalData(), structure, Identifier(exec, "Object"))
......@@ -51,7 +52,8 @@ ObjectConstructor::ObjectConstructor(ExecState* exec, PassRefPtr<Structure> stru
putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().getPrototypeOf, objectConstructorGetPrototypeOf), DontEnum);
putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 2, exec->propertyNames().getOwnPropertyDescriptor, objectConstructorGetOwnPropertyDescriptor), DontEnum);
putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().keys, objectConstructorKeys), DontEnum);
putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 3, exec->propertyNames().defineProperty, objectConstructorDefineProperty), DontEnum);
putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 3, exec->propertyNames().defineProperty, objectConstructorDefineProperty), DontEnum);
putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 2, exec->propertyNames().defineProperties, objectConstructorDefineProperties), DontEnum);
}
// ECMA 15.2.2
......@@ -237,4 +239,47 @@ JSValue JSC_HOST_CALL objectConstructorDefineProperty(ExecState* exec, JSObject*
return O;
}
static JSValue defineProperties(ExecState* exec, JSObject* object, JSObject* properties)
{
PropertyNameArray propertyNames(exec);
asObject(properties)->getOwnPropertyNames(exec, propertyNames);
size_t numProperties = propertyNames.size();
Vector<PropertyDescriptor> descriptors;
MarkedArgumentBuffer markBuffer;
for (size_t i = 0; i < numProperties; i++) {
PropertySlot slot;
JSValue prop = properties->get(exec, propertyNames[i]);
if (exec->hadException())
return jsNull();
PropertyDescriptor descriptor;
if (!toPropertyDescriptor(exec, prop, descriptor))
return jsNull();
descriptors.append(descriptor);
// Ensure we mark all the values that we're accumulating
if (descriptor.isDataDescriptor() && descriptor.value())
markBuffer.append(descriptor.value());
if (descriptor.isAccessorDescriptor()) {
if (descriptor.getter())
markBuffer.append(descriptor.getter());
if (descriptor.setter())
markBuffer.append(descriptor.setter());
}
}
for (size_t i = 0; i < numProperties; i++) {
object->defineOwnProperty(exec, propertyNames[i], descriptors[i], true);
if (exec->hadException())
return jsNull();
}
return object;
}
JSValue JSC_HOST_CALL objectConstructorDefineProperties(ExecState* exec, JSObject*, JSValue, const ArgList& args)
{
if (!args.at(0).isObject())
return throwError(exec, TypeError, "Properties can only be defined on Objects.");
if (!args.at(1).isObject())
return throwError(exec, TypeError, "Property descriptor list must be an Object.");
return defineProperties(exec, asObject(args.at(0)), asObject(args.at(1)));
}
} // namespace JSC
2009-09-19 Oliver Hunt <oliver@apple.com>
Reviewed by Sam Weinig.
Implement ES5 Object.defineProperties function
https://bugs.webkit.org/show_bug.cgi?id=29522
Add tests for Object.defineProperties API.
* fast/js/Object-defineProperties-expected.txt: Added.
* fast/js/Object-defineProperties.html: Added.
* fast/js/resources/Object-defineProperties.js: Added.
2009-09-19 Daniel Bates <dbates@webkit.org>
Reviewed by Adam Barth.
......
Test to ensure correct behaviour of Object.defineProperties
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
PASS Object.defineProperties() threw exception TypeError: Properties can only be defined on Objects..
PASS Object.defineProperties('a string') threw exception TypeError: Properties can only be defined on Objects..
PASS Object.defineProperties({}, 'a string') threw exception TypeError: Property descriptor list must be an Object..
PASS JSON.stringify(Object.defineProperties({},{property:{value:'foo', enumerable:true}, property2:{value:'foo', enumerable:true}})) is '{"property":"foo","property2":"foo"}'
PASS JSON.stringify(Object.defineProperties({},{property:{value:'foo'}, property2:{value:'foo', enumerable:true}})) is '{"property2":"foo"}'
PASS JSON.stringify(Object.defineProperties({property:'foo'},{property:{value:'foo', enumerable:true}, property2:{value:'foo', enumerable:true}})) is '{"property":"foo","property2":"foo"}'
PASS JSON.stringify(Object.defineProperties({property:'foo'},{property:{value:'foo', enumerable:false}, property2:{value:'foo', enumerable:true}})) is '{"property2":"foo"}'
PASS JSON.stringify(Object.defineProperties({property:'foo'},{property:{value:'foo'}, property2:{value:'foo', enumerable:true}})) is '{"property":"foo","property2":"foo"}'
PASS Object.defineProperties(emptyObject, {foo:{value: true}, bar:{get:function(){}, writable:true}}) threw exception TypeError: Invalid property. 'writable' present on property with getter or setter..
PASS 'foo' in emptyObject is false
PASS successfullyParsed is true
TEST COMPLETE
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<link rel="stylesheet" href="resources/js-test-style.css">
<script src="resources/js-test-pre.js"></script>
</head>
<body>
<p id="description"></p>
<div id="console"></div>
<script src="resources/Object-defineProperties.js"></script>
<script src="resources/js-test-post.js"></script>
</body>
</html>
description("Test to ensure correct behaviour of Object.defineProperties");
shouldThrow("Object.defineProperties()");
shouldThrow("Object.defineProperties('a string')");
shouldThrow("Object.defineProperties({}, 'a string')");
shouldBe("JSON.stringify(Object.defineProperties({},{property:{value:'foo', enumerable:true}, property2:{value:'foo', enumerable:true}}))", '\'{"property":"foo","property2":"foo"}\'');
shouldBe("JSON.stringify(Object.defineProperties({},{property:{value:'foo'}, property2:{value:'foo', enumerable:true}}))", '\'{"property2":"foo"}\'');
shouldBe("JSON.stringify(Object.defineProperties({property:'foo'},{property:{value:'foo', enumerable:true}, property2:{value:'foo', enumerable:true}}))", '\'{"property":"foo","property2":"foo"}\'');
shouldBe("JSON.stringify(Object.defineProperties({property:'foo'},{property:{value:'foo', enumerable:false}, property2:{value:'foo', enumerable:true}}))", '\'{"property2":"foo"}\'');
shouldBe("JSON.stringify(Object.defineProperties({property:'foo'},{property:{value:'foo'}, property2:{value:'foo', enumerable:true}}))", '\'{"property":"foo","property2":"foo"}\'');
emptyObject={};
shouldThrow("Object.defineProperties(emptyObject, {foo:{value: true}, bar:{get:function(){}, writable:true}})");
shouldBeFalse("'foo' in emptyObject");
successfullyParsed = true;
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment