1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: set ts=8 sts=2 et sw=2 tw=80:
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "js/PropertyAndElement.h"
9 #include "mozilla/Assertions.h" // MOZ_ASSERT
11 #include <stddef.h> // size_t
12 #include <stdint.h> // uint32_t
14 #include "jsfriendapi.h" // js::GetPropertyKeys, JSITER_OWNONLY
15 #include "jstypes.h" // JS_PUBLIC_API
17 #include "js/CallArgs.h" // JSNative
18 #include "js/Class.h" // JS::ObjectOpResult
19 #include "js/Context.h" // AssertHeapIsIdle
20 #include "js/GCVector.h" // JS::GCVector, JS::RootedVector
21 #include "js/Id.h" // JS::PropertyKey, jsid
22 #include "js/PropertyDescriptor.h" // JS::PropertyDescriptor, JSPROP_READONLY
23 #include "js/PropertySpec.h" // JSNativeWrapper
24 #include "js/RootingAPI.h" // JS::Rooted, JS::Handle, JS::MutableHandle
25 #include "js/Value.h" // JS::Value, JS::*Value
26 #include "vm/FunctionPrefixKind.h" // js::FunctionPrefixKind
27 #include "vm/GlobalObject.h" // js::GlobalObject
28 #include "vm/JSAtomUtils.h" // js::Atomize, js::AtomizeChars
29 #include "vm/JSContext.h" // JSContext, CHECK_THREAD
30 #include "vm/JSFunction.h" // js::IdToFunctionName, js::DefineFunction
31 #include "vm/JSObject.h" // JSObject, js::DefineFunctions
32 #include "vm/ObjectOperations.h" // js::DefineProperty, js::DefineDataProperty, js::HasOwnProperty
33 #include "vm/PropertyResult.h" // js::PropertyResult
34 #include "vm/StringType.h" // JSAtom, js::PropertyName
36 #include "vm/JSAtomUtils-inl.h" // js::AtomToId, js::IndexToId
37 #include "vm/JSContext-inl.h" // JSContext::check
38 #include "vm/JSObject-inl.h" // js::NewBuiltinClassInstance
39 #include "vm/NativeObject-inl.h" // js::NativeLookupOwnPropertyNoResolve
40 #include "vm/ObjectOperations-inl.h" // js::GetProperty, js::GetElement, js::SetProperty, js::HasProperty, js::DeleteProperty, js::DeleteElement
44 static bool DefinePropertyByDescriptor(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
46 JS::Handle
<JS::PropertyDescriptor
> desc
,
47 JS::ObjectOpResult
& result
) {
50 cx
->check(obj
, id
, desc
);
51 return js::DefineProperty(cx
, obj
, id
, desc
, result
);
54 JS_PUBLIC_API
bool JS_DefinePropertyById(
55 JSContext
* cx
, JS::Handle
<JSObject
*> obj
, JS::Handle
<jsid
> id
,
56 JS::Handle
<JS::PropertyDescriptor
> desc
, JS::ObjectOpResult
& result
) {
57 return ::DefinePropertyByDescriptor(cx
, obj
, id
, desc
, result
);
60 JS_PUBLIC_API
bool JS_DefinePropertyById(
61 JSContext
* cx
, JS::Handle
<JSObject
*> obj
, JS::Handle
<jsid
> id
,
62 JS::Handle
<JS::PropertyDescriptor
> desc
) {
63 JS::ObjectOpResult result
;
64 return ::DefinePropertyByDescriptor(cx
, obj
, id
, desc
, result
) &&
65 result
.checkStrict(cx
, obj
, id
);
68 static bool DefineDataPropertyById(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
70 JS::Handle
<JS::Value
> value
,
74 cx
->check(obj
, id
, value
);
76 return js::DefineDataProperty(cx
, obj
, id
, value
, attrs
);
79 JS_PUBLIC_API
bool JS_DefinePropertyById(JSContext
* cx
,
80 JS::Handle
<JSObject
*> obj
,
82 JS::Handle
<JS::Value
> value
,
84 return ::DefineDataPropertyById(cx
, obj
, id
, value
, attrs
);
87 static bool DefineAccessorPropertyById(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
89 JS::Handle
<JSObject
*> getter
,
90 JS::Handle
<JSObject
*> setter
,
92 // JSPROP_READONLY has no meaning when accessors are involved. Ideally we'd
93 // throw if this happens, but we've accepted it for long enough that it's
94 // not worth trying to make callers change their ways. Just flip it off on
95 // its way through the API layer so that we can enforce this internally.
96 attrs
&= ~JSPROP_READONLY
;
100 cx
->check(obj
, id
, getter
, setter
);
102 return js::DefineAccessorProperty(cx
, obj
, id
, getter
, setter
, attrs
);
105 static bool DefineAccessorPropertyById(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
107 const JSNativeWrapper
& get
,
108 const JSNativeWrapper
& set
,
110 // Getter/setter are both possibly-null JSNatives. Wrap them in JSFunctions.
112 // Use unprefixed name with LAZY_ACCESSOR_NAME flag, to avoid calculating
113 // the accessor name, which is less likely to be used.
114 JS::Rooted
<JSAtom
*> atom(cx
, IdToFunctionName(cx
, id
));
119 JS::Rooted
<JSFunction
*> getter(cx
);
121 getter
= NewNativeFunction(cx
, get
.op
, 0, atom
, gc::AllocKind::FUNCTION
,
123 FunctionFlags::NATIVE_GETTER_WITH_LAZY_NAME
);
129 getter
->setJitInfo(get
.info
);
133 JS::Rooted
<JSFunction
*> setter(cx
);
135 setter
= NewNativeFunction(cx
, set
.op
, 1, atom
, gc::AllocKind::FUNCTION
,
137 FunctionFlags::NATIVE_SETTER_WITH_LAZY_NAME
);
143 setter
->setJitInfo(set
.info
);
147 return ::DefineAccessorPropertyById(cx
, obj
, id
, getter
, setter
, attrs
);
151 * Wrapper functions to create wrappers with no corresponding JSJitInfo from API
152 * function arguments.
154 static JSNativeWrapper
NativeOpWrapper(Native native
) {
161 JS_PUBLIC_API
bool JS_DefinePropertyById(JSContext
* cx
,
162 JS::Handle
<JSObject
*> obj
,
163 JS::Handle
<jsid
> id
, JSNative getter
,
164 JSNative setter
, unsigned attrs
) {
165 return ::DefineAccessorPropertyById(cx
, obj
, id
, ::NativeOpWrapper(getter
),
166 ::NativeOpWrapper(setter
), attrs
);
169 JS_PUBLIC_API
bool JS_DefinePropertyById(JSContext
* cx
,
170 JS::Handle
<JSObject
*> obj
,
172 JS::Handle
<JSObject
*> getter
,
173 JS::Handle
<JSObject
*> setter
,
175 return ::DefineAccessorPropertyById(cx
, obj
, id
, getter
, setter
, attrs
);
178 JS_PUBLIC_API
bool JS_DefinePropertyById(JSContext
* cx
,
179 JS::Handle
<JSObject
*> obj
,
181 JS::Handle
<JSObject
*> valueArg
,
183 JS::Rooted
<JS::Value
> value(cx
, JS::ObjectValue(*valueArg
));
184 return ::DefineDataPropertyById(cx
, obj
, id
, value
, attrs
);
187 JS_PUBLIC_API
bool JS_DefinePropertyById(JSContext
* cx
,
188 JS::Handle
<JSObject
*> obj
,
190 HandleString valueArg
,
192 JS::Rooted
<JS::Value
> value(cx
, JS::StringValue(valueArg
));
193 return ::DefineDataPropertyById(cx
, obj
, id
, value
, attrs
);
196 JS_PUBLIC_API
bool JS_DefinePropertyById(JSContext
* cx
,
197 JS::Handle
<JSObject
*> obj
,
198 JS::Handle
<jsid
> id
, int32_t valueArg
,
200 JS::Value value
= JS::Int32Value(valueArg
);
201 return ::DefineDataPropertyById(
202 cx
, obj
, id
, JS::Handle
<JS::Value
>::fromMarkedLocation(&value
), attrs
);
205 JS_PUBLIC_API
bool JS_DefinePropertyById(JSContext
* cx
,
206 JS::Handle
<JSObject
*> obj
,
207 JS::Handle
<jsid
> id
, uint32_t valueArg
,
209 JS::Value value
= JS::NumberValue(valueArg
);
210 return ::DefineDataPropertyById(
211 cx
, obj
, id
, JS::Handle
<JS::Value
>::fromMarkedLocation(&value
), attrs
);
214 JS_PUBLIC_API
bool JS_DefinePropertyById(JSContext
* cx
,
215 JS::Handle
<JSObject
*> obj
,
216 JS::Handle
<jsid
> id
, double valueArg
,
218 JS::Value value
= JS::NumberValue(valueArg
);
219 return ::DefineDataPropertyById(
220 cx
, obj
, id
, JS::Handle
<JS::Value
>::fromMarkedLocation(&value
), attrs
);
223 static bool DefineDataProperty(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
224 const char* name
, JS::Handle
<JS::Value
> value
,
226 JSAtom
* atom
= Atomize(cx
, name
, strlen(name
));
230 JS::Rooted
<jsid
> id(cx
, AtomToId(atom
));
232 return ::DefineDataPropertyById(cx
, obj
, id
, value
, attrs
);
235 JS_PUBLIC_API
bool JS_DefineProperty(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
237 JS::Handle
<JS::Value
> value
,
239 return ::DefineDataProperty(cx
, obj
, name
, value
, attrs
);
242 JS_PUBLIC_API
bool JS_DefineProperty(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
243 const char* name
, JSNative getter
,
244 JSNative setter
, unsigned attrs
) {
245 JSAtom
* atom
= Atomize(cx
, name
, strlen(name
));
249 JS::Rooted
<jsid
> id(cx
, AtomToId(atom
));
250 return ::DefineAccessorPropertyById(cx
, obj
, id
, ::NativeOpWrapper(getter
),
251 ::NativeOpWrapper(setter
), attrs
);
254 JS_PUBLIC_API
bool JS_DefineProperty(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
256 JS::Handle
<JSObject
*> getter
,
257 JS::Handle
<JSObject
*> setter
,
259 JSAtom
* atom
= Atomize(cx
, name
, strlen(name
));
263 JS::Rooted
<jsid
> id(cx
, AtomToId(atom
));
265 return ::DefineAccessorPropertyById(cx
, obj
, id
, getter
, setter
, attrs
);
268 JS_PUBLIC_API
bool JS_DefineProperty(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
270 JS::Handle
<JSObject
*> valueArg
,
272 JS::Rooted
<JS::Value
> value(cx
, JS::ObjectValue(*valueArg
));
273 return ::DefineDataProperty(cx
, obj
, name
, value
, attrs
);
276 JS_PUBLIC_API
bool JS_DefineProperty(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
277 const char* name
, HandleString valueArg
,
279 JS::Rooted
<JS::Value
> value(cx
, JS::StringValue(valueArg
));
280 return ::DefineDataProperty(cx
, obj
, name
, value
, attrs
);
283 JS_PUBLIC_API
bool JS_DefineProperty(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
284 const char* name
, int32_t valueArg
,
286 JS::Value value
= JS::Int32Value(valueArg
);
287 return ::DefineDataProperty(
288 cx
, obj
, name
, JS::Handle
<JS::Value
>::fromMarkedLocation(&value
), attrs
);
291 JS_PUBLIC_API
bool JS_DefineProperty(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
292 const char* name
, uint32_t valueArg
,
294 JS::Value value
= JS::NumberValue(valueArg
);
295 return ::DefineDataProperty(
296 cx
, obj
, name
, JS::Handle
<JS::Value
>::fromMarkedLocation(&value
), attrs
);
299 JS_PUBLIC_API
bool JS_DefineProperty(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
300 const char* name
, double valueArg
,
302 JS::Value value
= JS::NumberValue(valueArg
);
303 return ::DefineDataProperty(
304 cx
, obj
, name
, JS::Handle
<JS::Value
>::fromMarkedLocation(&value
), attrs
);
307 #define AUTO_NAMELEN(s, n) (((n) == (size_t)-1) ? js_strlen(s) : (n))
309 JS_PUBLIC_API
bool JS_DefineUCProperty(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
310 const char16_t
* name
, size_t namelen
,
311 JS::Handle
<JS::PropertyDescriptor
> desc
,
312 JS::ObjectOpResult
& result
) {
313 JSAtom
* atom
= AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
));
317 JS::Rooted
<jsid
> id(cx
, AtomToId(atom
));
318 return ::DefinePropertyByDescriptor(cx
, obj
, id
, desc
, result
);
321 JS_PUBLIC_API
bool JS_DefineUCProperty(
322 JSContext
* cx
, JS::Handle
<JSObject
*> obj
, const char16_t
* name
,
323 size_t namelen
, JS::Handle
<JS::PropertyDescriptor
> desc
) {
324 JSAtom
* atom
= AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
));
328 JS::Rooted
<jsid
> id(cx
, AtomToId(atom
));
329 JS::ObjectOpResult result
;
330 return ::DefinePropertyByDescriptor(cx
, obj
, id
, desc
, result
) &&
331 result
.checkStrict(cx
, obj
, id
);
334 static bool DefineUCDataProperty(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
335 const char16_t
* name
, size_t namelen
,
336 JS::Handle
<JS::Value
> value
, unsigned attrs
) {
337 JSAtom
* atom
= AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
));
341 JS::Rooted
<jsid
> id(cx
, AtomToId(atom
));
342 return ::DefineDataPropertyById(cx
, obj
, id
, value
, attrs
);
345 JS_PUBLIC_API
bool JS_DefineUCProperty(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
346 const char16_t
* name
, size_t namelen
,
347 JS::Handle
<JS::Value
> value
,
349 return ::DefineUCDataProperty(cx
, obj
, name
, namelen
, value
, attrs
);
352 JS_PUBLIC_API
bool JS_DefineUCProperty(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
353 const char16_t
* name
, size_t namelen
,
354 JS::Handle
<JSObject
*> getter
,
355 JS::Handle
<JSObject
*> setter
,
357 JSAtom
* atom
= AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
));
361 JS::Rooted
<jsid
> id(cx
, AtomToId(atom
));
362 return ::DefineAccessorPropertyById(cx
, obj
, id
, getter
, setter
, attrs
);
365 JS_PUBLIC_API
bool JS_DefineUCProperty(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
366 const char16_t
* name
, size_t namelen
,
367 JS::Handle
<JSObject
*> valueArg
,
369 JS::Rooted
<JS::Value
> value(cx
, JS::ObjectValue(*valueArg
));
370 return ::DefineUCDataProperty(cx
, obj
, name
, namelen
, value
, attrs
);
373 JS_PUBLIC_API
bool JS_DefineUCProperty(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
374 const char16_t
* name
, size_t namelen
,
375 HandleString valueArg
, unsigned attrs
) {
376 JS::Rooted
<JS::Value
> value(cx
, JS::StringValue(valueArg
));
377 return ::DefineUCDataProperty(cx
, obj
, name
, namelen
, value
, attrs
);
380 JS_PUBLIC_API
bool JS_DefineUCProperty(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
381 const char16_t
* name
, size_t namelen
,
382 int32_t valueArg
, unsigned attrs
) {
383 JS::Value value
= JS::Int32Value(valueArg
);
384 return ::DefineUCDataProperty(
385 cx
, obj
, name
, namelen
, JS::Handle
<JS::Value
>::fromMarkedLocation(&value
),
389 JS_PUBLIC_API
bool JS_DefineUCProperty(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
390 const char16_t
* name
, size_t namelen
,
391 uint32_t valueArg
, unsigned attrs
) {
392 JS::Value value
= JS::NumberValue(valueArg
);
393 return ::DefineUCDataProperty(
394 cx
, obj
, name
, namelen
, JS::Handle
<JS::Value
>::fromMarkedLocation(&value
),
398 JS_PUBLIC_API
bool JS_DefineUCProperty(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
399 const char16_t
* name
, size_t namelen
,
400 double valueArg
, unsigned attrs
) {
401 JS::Value value
= JS::NumberValue(valueArg
);
402 return ::DefineUCDataProperty(
403 cx
, obj
, name
, namelen
, JS::Handle
<JS::Value
>::fromMarkedLocation(&value
),
407 extern bool PropertySpecNameToId(JSContext
* cx
, JSPropertySpec::Name name
,
410 static bool DefineSelfHostedProperty(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
412 const char* getterName
,
413 const char* setterName
, unsigned attrs
) {
414 JSAtom
* getterNameAtom
= Atomize(cx
, getterName
, strlen(getterName
));
415 if (!getterNameAtom
) {
418 JS::Rooted
<PropertyName
*> getterNameName(cx
,
419 getterNameAtom
->asPropertyName());
421 JS::Rooted
<JSAtom
*> name(cx
, IdToFunctionName(cx
, id
));
426 JS::Rooted
<JS::Value
> getterValue(cx
);
427 if (!GlobalObject::getSelfHostedFunction(cx
, cx
->global(), getterNameName
,
428 name
, 0, &getterValue
)) {
431 MOZ_ASSERT(getterValue
.isObject() && getterValue
.toObject().is
<JSFunction
>());
432 JS::Rooted
<JSFunction
*> getterFunc(cx
,
433 &getterValue
.toObject().as
<JSFunction
>());
435 JS::Rooted
<JSFunction
*> setterFunc(cx
);
437 JSAtom
* setterNameAtom
= Atomize(cx
, setterName
, strlen(setterName
));
438 if (!setterNameAtom
) {
441 JS::Rooted
<PropertyName
*> setterNameName(cx
,
442 setterNameAtom
->asPropertyName());
444 JS::Rooted
<JS::Value
> setterValue(cx
);
445 if (!GlobalObject::getSelfHostedFunction(cx
, cx
->global(), setterNameName
,
446 name
, 1, &setterValue
)) {
449 MOZ_ASSERT(setterValue
.isObject() &&
450 setterValue
.toObject().is
<JSFunction
>());
451 setterFunc
= &setterValue
.toObject().as
<JSFunction
>();
454 return ::DefineAccessorPropertyById(cx
, obj
, id
, getterFunc
, setterFunc
,
458 static bool DefineDataElement(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
459 uint32_t index
, JS::Handle
<JS::Value
> value
,
461 cx
->check(obj
, value
);
464 JS::Rooted
<jsid
> id(cx
);
465 if (!IndexToId(cx
, index
, &id
)) {
468 return ::DefineDataPropertyById(cx
, obj
, id
, value
, attrs
);
471 JS_PUBLIC_API
bool JS_DefineElement(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
472 uint32_t index
, JS::Handle
<JS::Value
> value
,
474 return ::DefineDataElement(cx
, obj
, index
, value
, attrs
);
477 JS_PUBLIC_API
bool JS_DefineElement(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
479 JS::Handle
<JSObject
*> getter
,
480 JS::Handle
<JSObject
*> setter
,
482 JS::Rooted
<jsid
> id(cx
);
483 if (!IndexToId(cx
, index
, &id
)) {
486 return ::DefineAccessorPropertyById(cx
, obj
, id
, getter
, setter
, attrs
);
489 JS_PUBLIC_API
bool JS_DefineElement(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
491 JS::Handle
<JSObject
*> valueArg
,
493 JS::Rooted
<JS::Value
> value(cx
, JS::ObjectValue(*valueArg
));
494 return ::DefineDataElement(cx
, obj
, index
, value
, attrs
);
497 JS_PUBLIC_API
bool JS_DefineElement(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
498 uint32_t index
, HandleString valueArg
,
500 JS::Rooted
<JS::Value
> value(cx
, JS::StringValue(valueArg
));
501 return ::DefineDataElement(cx
, obj
, index
, value
, attrs
);
504 JS_PUBLIC_API
bool JS_DefineElement(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
505 uint32_t index
, int32_t valueArg
,
507 JS::Value value
= JS::Int32Value(valueArg
);
508 return ::DefineDataElement(
509 cx
, obj
, index
, JS::Handle
<JS::Value
>::fromMarkedLocation(&value
), attrs
);
512 JS_PUBLIC_API
bool JS_DefineElement(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
513 uint32_t index
, uint32_t valueArg
,
515 JS::Value value
= JS::NumberValue(valueArg
);
516 return ::DefineDataElement(
517 cx
, obj
, index
, JS::Handle
<JS::Value
>::fromMarkedLocation(&value
), attrs
);
520 JS_PUBLIC_API
bool JS_DefineElement(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
521 uint32_t index
, double valueArg
,
523 JS::Value value
= JS::NumberValue(valueArg
);
524 return ::DefineDataElement(
525 cx
, obj
, index
, JS::Handle
<JS::Value
>::fromMarkedLocation(&value
), attrs
);
528 JS_PUBLIC_API
bool JS_HasPropertyById(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
529 JS::Handle
<jsid
> id
, bool* foundp
) {
534 return js::HasProperty(cx
, obj
, id
, foundp
);
537 JS_PUBLIC_API
bool JS_HasProperty(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
538 const char* name
, bool* foundp
) {
539 JSAtom
* atom
= Atomize(cx
, name
, strlen(name
));
543 JS::Rooted
<jsid
> id(cx
, AtomToId(atom
));
544 return JS_HasPropertyById(cx
, obj
, id
, foundp
);
547 JS_PUBLIC_API
bool JS_HasUCProperty(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
548 const char16_t
* name
, size_t namelen
,
550 JSAtom
* atom
= AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
));
554 JS::Rooted
<jsid
> id(cx
, AtomToId(atom
));
555 return JS_HasPropertyById(cx
, obj
, id
, foundp
);
558 JS_PUBLIC_API
bool JS_HasElement(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
559 uint32_t index
, bool* foundp
) {
562 JS::Rooted
<jsid
> id(cx
);
563 if (!IndexToId(cx
, index
, &id
)) {
566 return JS_HasPropertyById(cx
, obj
, id
, foundp
);
569 JS_PUBLIC_API
bool JS_HasOwnPropertyById(JSContext
* cx
,
570 JS::Handle
<JSObject
*> obj
,
571 JS::Handle
<jsid
> id
, bool* foundp
) {
576 return js::HasOwnProperty(cx
, obj
, id
, foundp
);
579 JS_PUBLIC_API
bool JS_HasOwnProperty(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
580 const char* name
, bool* foundp
) {
581 JSAtom
* atom
= Atomize(cx
, name
, strlen(name
));
585 JS::Rooted
<jsid
> id(cx
, AtomToId(atom
));
586 return JS_HasOwnPropertyById(cx
, obj
, id
, foundp
);
589 JS_PUBLIC_API
bool JS_ForwardGetPropertyTo(JSContext
* cx
,
590 JS::Handle
<JSObject
*> obj
,
592 JS::Handle
<JS::Value
> receiver
,
593 JS::MutableHandle
<JS::Value
> vp
) {
596 cx
->check(obj
, id
, receiver
);
598 return js::GetProperty(cx
, obj
, receiver
, id
, vp
);
601 JS_PUBLIC_API
bool JS_ForwardGetElementTo(JSContext
* cx
,
602 JS::Handle
<JSObject
*> obj
,
604 JS::Handle
<JSObject
*> receiver
,
605 JS::MutableHandle
<JS::Value
> vp
) {
610 return js::GetElement(cx
, obj
, receiver
, index
, vp
);
613 JS_PUBLIC_API
bool JS_GetPropertyById(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
615 JS::MutableHandle
<JS::Value
> vp
) {
616 JS::Rooted
<JS::Value
> receiver(cx
, JS::ObjectValue(*obj
));
617 return JS_ForwardGetPropertyTo(cx
, obj
, id
, receiver
, vp
);
620 JS_PUBLIC_API
bool JS_GetProperty(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
622 JS::MutableHandle
<JS::Value
> vp
) {
623 JSAtom
* atom
= Atomize(cx
, name
, strlen(name
));
627 JS::Rooted
<jsid
> id(cx
, AtomToId(atom
));
628 return JS_GetPropertyById(cx
, obj
, id
, vp
);
631 JS_PUBLIC_API
bool JS_GetUCProperty(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
632 const char16_t
* name
, size_t namelen
,
633 JS::MutableHandle
<JS::Value
> vp
) {
634 JSAtom
* atom
= AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
));
638 JS::Rooted
<jsid
> id(cx
, AtomToId(atom
));
639 return JS_GetPropertyById(cx
, obj
, id
, vp
);
642 JS_PUBLIC_API
bool JS_GetElement(JSContext
* cx
, JS::Handle
<JSObject
*> objArg
,
644 JS::MutableHandle
<JS::Value
> vp
) {
645 return JS_ForwardGetElementTo(cx
, objArg
, index
, objArg
, vp
);
648 JS_PUBLIC_API
bool JS_ForwardSetPropertyTo(JSContext
* cx
,
649 JS::Handle
<JSObject
*> obj
,
651 JS::Handle
<JS::Value
> v
,
652 JS::Handle
<JS::Value
> receiver
,
653 JS::ObjectOpResult
& result
) {
656 cx
->check(obj
, id
, v
, receiver
);
658 return js::SetProperty(cx
, obj
, id
, v
, receiver
, result
);
661 JS_PUBLIC_API
bool JS_SetPropertyById(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
663 JS::Handle
<JS::Value
> v
) {
666 cx
->check(obj
, id
, v
);
668 JS::Rooted
<JS::Value
> receiver(cx
, JS::ObjectValue(*obj
));
669 JS::ObjectOpResult ignored
;
670 return js::SetProperty(cx
, obj
, id
, v
, receiver
, ignored
);
673 JS_PUBLIC_API
bool JS_SetProperty(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
674 const char* name
, JS::Handle
<JS::Value
> v
) {
675 JSAtom
* atom
= Atomize(cx
, name
, strlen(name
));
679 JS::Rooted
<jsid
> id(cx
, AtomToId(atom
));
680 return JS_SetPropertyById(cx
, obj
, id
, v
);
683 JS_PUBLIC_API
bool JS_SetUCProperty(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
684 const char16_t
* name
, size_t namelen
,
685 JS::Handle
<JS::Value
> v
) {
686 JSAtom
* atom
= AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
));
690 JS::Rooted
<jsid
> id(cx
, AtomToId(atom
));
691 return JS_SetPropertyById(cx
, obj
, id
, v
);
694 static bool SetElement(JSContext
* cx
, JS::Handle
<JSObject
*> obj
, uint32_t index
,
695 JS::Handle
<JS::Value
> v
) {
700 JS::Rooted
<JS::Value
> receiver(cx
, JS::ObjectValue(*obj
));
701 JS::ObjectOpResult ignored
;
702 return js::SetElement(cx
, obj
, index
, v
, receiver
, ignored
);
705 JS_PUBLIC_API
bool JS_SetElement(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
706 uint32_t index
, JS::Handle
<JS::Value
> v
) {
707 return ::SetElement(cx
, obj
, index
, v
);
710 JS_PUBLIC_API
bool JS_SetElement(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
711 uint32_t index
, JS::Handle
<JSObject
*> v
) {
712 JS::Rooted
<JS::Value
> value(cx
, JS::ObjectOrNullValue(v
));
713 return ::SetElement(cx
, obj
, index
, value
);
716 JS_PUBLIC_API
bool JS_SetElement(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
717 uint32_t index
, HandleString v
) {
718 JS::Rooted
<JS::Value
> value(cx
, JS::StringValue(v
));
719 return ::SetElement(cx
, obj
, index
, value
);
722 JS_PUBLIC_API
bool JS_SetElement(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
723 uint32_t index
, int32_t v
) {
724 JS::Rooted
<JS::Value
> value(cx
, JS::NumberValue(v
));
725 return ::SetElement(cx
, obj
, index
, value
);
728 JS_PUBLIC_API
bool JS_SetElement(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
729 uint32_t index
, uint32_t v
) {
730 JS::Rooted
<JS::Value
> value(cx
, JS::NumberValue(v
));
731 return ::SetElement(cx
, obj
, index
, value
);
734 JS_PUBLIC_API
bool JS_SetElement(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
735 uint32_t index
, double v
) {
736 JS::Rooted
<JS::Value
> value(cx
, JS::NumberValue(v
));
737 return ::SetElement(cx
, obj
, index
, value
);
740 JS_PUBLIC_API
bool JS_DeletePropertyById(JSContext
* cx
,
741 JS::Handle
<JSObject
*> obj
,
743 JS::ObjectOpResult
& result
) {
748 return js::DeleteProperty(cx
, obj
, id
, result
);
751 JS_PUBLIC_API
bool JS_DeleteProperty(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
753 JS::ObjectOpResult
& result
) {
757 JSAtom
* atom
= Atomize(cx
, name
, strlen(name
));
761 JS::Rooted
<jsid
> id(cx
, AtomToId(atom
));
762 return js::DeleteProperty(cx
, obj
, id
, result
);
765 JS_PUBLIC_API
bool JS_DeleteUCProperty(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
766 const char16_t
* name
, size_t namelen
,
767 JS::ObjectOpResult
& result
) {
771 JSAtom
* atom
= AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
));
775 JS::Rooted
<jsid
> id(cx
, AtomToId(atom
));
776 return js::DeleteProperty(cx
, obj
, id
, result
);
779 JS_PUBLIC_API
bool JS_DeleteElement(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
781 JS::ObjectOpResult
& result
) {
786 return js::DeleteElement(cx
, obj
, index
, result
);
789 JS_PUBLIC_API
bool JS_DeletePropertyById(JSContext
* cx
,
790 JS::Handle
<JSObject
*> obj
,
791 JS::Handle
<jsid
> id
) {
792 JS::ObjectOpResult ignored
;
793 return JS_DeletePropertyById(cx
, obj
, id
, ignored
);
796 JS_PUBLIC_API
bool JS_DeleteProperty(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
798 JS::ObjectOpResult ignored
;
799 return JS_DeleteProperty(cx
, obj
, name
, ignored
);
802 JS_PUBLIC_API
bool JS_DeleteElement(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
804 JS::ObjectOpResult ignored
;
805 return JS_DeleteElement(cx
, obj
, index
, ignored
);
808 JS_PUBLIC_API
bool JS_Enumerate(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
809 JS::MutableHandle
<IdVector
> props
) {
812 cx
->check(obj
, props
);
813 MOZ_ASSERT(props
.empty());
815 JS::RootedVector
<JS::PropertyKey
> ids(cx
);
816 if (!js::GetPropertyKeys(cx
, obj
, JSITER_OWNONLY
, &ids
)) {
820 return props
.append(ids
.begin(), ids
.end());
823 JS_PUBLIC_API JSObject
* JS_DefineObject(JSContext
* cx
,
824 JS::Handle
<JSObject
*> obj
,
825 const char* name
, const JSClass
* clasp
,
831 JS::Rooted
<JSObject
*> nobj(cx
);
833 // Default class is Object.
834 nobj
= NewPlainObject(cx
);
836 nobj
= NewBuiltinClassInstance(cx
, clasp
);
842 JS::Rooted
<JS::Value
> nobjValue(cx
, JS::ObjectValue(*nobj
));
843 if (!::DefineDataProperty(cx
, obj
, name
, nobjValue
, attrs
)) {
850 JS_PUBLIC_API
bool JS_DefineProperties(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
851 const JSPropertySpec
* ps
) {
852 JS::Rooted
<jsid
> id(cx
);
854 for (; ps
->name
; ps
++) {
855 if (!PropertySpecNameToId(cx
, ps
->name
, &id
)) {
859 if (ShouldIgnorePropertyDefinition(cx
, StandardProtoKeyOrNull(obj
), id
)) {
863 if (ps
->isAccessor()) {
864 if (ps
->isSelfHosted()) {
865 if (!::DefineSelfHostedProperty(
866 cx
, obj
, id
, ps
->u
.accessors
.getter
.selfHosted
.funname
,
867 ps
->u
.accessors
.setter
.selfHosted
.funname
, ps
->attributes())) {
871 if (!::DefineAccessorPropertyById(
872 cx
, obj
, id
, ps
->u
.accessors
.getter
.native
,
873 ps
->u
.accessors
.setter
.native
, ps
->attributes())) {
878 JS::Rooted
<JS::Value
> v(cx
);
879 if (!ps
->getValue(cx
, &v
)) {
883 if (!::DefineDataPropertyById(cx
, obj
, id
, v
, ps
->attributes())) {
891 JS_PUBLIC_API
bool JS_AlreadyHasOwnPropertyById(JSContext
* cx
,
892 JS::Handle
<JSObject
*> obj
,
899 if (!obj
->is
<NativeObject
>()) {
900 return js::HasOwnProperty(cx
, obj
, id
, foundp
);
904 if (!NativeLookupOwnPropertyNoResolve(cx
, &obj
->as
<NativeObject
>(), id
,
908 *foundp
= prop
.isFound();
912 JS_PUBLIC_API
bool JS_AlreadyHasOwnProperty(JSContext
* cx
,
913 JS::Handle
<JSObject
*> obj
,
914 const char* name
, bool* foundp
) {
915 JSAtom
* atom
= Atomize(cx
, name
, strlen(name
));
919 JS::Rooted
<jsid
> id(cx
, AtomToId(atom
));
920 return JS_AlreadyHasOwnPropertyById(cx
, obj
, id
, foundp
);
923 JS_PUBLIC_API
bool JS_AlreadyHasOwnUCProperty(JSContext
* cx
,
924 JS::Handle
<JSObject
*> obj
,
925 const char16_t
* name
,
926 size_t namelen
, bool* foundp
) {
927 JSAtom
* atom
= AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
));
931 JS::Rooted
<jsid
> id(cx
, AtomToId(atom
));
932 return JS_AlreadyHasOwnPropertyById(cx
, obj
, id
, foundp
);
935 JS_PUBLIC_API
bool JS_AlreadyHasOwnElement(JSContext
* cx
,
936 JS::Handle
<JSObject
*> obj
,
937 uint32_t index
, bool* foundp
) {
940 JS::Rooted
<jsid
> id(cx
);
941 if (!IndexToId(cx
, index
, &id
)) {
944 return JS_AlreadyHasOwnPropertyById(cx
, obj
, id
, foundp
);
947 JS_PUBLIC_API
bool JS_DefineFunctions(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
948 const JSFunctionSpec
* fs
) {
949 MOZ_ASSERT(!cx
->zone()->isAtomsZone());
954 return js::DefineFunctions(cx
, obj
, fs
);
957 JS_PUBLIC_API JSFunction
* JS_DefineFunction(JSContext
* cx
,
958 JS::Handle
<JSObject
*> obj
,
959 const char* name
, JSNative call
,
960 unsigned nargs
, unsigned attrs
) {
961 MOZ_ASSERT(!cx
->zone()->isAtomsZone());
965 JSAtom
* atom
= Atomize(cx
, name
, strlen(name
));
969 Rooted
<jsid
> id(cx
, AtomToId(atom
));
970 return js::DefineFunction(cx
, obj
, id
, call
, nargs
, attrs
);
973 JS_PUBLIC_API JSFunction
* JS_DefineUCFunction(JSContext
* cx
,
974 JS::Handle
<JSObject
*> obj
,
975 const char16_t
* name
,
976 size_t namelen
, JSNative call
,
977 unsigned nargs
, unsigned attrs
) {
978 MOZ_ASSERT(!cx
->zone()->isAtomsZone());
982 JSAtom
* atom
= AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
));
986 Rooted
<jsid
> id(cx
, AtomToId(atom
));
987 return js::DefineFunction(cx
, obj
, id
, call
, nargs
, attrs
);
990 JS_PUBLIC_API JSFunction
* JS_DefineFunctionById(JSContext
* cx
,
991 JS::Handle
<JSObject
*> obj
,
993 JSNative call
, unsigned nargs
,
995 MOZ_ASSERT(!cx
->zone()->isAtomsZone());
999 return js::DefineFunction(cx
, obj
, id
, call
, nargs
, attrs
);