Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * vim: set ts=8 sts=4 et sw=4 tw=99:
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 /*
8 * JavaScript Debugging support - Value and Property support
9 */
11 #include "jsd.h"
12 #include "jsapi.h"
13 #include "jsfriendapi.h"
14 #include "jswrapper.h"
15 #include "nsCxPusher.h"
17 using mozilla::AutoSafeJSContext;
19 #ifdef DEBUG
20 void JSD_ASSERT_VALID_VALUE(JSDValue* jsdval)
21 {
22 MOZ_ASSERT(jsdval);
23 MOZ_ASSERT(jsdval->nref > 0);
24 if(!JS_CLIST_IS_EMPTY(&jsdval->props))
25 {
26 MOZ_ASSERT(CHECK_BIT_FLAG(jsdval->flags, GOT_PROPS));
27 MOZ_ASSERT(!JSVAL_IS_PRIMITIVE(jsdval->val));
28 }
30 if(jsdval->proto)
31 {
32 MOZ_ASSERT(CHECK_BIT_FLAG(jsdval->flags, GOT_PROTO));
33 MOZ_ASSERT(jsdval->proto->nref > 0);
34 }
35 if(jsdval->parent)
36 {
37 MOZ_ASSERT(CHECK_BIT_FLAG(jsdval->flags, GOT_PARENT));
38 MOZ_ASSERT(jsdval->parent->nref > 0);
39 }
40 if(jsdval->ctor)
41 {
42 MOZ_ASSERT(CHECK_BIT_FLAG(jsdval->flags, GOT_CTOR));
43 MOZ_ASSERT(jsdval->ctor->nref > 0);
44 }
45 }
47 void JSD_ASSERT_VALID_PROPERTY(JSDProperty* jsdprop)
48 {
49 MOZ_ASSERT(jsdprop);
50 MOZ_ASSERT(jsdprop->name);
51 MOZ_ASSERT(jsdprop->name->nref > 0);
52 MOZ_ASSERT(jsdprop->val);
53 MOZ_ASSERT(jsdprop->val->nref > 0);
54 if(jsdprop->alias)
55 MOZ_ASSERT(jsdprop->alias->nref > 0);
56 }
57 #endif
60 bool
61 jsd_IsValueObject(JSDContext* jsdc, JSDValue* jsdval)
62 {
63 return !JSVAL_IS_PRIMITIVE(jsdval->val) || JSVAL_IS_NULL(jsdval->val);
64 }
66 bool
67 jsd_IsValueNumber(JSDContext* jsdc, JSDValue* jsdval)
68 {
69 return JSVAL_IS_NUMBER(jsdval->val);
70 }
72 bool
73 jsd_IsValueInt(JSDContext* jsdc, JSDValue* jsdval)
74 {
75 return JSVAL_IS_INT(jsdval->val);
76 }
78 bool
79 jsd_IsValueDouble(JSDContext* jsdc, JSDValue* jsdval)
80 {
81 return JSVAL_IS_DOUBLE(jsdval->val);
82 }
84 bool
85 jsd_IsValueString(JSDContext* jsdc, JSDValue* jsdval)
86 {
87 return JSVAL_IS_STRING(jsdval->val);
88 }
90 bool
91 jsd_IsValueBoolean(JSDContext* jsdc, JSDValue* jsdval)
92 {
93 return JSVAL_IS_BOOLEAN(jsdval->val);
94 }
96 bool
97 jsd_IsValueNull(JSDContext* jsdc, JSDValue* jsdval)
98 {
99 return JSVAL_IS_NULL(jsdval->val);
100 }
102 bool
103 jsd_IsValueVoid(JSDContext* jsdc, JSDValue* jsdval)
104 {
105 return JSVAL_IS_VOID(jsdval->val);
106 }
108 bool
109 jsd_IsValuePrimitive(JSDContext* jsdc, JSDValue* jsdval)
110 {
111 return JSVAL_IS_PRIMITIVE(jsdval->val);
112 }
114 bool
115 jsd_IsValueFunction(JSDContext* jsdc, JSDValue* jsdval)
116 {
117 AutoSafeJSContext cx; // NB: Actually unused.
118 return !JSVAL_IS_PRIMITIVE(jsdval->val) &&
119 JS_ObjectIsCallable(cx, JSVAL_TO_OBJECT(jsdval->val));
120 }
122 bool
123 jsd_IsValueNative(JSDContext* jsdc, JSDValue* jsdval)
124 {
125 AutoSafeJSContext cx;
126 JS::RootedFunction fun(cx);
128 if(jsd_IsValueFunction(jsdc, jsdval))
129 {
130 JSAutoCompartment ac(cx, JSVAL_TO_OBJECT(jsdval->val));
131 AutoSaveExceptionState as(cx);
132 bool ok = false;
133 fun = JSD_GetValueFunction(jsdc, jsdval);
134 if(fun)
135 ok = JS_GetFunctionScript(cx, fun) ? false : true;
136 MOZ_ASSERT(fun);
137 return ok;
138 }
139 return !JSVAL_IS_PRIMITIVE(jsdval->val);
140 }
142 /***************************************************************************/
144 bool
145 jsd_GetValueBoolean(JSDContext* jsdc, JSDValue* jsdval)
146 {
147 jsval val = jsdval->val;
148 if(!JSVAL_IS_BOOLEAN(val))
149 return false;
150 return JSVAL_TO_BOOLEAN(val);
151 }
153 int32_t
154 jsd_GetValueInt(JSDContext* jsdc, JSDValue* jsdval)
155 {
156 jsval val = jsdval->val;
157 if(!JSVAL_IS_INT(val))
158 return 0;
159 return JSVAL_TO_INT(val);
160 }
162 double
163 jsd_GetValueDouble(JSDContext* jsdc, JSDValue* jsdval)
164 {
165 if(!JSVAL_IS_DOUBLE(jsdval->val))
166 return 0;
167 return JSVAL_TO_DOUBLE(jsdval->val);
168 }
170 JSString*
171 jsd_GetValueString(JSDContext* jsdc, JSDValue* jsdval)
172 {
173 AutoSafeJSContext cx;
174 JS::RootedValue stringval(cx);
175 JS::RootedString string(cx);
176 JS::RootedObject scopeObj(cx);
178 if(jsdval->string)
179 return jsdval->string;
181 /* Reuse the string without copying or re-rooting it */
182 if(JSVAL_IS_STRING(jsdval->val)) {
183 jsdval->string = JSVAL_TO_STRING(jsdval->val);
184 return jsdval->string;
185 }
187 /* Objects call JS_ValueToString in their own compartment. */
188 scopeObj = !JSVAL_IS_PRIMITIVE(jsdval->val) ? JSVAL_TO_OBJECT(jsdval->val) : jsdc->glob;
189 {
190 JSAutoCompartment ac(cx, scopeObj);
191 AutoSaveExceptionState as(cx);
192 JS::RootedValue v(cx, jsdval->val);
193 string = JS::ToString(cx, v);
194 }
196 JSAutoCompartment ac2(cx, jsdc->glob);
197 if(string) {
198 stringval = STRING_TO_JSVAL(string);
199 }
200 if(!string || !JS_WrapValue(cx, &stringval)) {
201 return nullptr;
202 }
204 jsdval->string = JSVAL_TO_STRING(stringval);
205 if(!JS::AddNamedStringRoot(cx, &jsdval->string, "ValueString"))
206 jsdval->string = nullptr;
208 return jsdval->string;
209 }
211 JSString*
212 jsd_GetValueFunctionId(JSDContext* jsdc, JSDValue* jsdval)
213 {
214 AutoSafeJSContext cx;
215 JS::RootedFunction fun(cx);
217 if(!jsdval->funName && jsd_IsValueFunction(jsdc, jsdval))
218 {
219 JSAutoCompartment ac(cx, JSVAL_TO_OBJECT(jsdval->val));
220 AutoSaveExceptionState as(cx);
221 fun = JSD_GetValueFunction(jsdc, jsdval);
222 if(!fun)
223 return nullptr;
224 jsdval->funName = JS_GetFunctionId(fun);
226 /* For compatibility we return "anonymous", not an empty string here. */
227 if (!jsdval->funName)
228 jsdval->funName = JS_GetAnonymousString(jsdc->jsrt);
229 }
230 return jsdval->funName;
231 }
233 /***************************************************************************/
235 /*
236 * Create a new JSD value referring to a jsval. Copy string values into the
237 * JSD compartment. Leave all other GCTHINGs in their native compartments
238 * and access them through cross-compartment calls.
239 */
240 JSDValue*
241 jsd_NewValue(JSDContext* jsdc, jsval value)
242 {
243 JS::RootedValue val(jsdc->jsrt, value);
244 AutoSafeJSContext cx;
245 JSDValue* jsdval;
247 if(!(jsdval = (JSDValue*) calloc(1, sizeof(JSDValue))))
248 return nullptr;
250 if(JSVAL_IS_GCTHING(val))
251 {
252 bool ok;
253 JSAutoCompartment ac(cx, jsdc->glob);
255 ok = JS::AddNamedValueRoot(cx, &jsdval->val, "JSDValue");
256 if(ok && JSVAL_IS_STRING(val)) {
257 if(!JS_WrapValue(cx, &val)) {
258 ok = false;
259 }
260 }
262 if(!ok)
263 {
264 free(jsdval);
265 return nullptr;
266 }
267 }
268 jsdval->val = val;
269 jsdval->nref = 1;
270 JS_INIT_CLIST(&jsdval->props);
272 return jsdval;
273 }
275 void
276 jsd_DropValue(JSDContext* jsdc, JSDValue* jsdval)
277 {
278 MOZ_ASSERT(jsdval->nref > 0);
279 if(0 == --jsdval->nref)
280 {
281 jsd_RefreshValue(jsdc, jsdval);
282 if(JSVAL_IS_GCTHING(jsdval->val))
283 {
284 AutoSafeJSContext cx;
285 JSAutoCompartment ac(cx, jsdc->glob);
286 JS::RemoveValueRoot(cx, &jsdval->val);
287 }
288 free(jsdval);
289 }
290 }
292 jsval
293 jsd_GetValueWrappedJSVal(JSDContext* jsdc, JSDValue* jsdval)
294 {
295 AutoSafeJSContext cx;
296 JS::RootedValue val(cx, jsdval->val);
297 if (!val.isPrimitive()) {
298 JS::RootedObject obj(cx, &val.toObject());
299 JSAutoCompartment ac(cx, obj);
300 obj = JS_ObjectToOuterObject(cx, obj);
301 if (!obj)
302 {
303 JS_ClearPendingException(cx);
304 val = JSVAL_NULL;
305 }
306 else
307 val = JS::ObjectValue(*obj);
308 }
310 return val;
311 }
313 static JSDProperty* _newProperty(JSDContext* jsdc, JS::HandleValue propId,
314 JS::HandleValue propValue, JS::HandleValue propAlias,
315 uint8_t propFlags, unsigned additionalFlags)
316 {
317 JSDProperty* jsdprop;
319 if(!(jsdprop = (JSDProperty*) calloc(1, sizeof(JSDProperty))))
320 return nullptr;
322 JS_INIT_CLIST(&jsdprop->links);
323 jsdprop->nref = 1;
324 jsdprop->flags = propFlags | additionalFlags;
326 if(!(jsdprop->name = jsd_NewValue(jsdc, propId)))
327 goto new_prop_fail;
329 if(!(jsdprop->val = jsd_NewValue(jsdc, propValue)))
330 goto new_prop_fail;
332 if((jsdprop->flags & JSDPD_ALIAS) &&
333 !(jsdprop->alias = jsd_NewValue(jsdc, propAlias)))
334 goto new_prop_fail;
336 return jsdprop;
337 new_prop_fail:
338 jsd_DropProperty(jsdc, jsdprop);
339 return nullptr;
340 }
342 static void _freeProps(JSDContext* jsdc, JSDValue* jsdval)
343 {
344 JSDProperty* jsdprop;
346 while(jsdprop = (JSDProperty*)jsdval->props.next,
347 jsdprop != (JSDProperty*)&jsdval->props)
348 {
349 JS_REMOVE_AND_INIT_LINK(&jsdprop->links);
350 jsd_DropProperty(jsdc, jsdprop);
351 }
352 MOZ_ASSERT(JS_CLIST_IS_EMPTY(&jsdval->props));
353 CLEAR_BIT_FLAG(jsdval->flags, GOT_PROPS);
354 }
356 static bool _buildProps(JSDContext* jsdc, JSDValue* jsdval)
357 {
358 AutoSafeJSContext cx;
359 JS::RootedObject obj(cx);
360 JSPropertyDescArray pda;
361 unsigned i;
363 MOZ_ASSERT(JS_CLIST_IS_EMPTY(&jsdval->props));
364 MOZ_ASSERT(!(CHECK_BIT_FLAG(jsdval->flags, GOT_PROPS)));
365 MOZ_ASSERT(!JSVAL_IS_PRIMITIVE(jsdval->val));
367 if(JSVAL_IS_PRIMITIVE(jsdval->val))
368 return false;
370 obj = JSVAL_TO_OBJECT(jsdval->val);
372 JSAutoCompartment ac(cx, obj);
374 if(!JS_GetPropertyDescArray(cx, obj, &pda))
375 {
376 return false;
377 }
379 JS::RootedValue propId(cx);
380 JS::RootedValue propValue(cx);
381 JS::RootedValue propAlias(cx);
382 uint8_t propFlags;
383 for(i = 0; i < pda.length; i++)
384 {
385 propId = pda.array[i].id;
386 propValue = pda.array[i].value;
387 propAlias = pda.array[i].alias;
388 propFlags = pda.array[i].flags;
389 JSDProperty* prop = _newProperty(jsdc, propId, propValue, propAlias, propFlags, 0);
390 if(!prop)
391 {
392 _freeProps(jsdc, jsdval);
393 break;
394 }
395 JS_APPEND_LINK(&prop->links, &jsdval->props);
396 }
397 JS_PutPropertyDescArray(cx, &pda);
398 SET_BIT_FLAG(jsdval->flags, GOT_PROPS);
399 return !JS_CLIST_IS_EMPTY(&jsdval->props);
400 }
402 #undef DROP_CLEAR_VALUE
403 #define DROP_CLEAR_VALUE(jsdc, x) if(x){jsd_DropValue(jsdc,x); x = nullptr;}
405 void
406 jsd_RefreshValue(JSDContext* jsdc, JSDValue* jsdval)
407 {
408 AutoSafeJSContext cx;
409 if(jsdval->string)
410 {
411 /* if the jsval is a string, then we didn't need to root the string */
412 if(!JSVAL_IS_STRING(jsdval->val))
413 {
414 JSAutoCompartment ac(cx, jsdc->glob);
415 JS::RemoveStringRoot(cx, &jsdval->string);
416 }
417 jsdval->string = nullptr;
418 }
420 jsdval->funName = nullptr;
421 jsdval->className = nullptr;
422 DROP_CLEAR_VALUE(jsdc, jsdval->proto);
423 DROP_CLEAR_VALUE(jsdc, jsdval->parent);
424 DROP_CLEAR_VALUE(jsdc, jsdval->ctor);
425 _freeProps(jsdc, jsdval);
426 jsdval->flags = 0;
427 }
429 /***************************************************************************/
431 unsigned
432 jsd_GetCountOfProperties(JSDContext* jsdc, JSDValue* jsdval)
433 {
434 JSDProperty* jsdprop;
435 unsigned count = 0;
437 if(!(CHECK_BIT_FLAG(jsdval->flags, GOT_PROPS)))
438 if(!_buildProps(jsdc, jsdval))
439 return 0;
441 for(jsdprop = (JSDProperty*)jsdval->props.next;
442 jsdprop != (JSDProperty*)&jsdval->props;
443 jsdprop = (JSDProperty*)jsdprop->links.next)
444 {
445 count++;
446 }
447 return count;
448 }
450 JSDProperty*
451 jsd_IterateProperties(JSDContext* jsdc, JSDValue* jsdval, JSDProperty **iterp)
452 {
453 JSDProperty* jsdprop = *iterp;
454 if(!(CHECK_BIT_FLAG(jsdval->flags, GOT_PROPS)))
455 {
456 MOZ_ASSERT(!jsdprop);
457 if(!_buildProps(jsdc, jsdval))
458 return nullptr;
459 }
461 if(!jsdprop)
462 jsdprop = (JSDProperty*)jsdval->props.next;
463 if(jsdprop == (JSDProperty*)&jsdval->props)
464 return nullptr;
465 *iterp = (JSDProperty*)jsdprop->links.next;
467 MOZ_ASSERT(jsdprop);
468 jsdprop->nref++;
469 return jsdprop;
470 }
472 JSDProperty*
473 jsd_GetValueProperty(JSDContext* jsdc, JSDValue* jsdval, JSString* nameStr)
474 {
475 JS::RootedString name(jsdc->jsrt, nameStr);
476 AutoSafeJSContext cx;
477 JSAutoCompartment acBase(cx, jsdc->glob);
478 JSDProperty* jsdprop;
479 JSDProperty* iter = nullptr;
480 JS::RootedObject obj(cx);
481 JS::RootedValue val(cx), nameval(cx);
482 JS::RootedId nameid(cx);
483 JS::RootedValue propId(cx);
484 JS::RootedValue propValue(cx);
485 JS::RootedValue propAlias(cx);
486 uint8_t propFlags;
488 if(!jsd_IsValueObject(jsdc, jsdval))
489 return nullptr;
491 /* If we already have the prop, then return it */
492 while(nullptr != (jsdprop = jsd_IterateProperties(jsdc, jsdval, &iter)))
493 {
494 JSString* propName = jsd_GetValueString(jsdc, jsdprop->name);
495 if(propName) {
496 int result;
497 if (JS_CompareStrings(cx, propName, name, &result) && !result)
498 return jsdprop;
499 }
500 JSD_DropProperty(jsdc, jsdprop);
501 }
502 /* Not found in property list, look it up explicitly */
504 nameval = STRING_TO_JSVAL(name);
505 if(!JS_ValueToId(cx, nameval, &nameid))
506 return nullptr;
508 if(!(obj = JSVAL_TO_OBJECT(jsdval->val)))
509 return nullptr;
511 JS::Rooted<JSPropertyDescriptor> desc(cx);
512 {
513 JSAutoCompartment ac(cx, obj);
514 JS::RootedId id(cx, nameid);
516 if(!JS_WrapId(cx, &id))
517 return nullptr;
518 if(!JS_GetOwnPropertyDescriptorById(cx, obj, id, &desc))
519 return nullptr;
520 if(!desc.object())
521 return nullptr;
523 JS_ClearPendingException(cx);
525 if(!JS_GetPropertyById(cx, obj, id, &val))
526 {
527 if (JS_IsExceptionPending(cx))
528 {
529 if (!JS_GetPendingException(cx, &propValue))
530 {
531 return nullptr;
532 }
533 propFlags = JSPD_EXCEPTION;
534 }
535 else
536 {
537 propFlags = JSPD_ERROR;
538 propValue = JSVAL_VOID;
539 }
540 }
541 else
542 {
543 propValue = val;
544 }
545 }
547 if (!JS_IdToValue(cx, nameid, &propId))
548 return nullptr;
550 propAlias = JSVAL_NULL;
551 propFlags |= desc.isEnumerable() ? JSPD_ENUMERATE : 0
552 | desc.isReadonly() ? JSPD_READONLY : 0
553 | desc.isPermanent() ? JSPD_PERMANENT : 0;
555 return _newProperty(jsdc, propId, propValue, propAlias, propFlags, JSDPD_HINTED);
556 }
558 /*
559 * Retrieve a JSFunction* from a JSDValue*. This differs from
560 * JS_ValueToFunction by fully unwrapping the object first.
561 */
562 JSFunction*
563 jsd_GetValueFunction(JSDContext* jsdc, JSDValue* jsdval)
564 {
565 AutoSafeJSContext cx;
567 JS::RootedObject obj(cx);
568 JS::RootedFunction fun(cx);
570 if (JSVAL_IS_PRIMITIVE(jsdval->val))
571 return nullptr;
573 obj = js::UncheckedUnwrap(JSVAL_TO_OBJECT(jsdval->val));
574 JSAutoCompartment ac(cx, obj);
575 JS::RootedValue funval(cx, JS::ObjectValue(*obj));
576 fun = JS_ValueToFunction(cx, funval);
578 return fun;
579 }
581 JSDValue*
582 jsd_GetValuePrototype(JSDContext* jsdc, JSDValue* jsdval)
583 {
584 AutoSafeJSContext cx;
585 if(!(CHECK_BIT_FLAG(jsdval->flags, GOT_PROTO)))
586 {
587 JS::RootedObject obj(cx);
588 JS::RootedObject proto(cx);
589 MOZ_ASSERT(!jsdval->proto);
590 SET_BIT_FLAG(jsdval->flags, GOT_PROTO);
591 if(JSVAL_IS_PRIMITIVE(jsdval->val))
592 return nullptr;
593 obj = JSVAL_TO_OBJECT(jsdval->val);
594 if(!JS_GetPrototype(cx, obj, &proto))
595 return nullptr;
596 if(!proto)
597 return nullptr;
598 jsdval->proto = jsd_NewValue(jsdc, OBJECT_TO_JSVAL(proto));
599 }
600 if(jsdval->proto)
601 jsdval->proto->nref++;
602 return jsdval->proto;
603 }
605 JSDValue*
606 jsd_GetValueParent(JSDContext* jsdc, JSDValue* jsdval)
607 {
608 if(!(CHECK_BIT_FLAG(jsdval->flags, GOT_PARENT)))
609 {
610 AutoSafeJSContext cx;
611 JS::RootedObject obj(cx);
612 JS::RootedObject parent(cx);
613 MOZ_ASSERT(!jsdval->parent);
614 SET_BIT_FLAG(jsdval->flags, GOT_PARENT);
615 if(JSVAL_IS_PRIMITIVE(jsdval->val))
616 return nullptr;
617 obj = JSVAL_TO_OBJECT(jsdval->val);
618 {
619 JSAutoCompartment ac(cx, obj);
620 parent = JS_GetParentOrScopeChain(cx, obj);
621 }
622 if(!parent)
623 return nullptr;
624 jsdval->parent = jsd_NewValue(jsdc, OBJECT_TO_JSVAL(parent));
625 }
626 if(jsdval->parent)
627 jsdval->parent->nref++;
628 return jsdval->parent;
629 }
631 JSDValue*
632 jsd_GetValueConstructor(JSDContext* jsdc, JSDValue* jsdval)
633 {
634 if(!(CHECK_BIT_FLAG(jsdval->flags, GOT_CTOR)))
635 {
636 AutoSafeJSContext cx;
637 JS::RootedObject obj(cx);
638 JS::RootedObject proto(cx);
639 JS::RootedObject ctor(cx);
640 MOZ_ASSERT(!jsdval->ctor);
641 SET_BIT_FLAG(jsdval->flags, GOT_CTOR);
642 if(JSVAL_IS_PRIMITIVE(jsdval->val))
643 return nullptr;
644 obj = JSVAL_TO_OBJECT(jsdval->val);
645 if(!JS_GetPrototype(cx, obj, &proto))
646 return nullptr;
647 if(!proto)
648 return nullptr;
649 {
650 JSAutoCompartment ac(cx, obj);
651 ctor = JS_GetConstructor(cx, proto);
652 }
653 if(!ctor)
654 return nullptr;
655 jsdval->ctor = jsd_NewValue(jsdc, OBJECT_TO_JSVAL(ctor));
656 }
657 if(jsdval->ctor)
658 jsdval->ctor->nref++;
659 return jsdval->ctor;
660 }
662 const char*
663 jsd_GetValueClassName(JSDContext* jsdc, JSDValue* jsdval)
664 {
665 jsval val = jsdval->val;
666 if(!jsdval->className && !JSVAL_IS_PRIMITIVE(val))
667 {
668 JS::RootedObject obj(jsdc->jsrt, JSVAL_TO_OBJECT(val));
669 AutoSafeJSContext cx;
670 JSAutoCompartment ac(cx, obj);
671 jsdval->className = JS_GetDebugClassName(obj);
672 }
673 return jsdval->className;
674 }
676 JSDScript*
677 jsd_GetScriptForValue(JSDContext* jsdc, JSDValue* jsdval)
678 {
679 AutoSafeJSContext cx;
680 JS::RootedValue val(cx, jsdval->val);
681 JS::RootedScript script(cx);
682 JSDScript* jsdscript;
684 if (!jsd_IsValueFunction(jsdc, jsdval))
685 return nullptr;
687 {
688 JSAutoCompartment ac(cx, JSVAL_TO_OBJECT(val));
689 AutoSaveExceptionState as(cx);
690 JS::RootedFunction fun(cx, JSD_GetValueFunction(jsdc, jsdval));
691 if (fun)
692 script = JS_GetFunctionScript(cx, fun);
693 }
695 if (!script)
696 return nullptr;
698 JSD_LOCK_SCRIPTS(jsdc);
699 jsdscript = jsd_FindJSDScript(jsdc, script);
700 JSD_UNLOCK_SCRIPTS(jsdc);
701 return jsdscript;
702 }
705 /***************************************************************************/
706 /***************************************************************************/
708 JSDValue*
709 jsd_GetPropertyName(JSDContext* jsdc, JSDProperty* jsdprop)
710 {
711 jsdprop->name->nref++;
712 return jsdprop->name;
713 }
715 JSDValue*
716 jsd_GetPropertyValue(JSDContext* jsdc, JSDProperty* jsdprop)
717 {
718 jsdprop->val->nref++;
719 return jsdprop->val;
720 }
722 JSDValue*
723 jsd_GetPropertyAlias(JSDContext* jsdc, JSDProperty* jsdprop)
724 {
725 if(jsdprop->alias)
726 jsdprop->alias->nref++;
727 return jsdprop->alias;
728 }
730 unsigned
731 jsd_GetPropertyFlags(JSDContext* jsdc, JSDProperty* jsdprop)
732 {
733 return jsdprop->flags;
734 }
736 void
737 jsd_DropProperty(JSDContext* jsdc, JSDProperty* jsdprop)
738 {
739 MOZ_ASSERT(jsdprop->nref > 0);
740 if(0 == --jsdprop->nref)
741 {
742 MOZ_ASSERT(JS_CLIST_IS_EMPTY(&jsdprop->links));
743 DROP_CLEAR_VALUE(jsdc, jsdprop->val);
744 DROP_CLEAR_VALUE(jsdc, jsdprop->name);
745 DROP_CLEAR_VALUE(jsdc, jsdprop->alias);
746 free(jsdprop);
747 }
748 }