22 #include "object_object.h"
24 #include "operations.h"
25 #include "function_object.h"
26 #include "propertydescriptor.h"
38 class ObjectObjectFuncImp :
public InternalFunctionImp
41 ObjectObjectFuncImp(ExecState *, FunctionPrototype *,
int i,
int len,
const Identifier &);
43 JSValue *
callAsFunction(ExecState *, JSObject *thisObj,
const List &args)
override;
45 enum { GetOwnPropertyDescriptor, DefineProperty, GetPrototypeOf,
46 GetOwnPropertyNames, Keys, DefineProperties,
Create, IsExtensible,
47 PreventExtensible, IsSealed, Seal, IsFrozen, Freeze,
58 ObjectPrototype::ObjectPrototype(ExecState *exec, FunctionPrototype *funcProto)
61 static const Identifier *hasOwnPropertyPropertyName =
new Identifier(
"hasOwnProperty");
62 static const Identifier *propertyIsEnumerablePropertyName =
new Identifier(
"propertyIsEnumerable");
63 static const Identifier *isPrototypeOfPropertyName =
new Identifier(
"isPrototypeOf");
64 static const Identifier *defineGetterPropertyName =
new Identifier(
"__defineGetter__");
65 static const Identifier *defineSetterPropertyName =
new Identifier(
"__defineSetter__");
66 static const Identifier *lookupGetterPropertyName =
new Identifier(
"__lookupGetter__");
67 static const Identifier *lookupSetterPropertyName =
new Identifier(
"__lookupSetter__");
69 putDirectFunction(
new ObjectProtoFunc(exec, funcProto, ObjectProtoFunc::ToString, 0, exec->propertyNames().toString), DontEnum);
70 putDirectFunction(
new ObjectProtoFunc(exec, funcProto, ObjectProtoFunc::ToLocaleString, 0, exec->propertyNames().toLocaleString), DontEnum);
71 putDirectFunction(
new ObjectProtoFunc(exec, funcProto, ObjectProtoFunc::ValueOf, 0, exec->propertyNames().valueOf), DontEnum);
72 putDirectFunction(
new ObjectProtoFunc(exec, funcProto, ObjectProtoFunc::HasOwnProperty, 1, *hasOwnPropertyPropertyName), DontEnum);
73 putDirectFunction(
new ObjectProtoFunc(exec, funcProto, ObjectProtoFunc::PropertyIsEnumerable, 1, *propertyIsEnumerablePropertyName), DontEnum);
74 putDirectFunction(
new ObjectProtoFunc(exec, funcProto, ObjectProtoFunc::IsPrototypeOf, 1, *isPrototypeOfPropertyName), DontEnum);
77 putDirectFunction(
new ObjectProtoFunc(exec, funcProto, ObjectProtoFunc::DefineGetter, 2, *defineGetterPropertyName), DontEnum);
78 putDirectFunction(
new ObjectProtoFunc(exec, funcProto, ObjectProtoFunc::DefineSetter, 2, *defineSetterPropertyName), DontEnum);
79 putDirectFunction(
new ObjectProtoFunc(exec, funcProto, ObjectProtoFunc::LookupGetter, 1, *lookupGetterPropertyName), DontEnum);
80 putDirectFunction(
new ObjectProtoFunc(exec, funcProto, ObjectProtoFunc::LookupSetter, 1, *lookupSetterPropertyName), DontEnum);
83 JSObject *ObjectPrototype::self(ExecState *exec)
85 return exec->lexicalInterpreter()->builtinObjectPrototype();
90 ObjectProtoFunc::ObjectProtoFunc(ExecState *exec, FunctionPrototype *funcProto,
int i,
int len,
const Identifier &name)
91 : InternalFunctionImp(funcProto,
name)
94 putDirect(exec->propertyNames().length, len, DontDelete | ReadOnly | DontEnum);
99 JSValue *ObjectProtoFunc::callAsFunction(ExecState *exec, JSObject *thisObj,
const List &args)
104 case HasOwnProperty: {
106 return jsBoolean(thisObj->getOwnPropertySlot(exec, Identifier(JSValue::toString(args[0], exec)), slot));
108 case IsPrototypeOf: {
109 if (!JSValue::isObject(args[0])) {
110 return jsBoolean(
false);
113 JSValue *v =
static_cast<JSObject *
>(args[0])->prototype();
116 if (!JSValue::isObject(v)) {
117 return jsBoolean(
false);
120 if (thisObj ==
static_cast<JSObject *
>(v))
121 return jsBoolean(
true);
123 v =
static_cast<JSObject *
>(v)->prototype();
128 if (!JSValue::isObject(args[1]) ||
130 if (
id == DefineGetter) {
131 return throwError(exec, SyntaxError,
"invalid getter usage");
133 return throwError(exec, SyntaxError,
"invalid setter usage");
137 if (
id == DefineGetter) {
138 thisObj->defineGetter(exec, Identifier(JSValue::toString(args[0], exec)),
static_cast<JSObject *
>(args[1]));
140 thisObj->defineSetter(exec, Identifier(JSValue::toString(args[0], exec)),
static_cast<JSObject *
>(args[1]));
142 return jsUndefined();
146 Identifier propertyName = Identifier(JSValue::toString(args[0], exec));
148 JSObject *obj = thisObj;
150 JSValue *v = obj->getDirect(propertyName);
153 if (JSValue::type(v) != GetterSetterType) {
154 return jsUndefined();
159 if (
id == LookupGetter) {
160 funcObj =
static_cast<GetterSetterImp *
>(v)->getGetter();
162 funcObj =
static_cast<GetterSetterImp *
>(v)->getSetter();
166 return jsUndefined();
172 if (!obj->prototype() || !JSValue::isObject(obj->prototype())) {
173 return jsUndefined();
176 obj =
static_cast<JSObject *
>(obj->prototype());
179 case PropertyIsEnumerable:
180 return jsBoolean(thisObj->propertyIsEnumerable(exec, Identifier(JSValue::toString(args[0], exec))));
182 return jsString(thisObj->toString(exec));
185 return jsString(
"[object " + thisObj->className() +
"]");
191 ObjectObjectImp::ObjectObjectImp(ExecState *exec, ObjectPrototype *objProto, FunctionPrototype *funcProto)
192 : InternalFunctionImp(funcProto)
194 static const Identifier *getOwnPropertyDescriptorName =
new Identifier(
"getOwnPropertyDescriptor");
195 static const Identifier *createName =
new Identifier(
"create");
196 static const Identifier *definePropertyName =
new Identifier(
"defineProperty");
197 static const Identifier *definePropertiesName =
new Identifier(
"defineProperties");
198 static const Identifier *getPrototypeOf =
new Identifier(
"getPrototypeOf");
199 static const Identifier *getOwnPropertyNames =
new Identifier(
"getOwnPropertyNames");
200 static const Identifier *sealName =
new Identifier(
"seal");
201 static const Identifier *freezeName =
new Identifier(
"freeze");
202 static const Identifier *preventExtensionsName =
new Identifier(
"preventExtensions");
203 static const Identifier *isSealedName =
new Identifier(
"isSealed");
204 static const Identifier *isFrozenName =
new Identifier(
"isFrozen");
205 static const Identifier *isExtensibleName =
new Identifier(
"isExtensible");
206 static const Identifier *keys =
new Identifier(
"keys");
207 static const Identifier* isName =
new Identifier(
"is");
210 putDirect(exec->propertyNames().prototype, objProto, DontEnum | DontDelete | ReadOnly);
212 putDirectFunction(
new ObjectObjectFuncImp(exec, funcProto, ObjectObjectFuncImp::GetOwnPropertyDescriptor, 2, *getOwnPropertyDescriptorName), DontEnum);
213 putDirectFunction(
new ObjectObjectFuncImp(exec, funcProto, ObjectObjectFuncImp::Create, 2, *createName), DontEnum);
214 putDirectFunction(
new ObjectObjectFuncImp(exec, funcProto, ObjectObjectFuncImp::DefineProperty, 3, *definePropertyName), DontEnum);
215 putDirectFunction(
new ObjectObjectFuncImp(exec, funcProto, ObjectObjectFuncImp::DefineProperties, 2, *definePropertiesName), DontEnum);
216 putDirectFunction(
new ObjectObjectFuncImp(exec, funcProto, ObjectObjectFuncImp::GetPrototypeOf, 1, *getPrototypeOf), DontEnum);
217 putDirectFunction(
new ObjectObjectFuncImp(exec, funcProto, ObjectObjectFuncImp::GetOwnPropertyNames, 1, *getOwnPropertyNames), DontEnum);
218 putDirectFunction(
new ObjectObjectFuncImp(exec, funcProto, ObjectObjectFuncImp::Seal, 1, *sealName), DontEnum);
219 putDirectFunction(
new ObjectObjectFuncImp(exec, funcProto, ObjectObjectFuncImp::Freeze, 1, *freezeName), DontEnum);
220 putDirectFunction(
new ObjectObjectFuncImp(exec, funcProto, ObjectObjectFuncImp::PreventExtensible, 1, *preventExtensionsName), DontEnum);
221 putDirectFunction(
new ObjectObjectFuncImp(exec, funcProto, ObjectObjectFuncImp::IsSealed, 1, *isSealedName), DontEnum);
222 putDirectFunction(
new ObjectObjectFuncImp(exec, funcProto, ObjectObjectFuncImp::IsFrozen, 1, *isFrozenName), DontEnum);
223 putDirectFunction(
new ObjectObjectFuncImp(exec, funcProto, ObjectObjectFuncImp::IsExtensible, 1, *isExtensibleName), DontEnum);
224 putDirectFunction(
new ObjectObjectFuncImp(exec, funcProto, ObjectObjectFuncImp::Keys, 1, *keys), DontEnum);
226 putDirectFunction(
new ObjectObjectFuncImp(exec, funcProto, ObjectObjectFuncImp::Is, 2, *isName), DontEnum);
229 putDirect(exec->propertyNames().length, jsNumber(1), ReadOnly | DontDelete | DontEnum);
232 bool ObjectObjectImp::implementsConstruct()
const
238 JSObject *ObjectObjectImp::construct(ExecState *exec,
const List &args)
240 JSValue *arg = args[0];
241 switch (JSValue::type(arg)) {
246 return JSValue::toObject(arg, exec);
249 return new JSObject(exec->lexicalInterpreter()->builtinObjectPrototype());
256 JSValue *ObjectObjectImp::callAsFunction(ExecState *exec, JSObject * ,
const List &args)
258 return construct(exec, args);
263 ObjectObjectFuncImp::ObjectObjectFuncImp(ExecState *exec, FunctionPrototype *funcProto,
int i,
int len,
const Identifier &name)
264 : InternalFunctionImp(funcProto,
name), id(i)
266 putDirect(exec->propertyNames().length, len, DontDelete | ReadOnly | DontEnum);
269 static JSValue *defineProperties(ExecState *exec, JSObject *
object, JSValue *properties)
271 JSObject *props = JSValue::toObject(properties, exec);
272 if (exec->hadException()) {
275 PropertyNameArray names;
276 props->getOwnPropertyNames(exec, names, PropertyMap::ExcludeDontEnumProperties);
277 int size = names.size();
278 Vector<PropertyDescriptor> descriptors;
279 for (
int i = 0; i < size; ++i) {
280 PropertyDescriptor desc;
281 if (!desc.setPropertyDescriptorFromObject(exec, props->get(exec, names[i]))) {
282 return jsUndefined();
284 descriptors.append(desc);
286 for (
int i = 0; i < size; ++i) {
287 object->defineOwnProperty(exec, names[i], descriptors[i],
true);
288 if (exec->hadException()) {
289 return jsUndefined();
298 case GetPrototypeOf: {
299 JSObject *jso = JSValue::getObject(args[0]);
301 return throwError(exec, TypeError,
"Not an Object");
303 return jso->prototype();
305 case GetOwnPropertyDescriptor: {
306 JSObject *jso = JSValue::getObject(args[0]);
308 return throwError(exec, TypeError,
"Not an Object");
311 UString
name = JSValue::toString(args[1], exec);
312 PropertyDescriptor desc;
313 if (!jso->getOwnPropertyDescriptor(exec, Identifier(name), desc)) {
314 return jsUndefined();
316 return desc.fromPropertyDescriptor(exec);
318 case GetOwnPropertyNames:
320 JSObject *jso = JSValue::getObject(args[0]);
322 return throwError(exec, TypeError,
"Not an Object");
325 JSObject *ret =
static_cast<JSObject *
>(exec->lexicalInterpreter()->builtinArray()->construct(exec,
List::empty()));
326 PropertyNameArray propertyNames;
329 jso->getOwnPropertyNames(exec, propertyNames, PropertyMap::ExcludeDontEnumProperties);
331 jso->getOwnPropertyNames(exec, propertyNames, PropertyMap::IncludeDontEnumProperties);
333 PropertyNameArrayIterator propEnd = propertyNames.end();
335 for (PropertyNameArrayIterator propIter = propertyNames.begin(); propIter != propEnd; ++propIter) {
336 Identifier
name = *propIter;
337 ret->put(exec, n, jsString(
name.ustring()),
None);
340 ret->put(exec, exec->propertyNames().length, jsNumber(n), DontEnum | DontDelete);
344 JSObject *proto = JSValue::getObject(args[0]);
345 if (!proto && !JSValue::isNull(args[0])) {
346 return throwError(exec, TypeError,
"Not an Object");
349 JSObject *ret =
static_cast<JSObject *
>(exec->lexicalInterpreter()->builtinObject()->construct(exec,
List::empty()));
351 ret->setPrototype(proto);
353 ret->setPrototype(jsNull());
355 if (args.size() >= 2 && !JSValue::isUndefined(args[1])) {
356 return defineProperties(exec, ret, args[1]);
360 case DefineProperty: {
361 JSObject *jso = JSValue::getObject(args[0]);
363 return throwError(exec, TypeError,
"Not an Object");
366 UString
name = JSValue::toString(args[1], exec);
367 PropertyDescriptor desc;
368 if (!desc.setPropertyDescriptorFromObject(exec, args[2])) {
369 return jsUndefined();
371 if (!jso->defineOwnProperty(exec, Identifier(name), desc,
true)) {
372 return jsUndefined();
376 case DefineProperties: {
377 if (!JSValue::isObject(args[0])) {
378 return throwError(exec, TypeError,
"Not an Object");
381 JSObject *jso = JSValue::getObject(args[0]);
382 return defineProperties(exec, jso, args[1]);
385 JSObject *jso = JSValue::getObject(args[0]);
387 return throwError(exec, TypeError,
"Not an Object");
390 PropertyNameArray names;
391 jso->getOwnPropertyNames(exec, names, PropertyMap::IncludeDontEnumProperties);
392 int size = names.size();
394 PropertyDescriptor desc;
395 for (
int i = 0; i < size; ++i) {
396 jso->getOwnPropertyDescriptor(exec, names[i], desc);
397 if (desc.configurable()) {
398 desc.setConfigureable(
false);
399 if (!jso->defineOwnProperty(exec, names[i], desc,
true)) {
400 return jsUndefined();
404 jso->preventExtensions();
408 JSObject *jso = JSValue::getObject(args[0]);
410 return throwError(exec, TypeError,
"Not an Object");
413 PropertyNameArray names;
414 jso->getOwnPropertyNames(exec, names, PropertyMap::IncludeDontEnumProperties);
415 int size = names.size();
417 PropertyDescriptor desc;
418 for (
int i = 0; i < size; ++i) {
419 jso->getOwnPropertyDescriptor(exec, names[i], desc);
420 if (desc.isDataDescriptor())
421 if (desc.writable()) {
422 desc.setWritable(
false);
424 if (desc.configurable()) {
425 desc.setConfigureable(
false);
427 if (!jso->defineOwnProperty(exec, names[i], desc,
true)) {
428 return jsUndefined();
431 jso->preventExtensions();
434 case PreventExtensible: {
435 JSObject *jso = JSValue::getObject(args[0]);
437 return throwError(exec, TypeError,
"Not an Object");
439 jso->preventExtensions();
443 JSObject *jso = JSValue::getObject(args[0]);
445 return throwError(exec, TypeError,
"Not an Object");
448 PropertyNameArray names;
449 jso->getOwnPropertyNames(exec, names, PropertyMap::IncludeDontEnumProperties);
450 int size = names.size();
452 PropertyDescriptor desc;
453 for (
int i = 0; i < size; ++i) {
454 jso->getOwnPropertyDescriptor(exec, names[i], desc);
455 if (desc.configurable()) {
456 return jsBoolean(
false);
459 return jsBoolean(!jso->isExtensible());
462 JSObject *jso = JSValue::getObject(args[0]);
464 return throwError(exec, TypeError,
"Not an Object");
467 PropertyNameArray names;
468 jso->getOwnPropertyNames(exec, names, PropertyMap::IncludeDontEnumProperties);
469 int size = names.size();
471 PropertyDescriptor desc;
472 for (
int i = 0; i < size; ++i) {
473 jso->getOwnPropertyDescriptor(exec, names[i], desc);
474 if (desc.isDataDescriptor())
475 if (desc.writable()) {
476 return jsBoolean(
false);
478 if (desc.configurable()) {
479 return jsBoolean(
false);
482 return jsBoolean(!jso->isExtensible());
485 JSObject *jso = JSValue::getObject(args[0]);
487 return throwError(exec, TypeError,
"Not an Object");
489 return jsBoolean(jso->isExtensible());
492 return jsBoolean(sameValue(exec, args[0], args[1]));
495 return jsUndefined();