1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * vim: set ts=8 sw=4 et tw=78:
4 * ***** BEGIN LICENSE BLOCK *****
5 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
7 * The contents of this file are subject to the Mozilla Public License Version
8 * 1.1 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://www.mozilla.org/MPL/
12 * Software distributed under the License is distributed on an "AS IS" basis,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 * for the specific language governing rights and limitations under the
17 * The Original Code is Mozilla Communicator client code, released
20 * The Initial Developer of the Original Code is
21 * Netscape Communications Corporation.
22 * Portions created by the Initial Developer are Copyright (C) 1998
23 * the Initial Developer. All Rights Reserved.
27 * Alternatively, the contents of this file may be used under the terms of
28 * either of the GNU General Public License Version 2 or later (the "GPL"),
29 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30 * in which case the provisions of the GPL or the LGPL are applicable instead
31 * of those above. If you wish to allow use of your version of this file only
32 * under the terms of either the GPL or the LGPL, and not to allow others to
33 * use your version of this file under the terms of the MPL, indicate your
34 * decision by deleting the provisions above and replace them with the notice
35 * and other provisions required by the GPL or the LGPL. If you do not delete
36 * the provisions above, a recipient may use your version of this file under
37 * the terms of any one of the MPL, the GPL or the LGPL.
39 * ***** END LICENSE BLOCK ***** */
59 #include "jsbuiltins.h"
62 #include "jsversion.h"
86 #include "jsstaticcheck.h"
88 #include "jswrapper.h"
89 #include "jstypedarray.h"
91 #include "jsatominlines.h"
92 #include "jscntxtinlines.h"
93 #include "jsinterpinlines.h"
94 #include "jsobjinlines.h"
95 #include "jsscopeinlines.h"
96 #include "jscntxtinlines.h"
97 #include "jsregexpinlines.h"
98 #include "assembler/wtf/Platform.h"
101 #include "assembler/jit/ExecutableAllocator.h"
102 #include "methodjit/Logging.h"
105 #if JS_HAS_XML_SUPPORT
110 using namespace js::gc
;
114 JSContext
* const cx
;
115 JSVersion oldVersion
;
116 bool oldVersionWasOverride
;
120 explicit AutoVersionAPI(JSContext
*cx
, JSVersion newVersion
)
121 : cx(cx
), oldVersion(cx
->findVersion()), oldVersionWasOverride(cx
->isVersionOverridden()),
122 oldOptions(cx
->options
) {
123 JS_ASSERT(!VersionExtractFlags(newVersion
) ||
124 VersionExtractFlags(newVersion
) == VersionFlags::HAS_XML
);
125 cx
->options
= VersionHasXML(newVersion
)
126 ? (cx
->options
| JSOPTION_XML
)
127 : (cx
->options
& ~JSOPTION_XML
);
128 cx
->maybeOverrideVersion(newVersion
);
129 SyncOptionsToVersion(cx
);
133 cx
->options
= oldOptions
;
134 if (oldVersionWasOverride
) {
135 JS_ALWAYS_TRUE(cx
->maybeOverrideVersion(oldVersion
));
137 cx
->clearVersionOverride();
138 cx
->setDefaultVersion(oldVersion
);
140 JS_ASSERT(cx
->findVersion() == oldVersion
);
144 #ifdef HAVE_VA_LIST_AS_ARRAY
145 #define JS_ADDRESSOF_VA_LIST(ap) ((va_list *)(ap))
147 #define JS_ADDRESSOF_VA_LIST(ap) (&(ap))
150 #ifdef JS_USE_JSVAL_JSID_STRUCT_TYPES
151 JS_PUBLIC_DATA(jsid
) JS_DEFAULT_XML_NAMESPACE_ID
= { size_t(JSID_TYPE_DEFAULT_XML_NAMESPACE
) };
152 JS_PUBLIC_DATA(jsid
) JSID_VOID
= { size_t(JSID_TYPE_VOID
) };
153 JS_PUBLIC_DATA(jsid
) JSID_EMPTY
= { size_t(JSID_TYPE_OBJECT
) };
156 #ifdef JS_USE_JSVAL_JSID_STRUCT_TYPES
157 JS_PUBLIC_DATA(jsval
) JSVAL_NULL
= { BUILD_JSVAL(JSVAL_TAG_NULL
, 0) };
158 JS_PUBLIC_DATA(jsval
) JSVAL_ZERO
= { BUILD_JSVAL(JSVAL_TAG_INT32
, 0) };
159 JS_PUBLIC_DATA(jsval
) JSVAL_ONE
= { BUILD_JSVAL(JSVAL_TAG_INT32
, 1) };
160 JS_PUBLIC_DATA(jsval
) JSVAL_FALSE
= { BUILD_JSVAL(JSVAL_TAG_BOOLEAN
, JS_FALSE
) };
161 JS_PUBLIC_DATA(jsval
) JSVAL_TRUE
= { BUILD_JSVAL(JSVAL_TAG_BOOLEAN
, JS_TRUE
) };
162 JS_PUBLIC_DATA(jsval
) JSVAL_VOID
= { BUILD_JSVAL(JSVAL_TAG_UNDEFINED
, 0) };
165 /* Make sure that jschar is two bytes unsigned integer */
166 JS_STATIC_ASSERT((jschar
)-1 > 0);
167 JS_STATIC_ASSERT(sizeof(jschar
) == 2);
176 JS_GetNaNValue(JSContext
*cx
)
178 return Jsvalify(cx
->runtime
->NaNValue
);
182 JS_GetNegativeInfinityValue(JSContext
*cx
)
184 return Jsvalify(cx
->runtime
->negativeInfinityValue
);
188 JS_GetPositiveInfinityValue(JSContext
*cx
)
190 return Jsvalify(cx
->runtime
->positiveInfinityValue
);
194 JS_GetEmptyStringValue(JSContext
*cx
)
196 return STRING_TO_JSVAL(cx
->runtime
->emptyString
);
200 TryArgumentFormatter(JSContext
*cx
, const char **formatp
, JSBool fromJS
, jsval
**vpp
, va_list *app
)
203 JSArgumentFormatMap
*map
;
206 for (map
= cx
->argumentFormatMap
; map
; map
= map
->next
) {
207 if (!strncmp(format
, map
->format
, map
->length
)) {
208 *formatp
= format
+ map
->length
;
209 return map
->formatter(cx
, format
, fromJS
, vpp
, app
);
212 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_BAD_CHAR
, format
);
216 JS_PUBLIC_API(JSBool
)
217 JS_ConvertArguments(JSContext
*cx
, uintN argc
, jsval
*argv
, const char *format
, ...)
222 va_start(ap
, format
);
223 ok
= JS_ConvertArgumentsVA(cx
, argc
, argv
, format
, ap
);
228 JS_PUBLIC_API(JSBool
)
229 JS_ConvertArgumentsVA(JSContext
*cx
, uintN argc
, jsval
*argv
, const char *format
, va_list ap
)
240 assertSameCompartment(cx
, JSValueArray(argv
- 2, argc
+ 2));
243 while ((c
= *format
++) != '\0') {
250 if (sp
== argv
+ argc
) {
252 fun
= js_ValueToFunction(cx
, Valueify(&argv
[-2]), 0);
255 JS_snprintf(numBuf
, sizeof numBuf
, "%u", argc
);
256 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
,
257 JSMSG_MORE_ARGS_NEEDED
,
258 JS_GetFunctionName(fun
), numBuf
,
259 (argc
== 1) ? "" : "s");
267 *va_arg(ap
, JSBool
*) = js_ValueToBoolean(Valueify(*sp
));
270 if (!JS_ValueToUint16(cx
, *sp
, va_arg(ap
, uint16
*)))
274 if (!JS_ValueToECMAInt32(cx
, *sp
, va_arg(ap
, int32
*)))
278 if (!JS_ValueToECMAUint32(cx
, *sp
, va_arg(ap
, uint32
*)))
282 if (!JS_ValueToInt32(cx
, *sp
, va_arg(ap
, int32
*)))
286 if (!JS_ValueToNumber(cx
, *sp
, va_arg(ap
, jsdouble
*)))
290 if (!JS_ValueToNumber(cx
, *sp
, &d
))
292 *va_arg(ap
, jsdouble
*) = js_DoubleToInteger(d
);
297 str
= js_ValueToString(cx
, Valueify(*sp
));
300 *sp
= STRING_TO_JSVAL(str
);
302 const char *bytes
= js_GetStringBytes(cx
, str
);
305 *va_arg(ap
, const char **) = bytes
;
306 } else if (c
== 'W') {
307 const jschar
*chars
= js_GetStringChars(cx
, str
);
310 *va_arg(ap
, const jschar
**) = chars
;
312 *va_arg(ap
, JSString
**) = str
;
316 if (!js_ValueToObjectOrNull(cx
, Valueify(*sp
), &obj
))
318 *sp
= OBJECT_TO_JSVAL(obj
);
319 *va_arg(ap
, JSObject
**) = obj
;
322 obj
= js_ValueToFunctionObject(cx
, Valueify(sp
), 0);
325 *sp
= OBJECT_TO_JSVAL(obj
);
326 *va_arg(ap
, JSFunction
**) = GET_FUNCTION_PRIVATE(cx
, obj
);
329 *va_arg(ap
, jsval
*) = *sp
;
335 if (!TryArgumentFormatter(cx
, &format
, JS_TRUE
, &sp
,
336 JS_ADDRESSOF_VA_LIST(ap
))) {
339 /* NB: the formatter already updated sp, so we continue here. */
347 JS_PUBLIC_API(JSBool
)
348 JS_AddArgumentFormatter(JSContext
*cx
, const char *format
, JSArgumentFormatter formatter
)
351 JSArgumentFormatMap
**mpp
, *map
;
353 length
= strlen(format
);
354 mpp
= &cx
->argumentFormatMap
;
355 while ((map
= *mpp
) != NULL
) {
356 /* Insert before any shorter string to match before prefixes. */
357 if (map
->length
< length
)
359 if (map
->length
== length
&& !strcmp(map
->format
, format
))
363 map
= (JSArgumentFormatMap
*) cx
->malloc(sizeof *map
);
366 map
->format
= format
;
367 map
->length
= length
;
371 map
->formatter
= formatter
;
376 JS_RemoveArgumentFormatter(JSContext
*cx
, const char *format
)
379 JSArgumentFormatMap
**mpp
, *map
;
381 length
= strlen(format
);
382 mpp
= &cx
->argumentFormatMap
;
383 while ((map
= *mpp
) != NULL
) {
384 if (map
->length
== length
&& !strcmp(map
->format
, format
)) {
393 JS_PUBLIC_API(JSBool
)
394 JS_ConvertValue(JSContext
*cx
, jsval v
, JSType type
, jsval
*vp
)
402 assertSameCompartment(cx
, v
);
409 ok
= js_ValueToObjectOrNull(cx
, Valueify(v
), &obj
);
411 *vp
= OBJECT_TO_JSVAL(obj
);
413 case JSTYPE_FUNCTION
:
415 obj
= js_ValueToFunctionObject(cx
, Valueify(vp
), JSV2F_SEARCH_STACK
);
419 str
= js_ValueToString(cx
, Valueify(v
));
422 *vp
= STRING_TO_JSVAL(str
);
425 ok
= JS_ValueToNumber(cx
, v
, &d
);
427 *vp
= DOUBLE_TO_JSVAL(d
);
430 *vp
= BOOLEAN_TO_JSVAL(js_ValueToBoolean(Valueify(v
)));
434 JS_snprintf(numBuf
, sizeof numBuf
, "%d", (int)type
);
435 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_BAD_TYPE
, numBuf
);
443 JS_PUBLIC_API(JSBool
)
444 JS_ValueToObject(JSContext
*cx
, jsval v
, JSObject
**objp
)
447 assertSameCompartment(cx
, v
);
448 return js_ValueToObjectOrNull(cx
, Valueify(v
), objp
);
451 JS_PUBLIC_API(JSFunction
*)
452 JS_ValueToFunction(JSContext
*cx
, jsval v
)
455 assertSameCompartment(cx
, v
);
456 return js_ValueToFunction(cx
, Valueify(&v
), JSV2F_SEARCH_STACK
);
459 JS_PUBLIC_API(JSFunction
*)
460 JS_ValueToConstructor(JSContext
*cx
, jsval v
)
463 assertSameCompartment(cx
, v
);
464 return js_ValueToFunction(cx
, Valueify(&v
), JSV2F_SEARCH_STACK
);
467 JS_PUBLIC_API(JSString
*)
468 JS_ValueToString(JSContext
*cx
, jsval v
)
471 assertSameCompartment(cx
, v
);
472 return js_ValueToString(cx
, Valueify(v
));
475 JS_PUBLIC_API(JSString
*)
476 JS_ValueToSource(JSContext
*cx
, jsval v
)
479 assertSameCompartment(cx
, v
);
480 return js_ValueToSource(cx
, Valueify(v
));
483 JS_PUBLIC_API(JSBool
)
484 JS_ValueToNumber(JSContext
*cx
, jsval v
, jsdouble
*dp
)
487 assertSameCompartment(cx
, v
);
489 AutoValueRooter
tvr(cx
, Valueify(v
));
490 return ValueToNumber(cx
, tvr
.value(), dp
);
493 JS_PUBLIC_API(JSBool
)
494 JS_DoubleIsInt32(jsdouble d
, jsint
*ip
)
496 return JSDOUBLE_IS_INT32(d
, (int32_t *)ip
);
499 JS_PUBLIC_API(JSBool
)
500 JS_ValueToECMAInt32(JSContext
*cx
, jsval v
, int32
*ip
)
503 assertSameCompartment(cx
, v
);
505 AutoValueRooter
tvr(cx
, Valueify(v
));
506 return ValueToECMAInt32(cx
, tvr
.value(), (int32_t *)ip
);
509 JS_PUBLIC_API(JSBool
)
510 JS_ValueToECMAUint32(JSContext
*cx
, jsval v
, uint32
*ip
)
513 assertSameCompartment(cx
, v
);
515 AutoValueRooter
tvr(cx
, Valueify(v
));
516 return ValueToECMAUint32(cx
, tvr
.value(), (uint32_t *)ip
);
519 JS_PUBLIC_API(JSBool
)
520 JS_ValueToInt32(JSContext
*cx
, jsval v
, int32
*ip
)
523 assertSameCompartment(cx
, v
);
525 AutoValueRooter
tvr(cx
, Valueify(v
));
526 return ValueToInt32(cx
, tvr
.value(), (int32_t *)ip
);
529 JS_PUBLIC_API(JSBool
)
530 JS_ValueToUint16(JSContext
*cx
, jsval v
, uint16
*ip
)
533 assertSameCompartment(cx
, v
);
535 AutoValueRooter
tvr(cx
, Valueify(v
));
536 return ValueToUint16(cx
, tvr
.value(), (uint16_t *)ip
);
539 JS_PUBLIC_API(JSBool
)
540 JS_ValueToBoolean(JSContext
*cx
, jsval v
, JSBool
*bp
)
543 assertSameCompartment(cx
, v
);
544 *bp
= js_ValueToBoolean(Valueify(v
));
548 JS_PUBLIC_API(JSType
)
549 JS_TypeOfValue(JSContext
*cx
, jsval v
)
552 assertSameCompartment(cx
, v
);
553 return TypeOfValue(cx
, Valueify(v
));
556 JS_PUBLIC_API(const char *)
557 JS_GetTypeName(JSContext
*cx
, JSType type
)
559 if ((uintN
)type
>= (uintN
)JSTYPE_LIMIT
)
561 return JS_TYPE_STR(type
);
564 JS_PUBLIC_API(JSBool
)
565 JS_StrictlyEqual(JSContext
*cx
, jsval v1
, jsval v2
)
567 assertSameCompartment(cx
, v1
, v2
);
568 return StrictlyEqual(cx
, Valueify(v1
), Valueify(v2
));
571 JS_PUBLIC_API(JSBool
)
572 JS_SameValue(JSContext
*cx
, jsval v1
, jsval v2
)
574 assertSameCompartment(cx
, v1
, v2
);
575 return SameValue(Valueify(v1
), Valueify(v2
), cx
);
578 /************************************************************************/
581 * Has a new runtime ever been created? This flag is used to detect unsafe
582 * changes to js_CStringsAreUTF8 after a runtime has been created, and to
583 * ensure that "first checks" on runtime creation are run only once.
586 static JSBool js_NewRuntimeWasCalled
= JS_FALSE
;
589 JSRuntime::JSRuntime()
590 : gcChunkAllocator(&defaultGCChunkAllocator
)
592 /* Initialize infallibly first, so we can goto bad and JS_DestroyRuntime. */
593 JS_INIT_CLIST(&contextList
);
594 JS_INIT_CLIST(&trapList
);
595 JS_INIT_CLIST(&watchPointList
);
599 JSRuntime::init(uint32 maxbytes
)
601 #ifdef JS_METHODJIT_SPEW
606 functionMeterFilename
= getenv("JS_FUNCTION_STATFILE");
607 if (functionMeterFilename
) {
608 if (!methodReadBarrierCountMap
.init())
610 if (!unjoinedFunctionCountMap
.init())
613 propTreeStatFilename
= getenv("JS_PROPTREE_STATFILE");
614 propTreeDumpFilename
= getenv("JS_PROPTREE_DUMPFILE");
615 if (meterEmptyShapes()) {
616 if (!emptyShapes
.init())
621 if (!(defaultCompartment
= new JSCompartment(this)) ||
622 !defaultCompartment
->init() ||
623 !compartments
.append(defaultCompartment
)) {
627 if (!js_InitGC(this, maxbytes
) || !js_InitAtomState(this))
631 regExpAllocator
= JSC::ExecutableAllocator::create();
632 if (!regExpAllocator
)
636 deflatedStringCache
= new js::DeflatedStringCache();
637 if (!deflatedStringCache
|| !deflatedStringCache
->init())
640 wrapObjectCallback
= js::TransparentObjectWrapper
;
643 /* this is asymmetric with JS_ShutDown: */
644 if (!js_SetupLocks(8, 16))
646 rtLock
= JS_NEW_LOCK();
649 stateChange
= JS_NEW_CONDVAR(gcLock
);
652 debuggerLock
= JS_NEW_LOCK();
657 debugMode
= JS_FALSE
;
659 return propertyTree
.init() && js_InitThreads(this);
662 JSRuntime::~JSRuntime()
665 /* Don't hurt everyone in leaky ol' Mozilla with a fatal JS_ASSERT! */
666 if (!JS_CLIST_IS_EMPTY(&contextList
)) {
667 JSContext
*cx
, *iter
= NULL
;
669 while ((cx
= js_ContextIterator(this, JS_TRUE
, &iter
)) != NULL
) {
671 "JS API usage error: found live context at %p\n",
676 "JS API usage error: %u context%s left in runtime upon JS_DestroyRuntime.\n",
677 cxcount
, (cxcount
== 1) ? "" : "s");
681 js_FinishThreads(this);
682 js_FreeRuntimeScriptState(this);
683 js_FinishAtomState(this);
686 * Finish the deflated string cache after the last GC and after
687 * calling js_FinishAtomState, which finalizes strings.
689 delete deflatedStringCache
;
691 delete regExpAllocator
;
696 JS_DESTROY_LOCK(gcLock
);
698 JS_DESTROY_CONDVAR(gcDone
);
700 JS_DESTROY_CONDVAR(requestDone
);
702 JS_DESTROY_LOCK(rtLock
);
704 JS_DESTROY_CONDVAR(stateChange
);
706 JS_DESTROY_LOCK(debuggerLock
);
708 propertyTree
.finish();
711 JS_PUBLIC_API(JSRuntime
*)
712 JS_NewRuntime(uint32 maxbytes
)
715 if (!js_NewRuntimeWasCalled
) {
717 * This code asserts that the numbers associated with the error names
718 * in jsmsg.def are monotonically increasing. It uses values for the
719 * error names enumerated in jscntxt.c. It's not a compile-time check
720 * but it's better than nothing.
723 #define MSG_DEF(name, number, count, exception, format) \
724 JS_ASSERT(name == errorNumber++);
728 #define MSG_DEF(name, number, count, exception, format) \
730 uintN numfmtspecs = 0; \
732 for (fmt = format; *fmt != '\0'; fmt++) { \
733 if (*fmt == '{' && isdigit(fmt[1])) \
736 JS_ASSERT(count == numfmtspecs); \
741 js_NewRuntimeWasCalled
= JS_TRUE
;
745 void *mem
= js_calloc(sizeof(JSRuntime
));
749 JSRuntime
*rt
= new (mem
) JSRuntime();
750 if (!rt
->init(maxbytes
)) {
751 JS_DestroyRuntime(rt
);
759 JS_DestroyRuntime(JSRuntime
*rt
)
767 namespace reprmeter
{
768 extern void js_DumpReprMeter();
780 extern void js_DumpOpMeters();
785 reprmeter::js_DumpReprMeter();
794 JS_PUBLIC_API(void *)
795 JS_GetRuntimePrivate(JSRuntime
*rt
)
801 JS_SetRuntimePrivate(JSRuntime
*rt
, void *data
)
808 StartRequest(JSContext
*cx
)
810 JSThread
*t
= cx
->thread
;
811 JS_ASSERT(CURRENT_THREAD_IS_ME(t
));
813 if (t
->data
.requestDepth
) {
814 t
->data
.requestDepth
++;
816 JSRuntime
*rt
= cx
->runtime
;
819 /* Wait until the GC is finished. */
820 if (rt
->gcThread
!= cx
->thread
) {
822 JS_AWAIT_GC_DONE(rt
);
825 /* Indicate that a request is running. */
827 t
->data
.requestDepth
= 1;
830 * Adjust rt->interruptCounter to reflect any interrupts added while the
831 * thread was suspended.
833 if (t
->data
.interruptFlags
)
834 JS_ATOMIC_INCREMENT(&rt
->interruptCounter
);
836 if (rt
->requestCount
== 1 && rt
->activityCallback
)
837 rt
->activityCallback(rt
->activityCallbackArg
, true);
842 StopRequest(JSContext
*cx
)
844 JSThread
*t
= cx
->thread
;
845 JS_ASSERT(CURRENT_THREAD_IS_ME(t
));
846 JS_ASSERT(t
->data
.requestDepth
!= 0);
847 if (t
->data
.requestDepth
!= 1) {
848 t
->data
.requestDepth
--;
850 LeaveTrace(cx
); /* for GC safety */
852 t
->data
.conservativeGC
.updateForRequestEnd(t
->suspendCount
);
854 /* Lock before clearing to interlock with ClaimScope, in jslock.c. */
855 JSRuntime
*rt
= cx
->runtime
;
858 t
->data
.requestDepth
= 0;
861 * Adjust rt->interruptCounter to reflect any interrupts added while the
862 * thread still had active requests.
864 if (t
->data
.interruptFlags
)
865 JS_ATOMIC_DECREMENT(&rt
->interruptCounter
);
867 /* Give the GC a chance to run if this was the last request running. */
868 JS_ASSERT(rt
->requestCount
> 0);
870 if (rt
->requestCount
== 0) {
871 JS_NOTIFY_REQUEST_DONE(rt
);
872 if (rt
->activityCallback
)
873 rt
->activityCallback(rt
->activityCallbackArg
, false);
877 #endif /* JS_THREADSAFE */
880 JS_BeginRequest(JSContext
*cx
)
883 cx
->outstandingRequests
++;
889 JS_EndRequest(JSContext
*cx
)
892 JS_ASSERT(cx
->outstandingRequests
!= 0);
893 cx
->outstandingRequests
--;
898 /* Yield to pending GC operations, regardless of request depth */
900 JS_YieldRequest(JSContext
*cx
)
904 JS_ResumeRequest(cx
, JS_SuspendRequest(cx
));
908 JS_PUBLIC_API(jsrefcount
)
909 JS_SuspendRequest(JSContext
*cx
)
912 JSThread
*t
= cx
->thread
;
913 JS_ASSERT(CURRENT_THREAD_IS_ME(t
));
915 jsrefcount saveDepth
= t
->data
.requestDepth
;
920 t
->data
.requestDepth
= 1;
929 JS_ResumeRequest(JSContext
*cx
, jsrefcount saveDepth
)
932 JSThread
*t
= cx
->thread
;
933 JS_ASSERT(CURRENT_THREAD_IS_ME(t
));
936 JS_ASSERT(saveDepth
>= 1);
937 JS_ASSERT(!t
->data
.requestDepth
);
938 JS_ASSERT(t
->suspendCount
);
940 t
->data
.requestDepth
= saveDepth
;
946 JS_Lock(JSRuntime
*rt
)
952 JS_Unlock(JSRuntime
*rt
)
954 JS_UNLOCK_RUNTIME(rt
);
957 JS_PUBLIC_API(JSContextCallback
)
958 JS_SetContextCallback(JSRuntime
*rt
, JSContextCallback cxCallback
)
960 JSContextCallback old
;
962 old
= rt
->cxCallback
;
963 rt
->cxCallback
= cxCallback
;
967 JS_PUBLIC_API(JSContext
*)
968 JS_NewContext(JSRuntime
*rt
, size_t stackChunkSize
)
970 return js_NewContext(rt
, stackChunkSize
);
974 JS_DestroyContext(JSContext
*cx
)
976 js_DestroyContext(cx
, JSDCM_FORCE_GC
);
980 JS_DestroyContextNoGC(JSContext
*cx
)
982 js_DestroyContext(cx
, JSDCM_NO_GC
);
986 JS_DestroyContextMaybeGC(JSContext
*cx
)
988 js_DestroyContext(cx
, JSDCM_MAYBE_GC
);
991 JS_PUBLIC_API(void *)
992 JS_GetContextPrivate(JSContext
*cx
)
998 JS_SetContextPrivate(JSContext
*cx
, void *data
)
1003 JS_PUBLIC_API(JSRuntime
*)
1004 JS_GetRuntime(JSContext
*cx
)
1009 JS_PUBLIC_API(JSContext
*)
1010 JS_ContextIterator(JSRuntime
*rt
, JSContext
**iterp
)
1012 return js_ContextIterator(rt
, JS_TRUE
, iterp
);
1015 JS_PUBLIC_API(JSVersion
)
1016 JS_GetVersion(JSContext
*cx
)
1018 return VersionNumber(cx
->findVersion());
1022 CheckOptionVersionSync(JSContext
*cx
)
1025 uint32 options
= cx
->options
;
1026 JSVersion version
= cx
->findVersion();
1027 JS_ASSERT(OptionsHasXML(options
) == VersionHasXML(version
));
1028 JS_ASSERT(OptionsHasAnonFunFix(options
) == VersionHasAnonFunFix(version
));
1032 JS_PUBLIC_API(JSVersion
)
1033 JS_SetVersion(JSContext
*cx
, JSVersion newVersion
)
1035 JS_ASSERT(VersionIsKnown(newVersion
));
1036 JS_ASSERT(!VersionHasFlags(newVersion
));
1037 JSVersion newVersionNumber
= newVersion
;
1039 JSVersion oldVersion
= cx
->findVersion();
1040 JSVersion oldVersionNumber
= VersionNumber(oldVersion
);
1041 if (oldVersionNumber
== newVersionNumber
)
1042 return oldVersionNumber
; /* No override actually occurs! */
1044 /* We no longer support 1.4 or below. */
1045 if (newVersionNumber
!= JSVERSION_DEFAULT
&& newVersionNumber
<= JSVERSION_1_4
)
1046 return oldVersionNumber
;
1048 VersionCloneFlags(oldVersion
, &newVersion
);
1049 cx
->maybeOverrideVersion(newVersion
);
1050 CheckOptionVersionSync(cx
);
1051 return oldVersionNumber
;
1054 static struct v2smap
{
1058 {JSVERSION_1_0
, "1.0"},
1059 {JSVERSION_1_1
, "1.1"},
1060 {JSVERSION_1_2
, "1.2"},
1061 {JSVERSION_1_3
, "1.3"},
1062 {JSVERSION_1_4
, "1.4"},
1063 {JSVERSION_ECMA_3
, "ECMAv3"},
1064 {JSVERSION_1_5
, "1.5"},
1065 {JSVERSION_1_6
, "1.6"},
1066 {JSVERSION_1_7
, "1.7"},
1067 {JSVERSION_1_8
, "1.8"},
1068 {JSVERSION_ECMA_5
, "ECMAv5"},
1069 {JSVERSION_DEFAULT
, js_default_str
},
1070 {JSVERSION_UNKNOWN
, NULL
}, /* must be last, NULL is sentinel */
1073 JS_PUBLIC_API(const char *)
1074 JS_VersionToString(JSVersion version
)
1078 for (i
= 0; v2smap
[i
].string
; i
++)
1079 if (v2smap
[i
].version
== version
)
1080 return v2smap
[i
].string
;
1084 JS_PUBLIC_API(JSVersion
)
1085 JS_StringToVersion(const char *string
)
1089 for (i
= 0; v2smap
[i
].string
; i
++)
1090 if (strcmp(v2smap
[i
].string
, string
) == 0)
1091 return v2smap
[i
].version
;
1092 return JSVERSION_UNKNOWN
;
1095 JS_PUBLIC_API(uint32
)
1096 JS_GetOptions(JSContext
*cx
)
1099 * Can't check option/version synchronization here.
1100 * We may have been synchronized with a script version that was formerly on
1101 * the stack, but has now been popped.
1106 JS_PUBLIC_API(uint32
)
1107 JS_SetOptions(JSContext
*cx
, uint32 options
)
1109 AutoLockGC
lock(cx
->runtime
);
1110 uint32 oldopts
= cx
->options
;
1111 cx
->options
= options
;
1112 SyncOptionsToVersion(cx
);
1113 cx
->updateJITEnabled();
1114 CheckOptionVersionSync(cx
);
1118 JS_PUBLIC_API(uint32
)
1119 JS_ToggleOptions(JSContext
*cx
, uint32 options
)
1121 AutoLockGC
lock(cx
->runtime
);
1122 CheckOptionVersionSync(cx
);
1123 uint32 oldopts
= cx
->options
;
1124 cx
->options
^= options
;
1125 (void) SyncOptionsToVersion(cx
);
1126 cx
->updateJITEnabled();
1127 CheckOptionVersionSync(cx
);
1131 JS_PUBLIC_API(const char *)
1132 JS_GetImplementationVersion(void)
1134 return "JavaScript-C 1.8.0 pre-release 1 2007-10-03";
1137 JS_PUBLIC_API(JSCompartmentCallback
)
1138 JS_SetCompartmentCallback(JSRuntime
*rt
, JSCompartmentCallback callback
)
1140 JSCompartmentCallback old
= rt
->compartmentCallback
;
1141 rt
->compartmentCallback
= callback
;
1145 JS_PUBLIC_API(JSWrapObjectCallback
)
1146 JS_SetWrapObjectCallbacks(JSRuntime
*rt
,
1147 JSWrapObjectCallback callback
,
1148 JSPreWrapCallback precallback
)
1150 JSWrapObjectCallback old
= rt
->wrapObjectCallback
;
1151 rt
->wrapObjectCallback
= callback
;
1152 rt
->preWrapObjectCallback
= precallback
;
1156 JS_PUBLIC_API(JSCrossCompartmentCall
*)
1157 JS_EnterCrossCompartmentCall(JSContext
*cx
, JSObject
*target
)
1162 AutoCompartment
*call
= new AutoCompartment(cx
, target
);
1165 if (!call
->enter()) {
1169 return reinterpret_cast<JSCrossCompartmentCall
*>(call
);
1173 JS_LeaveCrossCompartmentCall(JSCrossCompartmentCall
*call
)
1175 AutoCompartment
*realcall
= reinterpret_cast<AutoCompartment
*>(call
);
1176 CHECK_REQUEST(realcall
->context
);
1182 JSAutoEnterCompartment::enter(JSContext
*cx
, JSObject
*target
)
1185 if (cx
->compartment
== target
->getCompartment()) {
1186 call
= reinterpret_cast<JSCrossCompartmentCall
*>(1);
1189 call
= JS_EnterCrossCompartmentCall(cx
, target
);
1190 return call
!= NULL
;
1194 JSAutoEnterCompartment::enterAndIgnoreErrors(JSContext
*cx
, JSObject
*target
)
1196 (void) enter(cx
, target
);
1199 JS_PUBLIC_API(void *)
1200 JS_SetCompartmentPrivate(JSContext
*cx
, JSCompartment
*compartment
, void *data
)
1203 void *old
= compartment
->data
;
1204 compartment
->data
= data
;
1208 JS_PUBLIC_API(void *)
1209 JS_GetCompartmentPrivate(JSContext
*cx
, JSCompartment
*compartment
)
1212 return compartment
->data
;
1215 JS_PUBLIC_API(JSBool
)
1216 JS_WrapObject(JSContext
*cx
, JSObject
**objp
)
1219 return cx
->compartment
->wrap(cx
, objp
);
1222 JS_PUBLIC_API(JSBool
)
1223 JS_WrapValue(JSContext
*cx
, jsval
*vp
)
1226 return cx
->compartment
->wrap(cx
, Valueify(vp
));
1229 JS_PUBLIC_API(JSObject
*)
1230 JS_TransplantWrapper(JSContext
*cx
, JSObject
*wrapper
, JSObject
*target
)
1232 JS_ASSERT(wrapper
->isWrapper());
1235 * This function is called when a window is navigating. In that case, we
1236 * need to "move" the window from wrapper's compartment to target's
1239 JSCompartment
*destination
= target
->getCompartment();
1240 if (wrapper
->getCompartment() == destination
) {
1241 // If the wrapper is in the same compartment as the destination, then
1242 // we know that we won't find wrapper in the destination's cross
1243 // compartment map and that the same object will continue to work.
1244 if (!wrapper
->swap(cx
, target
))
1250 WrapperMap
&map
= destination
->crossCompartmentWrappers
;
1251 Value wrapperv
= ObjectValue(*wrapper
);
1253 // There might already be a wrapper for the window in the new compartment.
1254 if (WrapperMap::Ptr p
= map
.lookup(wrapperv
)) {
1255 // If there is, make it the primary outer window proxy around the
1256 // inner (accomplished by swapping target's innards with the old,
1257 // possibly security wrapper, innards).
1258 obj
= &p
->value
.toObject();
1260 if (!obj
->swap(cx
, target
))
1263 // Otherwise, this is going to be our outer window proxy in the new
1268 // Now, iterate through other scopes looking for references to the old
1269 // outer window. They need to be updated to point at the new outer window.
1270 // They also might transition between different types of security wrappers
1271 // based on whether the new compartment is same origin with them.
1272 Value targetv
= ObjectValue(*obj
);
1273 WrapperVector
&vector
= cx
->runtime
->compartments
;
1274 AutoValueVector
toTransplant(cx
);
1275 toTransplant
.reserve(vector
.length());
1277 for (JSCompartment
**p
= vector
.begin(), **end
= vector
.end(); p
!= end
; ++p
) {
1278 WrapperMap
&pmap
= (*p
)->crossCompartmentWrappers
;
1279 if (WrapperMap::Ptr wp
= pmap
.lookup(wrapperv
)) {
1280 // We found a wrapper. Remember and root it.
1281 toTransplant
.append(wp
->value
);
1285 for (Value
*begin
= toTransplant
.begin(), *end
= toTransplant
.end(); begin
!= end
; ++begin
) {
1286 JSObject
*wobj
= &begin
->toObject();
1287 JSCompartment
*wcompartment
= wobj
->compartment();
1288 WrapperMap
&pmap
= wcompartment
->crossCompartmentWrappers
;
1289 JS_ASSERT(pmap
.lookup(wrapperv
));
1290 pmap
.remove(wrapperv
);
1292 // First, we wrap it in the new compartment. This will return a
1294 AutoCompartment
ac(cx
, wobj
);
1295 JSObject
*tobj
= obj
;
1296 if (!ac
.enter() || !wcompartment
->wrap(cx
, &tobj
))
1299 // Now, because we need to maintain object identity, we do a brain
1300 // transplant on the old object. At the same time, we update the
1301 // entry in the compartment's wrapper map to point to the old
1303 JS_ASSERT(tobj
!= wobj
);
1304 if (!wobj
->swap(cx
, tobj
))
1306 pmap
.put(targetv
, ObjectValue(*wobj
));
1309 // Lastly, update the old outer window proxy to point to the new one.
1311 AutoCompartment
ac(cx
, wrapper
);
1312 JSObject
*tobj
= obj
;
1313 if (!ac
.enter() || !JS_WrapObject(cx
, &tobj
))
1315 if (!wrapper
->swap(cx
, tobj
))
1317 wrapper
->getCompartment()->crossCompartmentWrappers
.put(targetv
, wrapperv
);
1323 JS_PUBLIC_API(JSObject
*)
1324 JS_GetGlobalObject(JSContext
*cx
)
1326 return cx
->globalObject
;
1330 JS_SetGlobalObject(JSContext
*cx
, JSObject
*obj
)
1334 cx
->globalObject
= obj
;
1336 cx
->resetCompartment();
1339 class AutoResolvingEntry
{
1341 AutoResolvingEntry() : entry(NULL
) {}
1344 * Returns false on error. But N.B. if obj[id] was already being resolved,
1345 * this is a no-op, and we silently treat that as success.
1347 bool start(JSContext
*cx
, JSObject
*obj
, jsid id
, uint32 flag
) {
1353 bool ok
= !!js_StartResolving(cx
, &key
, flag
, &entry
);
1354 JS_ASSERT_IF(!ok
, !entry
);
1358 ~AutoResolvingEntry() {
1360 js_StopResolving(cx
, &key
, flag
, NULL
, 0);
1367 JSResolvingEntry
*entry
;
1371 js_InitFunctionAndObjectClasses(JSContext
*cx
, JSObject
*obj
)
1373 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
1374 JSObject
*fun_proto
, *obj_proto
;
1376 /* If cx has no global object, use obj so prototypes can be found. */
1377 if (!cx
->globalObject
)
1378 JS_SetGlobalObject(cx
, obj
);
1380 /* Record Function and Object in cx->resolvingTable. */
1381 AutoResolvingEntry e1
, e2
;
1382 JSAtom
**classAtoms
= cx
->runtime
->atomState
.classAtoms
;
1383 if (!e1
.start(cx
, obj
, ATOM_TO_JSID(classAtoms
[JSProto_Function
]), JSRESFLAG_LOOKUP
) ||
1384 !e2
.start(cx
, obj
, ATOM_TO_JSID(classAtoms
[JSProto_Object
]), JSRESFLAG_LOOKUP
)) {
1388 /* Initialize the function class first so constructors can be made. */
1389 if (!js_GetClassPrototype(cx
, obj
, JSProto_Function
, &fun_proto
))
1392 fun_proto
= js_InitFunctionClass(cx
, obj
);
1398 ctor
= JS_GetConstructor(cx
, fun_proto
);
1401 obj
->defineProperty(cx
, ATOM_TO_JSID(CLASS_ATOM(cx
, Function
)),
1402 ObjectValue(*ctor
), 0, 0, 0);
1405 /* Initialize the object class next so Object.prototype works. */
1406 if (!js_GetClassPrototype(cx
, obj
, JSProto_Object
, &obj_proto
))
1409 obj_proto
= js_InitObjectClass(cx
, obj
);
1413 /* Function.prototype and the global object delegate to Object.prototype. */
1414 fun_proto
->setProto(obj_proto
);
1415 if (!obj
->getProto())
1416 obj
->setProto(obj_proto
);
1421 JS_PUBLIC_API(JSBool
)
1422 JS_InitStandardClasses(JSContext
*cx
, JSObject
*obj
)
1424 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
1428 * JS_SetGlobalObject might or might not change cx's compartment, so call
1429 * it before assertSameCompartment. (The API contract is that *after* this,
1430 * cx and obj must be in the same compartment.)
1432 if (!cx
->globalObject
)
1433 JS_SetGlobalObject(cx
, obj
);
1434 assertSameCompartment(cx
, obj
);
1436 /* Define a top-level property 'undefined' with the undefined value. */
1437 JSAtom
*atom
= cx
->runtime
->atomState
.typeAtoms
[JSTYPE_VOID
];
1438 if (!obj
->defineProperty(cx
, ATOM_TO_JSID(atom
), UndefinedValue(),
1439 PropertyStub
, PropertyStub
,
1440 JSPROP_PERMANENT
| JSPROP_READONLY
)) {
1444 /* Function and Object require cooperative bootstrapping magic. */
1445 if (!js_InitFunctionAndObjectClasses(cx
, obj
))
1448 /* Initialize the rest of the standard objects and functions. */
1449 return js_InitArrayClass(cx
, obj
) &&
1450 js_InitBooleanClass(cx
, obj
) &&
1451 js_InitExceptionClasses(cx
, obj
) &&
1452 js_InitMathClass(cx
, obj
) &&
1453 js_InitNumberClass(cx
, obj
) &&
1454 js_InitJSONClass(cx
, obj
) &&
1455 js_InitRegExpClass(cx
, obj
) &&
1456 js_InitStringClass(cx
, obj
) &&
1457 js_InitTypedArrayClasses(cx
, obj
) &&
1458 #if JS_HAS_XML_SUPPORT
1459 js_InitXMLClasses(cx
, obj
) &&
1461 #if JS_HAS_GENERATORS
1462 js_InitIteratorClasses(cx
, obj
) &&
1464 js_InitDateClass(cx
, obj
) &&
1465 js_InitProxyClass(cx
, obj
);
1468 #define CLASP(name) (&js_##name##Class)
1469 #define TYPED_ARRAY_CLASP(type) (&TypedArray::fastClasses[TypedArray::type])
1470 #define EAGER_ATOM(name) ATOM_OFFSET(name), NULL
1471 #define EAGER_CLASS_ATOM(name) CLASS_ATOM_OFFSET(name), NULL
1472 #define EAGER_ATOM_AND_CLASP(name) EAGER_CLASS_ATOM(name), CLASP(name)
1473 #define LAZY_ATOM(name) ATOM_OFFSET(lazy.name), js_##name##_str
1475 typedef struct JSStdName
{
1477 size_t atomOffset
; /* offset of atom pointer in JSAtomState */
1478 const char *name
; /* null if atom is pre-pinned, else name */
1483 StdNameToAtom(JSContext
*cx
, JSStdName
*stdn
)
1489 offset
= stdn
->atomOffset
;
1490 atom
= OFFSET_TO_ATOM(cx
->runtime
, offset
);
1494 atom
= js_Atomize(cx
, name
, strlen(name
), ATOM_PINNED
);
1495 OFFSET_TO_ATOM(cx
->runtime
, offset
) = atom
;
1502 * Table of class initializers and their atom offsets in rt->atomState.
1503 * If you add a "standard" class, remember to update this table.
1505 static JSStdName standard_class_atoms
[] = {
1506 {js_InitFunctionAndObjectClasses
, EAGER_ATOM_AND_CLASP(Function
)},
1507 {js_InitFunctionAndObjectClasses
, EAGER_ATOM_AND_CLASP(Object
)},
1508 {js_InitArrayClass
, EAGER_ATOM_AND_CLASP(Array
)},
1509 {js_InitBooleanClass
, EAGER_ATOM_AND_CLASP(Boolean
)},
1510 {js_InitDateClass
, EAGER_ATOM_AND_CLASP(Date
)},
1511 {js_InitMathClass
, EAGER_ATOM_AND_CLASP(Math
)},
1512 {js_InitNumberClass
, EAGER_ATOM_AND_CLASP(Number
)},
1513 {js_InitStringClass
, EAGER_ATOM_AND_CLASP(String
)},
1514 {js_InitExceptionClasses
, EAGER_ATOM_AND_CLASP(Error
)},
1515 {js_InitRegExpClass
, EAGER_ATOM_AND_CLASP(RegExp
)},
1516 #if JS_HAS_XML_SUPPORT
1517 {js_InitXMLClass
, EAGER_ATOM_AND_CLASP(XML
)},
1518 {js_InitNamespaceClass
, EAGER_ATOM_AND_CLASP(Namespace
)},
1519 {js_InitQNameClass
, EAGER_ATOM_AND_CLASP(QName
)},
1521 #if JS_HAS_GENERATORS
1522 {js_InitIteratorClasses
, EAGER_ATOM_AND_CLASP(StopIteration
)},
1524 {js_InitJSONClass
, EAGER_ATOM_AND_CLASP(JSON
)},
1525 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(ArrayBuffer
), &js::ArrayBuffer::jsclass
},
1526 {NULL
, 0, NULL
, NULL
}
1530 * Table of top-level function and constant names and their init functions.
1531 * If you add a "standard" global function or property, remember to update
1534 static JSStdName standard_class_names
[] = {
1535 {js_InitObjectClass
, EAGER_ATOM(eval
), CLASP(Object
)},
1537 /* Global properties and functions defined by the Number class. */
1538 {js_InitNumberClass
, LAZY_ATOM(NaN
), CLASP(Number
)},
1539 {js_InitNumberClass
, LAZY_ATOM(Infinity
), CLASP(Number
)},
1540 {js_InitNumberClass
, LAZY_ATOM(isNaN
), CLASP(Number
)},
1541 {js_InitNumberClass
, LAZY_ATOM(isFinite
), CLASP(Number
)},
1542 {js_InitNumberClass
, LAZY_ATOM(parseFloat
), CLASP(Number
)},
1543 {js_InitNumberClass
, LAZY_ATOM(parseInt
), CLASP(Number
)},
1545 /* String global functions. */
1546 {js_InitStringClass
, LAZY_ATOM(escape
), CLASP(String
)},
1547 {js_InitStringClass
, LAZY_ATOM(unescape
), CLASP(String
)},
1548 {js_InitStringClass
, LAZY_ATOM(decodeURI
), CLASP(String
)},
1549 {js_InitStringClass
, LAZY_ATOM(encodeURI
), CLASP(String
)},
1550 {js_InitStringClass
, LAZY_ATOM(decodeURIComponent
), CLASP(String
)},
1551 {js_InitStringClass
, LAZY_ATOM(encodeURIComponent
), CLASP(String
)},
1553 {js_InitStringClass
, LAZY_ATOM(uneval
), CLASP(String
)},
1556 /* Exception constructors. */
1557 {js_InitExceptionClasses
, EAGER_CLASS_ATOM(Error
), CLASP(Error
)},
1558 {js_InitExceptionClasses
, EAGER_CLASS_ATOM(InternalError
), CLASP(Error
)},
1559 {js_InitExceptionClasses
, EAGER_CLASS_ATOM(EvalError
), CLASP(Error
)},
1560 {js_InitExceptionClasses
, EAGER_CLASS_ATOM(RangeError
), CLASP(Error
)},
1561 {js_InitExceptionClasses
, EAGER_CLASS_ATOM(ReferenceError
), CLASP(Error
)},
1562 {js_InitExceptionClasses
, EAGER_CLASS_ATOM(SyntaxError
), CLASP(Error
)},
1563 {js_InitExceptionClasses
, EAGER_CLASS_ATOM(TypeError
), CLASP(Error
)},
1564 {js_InitExceptionClasses
, EAGER_CLASS_ATOM(URIError
), CLASP(Error
)},
1566 #if JS_HAS_XML_SUPPORT
1567 {js_InitAnyNameClass
, EAGER_ATOM_AND_CLASP(AnyName
)},
1568 {js_InitAttributeNameClass
, EAGER_ATOM_AND_CLASP(AttributeName
)},
1569 {js_InitXMLClass
, LAZY_ATOM(XMLList
), CLASP(XML
)},
1570 {js_InitXMLClass
, LAZY_ATOM(isXMLName
), CLASP(XML
)},
1573 #if JS_HAS_GENERATORS
1574 {js_InitIteratorClasses
, EAGER_ATOM_AND_CLASP(Iterator
)},
1575 {js_InitIteratorClasses
, EAGER_ATOM_AND_CLASP(Generator
)},
1579 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(ArrayBuffer
), &js::ArrayBuffer::jsclass
},
1580 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(Int8Array
), TYPED_ARRAY_CLASP(TYPE_INT8
)},
1581 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(Uint8Array
), TYPED_ARRAY_CLASP(TYPE_UINT8
)},
1582 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(Int16Array
), TYPED_ARRAY_CLASP(TYPE_INT16
)},
1583 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(Uint16Array
), TYPED_ARRAY_CLASP(TYPE_UINT16
)},
1584 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(Int32Array
), TYPED_ARRAY_CLASP(TYPE_INT32
)},
1585 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(Uint32Array
), TYPED_ARRAY_CLASP(TYPE_UINT32
)},
1586 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(Float32Array
), TYPED_ARRAY_CLASP(TYPE_FLOAT32
)},
1587 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(Float64Array
), TYPED_ARRAY_CLASP(TYPE_FLOAT64
)},
1588 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(Uint8ClampedArray
),
1589 TYPED_ARRAY_CLASP(TYPE_UINT8_CLAMPED
)},
1591 {js_InitProxyClass
, EAGER_ATOM_AND_CLASP(Proxy
)},
1593 {NULL
, 0, NULL
, NULL
}
1596 static JSStdName object_prototype_names
[] = {
1597 /* Object.prototype properties (global delegates to Object.prototype). */
1598 {js_InitObjectClass
, EAGER_ATOM(proto
), CLASP(Object
)},
1600 {js_InitObjectClass
, EAGER_ATOM(toSource
), CLASP(Object
)},
1602 {js_InitObjectClass
, EAGER_ATOM(toString
), CLASP(Object
)},
1603 {js_InitObjectClass
, EAGER_ATOM(toLocaleString
), CLASP(Object
)},
1604 {js_InitObjectClass
, EAGER_ATOM(valueOf
), CLASP(Object
)},
1605 #if JS_HAS_OBJ_WATCHPOINT
1606 {js_InitObjectClass
, LAZY_ATOM(watch
), CLASP(Object
)},
1607 {js_InitObjectClass
, LAZY_ATOM(unwatch
), CLASP(Object
)},
1609 {js_InitObjectClass
, LAZY_ATOM(hasOwnProperty
), CLASP(Object
)},
1610 {js_InitObjectClass
, LAZY_ATOM(isPrototypeOf
), CLASP(Object
)},
1611 {js_InitObjectClass
, LAZY_ATOM(propertyIsEnumerable
), CLASP(Object
)},
1612 #if OLD_GETTER_SETTER_METHODS
1613 {js_InitObjectClass
, LAZY_ATOM(defineGetter
), CLASP(Object
)},
1614 {js_InitObjectClass
, LAZY_ATOM(defineSetter
), CLASP(Object
)},
1615 {js_InitObjectClass
, LAZY_ATOM(lookupGetter
), CLASP(Object
)},
1616 {js_InitObjectClass
, LAZY_ATOM(lookupSetter
), CLASP(Object
)},
1619 {NULL
, 0, NULL
, NULL
}
1622 JS_PUBLIC_API(JSBool
)
1623 JS_ResolveStandardClass(JSContext
*cx
, JSObject
*obj
, jsid id
, JSBool
*resolved
)
1632 assertSameCompartment(cx
, obj
, id
);
1633 *resolved
= JS_FALSE
;
1636 JS_ASSERT(rt
->state
!= JSRTS_DOWN
);
1637 if (rt
->state
== JSRTS_LANDING
|| !JSID_IS_ATOM(id
))
1640 idstr
= JSID_TO_STRING(id
);
1642 /* Check whether we're resolving 'undefined', and define it if so. */
1643 atom
= rt
->atomState
.typeAtoms
[JSTYPE_VOID
];
1644 if (idstr
== ATOM_TO_STRING(atom
)) {
1645 *resolved
= JS_TRUE
;
1646 return obj
->defineProperty(cx
, ATOM_TO_JSID(atom
), UndefinedValue(),
1647 PropertyStub
, PropertyStub
,
1648 JSPROP_PERMANENT
| JSPROP_READONLY
);
1651 /* Try for class constructors/prototypes named by well-known atoms. */
1653 for (i
= 0; standard_class_atoms
[i
].init
; i
++) {
1654 JS_ASSERT(standard_class_atoms
[i
].clasp
);
1655 atom
= OFFSET_TO_ATOM(rt
, standard_class_atoms
[i
].atomOffset
);
1656 if (idstr
== ATOM_TO_STRING(atom
)) {
1657 stdnm
= &standard_class_atoms
[i
];
1663 /* Try less frequently used top-level functions and constants. */
1664 for (i
= 0; standard_class_names
[i
].init
; i
++) {
1665 JS_ASSERT(standard_class_names
[i
].clasp
);
1666 atom
= StdNameToAtom(cx
, &standard_class_names
[i
]);
1669 if (idstr
== ATOM_TO_STRING(atom
)) {
1670 stdnm
= &standard_class_names
[i
];
1675 if (!stdnm
&& !obj
->getProto()) {
1677 * Try even less frequently used names delegated from the global
1678 * object to Object.prototype, but only if the Object class hasn't
1679 * yet been initialized.
1681 for (i
= 0; object_prototype_names
[i
].init
; i
++) {
1682 JS_ASSERT(object_prototype_names
[i
].clasp
);
1683 atom
= StdNameToAtom(cx
, &object_prototype_names
[i
]);
1686 if (idstr
== ATOM_TO_STRING(atom
)) {
1687 stdnm
= &object_prototype_names
[i
];
1696 * If this standard class is anonymous, then we don't want to resolve
1699 JS_ASSERT(obj
->getClass()->flags
& JSCLASS_IS_GLOBAL
);
1700 if (stdnm
->clasp
->flags
& JSCLASS_IS_ANONYMOUS
)
1703 JSProtoKey key
= JSCLASS_CACHED_PROTO_KEY(stdnm
->clasp
);
1704 if (obj
->getReservedSlot(key
).isObject())
1707 if (!stdnm
->init(cx
, obj
))
1709 *resolved
= JS_TRUE
;
1714 JS_PUBLIC_API(JSBool
)
1715 JS_EnumerateStandardClasses(JSContext
*cx
, JSObject
*obj
)
1722 assertSameCompartment(cx
, obj
);
1725 /* Check whether we need to bind 'undefined' and define it if so. */
1726 atom
= rt
->atomState
.typeAtoms
[JSTYPE_VOID
];
1727 if (!obj
->nativeContains(ATOM_TO_JSID(atom
)) &&
1728 !obj
->defineProperty(cx
, ATOM_TO_JSID(atom
), UndefinedValue(),
1729 PropertyStub
, PropertyStub
,
1730 JSPROP_PERMANENT
| JSPROP_READONLY
)) {
1734 /* Initialize any classes that have not been resolved yet. */
1735 for (i
= 0; standard_class_atoms
[i
].init
; i
++) {
1736 atom
= OFFSET_TO_ATOM(rt
, standard_class_atoms
[i
].atomOffset
);
1737 if (!obj
->nativeContains(ATOM_TO_JSID(atom
)) &&
1738 !standard_class_atoms
[i
].init(cx
, obj
)) {
1749 NewIdArray(JSContext
*cx
, jsint length
)
1754 cx
->calloc(offsetof(JSIdArray
, vector
) + length
* sizeof(jsval
));
1756 ida
->length
= length
;
1763 * Unlike realloc(3), this function frees ida on failure.
1766 SetIdArrayLength(JSContext
*cx
, JSIdArray
*ida
, jsint length
)
1770 rida
= (JSIdArray
*)
1772 offsetof(JSIdArray
, vector
) + length
* sizeof(jsval
));
1774 JS_DestroyIdArray(cx
, ida
);
1776 rida
->length
= length
;
1782 AddAtomToArray(JSContext
*cx
, JSAtom
*atom
, JSIdArray
*ida
, jsint
*ip
)
1787 length
= ida
->length
;
1789 ida
= SetIdArrayLength(cx
, ida
, JS_MAX(length
* 2, 8));
1792 JS_ASSERT(i
< ida
->length
);
1794 ida
->vector
[i
] = ATOM_TO_JSID(atom
);
1800 EnumerateIfResolved(JSContext
*cx
, JSObject
*obj
, JSAtom
*atom
, JSIdArray
*ida
,
1801 jsint
*ip
, JSBool
*foundp
)
1803 *foundp
= obj
->nativeContains(ATOM_TO_JSID(atom
));
1805 ida
= AddAtomToArray(cx
, atom
, ida
, ip
);
1809 JS_PUBLIC_API(JSIdArray
*)
1810 JS_EnumerateResolvedStandardClasses(JSContext
*cx
, JSObject
*obj
, JSIdArray
*ida
)
1819 assertSameCompartment(cx
, obj
, ida
);
1824 ida
= NewIdArray(cx
, 8);
1830 /* Check whether 'undefined' has been resolved and enumerate it if so. */
1831 atom
= rt
->atomState
.typeAtoms
[JSTYPE_VOID
];
1832 ida
= EnumerateIfResolved(cx
, obj
, atom
, ida
, &i
, &found
);
1836 /* Enumerate only classes that *have* been resolved. */
1837 for (j
= 0; standard_class_atoms
[j
].init
; j
++) {
1838 atom
= OFFSET_TO_ATOM(rt
, standard_class_atoms
[j
].atomOffset
);
1839 ida
= EnumerateIfResolved(cx
, obj
, atom
, ida
, &i
, &found
);
1844 init
= standard_class_atoms
[j
].init
;
1846 for (k
= 0; standard_class_names
[k
].init
; k
++) {
1847 if (standard_class_names
[k
].init
== init
) {
1848 atom
= StdNameToAtom(cx
, &standard_class_names
[k
]);
1849 ida
= AddAtomToArray(cx
, atom
, ida
, &i
);
1855 if (init
== js_InitObjectClass
) {
1856 for (k
= 0; object_prototype_names
[k
].init
; k
++) {
1857 atom
= StdNameToAtom(cx
, &object_prototype_names
[k
]);
1858 ida
= AddAtomToArray(cx
, atom
, ida
, &i
);
1866 /* Trim to exact length. */
1867 return SetIdArrayLength(cx
, ida
, i
);
1872 #undef EAGER_CLASS_ATOM
1873 #undef EAGER_ATOM_CLASP
1876 JS_PUBLIC_API(JSBool
)
1877 JS_GetClassObject(JSContext
*cx
, JSObject
*obj
, JSProtoKey key
, JSObject
**objp
)
1880 assertSameCompartment(cx
, obj
);
1881 return js_GetClassObject(cx
, obj
, key
, objp
);
1884 JS_PUBLIC_API(JSObject
*)
1885 JS_GetScopeChain(JSContext
*cx
)
1888 return GetScopeChain(cx
);
1891 JS_PUBLIC_API(JSObject
*)
1892 JS_GetGlobalForObject(JSContext
*cx
, JSObject
*obj
)
1894 assertSameCompartment(cx
, obj
);
1895 return obj
->getGlobal();
1898 JS_PUBLIC_API(JSObject
*)
1899 JS_GetGlobalForScopeChain(JSContext
*cx
)
1902 return GetGlobalForScopeChain(cx
);
1905 JS_PUBLIC_API(jsval
)
1906 JS_ComputeThis(JSContext
*cx
, jsval
*vp
)
1908 assertSameCompartment(cx
, JSValueArray(vp
, 2));
1909 if (!ComputeThisFromVp(cx
, Valueify(vp
)))
1914 JS_PUBLIC_API(void *)
1915 JS_malloc(JSContext
*cx
, size_t nbytes
)
1917 return cx
->malloc(nbytes
);
1920 JS_PUBLIC_API(void *)
1921 JS_realloc(JSContext
*cx
, void *p
, size_t nbytes
)
1923 return cx
->realloc(p
, nbytes
);
1927 JS_free(JSContext
*cx
, void *p
)
1933 JS_updateMallocCounter(JSContext
*cx
, size_t nbytes
)
1935 return cx
->runtime
->updateMallocCounter(nbytes
);
1938 JS_PUBLIC_API(char *)
1939 JS_strdup(JSContext
*cx
, const char *s
)
1948 return (char *)memcpy(p
, s
, n
);
1951 JS_PUBLIC_API(JSBool
)
1952 JS_NewNumberValue(JSContext
*cx
, jsdouble d
, jsval
*rval
)
1954 d
= JS_CANONICALIZE_NAN(d
);
1955 Valueify(rval
)->setNumber(d
);
1961 JS_PUBLIC_API(JSBool
)
1962 JS_AddValueRoot(JSContext
*cx
, jsval
*vp
)
1965 return js_AddRoot(cx
, Valueify(vp
), NULL
);
1968 JS_PUBLIC_API(JSBool
)
1969 JS_AddStringRoot(JSContext
*cx
, JSString
**rp
)
1972 return js_AddGCThingRoot(cx
, (void **)rp
, NULL
);
1975 JS_PUBLIC_API(JSBool
)
1976 JS_AddObjectRoot(JSContext
*cx
, JSObject
**rp
)
1979 return js_AddGCThingRoot(cx
, (void **)rp
, NULL
);
1982 JS_PUBLIC_API(JSBool
)
1983 JS_AddGCThingRoot(JSContext
*cx
, void **rp
)
1986 return js_AddGCThingRoot(cx
, (void **)rp
, NULL
);
1989 JS_PUBLIC_API(JSBool
)
1990 JS_AddNamedValueRoot(JSContext
*cx
, jsval
*vp
, const char *name
)
1993 return js_AddRoot(cx
, Valueify(vp
), name
);
1996 JS_PUBLIC_API(JSBool
)
1997 JS_AddNamedStringRoot(JSContext
*cx
, JSString
**rp
, const char *name
)
2000 return js_AddGCThingRoot(cx
, (void **)rp
, name
);
2003 JS_PUBLIC_API(JSBool
)
2004 JS_AddNamedObjectRoot(JSContext
*cx
, JSObject
**rp
, const char *name
)
2007 return js_AddGCThingRoot(cx
, (void **)rp
, name
);
2010 JS_PUBLIC_API(JSBool
)
2011 JS_AddNamedGCThingRoot(JSContext
*cx
, void **rp
, const char *name
)
2014 return js_AddGCThingRoot(cx
, (void **)rp
, name
);
2017 JS_PUBLIC_API(JSBool
)
2018 JS_RemoveValueRoot(JSContext
*cx
, jsval
*vp
)
2021 return js_RemoveRoot(cx
->runtime
, (void *)vp
);
2024 JS_PUBLIC_API(JSBool
)
2025 JS_RemoveStringRoot(JSContext
*cx
, JSString
**rp
)
2028 return js_RemoveRoot(cx
->runtime
, (void *)rp
);
2031 JS_PUBLIC_API(JSBool
)
2032 JS_RemoveObjectRoot(JSContext
*cx
, JSObject
**rp
)
2035 return js_RemoveRoot(cx
->runtime
, (void *)rp
);
2038 JS_PUBLIC_API(JSBool
)
2039 JS_RemoveGCThingRoot(JSContext
*cx
, void **rp
)
2042 return js_RemoveRoot(cx
->runtime
, (void *)rp
);
2048 JS_DumpNamedRoots(JSRuntime
*rt
,
2049 void (*dump
)(const char *name
, void *rp
, JSGCRootType type
, void *data
),
2052 js_DumpNamedRoots(rt
, dump
, data
);
2057 JS_PUBLIC_API(uint32
)
2058 JS_MapGCRoots(JSRuntime
*rt
, JSGCRootMapFun map
, void *data
)
2060 return js_MapGCRoots(rt
, map
, data
);
2063 JS_PUBLIC_API(JSBool
)
2064 JS_LockGCThing(JSContext
*cx
, void *thing
)
2069 ok
= js_LockGCThingRT(cx
->runtime
, thing
);
2071 JS_ReportOutOfMemory(cx
);
2075 JS_PUBLIC_API(JSBool
)
2076 JS_LockGCThingRT(JSRuntime
*rt
, void *thing
)
2078 return js_LockGCThingRT(rt
, thing
);
2081 JS_PUBLIC_API(JSBool
)
2082 JS_UnlockGCThing(JSContext
*cx
, void *thing
)
2085 js_UnlockGCThingRT(cx
->runtime
, thing
);
2089 JS_PUBLIC_API(JSBool
)
2090 JS_UnlockGCThingRT(JSRuntime
*rt
, void *thing
)
2092 js_UnlockGCThingRT(rt
, thing
);
2097 JS_SetExtraGCRoots(JSRuntime
*rt
, JSTraceDataOp traceOp
, void *data
)
2099 rt
->gcExtraRootsTraceOp
= traceOp
;
2100 rt
->gcExtraRootsData
= data
;
2104 JS_TraceRuntime(JSTracer
*trc
)
2110 JS_CallTracer(JSTracer
*trc
, void *thing
, uint32 kind
)
2113 MarkKind(trc
, thing
, kind
);
2118 #ifdef HAVE_XPCONNECT
2119 #include "dump_xpc.h"
2123 JS_PrintTraceThingInfo(char *buf
, size_t bufsize
, JSTracer
*trc
, void *thing
, uint32 kind
,
2133 case JSTRACE_OBJECT
:
2135 JSObject
*obj
= (JSObject
*)thing
;
2136 Class
*clasp
= obj
->getClass();
2139 #ifdef HAVE_XPCONNECT
2140 if (clasp
->flags
& JSCLASS_PRIVATE_IS_NSISUPPORTS
) {
2141 void *privateThing
= obj
->getPrivate();
2143 const char *xpcClassName
= GetXPCObjectClassName(privateThing
);
2145 name
= xpcClassName
;
2152 case JSTRACE_STRING
:
2153 name
= ((JSString
*)thing
)->isDependent()
2158 #if JS_HAS_XML_SUPPORT
2170 if (n
> bufsize
- 1)
2172 memcpy(buf
, name
, n
+ 1);
2176 if (details
&& bufsize
> 2) {
2181 case JSTRACE_OBJECT
:
2183 JSObject
*obj
= (JSObject
*)thing
;
2184 Class
*clasp
= obj
->getClass();
2185 if (clasp
== &js_FunctionClass
) {
2186 JSFunction
*fun
= GET_FUNCTION_PRIVATE(trc
->context
, obj
);
2188 JS_snprintf(buf
, bufsize
, "<newborn>");
2189 } else if (FUN_OBJECT(fun
) != obj
) {
2190 JS_snprintf(buf
, bufsize
, "%p", fun
);
2193 js_PutEscapedString(buf
, bufsize
, ATOM_TO_STRING(fun
->atom
), 0);
2195 } else if (clasp
->flags
& JSCLASS_HAS_PRIVATE
) {
2196 JS_snprintf(buf
, bufsize
, "%p", obj
->getPrivate());
2198 JS_snprintf(buf
, bufsize
, "<no private>");
2203 case JSTRACE_STRING
:
2204 js_PutEscapedString(buf
, bufsize
, (JSString
*)thing
, 0);
2207 #if JS_HAS_XML_SUPPORT
2210 extern const char *js_xml_class_str
[];
2211 JSXML
*xml
= (JSXML
*)thing
;
2213 JS_snprintf(buf
, bufsize
, "%s", js_xml_class_str
[xml
->xml_class
]);
2222 buf
[bufsize
- 1] = '\0';
2225 typedef struct JSHeapDumpNode JSHeapDumpNode
;
2227 struct JSHeapDumpNode
{
2230 JSHeapDumpNode
*next
; /* next sibling */
2231 JSHeapDumpNode
*parent
; /* node with the thing that refer to thing
2233 char edgeName
[1]; /* name of the edge from parent->thing
2237 typedef struct JSDumpingTracer
{
2239 JSDHashTable visited
;
2243 void *thingToIgnore
;
2244 JSHeapDumpNode
*parentNode
;
2245 JSHeapDumpNode
**lastNodep
;
2250 DumpNotify(JSTracer
*trc
, void *thing
, uint32 kind
)
2252 JSDumpingTracer
*dtrc
;
2254 JSDHashEntryStub
*entry
;
2255 JSHeapDumpNode
*node
;
2256 const char *edgeName
;
2257 size_t edgeNameSize
;
2259 JS_ASSERT(trc
->callback
== DumpNotify
);
2260 dtrc
= (JSDumpingTracer
*)trc
;
2262 if (!dtrc
->ok
|| thing
== dtrc
->thingToIgnore
)
2268 * Check if we have already seen thing unless it is thingToFind to include
2269 * it to the graph each time we reach it and print all live things that
2270 * refer to thingToFind.
2272 * This does not print all possible paths leading to thingToFind since
2273 * when a thing A refers directly or indirectly to thingToFind and A is
2274 * present several times in the graph, we will print only the first path
2275 * leading to A and thingToFind, other ways to reach A will be ignored.
2277 if (dtrc
->thingToFind
!= thing
) {
2279 * The startThing check allows to avoid putting startThing into the
2280 * hash table before tracing startThing in JS_DumpHeap.
2282 if (thing
== dtrc
->startThing
)
2284 entry
= (JSDHashEntryStub
*)
2285 JS_DHashTableOperate(&dtrc
->visited
, thing
, JS_DHASH_ADD
);
2287 JS_ReportOutOfMemory(cx
);
2288 dtrc
->ok
= JS_FALSE
;
2296 if (dtrc
->base
.debugPrinter
) {
2297 dtrc
->base
.debugPrinter(trc
, dtrc
->buffer
, sizeof(dtrc
->buffer
));
2298 edgeName
= dtrc
->buffer
;
2299 } else if (dtrc
->base
.debugPrintIndex
!= (size_t)-1) {
2300 JS_snprintf(dtrc
->buffer
, sizeof(dtrc
->buffer
), "%s[%lu]",
2301 (const char *)dtrc
->base
.debugPrintArg
,
2302 dtrc
->base
.debugPrintIndex
);
2303 edgeName
= dtrc
->buffer
;
2305 edgeName
= (const char*)dtrc
->base
.debugPrintArg
;
2308 edgeNameSize
= strlen(edgeName
) + 1;
2309 node
= (JSHeapDumpNode
*)
2310 cx
->malloc(offsetof(JSHeapDumpNode
, edgeName
) + edgeNameSize
);
2312 dtrc
->ok
= JS_FALSE
;
2316 node
->thing
= thing
;
2319 node
->parent
= dtrc
->parentNode
;
2320 memcpy(node
->edgeName
, edgeName
, edgeNameSize
);
2322 JS_ASSERT(!*dtrc
->lastNodep
);
2323 *dtrc
->lastNodep
= node
;
2324 dtrc
->lastNodep
= &node
->next
;
2327 /* Dump node and the chain that leads to thing it contains. */
2329 DumpNode(JSDumpingTracer
*dtrc
, FILE* fp
, JSHeapDumpNode
*node
)
2331 JSHeapDumpNode
*prev
, *following
;
2334 enum { MAX_PARENTS_TO_PRINT
= 10 };
2336 JS_PrintTraceThingInfo(dtrc
->buffer
, sizeof dtrc
->buffer
,
2337 &dtrc
->base
, node
->thing
, node
->kind
, JS_TRUE
);
2338 if (fprintf(fp
, "%p %-22s via ", node
->thing
, dtrc
->buffer
) < 0)
2342 * We need to print the parent chain in the reverse order. To do it in
2343 * O(N) time where N is the chain length we first reverse the chain while
2344 * searching for the top and then print each node while restoring the
2347 chainLimit
= MAX_PARENTS_TO_PRINT
;
2350 following
= node
->parent
;
2351 node
->parent
= prev
;
2356 if (chainLimit
== 0) {
2357 if (fputs("...", fp
) < 0)
2368 /* Loop must continue even when !ok to restore the parent chain. */
2371 /* Print edge from some runtime root or startThing. */
2372 if (fputs(node
->edgeName
, fp
) < 0)
2375 JS_PrintTraceThingInfo(dtrc
->buffer
, sizeof dtrc
->buffer
,
2376 &dtrc
->base
, prev
->thing
, prev
->kind
,
2378 if (fprintf(fp
, "(%p %s).%s",
2379 prev
->thing
, dtrc
->buffer
, node
->edgeName
) < 0) {
2384 following
= node
->parent
;
2385 node
->parent
= prev
;
2390 return ok
&& putc('\n', fp
) >= 0;
2393 JS_PUBLIC_API(JSBool
)
2394 JS_DumpHeap(JSContext
*cx
, FILE *fp
, void* startThing
, uint32 startKind
,
2395 void *thingToFind
, size_t maxDepth
, void *thingToIgnore
)
2397 JSDumpingTracer dtrc
;
2398 JSHeapDumpNode
*node
, *children
, *next
, *parent
;
2400 JSBool thingToFindWasTraced
;
2405 JS_TRACER_INIT(&dtrc
.base
, cx
, DumpNotify
);
2406 if (!JS_DHashTableInit(&dtrc
.visited
, JS_DHashGetStubOps(),
2407 NULL
, sizeof(JSDHashEntryStub
),
2408 JS_DHASH_DEFAULT_CAPACITY(100))) {
2409 JS_ReportOutOfMemory(cx
);
2413 dtrc
.startThing
= startThing
;
2414 dtrc
.thingToFind
= thingToFind
;
2415 dtrc
.thingToIgnore
= thingToIgnore
;
2416 dtrc
.parentNode
= NULL
;
2418 dtrc
.lastNodep
= &node
;
2420 JS_ASSERT(startKind
== 0);
2421 TraceRuntime(&dtrc
.base
);
2423 JS_TraceChildren(&dtrc
.base
, startThing
, startKind
);
2430 thingToFindWasTraced
= thingToFind
&& thingToFind
== startThing
;
2433 * Loop must continue even when !dtrc.ok to free all nodes allocated
2437 if (thingToFind
== NULL
|| thingToFind
== node
->thing
)
2438 dtrc
.ok
= DumpNode(&dtrc
, fp
, node
);
2440 /* Descend into children. */
2443 (thingToFind
!= node
->thing
|| !thingToFindWasTraced
)) {
2444 dtrc
.parentNode
= node
;
2446 dtrc
.lastNodep
= &children
;
2447 JS_TraceChildren(&dtrc
.base
, node
->thing
, node
->kind
);
2448 if (thingToFind
== node
->thing
)
2449 thingToFindWasTraced
= JS_TRUE
;
2450 if (children
!= NULL
) {
2458 /* Move to next or parents next and free the node. */
2461 parent
= node
->parent
;
2468 JS_ASSERT(depth
> 1);
2475 JS_ASSERT(depth
== 1);
2476 JS_DHashTableFinish(&dtrc
.visited
);
2483 JS_MarkGCThing(JSContext
*cx
, jsval v
, const char *name
, void *arg
)
2487 trc
= (JSTracer
*)arg
;
2489 trc
= cx
->runtime
->gcMarkingTracer
;
2491 JS_ASSERT(trc
== cx
->runtime
->gcMarkingTracer
);
2493 #ifdef JS_THREADSAFE
2494 JS_ASSERT(cx
->runtime
->gcThread
== trc
->context
->thread
);
2496 MarkValue(trc
, Valueify(v
), name
? name
: "unknown");
2499 extern JS_PUBLIC_API(JSBool
)
2500 JS_IsGCMarkingTracer(JSTracer
*trc
)
2502 return IS_GC_MARKING_TRACER(trc
);
2506 JS_GC(JSContext
*cx
)
2510 /* Don't nuke active arenas if executing or compiling. */
2511 if (cx
->tempPool
.current
== &cx
->tempPool
.first
)
2512 JS_FinishArenaPool(&cx
->tempPool
);
2513 js_GC(cx
, GC_NORMAL
);
2517 JS_MaybeGC(JSContext
*cx
)
2520 uint32 bytes
, lastBytes
;
2525 if (rt
->gcZeal
> 0) {
2531 bytes
= rt
->gcBytes
;
2532 lastBytes
= rt
->gcLastBytes
;
2535 * We run the GC if we used all available free GC cells and had to
2536 * allocate extra 1/3 of GC arenas since the last run of GC, or if
2537 * we have malloc'd more bytes through JS_malloc than we were told
2538 * to allocate by JS_NewRuntime.
2541 * bytes > 4/3 lastBytes
2542 * condition is the following. Bug 312238 changed bytes and lastBytes
2543 * to mean the total amount of memory that the GC uses now and right
2544 * after the last GC.
2546 * Before the bug the variables meant the size of allocated GC things
2547 * now and right after the last GC. That size did not include the
2548 * memory taken by free GC cells and the condition was
2549 * bytes > 3/2 lastBytes.
2550 * That is, we run the GC if we have half again as many bytes of
2551 * GC-things as the last time we GC'd. To be compatible we need to
2552 * express that condition through the new meaning of bytes and
2555 * We write the original condition as
2556 * B*(1-F) > 3/2 Bl*(1-Fl)
2557 * where B is the total memory size allocated by GC and F is the free
2558 * cell density currently and Sl and Fl are the size and the density
2559 * right after GC. The density by definition is memory taken by free
2560 * cells divided by total amount of memory. In other words, B and Bl
2561 * are bytes and lastBytes with the new meaning and B*(1-F) and
2562 * Bl*(1-Fl) are bytes and lastBytes with the original meaning.
2564 * Our task is to exclude F and Fl from the last statement. According
2565 * to the stats from bug 331966 comment 23, Fl is about 10-25% for a
2566 * typical run of the browser. It means that the original condition
2567 * implied that we did not run GC unless we exhausted the pool of
2568 * free cells. Indeed if we still have free cells, then B == Bl since
2569 * we did not yet allocated any new arenas and the condition means
2570 * 1 - F > 3/2 (1-Fl) or 3/2Fl > 1/2 + F
2571 * That implies 3/2 Fl > 1/2 or Fl > 1/3. That cannot be fulfilled
2572 * for the state described by the stats. So we can write the original
2574 * F == 0 && B > 3/2 Bl(1-Fl)
2575 * Again using the stats we see that Fl is about 11% when the browser
2576 * starts up and when we are far from hitting rt->gcMaxBytes. With
2578 * F == 0 && B > 3/2 Bl(1-0.11)
2579 * or approximately F == 0 && B > 4/3 Bl.
2581 if ((bytes
> 8192 && bytes
> lastBytes
+ lastBytes
/ 3) ||
2582 rt
->isGCMallocLimitReached()) {
2587 JS_PUBLIC_API(JSGCCallback
)
2588 JS_SetGCCallback(JSContext
*cx
, JSGCCallback cb
)
2591 return JS_SetGCCallbackRT(cx
->runtime
, cb
);
2594 JS_PUBLIC_API(JSGCCallback
)
2595 JS_SetGCCallbackRT(JSRuntime
*rt
, JSGCCallback cb
)
2599 oldcb
= rt
->gcCallback
;
2600 rt
->gcCallback
= cb
;
2604 JS_PUBLIC_API(JSBool
)
2605 JS_IsAboutToBeFinalized(JSContext
*cx
, void *thing
)
2608 JS_ASSERT(!cx
->runtime
->gcMarkingTracer
);
2609 return IsAboutToBeFinalized(thing
);
2613 JS_SetGCParameter(JSRuntime
*rt
, JSGCParamKey key
, uint32 value
)
2616 case JSGC_MAX_BYTES
:
2617 rt
->gcMaxBytes
= value
;
2619 case JSGC_MAX_MALLOC_BYTES
:
2620 rt
->setGCMaxMallocBytes(value
);
2622 case JSGC_STACKPOOL_LIFESPAN
:
2623 rt
->gcEmptyArenaPoolLifespan
= value
;
2626 JS_ASSERT(key
== JSGC_TRIGGER_FACTOR
);
2627 JS_ASSERT(value
>= 100);
2628 rt
->setGCTriggerFactor(value
);
2633 JS_PUBLIC_API(uint32
)
2634 JS_GetGCParameter(JSRuntime
*rt
, JSGCParamKey key
)
2637 case JSGC_MAX_BYTES
:
2638 return rt
->gcMaxBytes
;
2639 case JSGC_MAX_MALLOC_BYTES
:
2640 return rt
->gcMaxMallocBytes
;
2641 case JSGC_STACKPOOL_LIFESPAN
:
2642 return rt
->gcEmptyArenaPoolLifespan
;
2643 case JSGC_TRIGGER_FACTOR
:
2644 return rt
->gcTriggerFactor
;
2648 JS_ASSERT(key
== JSGC_NUMBER
);
2649 return rt
->gcNumber
;
2654 JS_SetGCParameterForThread(JSContext
*cx
, JSGCParamKey key
, uint32 value
)
2656 JS_ASSERT(key
== JSGC_MAX_CODE_CACHE_BYTES
);
2658 SetMaxCodeCacheBytes(cx
, value
);
2662 JS_PUBLIC_API(uint32
)
2663 JS_GetGCParameterForThread(JSContext
*cx
, JSGCParamKey key
)
2665 JS_ASSERT(key
== JSGC_MAX_CODE_CACHE_BYTES
);
2667 return JS_THREAD_DATA(cx
)->traceMonitor
.maxCodeCacheBytes
;
2674 JS_FlushCaches(JSContext
*cx
)
2682 JS_AddExternalStringFinalizer(JSStringFinalizeOp finalizer
)
2684 return js_ChangeExternalStringFinalizer(NULL
, finalizer
);
2688 JS_RemoveExternalStringFinalizer(JSStringFinalizeOp finalizer
)
2690 return js_ChangeExternalStringFinalizer(finalizer
, NULL
);
2693 JS_PUBLIC_API(JSString
*)
2694 JS_NewExternalString(JSContext
*cx
, jschar
*chars
, size_t length
, intN type
)
2697 JS_ASSERT(uintN(type
) < JS_EXTERNAL_STRING_LIMIT
);
2699 JSString
*str
= js_NewGCExternalString(cx
, uintN(type
));
2702 str
->initFlat(chars
, length
);
2703 cx
->runtime
->updateMallocCounter((length
+ 1) * sizeof(jschar
));
2708 JS_GetExternalStringGCType(JSRuntime
*rt
, JSString
*str
)
2711 * No need to test this in js_GetExternalStringGCType, which asserts its
2712 * inverse instead of wasting cycles on testing a condition we can ensure
2713 * by auditing in-VM calls to the js_... helper.
2715 if (JSString::isStatic(str
))
2718 return js_GetExternalStringGCType(str
);
2722 JS_SetThreadStackLimit(JSContext
*cx
, jsuword limitAddr
)
2724 #if JS_STACK_GROWTH_DIRECTION > 0
2726 limitAddr
= jsuword(-1);
2728 cx
->stackLimit
= limitAddr
;
2732 JS_SetNativeStackQuota(JSContext
*cx
, size_t stackSize
)
2734 #ifdef JS_THREADSAFE
2735 JS_ASSERT(cx
->thread
);
2738 #if JS_STACK_GROWTH_DIRECTION > 0
2739 if (stackSize
== 0) {
2740 cx
->stackLimit
= jsuword(-1);
2742 jsuword stackBase
= reinterpret_cast<jsuword
>(JS_THREAD_DATA(cx
)->nativeStackBase
);
2743 JS_ASSERT(stackBase
<= size_t(-1) - stackSize
);
2744 cx
->stackLimit
= stackBase
+ stackSize
- 1;
2747 if (stackSize
== 0) {
2750 jsuword stackBase
= reinterpret_cast<jsuword
>(JS_THREAD_DATA(cx
)->nativeStackBase
);
2751 JS_ASSERT(stackBase
>= stackSize
);
2752 cx
->stackLimit
= stackBase
- (stackSize
- 1);
2758 JS_SetScriptStackQuota(JSContext
*cx
, size_t quota
)
2760 cx
->scriptStackQuota
= quota
;
2763 /************************************************************************/
2766 JS_DestroyIdArray(JSContext
*cx
, JSIdArray
*ida
)
2771 JS_PUBLIC_API(JSBool
)
2772 JS_ValueToId(JSContext
*cx
, jsval v
, jsid
*idp
)
2775 assertSameCompartment(cx
, v
);
2776 return ValueToId(cx
, Valueify(v
), idp
);
2779 JS_PUBLIC_API(JSBool
)
2780 JS_IdToValue(JSContext
*cx
, jsid id
, jsval
*vp
)
2783 *vp
= IdToJsval(id
);
2784 assertSameCompartment(cx
, *vp
);
2788 JS_PUBLIC_API(JSBool
)
2789 JS_PropertyStub(JSContext
*cx
, JSObject
*obj
, jsid id
, jsval
*vp
)
2794 JS_PUBLIC_API(JSBool
)
2795 JS_EnumerateStub(JSContext
*cx
, JSObject
*obj
)
2800 JS_PUBLIC_API(JSBool
)
2801 JS_ResolveStub(JSContext
*cx
, JSObject
*obj
, jsid id
)
2806 JS_PUBLIC_API(JSBool
)
2807 JS_ConvertStub(JSContext
*cx
, JSObject
*obj
, JSType type
, jsval
*vp
)
2809 JS_ASSERT(type
!= JSTYPE_OBJECT
&& type
!= JSTYPE_FUNCTION
);
2810 return js_TryValueOf(cx
, obj
, type
, Valueify(vp
));
2814 JS_FinalizeStub(JSContext
*cx
, JSObject
*obj
)
2817 JS_PUBLIC_API(JSObject
*)
2818 JS_InitClass(JSContext
*cx
, JSObject
*obj
, JSObject
*parent_proto
,
2819 JSClass
*clasp
, JSNative constructor
, uintN nargs
,
2820 JSPropertySpec
*ps
, JSFunctionSpec
*fs
,
2821 JSPropertySpec
*static_ps
, JSFunctionSpec
*static_fs
)
2824 assertSameCompartment(cx
, obj
, parent_proto
);
2825 return js_InitClass(cx
, obj
, parent_proto
, Valueify(clasp
),
2826 Valueify(constructor
), nargs
,
2827 ps
, fs
, static_ps
, static_fs
);
2830 #ifdef JS_THREADSAFE
2831 JS_PUBLIC_API(JSClass
*)
2832 JS_GetClass(JSContext
*cx
, JSObject
*obj
)
2834 return Jsvalify(obj
->getClass());
2837 JS_PUBLIC_API(JSClass
*)
2838 JS_GetClass(JSObject
*obj
)
2840 return Jsvalify(obj
->getClass());
2844 JS_PUBLIC_API(JSBool
)
2845 JS_InstanceOf(JSContext
*cx
, JSObject
*obj
, JSClass
*clasp
, jsval
*argv
)
2848 assertSameCompartment(cx
, obj
);
2849 return InstanceOf(cx
, obj
, Valueify(clasp
), Valueify(argv
));
2852 JS_PUBLIC_API(JSBool
)
2853 JS_HasInstance(JSContext
*cx
, JSObject
*obj
, jsval v
, JSBool
*bp
)
2855 assertSameCompartment(cx
, obj
, v
);
2856 return HasInstance(cx
, obj
, Valueify(&v
), bp
);
2859 JS_PUBLIC_API(void *)
2860 JS_GetPrivate(JSContext
*cx
, JSObject
*obj
)
2862 return obj
->getPrivate();
2865 JS_PUBLIC_API(JSBool
)
2866 JS_SetPrivate(JSContext
*cx
, JSObject
*obj
, void *data
)
2868 obj
->setPrivate(data
);
2872 JS_PUBLIC_API(void *)
2873 JS_GetInstancePrivate(JSContext
*cx
, JSObject
*obj
, JSClass
*clasp
, jsval
*argv
)
2875 if (!InstanceOf(cx
, obj
, Valueify(clasp
), Valueify(argv
)))
2877 return obj
->getPrivate();
2880 JS_PUBLIC_API(JSObject
*)
2881 JS_GetPrototype(JSContext
*cx
, JSObject
*obj
)
2886 assertSameCompartment(cx
, obj
);
2887 proto
= obj
->getProto();
2889 /* Beware ref to dead object (we may be called from obj's finalizer). */
2890 return proto
&& proto
->map
? proto
: NULL
;
2893 JS_PUBLIC_API(JSBool
)
2894 JS_SetPrototype(JSContext
*cx
, JSObject
*obj
, JSObject
*proto
)
2897 assertSameCompartment(cx
, obj
, proto
);
2898 return SetProto(cx
, obj
, proto
, JS_FALSE
);
2901 JS_PUBLIC_API(JSObject
*)
2902 JS_GetParent(JSContext
*cx
, JSObject
*obj
)
2904 assertSameCompartment(cx
, obj
);
2905 JSObject
*parent
= obj
->getParent();
2907 /* Beware ref to dead object (we may be called from obj's finalizer). */
2908 return parent
&& parent
->map
? parent
: NULL
;
2911 JS_PUBLIC_API(JSBool
)
2912 JS_SetParent(JSContext
*cx
, JSObject
*obj
, JSObject
*parent
)
2915 JS_ASSERT(parent
|| !obj
->getParent());
2916 assertSameCompartment(cx
, obj
, parent
);
2917 obj
->setParent(parent
);
2921 JS_PUBLIC_API(JSObject
*)
2922 JS_GetConstructor(JSContext
*cx
, JSObject
*proto
)
2927 assertSameCompartment(cx
, proto
);
2929 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
);
2931 if (!proto
->getProperty(cx
, ATOM_TO_JSID(cx
->runtime
->atomState
.constructorAtom
), &cval
))
2935 if (!IsFunctionObject(cval
, &funobj
)) {
2936 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_NO_CONSTRUCTOR
,
2937 proto
->getClass()->name
);
2940 return &cval
.toObject();
2943 JS_PUBLIC_API(JSBool
)
2944 JS_GetObjectId(JSContext
*cx
, JSObject
*obj
, jsid
*idp
)
2946 assertSameCompartment(cx
, obj
);
2947 *idp
= OBJECT_TO_JSID(obj
);
2951 JS_PUBLIC_API(JSObject
*)
2952 JS_NewGlobalObject(JSContext
*cx
, JSClass
*clasp
)
2954 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
2956 JS_ASSERT(clasp
->flags
& JSCLASS_IS_GLOBAL
);
2957 JSObject
*obj
= NewNonFunction
<WithProto::Given
>(cx
, Valueify(clasp
), NULL
, NULL
);
2961 /* Construct a regexp statics object for this global object. */
2962 JSObject
*res
= regexp_statics_construct(cx
, obj
);
2964 !js_SetReservedSlot(cx
, obj
, JSRESERVED_GLOBAL_REGEXP_STATICS
,
2965 ObjectValue(*res
))) {
2972 JS_PUBLIC_API(JSObject
*)
2973 JS_NewCompartmentAndGlobalObject(JSContext
*cx
, JSClass
*clasp
, JSPrincipals
*principals
)
2976 JSCompartment
*compartment
= NewCompartment(cx
, principals
);
2980 JSCompartment
*saved
= cx
->compartment
;
2981 cx
->compartment
= compartment
;
2982 JSObject
*obj
= JS_NewGlobalObject(cx
, clasp
);
2983 cx
->compartment
= saved
;
2988 JS_PUBLIC_API(JSObject
*)
2989 JS_NewObject(JSContext
*cx
, JSClass
*jsclasp
, JSObject
*proto
, JSObject
*parent
)
2991 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
2993 assertSameCompartment(cx
, proto
, parent
);
2995 Class
*clasp
= Valueify(jsclasp
);
2997 clasp
= &js_ObjectClass
; /* default class is Object */
2999 JS_ASSERT(clasp
!= &js_FunctionClass
);
3000 JS_ASSERT(!(clasp
->flags
& JSCLASS_IS_GLOBAL
));
3002 JSObject
*obj
= NewNonFunction
<WithProto::Class
>(cx
, clasp
, proto
, parent
);
3004 JS_ASSERT_IF(obj
, obj
->getParent());
3008 JS_PUBLIC_API(JSObject
*)
3009 JS_NewObjectWithGivenProto(JSContext
*cx
, JSClass
*jsclasp
, JSObject
*proto
, JSObject
*parent
)
3011 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
3013 assertSameCompartment(cx
, proto
, parent
);
3015 Class
*clasp
= Valueify(jsclasp
);
3017 clasp
= &js_ObjectClass
; /* default class is Object */
3019 JS_ASSERT(clasp
!= &js_FunctionClass
);
3020 JS_ASSERT(!(clasp
->flags
& JSCLASS_IS_GLOBAL
));
3022 return NewNonFunction
<WithProto::Given
>(cx
, clasp
, proto
, parent
);
3025 JS_PUBLIC_API(JSObject
*)
3026 JS_NewObjectForConstructor(JSContext
*cx
, const jsval
*vp
)
3029 assertSameCompartment(cx
, *vp
);
3031 return js_CreateThis(cx
, JSVAL_TO_OBJECT(*vp
));
3034 JS_PUBLIC_API(JSBool
)
3035 JS_IsExtensible(JSObject
*obj
)
3037 return obj
->isExtensible();
3040 JS_PUBLIC_API(JSBool
)
3041 JS_FreezeObject(JSContext
*cx
, JSObject
*obj
)
3044 assertSameCompartment(cx
, obj
);
3046 return obj
->freeze(cx
);
3049 JS_PUBLIC_API(JSBool
)
3050 JS_DeepFreezeObject(JSContext
*cx
, JSObject
*obj
)
3053 assertSameCompartment(cx
, obj
);
3055 /* Assume that non-extensible objects are already deep-frozen, to avoid divergence. */
3056 if (obj
->isExtensible())
3059 if (!obj
->freeze(cx
))
3062 /* Walk slots in obj and if any value is a non-null object, seal it. */
3063 for (uint32 i
= 0, n
= obj
->slotSpan(); i
< n
; ++i
) {
3064 const Value
&v
= obj
->getSlot(i
);
3065 if (v
.isPrimitive())
3067 if (!JS_DeepFreezeObject(cx
, &v
.toObject()))
3074 JS_PUBLIC_API(JSObject
*)
3075 JS_ConstructObject(JSContext
*cx
, JSClass
*jsclasp
, JSObject
*proto
, JSObject
*parent
)
3078 assertSameCompartment(cx
, proto
, parent
);
3079 Class
*clasp
= Valueify(jsclasp
);
3081 clasp
= &js_ObjectClass
; /* default class is Object */
3082 return js_ConstructObject(cx
, clasp
, proto
, parent
, 0, NULL
);
3085 JS_PUBLIC_API(JSObject
*)
3086 JS_ConstructObjectWithArguments(JSContext
*cx
, JSClass
*jsclasp
, JSObject
*proto
,
3087 JSObject
*parent
, uintN argc
, jsval
*argv
)
3090 assertSameCompartment(cx
, proto
, parent
, JSValueArray(argv
, argc
));
3091 Class
*clasp
= Valueify(jsclasp
);
3093 clasp
= &js_ObjectClass
; /* default class is Object */
3094 return js_ConstructObject(cx
, clasp
, proto
, parent
, argc
, Valueify(argv
));
3098 LookupPropertyById(JSContext
*cx
, JSObject
*obj
, jsid id
, uintN flags
,
3099 JSObject
**objp
, JSProperty
**propp
)
3102 assertSameCompartment(cx
, obj
, id
);
3104 JSAutoResolveFlags
rf(cx
, flags
);
3105 id
= js_CheckForStringIndex(id
);
3106 return obj
->lookupProperty(cx
, id
, objp
, propp
);
3109 #define AUTO_NAMELEN(s,n) (((n) == (size_t)-1) ? js_strlen(s) : (n))
3112 LookupResult(JSContext
*cx
, JSObject
*obj
, JSObject
*obj2
, jsid id
,
3113 JSProperty
*prop
, Value
*vp
)
3116 /* XXX bad API: no way to tell "not defined" from "void value" */
3121 if (obj2
->isNative()) {
3122 Shape
*shape
= (Shape
*) prop
;
3124 if (shape
->isMethod()) {
3125 AutoShapeRooter
root(cx
, shape
);
3126 vp
->setObject(shape
->methodObject());
3127 return obj2
->methodReadBarrier(cx
, *shape
, vp
);
3130 /* Peek at the native property's slot value, without doing a Get. */
3131 if (obj2
->containsSlot(shape
->slot
)) {
3132 *vp
= obj2
->nativeGetSlot(shape
->slot
);
3136 if (obj2
->isDenseArray())
3137 return js_GetDenseArrayElementValue(cx
, obj2
, id
, vp
);
3138 if (obj2
->isProxy()) {
3139 AutoPropertyDescriptorRooter
desc(cx
);
3140 if (!JSProxy::getPropertyDescriptor(cx
, obj2
, id
, false, &desc
))
3142 if (!(desc
.attrs
& JSPROP_SHARED
)) {
3149 /* XXX bad API: no way to return "defined but value unknown" */
3150 vp
->setBoolean(true);
3154 JS_PUBLIC_API(JSBool
)
3155 JS_LookupPropertyById(JSContext
*cx
, JSObject
*obj
, jsid id
, jsval
*vp
)
3159 return LookupPropertyById(cx
, obj
, id
, JSRESOLVE_QUALIFIED
, &obj2
, &prop
) &&
3160 LookupResult(cx
, obj
, obj2
, id
, prop
, Valueify(vp
));
3163 JS_PUBLIC_API(JSBool
)
3164 JS_LookupElement(JSContext
*cx
, JSObject
*obj
, jsint index
, jsval
*vp
)
3166 return JS_LookupPropertyById(cx
, obj
, INT_TO_JSID(index
), vp
);
3169 JS_PUBLIC_API(JSBool
)
3170 JS_LookupProperty(JSContext
*cx
, JSObject
*obj
, const char *name
, jsval
*vp
)
3172 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3173 return atom
&& JS_LookupPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), vp
);
3176 JS_PUBLIC_API(JSBool
)
3177 JS_LookupUCProperty(JSContext
*cx
, JSObject
*obj
, const jschar
*name
, size_t namelen
, jsval
*vp
)
3179 JSAtom
*atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
3180 return atom
&& JS_LookupPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), vp
);
3183 JS_PUBLIC_API(JSBool
)
3184 JS_LookupPropertyWithFlagsById(JSContext
*cx
, JSObject
*obj
, jsid id
, uintN flags
,
3185 JSObject
**objp
, jsval
*vp
)
3191 assertSameCompartment(cx
, obj
, id
);
3192 ok
= obj
->isNative()
3193 ? js_LookupPropertyWithFlags(cx
, obj
, id
, flags
, objp
, &prop
) >= 0
3194 : obj
->lookupProperty(cx
, id
, objp
, &prop
);
3195 return ok
&& LookupResult(cx
, obj
, *objp
, id
, prop
, Valueify(vp
));
3198 JS_PUBLIC_API(JSBool
)
3199 JS_LookupPropertyWithFlags(JSContext
*cx
, JSObject
*obj
, const char *name
, uintN flags
, jsval
*vp
)
3202 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3203 return atom
&& JS_LookupPropertyWithFlagsById(cx
, obj
, ATOM_TO_JSID(atom
), flags
, &obj2
, vp
);
3206 JS_PUBLIC_API(JSBool
)
3207 JS_HasPropertyById(JSContext
*cx
, JSObject
*obj
, jsid id
, JSBool
*foundp
)
3211 JSBool ok
= LookupPropertyById(cx
, obj
, id
, JSRESOLVE_QUALIFIED
| JSRESOLVE_DETECTING
,
3213 *foundp
= (prop
!= NULL
);
3217 JS_PUBLIC_API(JSBool
)
3218 JS_HasElement(JSContext
*cx
, JSObject
*obj
, jsint index
, JSBool
*foundp
)
3220 return JS_HasPropertyById(cx
, obj
, INT_TO_JSID(index
), foundp
);
3223 JS_PUBLIC_API(JSBool
)
3224 JS_HasProperty(JSContext
*cx
, JSObject
*obj
, const char *name
, JSBool
*foundp
)
3226 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3227 return atom
&& JS_HasPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), foundp
);
3230 JS_PUBLIC_API(JSBool
)
3231 JS_HasUCProperty(JSContext
*cx
, JSObject
*obj
, const jschar
*name
, size_t namelen
, JSBool
*foundp
)
3233 JSAtom
*atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
3234 return atom
&& JS_HasPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), foundp
);
3237 JS_PUBLIC_API(JSBool
)
3238 JS_AlreadyHasOwnPropertyById(JSContext
*cx
, JSObject
*obj
, jsid id
, JSBool
*foundp
)
3241 assertSameCompartment(cx
, obj
, id
);
3243 if (!obj
->isNative()) {
3247 if (!LookupPropertyById(cx
, obj
, id
, JSRESOLVE_QUALIFIED
| JSRESOLVE_DETECTING
,
3251 *foundp
= (obj
== obj2
);
3255 *foundp
= obj
->nativeContains(id
);
3259 JS_PUBLIC_API(JSBool
)
3260 JS_AlreadyHasOwnElement(JSContext
*cx
, JSObject
*obj
, jsint index
, JSBool
*foundp
)
3262 return JS_AlreadyHasOwnPropertyById(cx
, obj
, INT_TO_JSID(index
), foundp
);
3265 JS_PUBLIC_API(JSBool
)
3266 JS_AlreadyHasOwnProperty(JSContext
*cx
, JSObject
*obj
, const char *name
, JSBool
*foundp
)
3268 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3269 return atom
&& JS_AlreadyHasOwnPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), foundp
);
3272 JS_PUBLIC_API(JSBool
)
3273 JS_AlreadyHasOwnUCProperty(JSContext
*cx
, JSObject
*obj
, const jschar
*name
, size_t namelen
,
3276 JSAtom
*atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
3277 return atom
&& JS_AlreadyHasOwnPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), foundp
);
3281 DefinePropertyById(JSContext
*cx
, JSObject
*obj
, jsid id
, const Value
&value
,
3282 PropertyOp getter
, PropertyOp setter
, uintN attrs
,
3283 uintN flags
, intN tinyid
)
3286 assertSameCompartment(cx
, obj
, id
, value
,
3287 (attrs
& JSPROP_GETTER
)
3288 ? JS_FUNC_TO_DATA_PTR(JSObject
*, getter
)
3290 (attrs
& JSPROP_SETTER
)
3291 ? JS_FUNC_TO_DATA_PTR(JSObject
*, setter
)
3294 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
| JSRESOLVE_DECLARING
);
3295 if (flags
!= 0 && obj
->isNative()) {
3296 return !!js_DefineNativeProperty(cx
, obj
, id
, value
, getter
, setter
,
3297 attrs
, flags
, tinyid
, NULL
);
3299 return obj
->defineProperty(cx
, id
, value
, getter
, setter
, attrs
);
3302 JS_PUBLIC_API(JSBool
)
3303 JS_DefinePropertyById(JSContext
*cx
, JSObject
*obj
, jsid id
, jsval value
,
3304 JSPropertyOp getter
, JSPropertyOp setter
, uintN attrs
)
3306 return DefinePropertyById(cx
, obj
, id
, Valueify(value
), Valueify(getter
),
3307 Valueify(setter
), attrs
, 0, 0);
3310 JS_PUBLIC_API(JSBool
)
3311 JS_DefineElement(JSContext
*cx
, JSObject
*obj
, jsint index
, jsval value
,
3312 JSPropertyOp getter
, JSPropertyOp setter
, uintN attrs
)
3314 return DefinePropertyById(cx
, obj
, INT_TO_JSID(index
), Valueify(value
),
3315 Valueify(getter
), Valueify(setter
), attrs
, 0, 0);
3319 DefineProperty(JSContext
*cx
, JSObject
*obj
, const char *name
, const Value
&value
,
3320 PropertyOp getter
, PropertyOp setter
, uintN attrs
,
3321 uintN flags
, intN tinyid
)
3326 if (attrs
& JSPROP_INDEX
) {
3327 id
= INT_TO_JSID(intptr_t(name
));
3329 attrs
&= ~JSPROP_INDEX
;
3331 atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3334 id
= ATOM_TO_JSID(atom
);
3336 return DefinePropertyById(cx
, obj
, id
, value
, getter
, setter
, attrs
, flags
, tinyid
);
3339 JS_PUBLIC_API(JSBool
)
3340 JS_DefineProperty(JSContext
*cx
, JSObject
*obj
, const char *name
, jsval value
,
3341 JSPropertyOp getter
, JSPropertyOp setter
, uintN attrs
)
3343 return DefineProperty(cx
, obj
, name
, Valueify(value
), Valueify(getter
),
3344 Valueify(setter
), attrs
, 0, 0);
3347 JS_PUBLIC_API(JSBool
)
3348 JS_DefinePropertyWithTinyId(JSContext
*cx
, JSObject
*obj
, const char *name
, int8 tinyid
,
3349 jsval value
, JSPropertyOp getter
, JSPropertyOp setter
, uintN attrs
)
3351 return DefineProperty(cx
, obj
, name
, Valueify(value
), Valueify(getter
),
3352 Valueify(setter
), attrs
, Shape::HAS_SHORTID
, tinyid
);
3356 DefineUCProperty(JSContext
*cx
, JSObject
*obj
, const jschar
*name
, size_t namelen
,
3357 const Value
&value
, PropertyOp getter
, PropertyOp setter
, uintN attrs
,
3358 uintN flags
, intN tinyid
)
3360 JSAtom
*atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
3361 return atom
&& DefinePropertyById(cx
, obj
, ATOM_TO_JSID(atom
), value
, getter
, setter
, attrs
,
3365 JS_PUBLIC_API(JSBool
)
3366 JS_DefineUCProperty(JSContext
*cx
, JSObject
*obj
, const jschar
*name
, size_t namelen
,
3367 jsval value
, JSPropertyOp getter
, JSPropertyOp setter
, uintN attrs
)
3369 return DefineUCProperty(cx
, obj
, name
, namelen
, Valueify(value
),
3370 Valueify(getter
), Valueify(setter
), attrs
, 0, 0);
3373 JS_PUBLIC_API(JSBool
)
3374 JS_DefineUCPropertyWithTinyId(JSContext
*cx
, JSObject
*obj
, const jschar
*name
, size_t namelen
,
3375 int8 tinyid
, jsval value
, JSPropertyOp getter
, JSPropertyOp setter
,
3378 return DefineUCProperty(cx
, obj
, name
, namelen
, Valueify(value
), Valueify(getter
),
3379 Valueify(setter
), attrs
, Shape::HAS_SHORTID
, tinyid
);
3382 JS_PUBLIC_API(JSBool
)
3383 JS_DefineOwnProperty(JSContext
*cx
, JSObject
*obj
, jsid id
, jsval descriptor
, JSBool
*bp
)
3386 assertSameCompartment(cx
, obj
, id
, descriptor
);
3387 return js_DefineOwnProperty(cx
, obj
, id
, Valueify(descriptor
), bp
);
3390 JS_PUBLIC_API(JSObject
*)
3391 JS_DefineObject(JSContext
*cx
, JSObject
*obj
, const char *name
, JSClass
*jsclasp
,
3392 JSObject
*proto
, uintN attrs
)
3395 assertSameCompartment(cx
, obj
, proto
);
3397 Class
*clasp
= Valueify(jsclasp
);
3399 clasp
= &js_ObjectClass
; /* default class is Object */
3401 JSObject
*nobj
= NewObject
<WithProto::Class
>(cx
, clasp
, proto
, obj
);
3405 if (!DefineProperty(cx
, obj
, name
, ObjectValue(*nobj
), NULL
, NULL
, attrs
, 0, 0))
3411 JS_PUBLIC_API(JSBool
)
3412 JS_DefineConstDoubles(JSContext
*cx
, JSObject
*obj
, JSConstDoubleSpec
*cds
)
3418 for (ok
= JS_TRUE
; cds
->name
; cds
++) {
3419 Value value
= DoubleValue(cds
->dval
);
3422 attrs
= JSPROP_READONLY
| JSPROP_PERMANENT
;
3423 ok
= DefineProperty(cx
, obj
, cds
->name
, value
, NULL
, NULL
, attrs
, 0, 0);
3430 JS_PUBLIC_API(JSBool
)
3431 JS_DefineProperties(JSContext
*cx
, JSObject
*obj
, JSPropertySpec
*ps
)
3435 for (ok
= true; ps
->name
; ps
++) {
3436 ok
= DefineProperty(cx
, obj
, ps
->name
, UndefinedValue(),
3437 Valueify(ps
->getter
), Valueify(ps
->setter
),
3438 ps
->flags
, Shape::HAS_SHORTID
, ps
->tinyid
);
3445 JS_PUBLIC_API(JSBool
)
3446 JS_AliasProperty(JSContext
*cx
, JSObject
*obj
, const char *name
, const char *alias
)
3454 assertSameCompartment(cx
, obj
);
3456 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3459 if (!LookupPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), JSRESOLVE_QUALIFIED
, &obj2
, &prop
))
3462 js_ReportIsNotDefined(cx
, name
);
3465 if (obj2
!= obj
|| !obj
->isNative()) {
3466 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_CANT_ALIAS
,
3467 alias
, name
, obj2
->getClass()->name
);
3470 atom
= js_Atomize(cx
, alias
, strlen(alias
), 0);
3474 shape
= (Shape
*)prop
;
3475 ok
= (js_AddNativeProperty(cx
, obj
, ATOM_TO_JSID(atom
),
3476 shape
->getter(), shape
->setter(), shape
->slot
,
3477 shape
->attributes(), shape
->getFlags() | Shape::ALIAS
,
3484 JS_PUBLIC_API(JSBool
)
3485 JS_AliasElement(JSContext
*cx
, JSObject
*obj
, const char *name
, jsint alias
)
3492 assertSameCompartment(cx
, obj
);
3494 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3497 if (!LookupPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), JSRESOLVE_QUALIFIED
, &obj2
, &prop
))
3500 js_ReportIsNotDefined(cx
, name
);
3503 if (obj2
!= obj
|| !obj
->isNative()) {
3505 JS_snprintf(numBuf
, sizeof numBuf
, "%ld", (long)alias
);
3506 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_CANT_ALIAS
,
3507 numBuf
, name
, obj2
->getClass()->name
);
3510 shape
= (Shape
*)prop
;
3511 return js_AddNativeProperty(cx
, obj
, INT_TO_JSID(alias
),
3512 shape
->getter(), shape
->setter(), shape
->slot
,
3513 shape
->attributes(), shape
->getFlags() | Shape::ALIAS
,
3519 GetPropertyDescriptorById(JSContext
*cx
, JSObject
*obj
, jsid id
, uintN flags
,
3520 JSBool own
, PropertyDescriptor
*desc
)
3525 if (!LookupPropertyById(cx
, obj
, id
, flags
, &obj2
, &prop
))
3528 if (!prop
|| (own
&& obj
!= obj2
)) {
3531 desc
->getter
= NULL
;
3532 desc
->setter
= NULL
;
3533 desc
->value
.setUndefined();
3538 if (obj2
->isNative()) {
3539 Shape
*shape
= (Shape
*) prop
;
3540 desc
->attrs
= shape
->attributes();
3542 if (shape
->isMethod()) {
3543 desc
->getter
= desc
->setter
= PropertyStub
;
3544 desc
->value
.setObject(shape
->methodObject());
3546 desc
->getter
= shape
->getter();
3547 desc
->setter
= shape
->setter();
3548 if (obj2
->containsSlot(shape
->slot
))
3549 desc
->value
= obj2
->nativeGetSlot(shape
->slot
);
3551 desc
->value
.setUndefined();
3554 if (obj2
->isProxy()) {
3555 JSAutoResolveFlags
rf(cx
, flags
);
3557 ? JSProxy::getOwnPropertyDescriptor(cx
, obj2
, id
, false, desc
)
3558 : JSProxy::getPropertyDescriptor(cx
, obj2
, id
, false, desc
);
3560 if (!obj2
->getAttributes(cx
, id
, &desc
->attrs
))
3562 desc
->getter
= NULL
;
3563 desc
->setter
= NULL
;
3564 desc
->value
.setUndefined();
3569 JS_PUBLIC_API(JSBool
)
3570 JS_GetPropertyDescriptorById(JSContext
*cx
, JSObject
*obj
, jsid id
, uintN flags
,
3571 JSPropertyDescriptor
*desc
)
3573 return GetPropertyDescriptorById(cx
, obj
, id
, flags
, JS_FALSE
, Valueify(desc
));
3576 JS_PUBLIC_API(JSBool
)
3577 JS_GetPropertyAttrsGetterAndSetterById(JSContext
*cx
, JSObject
*obj
, jsid id
,
3578 uintN
*attrsp
, JSBool
*foundp
,
3579 JSPropertyOp
*getterp
, JSPropertyOp
*setterp
)
3581 PropertyDescriptor desc
;
3582 if (!GetPropertyDescriptorById(cx
, obj
, id
, JSRESOLVE_QUALIFIED
, JS_FALSE
, &desc
))
3585 *attrsp
= desc
.attrs
;
3586 *foundp
= (desc
.obj
!= NULL
);
3588 *getterp
= Jsvalify(desc
.getter
);
3590 *setterp
= Jsvalify(desc
.setter
);
3594 JS_PUBLIC_API(JSBool
)
3595 JS_GetPropertyAttributes(JSContext
*cx
, JSObject
*obj
, const char *name
,
3596 uintN
*attrsp
, JSBool
*foundp
)
3598 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3599 return atom
&& JS_GetPropertyAttrsGetterAndSetterById(cx
, obj
, ATOM_TO_JSID(atom
),
3600 attrsp
, foundp
, NULL
, NULL
);
3603 JS_PUBLIC_API(JSBool
)
3604 JS_GetUCPropertyAttributes(JSContext
*cx
, JSObject
*obj
, const jschar
*name
, size_t namelen
,
3605 uintN
*attrsp
, JSBool
*foundp
)
3607 JSAtom
*atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
3608 return atom
&& JS_GetPropertyAttrsGetterAndSetterById(cx
, obj
, ATOM_TO_JSID(atom
),
3609 attrsp
, foundp
, NULL
, NULL
);
3612 JS_PUBLIC_API(JSBool
)
3613 JS_GetPropertyAttrsGetterAndSetter(JSContext
*cx
, JSObject
*obj
, const char *name
,
3614 uintN
*attrsp
, JSBool
*foundp
,
3615 JSPropertyOp
*getterp
, JSPropertyOp
*setterp
)
3617 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3618 return atom
&& JS_GetPropertyAttrsGetterAndSetterById(cx
, obj
, ATOM_TO_JSID(atom
),
3619 attrsp
, foundp
, getterp
, setterp
);
3622 JS_PUBLIC_API(JSBool
)
3623 JS_GetUCPropertyAttrsGetterAndSetter(JSContext
*cx
, JSObject
*obj
,
3624 const jschar
*name
, size_t namelen
,
3625 uintN
*attrsp
, JSBool
*foundp
,
3626 JSPropertyOp
*getterp
, JSPropertyOp
*setterp
)
3628 JSAtom
*atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
3629 return atom
&& JS_GetPropertyAttrsGetterAndSetterById(cx
, obj
, ATOM_TO_JSID(atom
),
3630 attrsp
, foundp
, getterp
, setterp
);
3633 JS_PUBLIC_API(JSBool
)
3634 JS_GetOwnPropertyDescriptor(JSContext
*cx
, JSObject
*obj
, jsid id
, jsval
*vp
)
3637 return js_GetOwnPropertyDescriptor(cx
, obj
, id
, Valueify(vp
));
3641 SetPropertyAttributesById(JSContext
*cx
, JSObject
*obj
, jsid id
, uintN attrs
, JSBool
*foundp
)
3646 if (!LookupPropertyById(cx
, obj
, id
, JSRESOLVE_QUALIFIED
, &obj2
, &prop
))
3648 if (!prop
|| obj
!= obj2
) {
3652 JSBool ok
= obj
->isNative()
3653 ? js_SetNativeAttributes(cx
, obj
, (Shape
*) prop
, attrs
)
3654 : obj
->setAttributes(cx
, id
, &attrs
);
3660 JS_PUBLIC_API(JSBool
)
3661 JS_SetPropertyAttributes(JSContext
*cx
, JSObject
*obj
, const char *name
,
3662 uintN attrs
, JSBool
*foundp
)
3664 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3665 return atom
&& SetPropertyAttributesById(cx
, obj
, ATOM_TO_JSID(atom
), attrs
, foundp
);
3668 JS_PUBLIC_API(JSBool
)
3669 JS_SetUCPropertyAttributes(JSContext
*cx
, JSObject
*obj
, const jschar
*name
, size_t namelen
,
3670 uintN attrs
, JSBool
*foundp
)
3672 JSAtom
*atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
3673 return atom
&& SetPropertyAttributesById(cx
, obj
, ATOM_TO_JSID(atom
), attrs
, foundp
);
3676 JS_PUBLIC_API(JSBool
)
3677 JS_GetPropertyById(JSContext
*cx
, JSObject
*obj
, jsid id
, jsval
*vp
)
3680 assertSameCompartment(cx
, obj
, id
);
3681 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
);
3682 return obj
->getProperty(cx
, id
, Valueify(vp
));
3685 JS_PUBLIC_API(JSBool
)
3686 JS_GetPropertyByIdDefault(JSContext
*cx
, JSObject
*obj
, jsid id
, jsval def
, jsval
*vp
)
3688 return GetPropertyDefault(cx
, obj
, id
, Valueify(def
), Valueify(vp
));
3691 JS_PUBLIC_API(JSBool
)
3692 JS_GetElement(JSContext
*cx
, JSObject
*obj
, jsint index
, jsval
*vp
)
3694 return JS_GetPropertyById(cx
, obj
, INT_TO_JSID(index
), vp
);
3697 JS_PUBLIC_API(JSBool
)
3698 JS_GetProperty(JSContext
*cx
, JSObject
*obj
, const char *name
, jsval
*vp
)
3700 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3701 return atom
&& JS_GetPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), vp
);
3704 JS_PUBLIC_API(JSBool
)
3705 JS_GetPropertyDefault(JSContext
*cx
, JSObject
*obj
, const char *name
, jsval def
, jsval
*vp
)
3707 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3708 return atom
&& JS_GetPropertyByIdDefault(cx
, obj
, ATOM_TO_JSID(atom
), def
, vp
);
3711 JS_PUBLIC_API(JSBool
)
3712 JS_GetUCProperty(JSContext
*cx
, JSObject
*obj
, const jschar
*name
, size_t namelen
, jsval
*vp
)
3714 JSAtom
*atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
3715 return atom
&& JS_GetPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), vp
);
3718 JS_PUBLIC_API(JSBool
)
3719 JS_GetMethodById(JSContext
*cx
, JSObject
*obj
, jsid id
, JSObject
**objp
, jsval
*vp
)
3722 assertSameCompartment(cx
, obj
, id
);
3723 if (!js_GetMethod(cx
, obj
, id
, JSGET_METHOD_BARRIER
, Valueify(vp
)))
3730 JS_PUBLIC_API(JSBool
)
3731 JS_GetMethod(JSContext
*cx
, JSObject
*obj
, const char *name
, JSObject
**objp
, jsval
*vp
)
3733 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3734 return atom
&& JS_GetMethodById(cx
, obj
, ATOM_TO_JSID(atom
), objp
, vp
);
3737 JS_PUBLIC_API(JSBool
)
3738 JS_SetPropertyById(JSContext
*cx
, JSObject
*obj
, jsid id
, jsval
*vp
)
3741 assertSameCompartment(cx
, obj
, id
);
3742 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
| JSRESOLVE_ASSIGNING
);
3743 return obj
->setProperty(cx
, id
, Valueify(vp
), false);
3746 JS_PUBLIC_API(JSBool
)
3747 JS_SetElement(JSContext
*cx
, JSObject
*obj
, jsint index
, jsval
*vp
)
3749 return JS_SetPropertyById(cx
, obj
, INT_TO_JSID(index
), vp
);
3752 JS_PUBLIC_API(JSBool
)
3753 JS_SetProperty(JSContext
*cx
, JSObject
*obj
, const char *name
, jsval
*vp
)
3755 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3756 return atom
&& JS_SetPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), vp
);
3759 JS_PUBLIC_API(JSBool
)
3760 JS_SetUCProperty(JSContext
*cx
, JSObject
*obj
, const jschar
*name
, size_t namelen
, jsval
*vp
)
3762 JSAtom
*atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
3763 return atom
&& JS_SetPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), vp
);
3766 JS_PUBLIC_API(JSBool
)
3767 JS_DeletePropertyById2(JSContext
*cx
, JSObject
*obj
, jsid id
, jsval
*rval
)
3770 assertSameCompartment(cx
, obj
, id
);
3771 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
);
3772 return obj
->deleteProperty(cx
, id
, Valueify(rval
), false);
3775 JS_PUBLIC_API(JSBool
)
3776 JS_DeleteElement2(JSContext
*cx
, JSObject
*obj
, jsint index
, jsval
*rval
)
3778 return JS_DeletePropertyById2(cx
, obj
, INT_TO_JSID(index
), rval
);
3781 JS_PUBLIC_API(JSBool
)
3782 JS_DeleteProperty2(JSContext
*cx
, JSObject
*obj
, const char *name
, jsval
*rval
)
3784 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3785 return atom
&& JS_DeletePropertyById2(cx
, obj
, ATOM_TO_JSID(atom
), rval
);
3788 JS_PUBLIC_API(JSBool
)
3789 JS_DeleteUCProperty2(JSContext
*cx
, JSObject
*obj
, const jschar
*name
, size_t namelen
, jsval
*rval
)
3791 JSAtom
*atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
3792 return atom
&& JS_DeletePropertyById2(cx
, obj
, ATOM_TO_JSID(atom
), rval
);
3795 JS_PUBLIC_API(JSBool
)
3796 JS_DeletePropertyById(JSContext
*cx
, JSObject
*obj
, jsid id
)
3799 return JS_DeletePropertyById2(cx
, obj
, id
, &junk
);
3802 JS_PUBLIC_API(JSBool
)
3803 JS_DeleteElement(JSContext
*cx
, JSObject
*obj
, jsint index
)
3806 return JS_DeleteElement2(cx
, obj
, index
, &junk
);
3809 JS_PUBLIC_API(JSBool
)
3810 JS_DeleteProperty(JSContext
*cx
, JSObject
*obj
, const char *name
)
3813 return JS_DeleteProperty2(cx
, obj
, name
, &junk
);
3817 JS_ClearScope(JSContext
*cx
, JSObject
*obj
)
3820 assertSameCompartment(cx
, obj
);
3822 JSFinalizeOp clearOp
= obj
->getOps()->clear
;
3826 if (obj
->isNative())
3827 js_ClearNative(cx
, obj
);
3829 /* Clear cached class objects on the global object. */
3830 if (obj
->getClass()->flags
& JSCLASS_IS_GLOBAL
) {
3833 for (key
= JSProto_Null
; key
< JSProto_LIMIT
* 3; key
++)
3834 JS_SetReservedSlot(cx
, obj
, key
, JSVAL_VOID
);
3840 JS_PUBLIC_API(JSIdArray
*)
3841 JS_Enumerate(JSContext
*cx
, JSObject
*obj
)
3844 assertSameCompartment(cx
, obj
);
3846 AutoIdVector
props(cx
);
3848 if (!GetPropertyNames(cx
, obj
, JSITER_OWNONLY
, &props
) || !VectorToIdArray(cx
, props
, &ida
))
3850 for (size_t n
= 0; n
< size_t(ida
->length
); ++n
)
3851 JS_ASSERT(js_CheckForStringIndex(ida
->vector
[n
]) == ida
->vector
[n
]);
3856 * XXX reverse iterator for properties, unreverse and meld with jsinterp.c's
3857 * prop_iterator_class somehow...
3858 * + preserve the obj->enumerate API while optimizing the native object case
3859 * + native case here uses a Shape *, but that iterates in reverse!
3860 * + so we make non-native match, by reverse-iterating after JS_Enumerating
3862 const uint32 JSSLOT_ITER_INDEX
= 0;
3865 prop_iter_finalize(JSContext
*cx
, JSObject
*obj
)
3867 void *pdata
= obj
->getPrivate();
3871 if (obj
->getSlot(JSSLOT_ITER_INDEX
).toInt32() >= 0) {
3872 /* Non-native case: destroy the ida enumerated when obj was created. */
3873 JSIdArray
*ida
= (JSIdArray
*) pdata
;
3874 JS_DestroyIdArray(cx
, ida
);
3879 prop_iter_trace(JSTracer
*trc
, JSObject
*obj
)
3881 void *pdata
= obj
->getPrivate();
3885 if (obj
->getSlot(JSSLOT_ITER_INDEX
).toInt32() < 0) {
3886 /* Native case: just mark the next property to visit. */
3887 ((Shape
*) pdata
)->trace(trc
);
3889 /* Non-native case: mark each id in the JSIdArray private. */
3890 JSIdArray
*ida
= (JSIdArray
*) pdata
;
3891 MarkIdRange(trc
, ida
->length
, ida
->vector
, "prop iter");
3895 static Class prop_iter_class
= {
3897 JSCLASS_HAS_PRIVATE
| JSCLASS_HAS_RESERVED_SLOTS(1) |
3898 JSCLASS_MARK_IS_TRACE
,
3899 PropertyStub
, /* addProperty */
3900 PropertyStub
, /* delProperty */
3901 PropertyStub
, /* getProperty */
3902 PropertyStub
, /* setProperty */
3907 NULL
, /* reserved0 */
3908 NULL
, /* checkAccess */
3910 NULL
, /* construct */
3911 NULL
, /* xdrObject */
3912 NULL
, /* hasInstance */
3913 JS_CLASS_TRACE(prop_iter_trace
)
3916 JS_PUBLIC_API(JSObject
*)
3917 JS_NewPropertyIterator(JSContext
*cx
, JSObject
*obj
)
3925 assertSameCompartment(cx
, obj
);
3926 iterobj
= NewNonFunction
<WithProto::Class
>(cx
, &prop_iter_class
, NULL
, obj
);
3930 if (obj
->isNative()) {
3931 /* Native case: start with the last property in obj. */
3932 pdata
= obj
->lastProperty();
3936 * Non-native case: enumerate a JSIdArray and keep it via private.
3938 * Note: we have to make sure that we root obj around the call to
3939 * JS_Enumerate to protect against multiple allocations under it.
3941 AutoObjectRooter
tvr(cx
, iterobj
);
3942 ida
= JS_Enumerate(cx
, obj
);
3946 index
= ida
->length
;
3949 /* iterobj cannot escape to other threads here. */
3950 iterobj
->setPrivate(const_cast<void *>(pdata
));
3951 iterobj
->getSlotRef(JSSLOT_ITER_INDEX
).setInt32(index
);
3955 JS_PUBLIC_API(JSBool
)
3956 JS_NextProperty(JSContext
*cx
, JSObject
*iterobj
, jsid
*idp
)
3964 assertSameCompartment(cx
, iterobj
);
3965 i
= iterobj
->getSlot(JSSLOT_ITER_INDEX
).toInt32();
3967 /* Native case: private data is a property tree node pointer. */
3968 obj
= iterobj
->getParent();
3969 JS_ASSERT(obj
->isNative());
3970 shape
= (Shape
*) iterobj
->getPrivate();
3973 * If the next property mapped by obj in the property tree ancestor
3974 * line is not enumerable, or it's an alias, skip it and keep on trying
3975 * to find an enumerable property that is still in obj.
3977 while (shape
->previous() && (!shape
->enumerable() || shape
->isAlias()))
3978 shape
= shape
->previous();
3980 if (!shape
->previous()) {
3981 JS_ASSERT(JSID_IS_EMPTY(shape
->id
));
3984 iterobj
->setPrivate(const_cast<Shape
*>(shape
->previous()));
3988 /* Non-native case: use the ida enumerated when iterobj was created. */
3989 ida
= (JSIdArray
*) iterobj
->getPrivate();
3990 JS_ASSERT(i
<= ida
->length
);
3991 STATIC_ASSUME(i
<= ida
->length
);
3995 *idp
= ida
->vector
[--i
];
3996 iterobj
->setSlot(JSSLOT_ITER_INDEX
, Int32Value(i
));
4002 JS_PUBLIC_API(JSBool
)
4003 JS_GetReservedSlot(JSContext
*cx
, JSObject
*obj
, uint32 index
, jsval
*vp
)
4006 assertSameCompartment(cx
, obj
);
4007 return js_GetReservedSlot(cx
, obj
, index
, Valueify(vp
));
4010 JS_PUBLIC_API(JSBool
)
4011 JS_SetReservedSlot(JSContext
*cx
, JSObject
*obj
, uint32 index
, jsval v
)
4014 assertSameCompartment(cx
, obj
, v
);
4015 return js_SetReservedSlot(cx
, obj
, index
, Valueify(v
));
4018 JS_PUBLIC_API(JSObject
*)
4019 JS_NewArrayObject(JSContext
*cx
, jsint length
, jsval
*vector
)
4021 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
4023 /* NB: jsuint cast does ToUint32. */
4024 assertSameCompartment(cx
, JSValueArray(vector
, vector
? (jsuint
)length
: 0));
4025 return js_NewArrayObject(cx
, (jsuint
)length
, Valueify(vector
));
4028 JS_PUBLIC_API(JSBool
)
4029 JS_IsArrayObject(JSContext
*cx
, JSObject
*obj
)
4031 assertSameCompartment(cx
, obj
);
4032 return obj
->isArray() ||
4033 (obj
->isWrapper() && JSWrapper::wrappedObject(obj
)->isArray());
4036 JS_PUBLIC_API(JSBool
)
4037 JS_GetArrayLength(JSContext
*cx
, JSObject
*obj
, jsuint
*lengthp
)
4040 assertSameCompartment(cx
, obj
);
4041 return js_GetLengthProperty(cx
, obj
, lengthp
);
4044 JS_PUBLIC_API(JSBool
)
4045 JS_SetArrayLength(JSContext
*cx
, JSObject
*obj
, jsuint length
)
4048 assertSameCompartment(cx
, obj
);
4049 return js_SetLengthProperty(cx
, obj
, length
);
4052 JS_PUBLIC_API(JSBool
)
4053 JS_HasArrayLength(JSContext
*cx
, JSObject
*obj
, jsuint
*lengthp
)
4056 assertSameCompartment(cx
, obj
);
4057 return js_HasLengthProperty(cx
, obj
, lengthp
);
4060 JS_PUBLIC_API(JSBool
)
4061 JS_CheckAccess(JSContext
*cx
, JSObject
*obj
, jsid id
, JSAccessMode mode
,
4062 jsval
*vp
, uintN
*attrsp
)
4065 assertSameCompartment(cx
, obj
, id
);
4066 return CheckAccess(cx
, obj
, id
, mode
, Valueify(vp
), attrsp
);
4069 #ifdef JS_THREADSAFE
4070 JS_PUBLIC_API(jsrefcount
)
4071 JS_HoldPrincipals(JSContext
*cx
, JSPrincipals
*principals
)
4073 return JS_ATOMIC_INCREMENT(&principals
->refcount
);
4076 JS_PUBLIC_API(jsrefcount
)
4077 JS_DropPrincipals(JSContext
*cx
, JSPrincipals
*principals
)
4079 jsrefcount rc
= JS_ATOMIC_DECREMENT(&principals
->refcount
);
4081 principals
->destroy(cx
, principals
);
4086 JS_PUBLIC_API(JSSecurityCallbacks
*)
4087 JS_SetRuntimeSecurityCallbacks(JSRuntime
*rt
, JSSecurityCallbacks
*callbacks
)
4089 JSSecurityCallbacks
*oldcallbacks
;
4091 oldcallbacks
= rt
->securityCallbacks
;
4092 rt
->securityCallbacks
= callbacks
;
4093 return oldcallbacks
;
4096 JS_PUBLIC_API(JSSecurityCallbacks
*)
4097 JS_GetRuntimeSecurityCallbacks(JSRuntime
*rt
)
4099 return rt
->securityCallbacks
;
4102 JS_PUBLIC_API(JSSecurityCallbacks
*)
4103 JS_SetContextSecurityCallbacks(JSContext
*cx
, JSSecurityCallbacks
*callbacks
)
4105 JSSecurityCallbacks
*oldcallbacks
;
4107 oldcallbacks
= cx
->securityCallbacks
;
4108 cx
->securityCallbacks
= callbacks
;
4109 return oldcallbacks
;
4112 JS_PUBLIC_API(JSSecurityCallbacks
*)
4113 JS_GetSecurityCallbacks(JSContext
*cx
)
4115 return cx
->securityCallbacks
4116 ? cx
->securityCallbacks
4117 : cx
->runtime
->securityCallbacks
;
4120 JS_PUBLIC_API(JSFunction
*)
4121 JS_NewFunction(JSContext
*cx
, JSNative native
, uintN nargs
, uintN flags
,
4122 JSObject
*parent
, const char *name
)
4124 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
4128 assertSameCompartment(cx
, parent
);
4133 atom
= js_Atomize(cx
, name
, strlen(name
), 0);
4137 return js_NewFunction(cx
, NULL
, Valueify(native
), nargs
, flags
, parent
, atom
);
4140 JS_PUBLIC_API(JSObject
*)
4141 JS_CloneFunctionObject(JSContext
*cx
, JSObject
*funobj
, JSObject
*parent
)
4144 assertSameCompartment(cx
, parent
); // XXX no funobj for now
4147 parent
= GetScopeChain(cx
, cx
->fp());
4149 parent
= cx
->globalObject
;
4153 if (funobj
->getClass() != &js_FunctionClass
) {
4155 * We cannot clone this object, so fail (we used to return funobj, bad
4156 * idea, but we changed incompatibly to teach any abusers a lesson!).
4158 Value v
= ObjectValue(*funobj
);
4159 js_ReportIsNotFunction(cx
, &v
, 0);
4163 JSFunction
*fun
= GET_FUNCTION_PRIVATE(cx
, funobj
);
4164 if (!FUN_FLAT_CLOSURE(fun
))
4165 return CloneFunctionObject(cx
, fun
, parent
);
4168 * A flat closure carries its own environment, so why clone it? In case
4169 * someone wants to mutate its fixed slots or add ad-hoc properties. API
4170 * compatibility suggests we not return funobj and let callers mutate the
4171 * returned object at will.
4173 * But it's worse than that: API compatibility according to the test for
4174 * bug 300079 requires we get "upvars" from parent and its ancestors! So
4175 * we do that (grudgingly!). The scope chain ancestors are searched as if
4176 * they were activations, respecting the skip field in each upvar's cookie
4177 * but looking up the property by name instead of frame slot.
4179 JSObject
*clone
= js_AllocFlatClosure(cx
, fun
, parent
);
4183 JSUpvarArray
*uva
= fun
->u
.i
.script
->upvars();
4184 uint32 i
= uva
->length
;
4187 for (Shape::Range
r(fun
->lastUpvar()); i
-- != 0; r
.popFront()) {
4188 JSObject
*obj
= parent
;
4189 int skip
= uva
->vector
[i
].level();
4190 while (--skip
> 0) {
4192 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
,
4193 JSMSG_BAD_CLONE_FUNOBJ_SCOPE
);
4196 obj
= obj
->getParent();
4199 if (!obj
->getProperty(cx
, r
.front().id
, clone
->getFlatClosureUpvars() + i
))
4206 JS_PUBLIC_API(JSObject
*)
4207 JS_GetFunctionObject(JSFunction
*fun
)
4209 return FUN_OBJECT(fun
);
4212 JS_PUBLIC_API(const char *)
4213 JS_GetFunctionName(JSFunction
*fun
)
4216 ? JS_GetStringBytes(ATOM_TO_STRING(fun
->atom
))
4220 JS_PUBLIC_API(JSString
*)
4221 JS_GetFunctionId(JSFunction
*fun
)
4223 return fun
->atom
? ATOM_TO_STRING(fun
->atom
) : NULL
;
4226 JS_PUBLIC_API(uintN
)
4227 JS_GetFunctionFlags(JSFunction
*fun
)
4232 JS_PUBLIC_API(uint16
)
4233 JS_GetFunctionArity(JSFunction
*fun
)
4238 JS_PUBLIC_API(JSBool
)
4239 JS_ObjectIsFunction(JSContext
*cx
, JSObject
*obj
)
4241 return obj
->getClass() == &js_FunctionClass
;
4245 js_generic_native_method_dispatcher(JSContext
*cx
, uintN argc
, Value
*vp
)
4251 fs
= (JSFunctionSpec
*) vp
->toObject().getReservedSlot(0).toPrivate();
4252 JS_ASSERT((fs
->flags
& JSFUN_GENERIC_NATIVE
) != 0);
4255 js_ReportMissingArg(cx
, *vp
, 0);
4259 if (vp
[2].isPrimitive()) {
4261 * Make sure that this is an object or null, as required by the generic
4264 if (!js_ValueToObjectOrNull(cx
, vp
[2], &tmp
))
4266 vp
[2].setObjectOrNull(tmp
);
4270 * Copy all actual (argc) arguments down over our |this| parameter, vp[1],
4271 * which is almost always the class constructor object, e.g. Array. Then
4272 * call the corresponding prototype native method with our first argument
4275 memmove(vp
+ 1, vp
+ 2, argc
* sizeof(jsval
));
4278 * Follow Function.prototype.apply and .call by using the global object as
4279 * the 'this' param if no args.
4281 if (!ComputeThisFromArgv(cx
, vp
+ 2))
4284 /* Clear the last parameter in case too few arguments were passed. */
4285 vp
[2 + --argc
].setUndefined();
4289 (fs
->flags
& JSFUN_TRCINFO
)
4290 ? JS_FUNC_TO_DATA_PTR(JSNativeTraceInfo
*, fs
->call
)->native
4294 return native(cx
, argc
, vp
);
4297 JS_PUBLIC_API(JSBool
)
4298 JS_DefineFunctions(JSContext
*cx
, JSObject
*obj
, JSFunctionSpec
*fs
)
4300 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
4306 assertSameCompartment(cx
, obj
);
4308 for (; fs
->name
; fs
++) {
4312 * Define a generic arity N+1 static method for the arity N prototype
4313 * method if flags contains JSFUN_GENERIC_NATIVE.
4315 if (flags
& JSFUN_GENERIC_NATIVE
) {
4317 ctor
= JS_GetConstructor(cx
, obj
);
4322 flags
&= ~JSFUN_GENERIC_NATIVE
;
4323 fun
= JS_DefineFunction(cx
, ctor
, fs
->name
,
4324 Jsvalify(js_generic_native_method_dispatcher
),
4326 flags
& ~JSFUN_TRCINFO
);
4331 * As jsapi.h notes, fs must point to storage that lives as long
4332 * as fun->object lives.
4334 Value priv
= PrivateValue(fs
);
4335 if (!js_SetReservedSlot(cx
, FUN_OBJECT(fun
), 0, priv
))
4339 fun
= JS_DefineFunction(cx
, obj
, fs
->name
, fs
->call
, fs
->nargs
, flags
);
4346 JS_PUBLIC_API(JSFunction
*)
4347 JS_DefineFunction(JSContext
*cx
, JSObject
*obj
, const char *name
, JSNative call
,
4348 uintN nargs
, uintN attrs
)
4350 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
4352 assertSameCompartment(cx
, obj
);
4353 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
4354 return atom
? js_DefineFunction(cx
, obj
, atom
, Valueify(call
), nargs
, attrs
) : NULL
;
4357 JS_PUBLIC_API(JSFunction
*)
4358 JS_DefineUCFunction(JSContext
*cx
, JSObject
*obj
,
4359 const jschar
*name
, size_t namelen
, JSNative call
,
4360 uintN nargs
, uintN attrs
)
4362 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
4364 assertSameCompartment(cx
, obj
);
4365 JSAtom
*atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
4366 return atom
? js_DefineFunction(cx
, obj
, atom
, Valueify(call
), nargs
, attrs
) : NULL
;
4370 LAST_FRAME_EXCEPTION_CHECK(JSContext
*cx
, bool result
)
4372 if (!result
&& !(cx
->options
& JSOPTION_DONT_REPORT_UNCAUGHT
))
4373 js_ReportUncaughtException(cx
);
4377 LAST_FRAME_CHECKS(JSContext
*cx
, bool result
)
4379 if (!JS_IsRunning(cx
)) {
4380 LAST_FRAME_EXCEPTION_CHECK(cx
, result
);
4384 inline static uint32
4385 JS_OPTIONS_TO_TCFLAGS(JSContext
*cx
)
4387 return ((cx
->options
& JSOPTION_COMPILE_N_GO
) ? TCF_COMPILE_N_GO
: 0) |
4388 ((cx
->options
& JSOPTION_NO_SCRIPT_RVAL
) ? TCF_NO_SCRIPT_RVAL
: 0);
4391 extern JS_PUBLIC_API(JSScript
*)
4392 JS_CompileUCScriptForPrincipalsVersion(JSContext
*cx
, JSObject
*obj
,
4393 JSPrincipals
*principals
,
4394 const jschar
*chars
, size_t length
,
4395 const char *filename
, uintN lineno
,
4398 AutoVersionAPI
avi(cx
, version
);
4399 return JS_CompileUCScriptForPrincipals(cx
, obj
, principals
, chars
, length
, filename
, lineno
);
4402 JS_PUBLIC_API(JSScript
*)
4403 JS_CompileUCScriptForPrincipals(JSContext
*cx
, JSObject
*obj
, JSPrincipals
*principals
,
4404 const jschar
*chars
, size_t length
,
4405 const char *filename
, uintN lineno
)
4407 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
4409 assertSameCompartment(cx
, obj
, principals
);
4411 uint32 tcflags
= JS_OPTIONS_TO_TCFLAGS(cx
) | TCF_NEED_MUTABLE_SCRIPT
;
4412 JSScript
*script
= Compiler::compileScript(cx
, obj
, NULL
, principals
, tcflags
,
4413 chars
, length
, NULL
, filename
, lineno
);
4414 if (script
&& !js_NewScriptObject(cx
, script
)) {
4415 js_DestroyScript(cx
, script
);
4418 LAST_FRAME_CHECKS(cx
, script
);
4422 JS_PUBLIC_API(JSScript
*)
4423 JS_CompileUCScript(JSContext
*cx
, JSObject
*obj
, const jschar
*chars
, size_t length
,
4424 const char *filename
, uintN lineno
)
4426 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
4427 return JS_CompileUCScriptForPrincipals(cx
, obj
, NULL
, chars
, length
, filename
, lineno
);
4430 JS_PUBLIC_API(JSScript
*)
4431 JS_CompileScriptForPrincipals(JSContext
*cx
, JSObject
*obj
,
4432 JSPrincipals
*principals
,
4433 const char *bytes
, size_t length
,
4434 const char *filename
, uintN lineno
)
4436 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
4439 jschar
*chars
= js_InflateString(cx
, bytes
, &length
);
4442 JSScript
*script
= JS_CompileUCScriptForPrincipals(cx
, obj
, principals
, chars
, length
, filename
, lineno
);
4447 JS_PUBLIC_API(JSScript
*)
4448 JS_CompileScript(JSContext
*cx
, JSObject
*obj
, const char *bytes
, size_t length
,
4449 const char *filename
, uintN lineno
)
4451 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
4452 return JS_CompileScriptForPrincipals(cx
, obj
, NULL
, bytes
, length
, filename
, lineno
);
4455 JS_PUBLIC_API(JSBool
)
4456 JS_BufferIsCompilableUnit(JSContext
*cx
, JSObject
*obj
, const char *bytes
, size_t length
)
4460 JSExceptionState
*exnState
;
4461 JSErrorReporter older
;
4464 assertSameCompartment(cx
, obj
);
4465 chars
= js_InflateString(cx
, bytes
, &length
);
4470 * Return true on any out-of-memory error, so our caller doesn't try to
4471 * collect more buffered source.
4474 exnState
= JS_SaveExceptionState(cx
);
4477 if (parser
.init(chars
, length
, NULL
, NULL
, 1)) {
4478 older
= JS_SetErrorReporter(cx
, NULL
);
4479 if (!parser
.parse(obj
) &&
4480 parser
.tokenStream
.isUnexpectedEOF()) {
4482 * We ran into an error. If it was because we ran out of
4483 * source, we return false so our caller knows to try to
4484 * collect more buffered source.
4488 JS_SetErrorReporter(cx
, older
);
4492 JS_RestoreExceptionState(cx
, exnState
);
4496 JS_PUBLIC_API(JSScript
*)
4497 JS_CompileFile(JSContext
*cx
, JSObject
*obj
, const char *filename
)
4499 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
4505 assertSameCompartment(cx
, obj
);
4506 if (!filename
|| strcmp(filename
, "-") == 0) {
4509 fp
= fopen(filename
, "r");
4511 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_CANT_OPEN
,
4512 filename
, "No such file or directory");
4517 tcflags
= JS_OPTIONS_TO_TCFLAGS(cx
) | TCF_NEED_MUTABLE_SCRIPT
;
4518 script
= Compiler::compileScript(cx
, obj
, NULL
, NULL
, tcflags
,
4519 NULL
, 0, fp
, filename
, 1);
4522 if (script
&& !js_NewScriptObject(cx
, script
)) {
4523 js_DestroyScript(cx
, script
);
4526 LAST_FRAME_CHECKS(cx
, script
);
4530 JS_PUBLIC_API(JSScript
*)
4531 JS_CompileFileHandleForPrincipals(JSContext
*cx
, JSObject
*obj
, const char *filename
, FILE *file
,
4532 JSPrincipals
*principals
)
4534 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
4539 assertSameCompartment(cx
, obj
, principals
);
4540 tcflags
= JS_OPTIONS_TO_TCFLAGS(cx
) | TCF_NEED_MUTABLE_SCRIPT
;
4541 script
= Compiler::compileScript(cx
, obj
, NULL
, principals
, tcflags
,
4542 NULL
, 0, file
, filename
, 1);
4543 if (script
&& !js_NewScriptObject(cx
, script
)) {
4544 js_DestroyScript(cx
, script
);
4547 LAST_FRAME_CHECKS(cx
, script
);
4551 JS_PUBLIC_API(JSScript
*)
4552 JS_CompileFileHandle(JSContext
*cx
, JSObject
*obj
, const char *filename
, FILE *file
)
4554 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
4555 return JS_CompileFileHandleForPrincipals(cx
, obj
, filename
, file
, NULL
);
4558 JS_PUBLIC_API(JSObject
*)
4559 JS_NewScriptObject(JSContext
*cx
, JSScript
*script
)
4561 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
4563 assertSameCompartment(cx
, script
);
4565 return NewNonFunction
<WithProto::Class
>(cx
, &js_ScriptClass
, NULL
, NULL
);
4568 * This function should only ever be applied to JSScripts that had
4569 * script objects allocated for them when they were created, as
4570 * described in the comment for JSScript::u.object.
4572 JS_ASSERT(script
->u
.object
);
4573 JS_ASSERT(script
!= JSScript::emptyScript());
4574 return script
->u
.object
;
4577 JS_PUBLIC_API(JSObject
*)
4578 JS_GetScriptObject(JSScript
*script
)
4581 * This function should only ever be applied to JSScripts that had
4582 * script objects allocated for them when they were created, as
4583 * described in the comment for JSScript::u.object.
4585 JS_ASSERT(script
->u
.object
);
4586 return script
->u
.object
;
4590 JS_DestroyScript(JSContext
*cx
, JSScript
*script
)
4595 * Originally, JSScript lifetimes were managed explicitly, and this function
4596 * was used to free a JSScript. Now, this function does nothing, and the
4597 * garbage collector manages JSScripts; you must root the JSScript's script
4598 * object (obtained via JS_GetScriptObject) to keep it alive.
4600 * However, since the script objects have taken over this responsibility, it
4601 * follows that every script passed here must have a script object.
4603 JS_ASSERT(script
->u
.object
);
4606 JS_PUBLIC_API(JSFunction
*)
4607 JS_CompileUCFunctionForPrincipalsVersion(JSContext
*cx
, JSObject
*obj
,
4608 JSPrincipals
*principals
, const char *name
,
4609 uintN nargs
, const char **argnames
,
4610 const jschar
*chars
, size_t length
,
4611 const char *filename
, uintN lineno
,
4614 AutoVersionAPI
avi(cx
, version
);
4615 return JS_CompileUCFunctionForPrincipals(cx
, obj
, principals
, name
, nargs
, argnames
, chars
,
4616 length
, filename
, lineno
);
4619 JS_PUBLIC_API(JSFunction
*)
4620 JS_CompileUCFunctionForPrincipals(JSContext
*cx
, JSObject
*obj
,
4621 JSPrincipals
*principals
, const char *name
,
4622 uintN nargs
, const char **argnames
,
4623 const jschar
*chars
, size_t length
,
4624 const char *filename
, uintN lineno
)
4626 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
4628 JSAtom
*funAtom
, *argAtom
;
4632 assertSameCompartment(cx
, obj
, principals
);
4636 funAtom
= js_Atomize(cx
, name
, strlen(name
), 0);
4642 fun
= js_NewFunction(cx
, NULL
, NULL
, 0, JSFUN_INTERPRETED
, obj
, funAtom
);
4647 AutoObjectRooter
tvr(cx
, FUN_OBJECT(fun
));
4648 MUST_FLOW_THROUGH("out");
4650 for (i
= 0; i
< nargs
; i
++) {
4651 argAtom
= js_Atomize(cx
, argnames
[i
], strlen(argnames
[i
]), 0);
4656 if (!fun
->addLocal(cx
, argAtom
, JSLOCAL_ARG
)) {
4662 if (!Compiler::compileFunctionBody(cx
, fun
, principals
,
4663 chars
, length
, filename
, lineno
)) {
4668 if (obj
&& funAtom
&&
4669 !obj
->defineProperty(cx
, ATOM_TO_JSID(funAtom
), ObjectValue(*fun
),
4670 NULL
, NULL
, JSPROP_ENUMERATE
)) {
4674 #ifdef JS_SCOPE_DEPTH_METER
4676 JSObject
*pobj
= obj
;
4679 while ((pobj
= pobj
->getParent()) != NULL
)
4681 JS_BASIC_STATS_ACCUM(&cx
->runtime
->hostenvScopeDepthStats
, depth
);
4687 LAST_FRAME_CHECKS(cx
, fun
);
4691 JS_PUBLIC_API(JSFunction
*)
4692 JS_CompileUCFunction(JSContext
*cx
, JSObject
*obj
, const char *name
,
4693 uintN nargs
, const char **argnames
,
4694 const jschar
*chars
, size_t length
,
4695 const char *filename
, uintN lineno
)
4697 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
4698 return JS_CompileUCFunctionForPrincipals(cx
, obj
, NULL
, name
, nargs
, argnames
,
4699 chars
, length
, filename
, lineno
);
4702 JS_PUBLIC_API(JSFunction
*)
4703 JS_CompileFunctionForPrincipals(JSContext
*cx
, JSObject
*obj
,
4704 JSPrincipals
*principals
, const char *name
,
4705 uintN nargs
, const char **argnames
,
4706 const char *bytes
, size_t length
,
4707 const char *filename
, uintN lineno
)
4709 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
4710 jschar
*chars
= js_InflateString(cx
, bytes
, &length
);
4713 JSFunction
*fun
= JS_CompileUCFunctionForPrincipals(cx
, obj
, principals
, name
,
4714 nargs
, argnames
, chars
, length
,
4720 JS_PUBLIC_API(JSFunction
*)
4721 JS_CompileFunction(JSContext
*cx
, JSObject
*obj
, const char *name
,
4722 uintN nargs
, const char **argnames
,
4723 const char *bytes
, size_t length
,
4724 const char *filename
, uintN lineno
)
4726 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
4727 return JS_CompileFunctionForPrincipals(cx
, obj
, NULL
, name
, nargs
, argnames
, bytes
, length
,
4731 JS_PUBLIC_API(JSString
*)
4732 JS_DecompileScript(JSContext
*cx
, JSScript
*script
, const char *name
, uintN indent
)
4734 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
4740 if (cx
->compartment
!= script
->compartment
)
4741 CompartmentChecker::fail(cx
->compartment
, script
->compartment
);
4743 jp
= js_NewPrinter(cx
, name
, NULL
,
4744 indent
& ~JS_DONT_PRETTY_PRINT
,
4745 !(indent
& JS_DONT_PRETTY_PRINT
),
4749 if (js_DecompileScript(jp
, script
))
4750 str
= js_GetPrinterOutput(jp
);
4753 js_DestroyPrinter(jp
);
4757 JS_PUBLIC_API(JSString
*)
4758 JS_DecompileFunction(JSContext
*cx
, JSFunction
*fun
, uintN indent
)
4760 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
4762 assertSameCompartment(cx
, fun
);
4763 return js_DecompileToString(cx
, "JS_DecompileFunction", fun
,
4764 indent
& ~JS_DONT_PRETTY_PRINT
,
4765 !(indent
& JS_DONT_PRETTY_PRINT
),
4766 false, false, js_DecompileFunction
);
4769 JS_PUBLIC_API(JSString
*)
4770 JS_DecompileFunctionBody(JSContext
*cx
, JSFunction
*fun
, uintN indent
)
4772 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
4774 assertSameCompartment(cx
, fun
);
4775 return js_DecompileToString(cx
, "JS_DecompileFunctionBody", fun
,
4776 indent
& ~JS_DONT_PRETTY_PRINT
,
4777 !(indent
& JS_DONT_PRETTY_PRINT
),
4778 false, false, js_DecompileFunctionBody
);
4781 JS_PUBLIC_API(JSBool
)
4782 JS_ExecuteScript(JSContext
*cx
, JSObject
*obj
, JSScript
*script
, jsval
*rval
)
4784 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
4788 assertSameCompartment(cx
, obj
, script
);
4789 /* This should receive only scripts handed out via the JSAPI. */
4790 JS_ASSERT(script
== JSScript::emptyScript() || script
->u
.object
);
4791 ok
= Execute(cx
, obj
, script
, NULL
, 0, Valueify(rval
));
4792 LAST_FRAME_CHECKS(cx
, ok
);
4796 JS_PUBLIC_API(JSBool
)
4797 JS_EvaluateUCScriptForPrincipalsVersion(JSContext
*cx
, JSObject
*obj
,
4798 JSPrincipals
*principals
,
4799 const jschar
*chars
, uintN length
,
4800 const char *filename
, uintN lineno
,
4801 jsval
*rval
, JSVersion version
)
4803 AutoVersionAPI
avi(cx
, version
);
4804 return JS_EvaluateUCScriptForPrincipals(cx
, obj
, principals
, chars
, length
, filename
, lineno
,
4808 JS_PUBLIC_API(JSBool
)
4809 JS_EvaluateUCScriptForPrincipals(JSContext
*cx
, JSObject
*obj
,
4810 JSPrincipals
*principals
,
4811 const jschar
*chars
, uintN length
,
4812 const char *filename
, uintN lineno
,
4815 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
4820 script
= Compiler::compileScript(cx
, obj
, NULL
, principals
,
4822 ? TCF_COMPILE_N_GO
| TCF_NO_SCRIPT_RVAL
4824 chars
, length
, NULL
, filename
, lineno
);
4826 LAST_FRAME_CHECKS(cx
, script
);
4829 ok
= Execute(cx
, obj
, script
, NULL
, 0, Valueify(rval
));
4830 LAST_FRAME_CHECKS(cx
, ok
);
4831 js_DestroyScript(cx
, script
);
4835 JS_PUBLIC_API(JSBool
)
4836 JS_EvaluateUCScript(JSContext
*cx
, JSObject
*obj
, const jschar
*chars
, uintN length
,
4837 const char *filename
, uintN lineno
, jsval
*rval
)
4839 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
4840 return JS_EvaluateUCScriptForPrincipals(cx
, obj
, NULL
, chars
, length
, filename
, lineno
, rval
);
4843 /* Ancient uintN nbytes is part of API/ABI, so use size_t length local. */
4844 JS_PUBLIC_API(JSBool
)
4845 JS_EvaluateScriptForPrincipals(JSContext
*cx
, JSObject
*obj
, JSPrincipals
*principals
,
4846 const char *bytes
, uintN nbytes
,
4847 const char *filename
, uintN lineno
, jsval
*rval
)
4849 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
4850 size_t length
= nbytes
;
4851 jschar
*chars
= js_InflateString(cx
, bytes
, &length
);
4854 JSBool ok
= JS_EvaluateUCScriptForPrincipals(cx
, obj
, principals
, chars
, length
,
4855 filename
, lineno
, rval
);
4860 JS_PUBLIC_API(JSBool
)
4861 JS_EvaluateScript(JSContext
*cx
, JSObject
*obj
, const char *bytes
, uintN nbytes
,
4862 const char *filename
, uintN lineno
, jsval
*rval
)
4864 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
4865 return JS_EvaluateScriptForPrincipals(cx
, obj
, NULL
, bytes
, nbytes
, filename
, lineno
, rval
);
4868 JS_PUBLIC_API(JSBool
)
4869 JS_CallFunction(JSContext
*cx
, JSObject
*obj
, JSFunction
*fun
, uintN argc
, jsval
*argv
,
4872 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
4876 assertSameCompartment(cx
, obj
, fun
, JSValueArray(argv
, argc
));
4877 ok
= ExternalInvoke(cx
, obj
, ObjectValue(*fun
), argc
, Valueify(argv
), Valueify(rval
));
4878 LAST_FRAME_CHECKS(cx
, ok
);
4882 JS_PUBLIC_API(JSBool
)
4883 JS_CallFunctionName(JSContext
*cx
, JSObject
*obj
, const char *name
, uintN argc
, jsval
*argv
,
4886 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
4888 assertSameCompartment(cx
, obj
, JSValueArray(argv
, argc
));
4890 AutoValueRooter
tvr(cx
);
4891 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
4893 js_GetMethod(cx
, obj
, ATOM_TO_JSID(atom
), JSGET_NO_METHOD_BARRIER
, tvr
.addr()) &&
4894 ExternalInvoke(cx
, obj
, tvr
.value(), argc
, Valueify(argv
), Valueify(rval
));
4895 LAST_FRAME_CHECKS(cx
, ok
);
4899 JS_PUBLIC_API(JSBool
)
4900 JS_CallFunctionValue(JSContext
*cx
, JSObject
*obj
, jsval fval
, uintN argc
, jsval
*argv
,
4903 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
4907 assertSameCompartment(cx
, obj
, fval
, JSValueArray(argv
, argc
));
4908 ok
= ExternalInvoke(cx
, obj
, Valueify(fval
), argc
, Valueify(argv
), Valueify(rval
));
4909 LAST_FRAME_CHECKS(cx
, ok
);
4916 Call(JSContext
*cx
, jsval thisv
, jsval fval
, uintN argc
, jsval
*argv
, jsval
*rval
)
4921 assertSameCompartment(cx
, thisv
, fval
, JSValueArray(argv
, argc
));
4922 ok
= ExternalInvoke(cx
, Valueify(thisv
), Valueify(fval
), argc
, Valueify(argv
), Valueify(rval
));
4923 LAST_FRAME_CHECKS(cx
, ok
);
4929 JS_PUBLIC_API(JSObject
*)
4930 JS_New(JSContext
*cx
, JSObject
*ctor
, uintN argc
, jsval
*argv
)
4933 assertSameCompartment(cx
, ctor
, JSValueArray(argv
, argc
));
4935 // This is not a simple variation of JS_CallFunctionValue because JSOP_NEW
4936 // is not a simple variation of JSOP_CALL. We have to determine what class
4937 // of object to create, create it, and clamp the return value to an object,
4938 // among other details. js_InvokeConstructor does the hard work.
4939 InvokeArgsGuard args
;
4940 if (!cx
->stack().pushInvokeArgs(cx
, argc
, &args
))
4943 args
.callee().setObject(*ctor
);
4944 args
.thisv().setNull();
4945 memcpy(args
.argv(), argv
, argc
* sizeof(jsval
));
4947 bool ok
= InvokeConstructor(cx
, args
);
4948 JSObject
*obj
= (ok
&& args
.rval().isObject())
4949 ? &args
.rval().toObject()
4952 LAST_FRAME_CHECKS(cx
, ok
);
4956 JS_PUBLIC_API(JSOperationCallback
)
4957 JS_SetOperationCallback(JSContext
*cx
, JSOperationCallback callback
)
4959 #ifdef JS_THREADSAFE
4960 JS_ASSERT(CURRENT_THREAD_IS_ME(cx
->thread
));
4962 JSOperationCallback old
= cx
->operationCallback
;
4963 cx
->operationCallback
= callback
;
4967 JS_PUBLIC_API(JSOperationCallback
)
4968 JS_GetOperationCallback(JSContext
*cx
)
4970 return cx
->operationCallback
;
4974 JS_TriggerOperationCallback(JSContext
*cx
)
4976 #ifdef JS_THREADSAFE
4977 AutoLockGC
lock(cx
->runtime
);
4979 TriggerOperationCallback(cx
);
4983 JS_TriggerAllOperationCallbacks(JSRuntime
*rt
)
4985 #ifdef JS_THREADSAFE
4986 AutoLockGC
lock(rt
);
4988 TriggerAllOperationCallbacks(rt
);
4991 JS_PUBLIC_API(JSBool
)
4992 JS_IsRunning(JSContext
*cx
)
4995 * The use of cx->fp below is safe. Rationale: Here we don't care if the
4996 * interpreter state is stale. We just want to know if there *is* any
4997 * interpreter state.
4999 VOUCH_DOES_NOT_REQUIRE_STACK();
5002 JS_ASSERT_IF(JS_TRACE_MONITOR(cx
).tracecx
== cx
, cx
->hasfp());
5004 JSStackFrame
*fp
= cx
->maybefp();
5005 while (fp
&& fp
->isDummyFrame())
5010 JS_PUBLIC_API(JSStackFrame
*)
5011 JS_SaveFrameChain(JSContext
*cx
)
5014 JSStackFrame
*fp
= js_GetTopStackFrame(cx
);
5017 cx
->saveActiveSegment();
5022 JS_RestoreFrameChain(JSContext
*cx
, JSStackFrame
*fp
)
5025 JS_ASSERT_NOT_ON_TRACE(cx
);
5026 JS_ASSERT(!cx
->hasfp());
5029 cx
->restoreSegment();
5030 cx
->resetCompartment();
5033 /************************************************************************/
5035 JS_PUBLIC_API(JSString
*)
5036 JS_NewString(JSContext
*cx
, char *bytes
, size_t nbytes
)
5038 size_t length
= nbytes
;
5044 /* Make a UTF-16 vector from the 8-bit char codes in bytes. */
5045 chars
= js_InflateString(cx
, bytes
, &length
);
5049 /* Free chars (but not bytes, which caller frees on error) if we fail. */
5050 str
= js_NewString(cx
, chars
, length
);
5056 /* Hand off bytes to the deflated string cache, if possible. */
5057 if (!cx
->runtime
->deflatedStringCache
->setBytes(cx
, str
, bytes
))
5062 JS_PUBLIC_API(JSString
*)
5063 JS_NewStringCopyN(JSContext
*cx
, const char *s
, size_t n
)
5069 js
= js_InflateString(cx
, s
, &n
);
5072 str
= js_NewString(cx
, js
, n
);
5078 JS_PUBLIC_API(JSString
*)
5079 JS_NewStringCopyZ(JSContext
*cx
, const char *s
)
5087 return cx
->runtime
->emptyString
;
5089 js
= js_InflateString(cx
, s
, &n
);
5092 str
= js_NewString(cx
, js
, n
);
5098 JS_PUBLIC_API(JSBool
)
5099 JS_StringHasBeenInterned(JSString
*str
)
5101 return str
->isAtomized();
5104 JS_PUBLIC_API(JSString
*)
5105 JS_InternString(JSContext
*cx
, const char *s
)
5110 atom
= js_Atomize(cx
, s
, strlen(s
), ATOM_INTERNED
);
5113 return ATOM_TO_STRING(atom
);
5116 JS_PUBLIC_API(JSString
*)
5117 JS_NewUCString(JSContext
*cx
, jschar
*chars
, size_t length
)
5120 return js_NewString(cx
, chars
, length
);
5123 JS_PUBLIC_API(JSString
*)
5124 JS_NewUCStringCopyN(JSContext
*cx
, const jschar
*s
, size_t n
)
5127 return js_NewStringCopyN(cx
, s
, n
);
5130 JS_PUBLIC_API(JSString
*)
5131 JS_NewUCStringCopyZ(JSContext
*cx
, const jschar
*s
)
5135 return cx
->runtime
->emptyString
;
5136 return js_NewStringCopyZ(cx
, s
);
5139 JS_PUBLIC_API(JSString
*)
5140 JS_InternUCStringN(JSContext
*cx
, const jschar
*s
, size_t length
)
5145 atom
= js_AtomizeChars(cx
, s
, length
, ATOM_INTERNED
);
5148 return ATOM_TO_STRING(atom
);
5151 JS_PUBLIC_API(JSString
*)
5152 JS_InternUCString(JSContext
*cx
, const jschar
*s
)
5154 return JS_InternUCStringN(cx
, s
, js_strlen(s
));
5157 JS_PUBLIC_API(char *)
5158 JS_GetStringBytes(JSString
*str
)
5162 bytes
= js_GetStringBytes(NULL
, str
);
5163 return (char *)(bytes
? bytes
: "");
5166 JS_PUBLIC_API(jschar
*)
5167 JS_GetStringChars(JSString
*str
)
5172 str
->ensureNotRope();
5175 * API botch (again, shades of JS_GetStringBytes): we have no cx to report
5176 * out-of-memory when undepending strings, so we replace JSString::undepend
5177 * with explicit malloc call and ignore its errors.
5179 * If we fail to convert a dependent string into an independent one, our
5180 * caller will not be guaranteed a \u0000 terminator as a backstop. This
5181 * may break some clients who already misbehave on embedded NULs.
5183 * The gain of dependent strings, which cure quadratic and cubic growth
5184 * rate bugs in string concatenation, is worth this slight loss in API
5187 if (str
->isDependent()) {
5188 n
= str
->dependentLength();
5189 size
= (n
+ 1) * sizeof(jschar
);
5190 s
= (jschar
*) js_malloc(size
);
5192 memcpy(s
, str
->dependentChars(), n
* sizeof *s
);
5194 str
->initFlat(s
, n
);
5196 s
= str
->dependentChars();
5199 str
->flatClearMutable();
5200 s
= str
->flatChars();
5205 JS_PUBLIC_API(size_t)
5206 JS_GetStringLength(JSString
*str
)
5208 return str
->length();
5211 JS_PUBLIC_API(const char *)
5212 JS_GetStringBytesZ(JSContext
*cx
, JSString
*str
)
5214 assertSameCompartment(cx
, str
);
5215 return js_GetStringBytes(cx
, str
);
5218 JS_PUBLIC_API(const jschar
*)
5219 JS_GetStringCharsZ(JSContext
*cx
, JSString
*str
)
5221 assertSameCompartment(cx
, str
);
5222 return str
->undepend(cx
);
5226 JS_CompareStrings(JSString
*str1
, JSString
*str2
)
5228 return js_CompareStrings(str1
, str2
);
5231 JS_PUBLIC_API(JSString
*)
5232 JS_NewGrowableString(JSContext
*cx
, jschar
*chars
, size_t length
)
5235 return js_NewString(cx
, chars
, length
);
5238 JS_PUBLIC_API(JSString
*)
5239 JS_NewDependentString(JSContext
*cx
, JSString
*str
, size_t start
, size_t length
)
5242 return js_NewDependentString(cx
, str
, start
, length
);
5245 JS_PUBLIC_API(JSString
*)
5246 JS_ConcatStrings(JSContext
*cx
, JSString
*left
, JSString
*right
)
5249 return js_ConcatStrings(cx
, left
, right
);
5252 JS_PUBLIC_API(const jschar
*)
5253 JS_UndependString(JSContext
*cx
, JSString
*str
)
5256 return str
->undepend(cx
);
5259 JS_PUBLIC_API(JSBool
)
5260 JS_MakeStringImmutable(JSContext
*cx
, JSString
*str
)
5263 return js_MakeStringImmutable(cx
, str
);
5266 JS_PUBLIC_API(JSBool
)
5267 JS_EncodeCharacters(JSContext
*cx
, const jschar
*src
, size_t srclen
, char *dst
, size_t *dstlenp
)
5272 n
= js_GetDeflatedStringLength(cx
, src
, srclen
);
5273 if (n
== (size_t)-1) {
5281 return js_DeflateStringToBuffer(cx
, src
, srclen
, dst
, dstlenp
);
5284 JS_PUBLIC_API(JSBool
)
5285 JS_DecodeBytes(JSContext
*cx
, const char *src
, size_t srclen
, jschar
*dst
, size_t *dstlenp
)
5287 return js_InflateStringToBuffer(cx
, src
, srclen
, dst
, dstlenp
);
5290 JS_PUBLIC_API(char *)
5291 JS_EncodeString(JSContext
*cx
, JSString
*str
)
5293 return js_DeflateString(cx
, str
->chars(), str
->length());
5296 JS_PUBLIC_API(JSBool
)
5297 JS_Stringify(JSContext
*cx
, jsval
*vp
, JSObject
*replacer
, jsval space
,
5298 JSONWriteCallback callback
, void *data
)
5301 assertSameCompartment(cx
, replacer
, space
);
5302 JSCharBuffer
cb(cx
);
5303 if (!js_Stringify(cx
, Valueify(vp
), replacer
, Valueify(space
), cb
))
5305 return callback(cb
.begin(), cb
.length(), data
);
5308 JS_PUBLIC_API(JSBool
)
5309 JS_TryJSON(JSContext
*cx
, jsval
*vp
)
5312 assertSameCompartment(cx
, *vp
);
5313 return js_TryJSON(cx
, Valueify(vp
));
5316 JS_PUBLIC_API(JSONParser
*)
5317 JS_BeginJSONParse(JSContext
*cx
, jsval
*vp
)
5320 return js_BeginJSONParse(cx
, Valueify(vp
));
5323 JS_PUBLIC_API(JSBool
)
5324 JS_ConsumeJSONText(JSContext
*cx
, JSONParser
*jp
, const jschar
*data
, uint32 len
)
5327 return js_ConsumeJSONText(cx
, jp
, data
, len
);
5330 JS_PUBLIC_API(JSBool
)
5331 JS_FinishJSONParse(JSContext
*cx
, JSONParser
*jp
, jsval reviver
)
5334 assertSameCompartment(cx
, reviver
);
5335 return js_FinishJSONParse(cx
, jp
, Valueify(reviver
));
5338 JS_PUBLIC_API(JSBool
)
5339 JS_ReadStructuredClone(JSContext
*cx
, const uint64
*buf
, size_t nbytes
, jsval
*vp
)
5341 return ReadStructuredClone(cx
, buf
, nbytes
, Valueify(vp
));
5344 JS_PUBLIC_API(JSBool
)
5345 JS_WriteStructuredClone(JSContext
*cx
, jsval v
, uint64
**bufp
, size_t *nbytesp
)
5347 return WriteStructuredClone(cx
, Valueify(v
), (uint64_t **) bufp
, nbytesp
);
5350 JS_PUBLIC_API(JSBool
)
5351 JS_StructuredClone(JSContext
*cx
, jsval v
, jsval
*vp
)
5353 JSAutoStructuredCloneBuffer
buf(cx
);
5354 return buf
.write(v
) && buf
.read(vp
);
5358 JS_SetStructuredCloneCallbacks(JSRuntime
*rt
, const JSStructuredCloneCallbacks
*callbacks
)
5360 rt
->structuredCloneCallbacks
= callbacks
;
5363 JS_PUBLIC_API(JSBool
)
5364 JS_ReadUint32Pair(JSStructuredCloneReader
*r
, uint32
*p1
, uint32
*p2
)
5366 return r
->input().readPair((uint32_t *) p1
, (uint32_t *) p2
);
5369 JS_PUBLIC_API(JSBool
)
5370 JS_ReadBytes(JSStructuredCloneReader
*r
, void *p
, size_t len
)
5372 return r
->input().readBytes(p
, len
);
5375 JS_PUBLIC_API(JSBool
)
5376 JS_WriteUint32Pair(JSStructuredCloneWriter
*w
, uint32 tag
, uint32 data
)
5378 return w
->output().writePair(tag
, data
);
5381 JS_PUBLIC_API(JSBool
)
5382 JS_WriteBytes(JSStructuredCloneWriter
*w
, const void *p
, size_t len
)
5384 return w
->output().writeBytes(p
, len
);
5388 * The following determines whether C Strings are to be treated as UTF-8
5389 * or ISO-8859-1. For correct operation, it must be set prior to the
5390 * first call to JS_NewRuntime.
5392 #ifndef JS_C_STRINGS_ARE_UTF8
5393 JSBool js_CStringsAreUTF8
= JS_FALSE
;
5396 JS_PUBLIC_API(JSBool
)
5397 JS_CStringsAreUTF8()
5399 return js_CStringsAreUTF8
;
5403 JS_SetCStringsAreUTF8()
5405 JS_ASSERT(!js_NewRuntimeWasCalled
);
5407 #ifndef JS_C_STRINGS_ARE_UTF8
5408 js_CStringsAreUTF8
= JS_TRUE
;
5412 /************************************************************************/
5415 JS_ReportError(JSContext
*cx
, const char *format
, ...)
5419 va_start(ap
, format
);
5420 js_ReportErrorVA(cx
, JSREPORT_ERROR
, format
, ap
);
5425 JS_ReportErrorNumber(JSContext
*cx
, JSErrorCallback errorCallback
,
5426 void *userRef
, const uintN errorNumber
, ...)
5430 va_start(ap
, errorNumber
);
5431 js_ReportErrorNumberVA(cx
, JSREPORT_ERROR
, errorCallback
, userRef
,
5432 errorNumber
, JS_TRUE
, ap
);
5437 JS_ReportErrorNumberUC(JSContext
*cx
, JSErrorCallback errorCallback
,
5438 void *userRef
, const uintN errorNumber
, ...)
5442 va_start(ap
, errorNumber
);
5443 js_ReportErrorNumberVA(cx
, JSREPORT_ERROR
, errorCallback
, userRef
,
5444 errorNumber
, JS_FALSE
, ap
);
5448 JS_PUBLIC_API(JSBool
)
5449 JS_ReportWarning(JSContext
*cx
, const char *format
, ...)
5454 va_start(ap
, format
);
5455 ok
= js_ReportErrorVA(cx
, JSREPORT_WARNING
, format
, ap
);
5460 JS_PUBLIC_API(JSBool
)
5461 JS_ReportErrorFlagsAndNumber(JSContext
*cx
, uintN flags
,
5462 JSErrorCallback errorCallback
, void *userRef
,
5463 const uintN errorNumber
, ...)
5468 va_start(ap
, errorNumber
);
5469 ok
= js_ReportErrorNumberVA(cx
, flags
, errorCallback
, userRef
,
5470 errorNumber
, JS_TRUE
, ap
);
5475 JS_PUBLIC_API(JSBool
)
5476 JS_ReportErrorFlagsAndNumberUC(JSContext
*cx
, uintN flags
,
5477 JSErrorCallback errorCallback
, void *userRef
,
5478 const uintN errorNumber
, ...)
5483 va_start(ap
, errorNumber
);
5484 ok
= js_ReportErrorNumberVA(cx
, flags
, errorCallback
, userRef
,
5485 errorNumber
, JS_FALSE
, ap
);
5491 JS_ReportOutOfMemory(JSContext
*cx
)
5493 js_ReportOutOfMemory(cx
);
5497 JS_ReportAllocationOverflow(JSContext
*cx
)
5499 js_ReportAllocationOverflow(cx
);
5502 JS_PUBLIC_API(JSErrorReporter
)
5503 JS_SetErrorReporter(JSContext
*cx
, JSErrorReporter er
)
5505 JSErrorReporter older
;
5507 older
= cx
->errorReporter
;
5508 cx
->errorReporter
= er
;
5512 /************************************************************************/
5515 * Regular Expressions.
5517 JS_PUBLIC_API(JSObject
*)
5518 JS_NewRegExpObject(JSContext
*cx
, JSObject
*obj
, char *bytes
, size_t length
, uintN flags
)
5521 jschar
*chars
= js_InflateString(cx
, bytes
, &length
);
5524 RegExpStatics
*res
= RegExpStatics::extractFrom(obj
);
5525 JSObject
*reobj
= RegExp::createObject(cx
, res
, chars
, length
, flags
);
5530 JS_PUBLIC_API(JSObject
*)
5531 JS_NewUCRegExpObject(JSContext
*cx
, JSObject
*obj
, jschar
*chars
, size_t length
, uintN flags
)
5534 RegExpStatics
*res
= RegExpStatics::extractFrom(obj
);
5535 return RegExp::createObject(cx
, res
, chars
, length
, flags
);
5539 JS_SetRegExpInput(JSContext
*cx
, JSObject
*obj
, JSString
*input
, JSBool multiline
)
5542 assertSameCompartment(cx
, input
);
5544 RegExpStatics::extractFrom(obj
)->reset(input
, !!multiline
);
5548 JS_ClearRegExpStatics(JSContext
*cx
, JSObject
*obj
)
5553 RegExpStatics::extractFrom(obj
)->clear();
5556 JS_PUBLIC_API(JSBool
)
5557 JS_ExecuteRegExp(JSContext
*cx
, JSObject
*obj
, JSObject
*reobj
, jschar
*chars
, size_t length
,
5558 size_t *indexp
, JSBool test
, jsval
*rval
)
5562 RegExp
*re
= RegExp::extractFrom(reobj
);
5566 JSString
*str
= js_NewStringCopyN(cx
, chars
, length
);
5570 return re
->execute(cx
, RegExpStatics::extractFrom(obj
), str
, indexp
, test
, Valueify(rval
));
5573 JS_PUBLIC_API(JSObject
*)
5574 JS_NewRegExpObjectNoStatics(JSContext
*cx
, char *bytes
, size_t length
, uintN flags
)
5577 jschar
*chars
= js_InflateString(cx
, bytes
, &length
);
5580 JSObject
*obj
= RegExp::createObjectNoStatics(cx
, chars
, length
, flags
);
5585 JS_PUBLIC_API(JSObject
*)
5586 JS_NewUCRegExpObjectNoStatics(JSContext
*cx
, jschar
*chars
, size_t length
, uintN flags
)
5589 return RegExp::createObjectNoStatics(cx
, chars
, length
, flags
);
5592 JS_PUBLIC_API(JSBool
)
5593 JS_ExecuteRegExpNoStatics(JSContext
*cx
, JSObject
*obj
, jschar
*chars
, size_t length
,
5594 size_t *indexp
, JSBool test
, jsval
*rval
)
5598 RegExp
*re
= RegExp::extractFrom(obj
);
5602 JSString
*str
= js_NewStringCopyN(cx
, chars
, length
);
5606 return re
->executeNoStatics(cx
, str
, indexp
, test
, Valueify(rval
));
5609 /************************************************************************/
5612 JS_SetLocaleCallbacks(JSContext
*cx
, JSLocaleCallbacks
*callbacks
)
5614 cx
->localeCallbacks
= callbacks
;
5617 JS_PUBLIC_API(JSLocaleCallbacks
*)
5618 JS_GetLocaleCallbacks(JSContext
*cx
)
5620 return cx
->localeCallbacks
;
5623 /************************************************************************/
5625 JS_PUBLIC_API(JSBool
)
5626 JS_IsExceptionPending(JSContext
*cx
)
5628 return (JSBool
) cx
->throwing
;
5631 JS_PUBLIC_API(JSBool
)
5632 JS_GetPendingException(JSContext
*cx
, jsval
*vp
)
5637 Valueify(*vp
) = cx
->exception
;
5642 JS_SetPendingException(JSContext
*cx
, jsval v
)
5645 assertSameCompartment(cx
, v
);
5646 SetPendingException(cx
, Valueify(v
));
5650 JS_ClearPendingException(JSContext
*cx
)
5652 cx
->throwing
= JS_FALSE
;
5653 cx
->exception
.setUndefined();
5656 JS_PUBLIC_API(JSBool
)
5657 JS_ReportPendingException(JSContext
*cx
)
5665 * Set cx->generatingError to suppress the standard error-to-exception
5666 * conversion done by all {js,JS}_Report* functions except for OOM. The
5667 * cx->generatingError flag was added to suppress recursive divergence
5668 * under js_ErrorToException, but it serves for our purposes here too.
5670 save
= cx
->generatingError
;
5671 cx
->generatingError
= JS_TRUE
;
5672 ok
= js_ReportUncaughtException(cx
);
5673 cx
->generatingError
= save
;
5677 struct JSExceptionState
{
5682 JS_PUBLIC_API(JSExceptionState
*)
5683 JS_SaveExceptionState(JSContext
*cx
)
5685 JSExceptionState
*state
;
5688 state
= (JSExceptionState
*) cx
->malloc(sizeof(JSExceptionState
));
5690 state
->throwing
= JS_GetPendingException(cx
, &state
->exception
);
5691 if (state
->throwing
&& JSVAL_IS_GCTHING(state
->exception
))
5692 js_AddRoot(cx
, Valueify(&state
->exception
), "JSExceptionState.exception");
5698 JS_RestoreExceptionState(JSContext
*cx
, JSExceptionState
*state
)
5702 if (state
->throwing
)
5703 JS_SetPendingException(cx
, state
->exception
);
5705 JS_ClearPendingException(cx
);
5706 JS_DropExceptionState(cx
, state
);
5711 JS_DropExceptionState(JSContext
*cx
, JSExceptionState
*state
)
5715 if (state
->throwing
&& JSVAL_IS_GCTHING(state
->exception
)) {
5716 assertSameCompartment(cx
, state
->exception
);
5717 JS_RemoveValueRoot(cx
, &state
->exception
);
5723 JS_PUBLIC_API(JSErrorReport
*)
5724 JS_ErrorFromException(JSContext
*cx
, jsval v
)
5727 assertSameCompartment(cx
, v
);
5728 return js_ErrorFromException(cx
, v
);
5731 JS_PUBLIC_API(JSBool
)
5732 JS_ThrowReportedError(JSContext
*cx
, const char *message
,
5733 JSErrorReport
*reportp
)
5735 return JS_IsRunning(cx
) &&
5736 js_ErrorToException(cx
, message
, reportp
, NULL
, NULL
);
5739 JS_PUBLIC_API(JSBool
)
5740 JS_ThrowStopIteration(JSContext
*cx
)
5742 return js_ThrowStopIteration(cx
);
5746 * Get the owning thread id of a context. Returns 0 if the context is not
5747 * owned by any thread.
5749 JS_PUBLIC_API(jsword
)
5750 JS_GetContextThread(JSContext
*cx
)
5752 #ifdef JS_THREADSAFE
5753 return reinterpret_cast<jsword
>(JS_THREAD_ID(cx
));
5760 * Set the current thread as the owning thread of a context. Returns the
5761 * old owning thread id, or -1 if the operation failed.
5763 JS_PUBLIC_API(jsword
)
5764 JS_SetContextThread(JSContext
*cx
)
5766 #ifdef JS_THREADSAFE
5767 JS_ASSERT(!cx
->outstandingRequests
);
5769 JS_ASSERT(CURRENT_THREAD_IS_ME(cx
->thread
));
5770 return reinterpret_cast<jsword
>(cx
->thread
->id
);
5773 if (!js_InitContextThread(cx
)) {
5774 js_ReportOutOfMemory(cx
);
5778 /* Here the GC lock is still held after js_InitContextThread took it. */
5779 JS_UNLOCK_GC(cx
->runtime
);
5784 JS_PUBLIC_API(jsword
)
5785 JS_ClearContextThread(JSContext
*cx
)
5787 #ifdef JS_THREADSAFE
5789 * cx must have exited all requests it entered and, if cx is associated
5790 * with a thread, this must be called only from that thread. If not, this
5791 * is a harmless no-op.
5793 JS_ASSERT(cx
->outstandingRequests
== 0);
5794 JSThread
*t
= cx
->thread
;
5797 JS_ASSERT(CURRENT_THREAD_IS_ME(t
));
5800 * We must not race with a GC that accesses cx->thread for all threads,
5803 JSRuntime
*rt
= cx
->runtime
;
5804 AutoLockGC
lock(rt
);
5806 js_ClearContextThread(cx
);
5807 JS_ASSERT_IF(JS_CLIST_IS_EMPTY(&t
->contextList
), !t
->data
.requestDepth
);
5810 * We can access t->id as long as the GC lock is held and we cannot race
5811 * with the GC that may delete t.
5813 return reinterpret_cast<jsword
>(t
->id
);
5819 #ifdef MOZ_TRACE_JSCALLS
5821 JS_SetFunctionCallback(JSContext
*cx
, JSFunctionCallback fcb
)
5823 cx
->functionCallback
= fcb
;
5826 JS_PUBLIC_API(JSFunctionCallback
)
5827 JS_GetFunctionCallback(JSContext
*cx
)
5829 return cx
->functionCallback
;
5835 JS_SetGCZeal(JSContext
*cx
, uint8 zeal
)
5837 cx
->runtime
->gcZeal
= zeal
;
5841 /************************************************************************/
5843 #if !defined(STATIC_EXPORTABLE_JS_API) && !defined(STATIC_JS_API) && defined(XP_WIN) && !defined (WINCE)
5848 * Initialization routine for the JS DLL.
5850 BOOL WINAPI
DllMain (HINSTANCE hDLL
, DWORD dwReason
, LPVOID lpReserved
)