Bug 1865597 - Add error checking when initializing parallel marking and disable on...
[gecko.git] / js / src / vm / PropertyAndElement.cpp
blob419e629f2f56235961439d000139ef8e19a492f5
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
42 using namespace js;
44 static bool DefinePropertyByDescriptor(JSContext* cx, JS::Handle<JSObject*> obj,
45 JS::Handle<jsid> id,
46 JS::Handle<JS::PropertyDescriptor> desc,
47 JS::ObjectOpResult& result) {
48 AssertHeapIsIdle();
49 CHECK_THREAD(cx);
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,
69 JS::Handle<jsid> id,
70 JS::Handle<JS::Value> value,
71 unsigned attrs) {
72 AssertHeapIsIdle();
73 CHECK_THREAD(cx);
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,
81 JS::Handle<jsid> id,
82 JS::Handle<JS::Value> value,
83 unsigned attrs) {
84 return ::DefineDataPropertyById(cx, obj, id, value, attrs);
87 static bool DefineAccessorPropertyById(JSContext* cx, JS::Handle<JSObject*> obj,
88 JS::Handle<jsid> id,
89 JS::Handle<JSObject*> getter,
90 JS::Handle<JSObject*> setter,
91 unsigned attrs) {
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;
98 AssertHeapIsIdle();
99 CHECK_THREAD(cx);
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,
106 JS::Handle<jsid> id,
107 const JSNativeWrapper& get,
108 const JSNativeWrapper& set,
109 unsigned attrs) {
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));
115 if (!atom) {
116 return false;
119 JS::Rooted<JSFunction*> getter(cx);
120 if (get.op) {
121 getter = NewNativeFunction(cx, get.op, 0, atom, gc::AllocKind::FUNCTION,
122 TenuredObject,
123 FunctionFlags::NATIVE_GETTER_WITH_LAZY_NAME);
124 if (!getter) {
125 return false;
128 if (get.info) {
129 getter->setJitInfo(get.info);
133 JS::Rooted<JSFunction*> setter(cx);
134 if (set.op) {
135 setter = NewNativeFunction(cx, set.op, 1, atom, gc::AllocKind::FUNCTION,
136 TenuredObject,
137 FunctionFlags::NATIVE_SETTER_WITH_LAZY_NAME);
138 if (!setter) {
139 return false;
142 if (set.info) {
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) {
155 JSNativeWrapper ret;
156 ret.op = native;
157 ret.info = nullptr;
158 return ret;
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,
171 JS::Handle<jsid> id,
172 JS::Handle<JSObject*> getter,
173 JS::Handle<JSObject*> setter,
174 unsigned attrs) {
175 return ::DefineAccessorPropertyById(cx, obj, id, getter, setter, attrs);
178 JS_PUBLIC_API bool JS_DefinePropertyById(JSContext* cx,
179 JS::Handle<JSObject*> obj,
180 JS::Handle<jsid> id,
181 JS::Handle<JSObject*> valueArg,
182 unsigned attrs) {
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,
189 JS::Handle<jsid> id,
190 HandleString valueArg,
191 unsigned attrs) {
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,
199 unsigned attrs) {
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,
208 unsigned attrs) {
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,
217 unsigned attrs) {
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,
225 unsigned attrs) {
226 JSAtom* atom = Atomize(cx, name, strlen(name));
227 if (!atom) {
228 return false;
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,
236 const char* name,
237 JS::Handle<JS::Value> value,
238 unsigned attrs) {
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));
246 if (!atom) {
247 return false;
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,
255 const char* name,
256 JS::Handle<JSObject*> getter,
257 JS::Handle<JSObject*> setter,
258 unsigned attrs) {
259 JSAtom* atom = Atomize(cx, name, strlen(name));
260 if (!atom) {
261 return false;
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,
269 const char* name,
270 JS::Handle<JSObject*> valueArg,
271 unsigned attrs) {
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,
278 unsigned attrs) {
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,
285 unsigned attrs) {
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,
293 unsigned attrs) {
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,
301 unsigned attrs) {
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));
314 if (!atom) {
315 return false;
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));
325 if (!atom) {
326 return false;
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));
338 if (!atom) {
339 return false;
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,
348 unsigned attrs) {
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,
356 unsigned attrs) {
357 JSAtom* atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
358 if (!atom) {
359 return false;
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,
368 unsigned attrs) {
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),
386 attrs);
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),
395 attrs);
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),
404 attrs);
407 extern bool PropertySpecNameToId(JSContext* cx, JSPropertySpec::Name name,
408 MutableHandleId id);
410 static bool DefineSelfHostedProperty(JSContext* cx, JS::Handle<JSObject*> obj,
411 JS::Handle<jsid> id,
412 const char* getterName,
413 const char* setterName, unsigned attrs) {
414 JSAtom* getterNameAtom = Atomize(cx, getterName, strlen(getterName));
415 if (!getterNameAtom) {
416 return false;
418 JS::Rooted<PropertyName*> getterNameName(cx,
419 getterNameAtom->asPropertyName());
421 JS::Rooted<JSAtom*> name(cx, IdToFunctionName(cx, id));
422 if (!name) {
423 return false;
426 JS::Rooted<JS::Value> getterValue(cx);
427 if (!GlobalObject::getSelfHostedFunction(cx, cx->global(), getterNameName,
428 name, 0, &getterValue)) {
429 return false;
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);
436 if (setterName) {
437 JSAtom* setterNameAtom = Atomize(cx, setterName, strlen(setterName));
438 if (!setterNameAtom) {
439 return false;
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)) {
447 return false;
449 MOZ_ASSERT(setterValue.isObject() &&
450 setterValue.toObject().is<JSFunction>());
451 setterFunc = &setterValue.toObject().as<JSFunction>();
454 return ::DefineAccessorPropertyById(cx, obj, id, getterFunc, setterFunc,
455 attrs);
458 static bool DefineDataElement(JSContext* cx, JS::Handle<JSObject*> obj,
459 uint32_t index, JS::Handle<JS::Value> value,
460 unsigned attrs) {
461 cx->check(obj, value);
462 AssertHeapIsIdle();
463 CHECK_THREAD(cx);
464 JS::Rooted<jsid> id(cx);
465 if (!IndexToId(cx, index, &id)) {
466 return false;
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,
473 unsigned attrs) {
474 return ::DefineDataElement(cx, obj, index, value, attrs);
477 JS_PUBLIC_API bool JS_DefineElement(JSContext* cx, JS::Handle<JSObject*> obj,
478 uint32_t index,
479 JS::Handle<JSObject*> getter,
480 JS::Handle<JSObject*> setter,
481 unsigned attrs) {
482 JS::Rooted<jsid> id(cx);
483 if (!IndexToId(cx, index, &id)) {
484 return false;
486 return ::DefineAccessorPropertyById(cx, obj, id, getter, setter, attrs);
489 JS_PUBLIC_API bool JS_DefineElement(JSContext* cx, JS::Handle<JSObject*> obj,
490 uint32_t index,
491 JS::Handle<JSObject*> valueArg,
492 unsigned attrs) {
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,
499 unsigned attrs) {
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,
506 unsigned attrs) {
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,
514 unsigned attrs) {
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,
522 unsigned attrs) {
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) {
530 AssertHeapIsIdle();
531 CHECK_THREAD(cx);
532 cx->check(obj, id);
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));
540 if (!atom) {
541 return false;
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,
549 bool* foundp) {
550 JSAtom* atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
551 if (!atom) {
552 return false;
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) {
560 AssertHeapIsIdle();
561 CHECK_THREAD(cx);
562 JS::Rooted<jsid> id(cx);
563 if (!IndexToId(cx, index, &id)) {
564 return false;
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) {
572 AssertHeapIsIdle();
573 CHECK_THREAD(cx);
574 cx->check(obj, id);
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));
582 if (!atom) {
583 return false;
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,
591 JS::Handle<jsid> id,
592 JS::Handle<JS::Value> receiver,
593 JS::MutableHandle<JS::Value> vp) {
594 AssertHeapIsIdle();
595 CHECK_THREAD(cx);
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,
603 uint32_t index,
604 JS::Handle<JSObject*> receiver,
605 JS::MutableHandle<JS::Value> vp) {
606 AssertHeapIsIdle();
607 CHECK_THREAD(cx);
608 cx->check(obj);
610 return js::GetElement(cx, obj, receiver, index, vp);
613 JS_PUBLIC_API bool JS_GetPropertyById(JSContext* cx, JS::Handle<JSObject*> obj,
614 JS::Handle<jsid> id,
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,
621 const char* name,
622 JS::MutableHandle<JS::Value> vp) {
623 JSAtom* atom = Atomize(cx, name, strlen(name));
624 if (!atom) {
625 return false;
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));
635 if (!atom) {
636 return false;
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,
643 uint32_t index,
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,
650 JS::Handle<jsid> id,
651 JS::Handle<JS::Value> v,
652 JS::Handle<JS::Value> receiver,
653 JS::ObjectOpResult& result) {
654 AssertHeapIsIdle();
655 CHECK_THREAD(cx);
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,
662 JS::Handle<jsid> id,
663 JS::Handle<JS::Value> v) {
664 AssertHeapIsIdle();
665 CHECK_THREAD(cx);
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));
676 if (!atom) {
677 return false;
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));
687 if (!atom) {
688 return false;
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) {
696 AssertHeapIsIdle();
697 CHECK_THREAD(cx);
698 cx->check(obj, 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,
742 JS::Handle<jsid> id,
743 JS::ObjectOpResult& result) {
744 AssertHeapIsIdle();
745 CHECK_THREAD(cx);
746 cx->check(obj, id);
748 return js::DeleteProperty(cx, obj, id, result);
751 JS_PUBLIC_API bool JS_DeleteProperty(JSContext* cx, JS::Handle<JSObject*> obj,
752 const char* name,
753 JS::ObjectOpResult& result) {
754 CHECK_THREAD(cx);
755 cx->check(obj);
757 JSAtom* atom = Atomize(cx, name, strlen(name));
758 if (!atom) {
759 return false;
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) {
768 CHECK_THREAD(cx);
769 cx->check(obj);
771 JSAtom* atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
772 if (!atom) {
773 return false;
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,
780 uint32_t index,
781 JS::ObjectOpResult& result) {
782 AssertHeapIsIdle();
783 CHECK_THREAD(cx);
784 cx->check(obj);
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,
797 const char* name) {
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,
803 uint32_t index) {
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) {
810 AssertHeapIsIdle();
811 CHECK_THREAD(cx);
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)) {
817 return false;
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,
826 unsigned attrs) {
827 AssertHeapIsIdle();
828 CHECK_THREAD(cx);
829 cx->check(obj);
831 JS::Rooted<JSObject*> nobj(cx);
832 if (!clasp) {
833 // Default class is Object.
834 nobj = NewPlainObject(cx);
835 } else {
836 nobj = NewBuiltinClassInstance(cx, clasp);
838 if (!nobj) {
839 return nullptr;
842 JS::Rooted<JS::Value> nobjValue(cx, JS::ObjectValue(*nobj));
843 if (!::DefineDataProperty(cx, obj, name, nobjValue, attrs)) {
844 return nullptr;
847 return nobj;
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)) {
856 return false;
859 if (ShouldIgnorePropertyDefinition(cx, StandardProtoKeyOrNull(obj), id)) {
860 continue;
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())) {
868 return false;
870 } else {
871 if (!::DefineAccessorPropertyById(
872 cx, obj, id, ps->u.accessors.getter.native,
873 ps->u.accessors.setter.native, ps->attributes())) {
874 return false;
877 } else {
878 JS::Rooted<JS::Value> v(cx);
879 if (!ps->getValue(cx, &v)) {
880 return false;
883 if (!::DefineDataPropertyById(cx, obj, id, v, ps->attributes())) {
884 return false;
888 return true;
891 JS_PUBLIC_API bool JS_AlreadyHasOwnPropertyById(JSContext* cx,
892 JS::Handle<JSObject*> obj,
893 JS::Handle<jsid> id,
894 bool* foundp) {
895 AssertHeapIsIdle();
896 CHECK_THREAD(cx);
897 cx->check(obj, id);
899 if (!obj->is<NativeObject>()) {
900 return js::HasOwnProperty(cx, obj, id, foundp);
903 PropertyResult prop;
904 if (!NativeLookupOwnPropertyNoResolve(cx, &obj->as<NativeObject>(), id,
905 &prop)) {
906 return false;
908 *foundp = prop.isFound();
909 return true;
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));
916 if (!atom) {
917 return false;
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));
928 if (!atom) {
929 return false;
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) {
938 AssertHeapIsIdle();
939 CHECK_THREAD(cx);
940 JS::Rooted<jsid> id(cx);
941 if (!IndexToId(cx, index, &id)) {
942 return false;
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());
950 AssertHeapIsIdle();
951 CHECK_THREAD(cx);
952 cx->check(obj);
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());
962 AssertHeapIsIdle();
963 CHECK_THREAD(cx);
964 cx->check(obj);
965 JSAtom* atom = Atomize(cx, name, strlen(name));
966 if (!atom) {
967 return nullptr;
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());
979 AssertHeapIsIdle();
980 CHECK_THREAD(cx);
981 cx->check(obj);
982 JSAtom* atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
983 if (!atom) {
984 return nullptr;
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,
992 JS::Handle<jsid> id,
993 JSNative call, unsigned nargs,
994 unsigned attrs) {
995 MOZ_ASSERT(!cx->zone()->isAtomsZone());
996 AssertHeapIsIdle();
997 CHECK_THREAD(cx);
998 cx->check(obj, id);
999 return js::DefineFunction(cx, obj, id, call, nargs, attrs);