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 ***** */
60 #include "jsbuiltins.h"
63 #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 "jsscriptinlines.h"
99 #include "jsstrinlines.h"
100 #include "assembler/wtf/Platform.h"
103 #include "assembler/jit/ExecutableAllocator.h"
104 #include "methodjit/Logging.h"
107 #if JS_HAS_XML_SUPPORT
112 using namespace js::gc;
115 * This class is a version-establising barrier at the head of a VM entry or
116 * re-entry. It ensures that:
118 * - |newVersion| is the starting (default) version used for the context.
119 * - The starting version state is not an override.
120 * - Overrides in the VM session are not propagated to the caller.
124 JSContext * const cx;
125 JSVersion oldDefaultVersion;
126 bool oldHasVersionOverride;
127 JSVersion oldVersionOverride;
129 uintN oldCompileOptions;
131 JSVersion newVersion;
134 explicit AutoVersionAPI(JSContext *cx, JSVersion newVersion)
136 oldDefaultVersion(cx->getDefaultVersion()),
137 oldHasVersionOverride(cx->isVersionOverridden()),
138 oldVersionOverride(oldHasVersionOverride ? cx->findVersion() : JSVERSION_UNKNOWN)
140 , oldCompileOptions(cx->getCompileOptions())
144 * Note: ANONFUNFIX in newVersion is ignored for backwards
145 * compatibility, must be set via JS_SetOptions. (Because of this, we
146 * inherit the current ANONFUNFIX setting from the options.
148 VersionSetAnonFunFix(&newVersion, OptionsHasAnonFunFix(cx->getCompileOptions()));
149 this->newVersion = newVersion;
150 cx->clearVersionOverride();
151 cx->setDefaultVersion(newVersion);
155 cx->setDefaultVersion(oldDefaultVersion);
156 if (oldHasVersionOverride)
157 cx->overrideVersion(oldVersionOverride);
159 cx->clearVersionOverride();
160 JS_ASSERT(oldCompileOptions == cx->getCompileOptions());
163 /* The version that this scoped-entity establishes. */
164 JSVersion version() const { return newVersion; }
167 #ifdef HAVE_VA_LIST_AS_ARRAY
168 #define JS_ADDRESSOF_VA_LIST(ap) ((va_list *)(ap))
170 #define JS_ADDRESSOF_VA_LIST(ap) (&(ap))
173 #ifdef JS_USE_JSVAL_JSID_STRUCT_TYPES
174 JS_PUBLIC_DATA(jsid) JS_DEFAULT_XML_NAMESPACE_ID = { size_t(JSID_TYPE_DEFAULT_XML_NAMESPACE) };
175 JS_PUBLIC_DATA(jsid) JSID_VOID = { size_t(JSID_TYPE_VOID) };
176 JS_PUBLIC_DATA(jsid) JSID_EMPTY = { size_t(JSID_TYPE_OBJECT) };
179 #ifdef JS_USE_JSVAL_JSID_STRUCT_TYPES
180 JS_PUBLIC_DATA(jsval) JSVAL_NULL = { BUILD_JSVAL(JSVAL_TAG_NULL, 0) };
181 JS_PUBLIC_DATA(jsval) JSVAL_ZERO = { BUILD_JSVAL(JSVAL_TAG_INT32, 0) };
182 JS_PUBLIC_DATA(jsval) JSVAL_ONE = { BUILD_JSVAL(JSVAL_TAG_INT32, 1) };
183 JS_PUBLIC_DATA(jsval) JSVAL_FALSE = { BUILD_JSVAL(JSVAL_TAG_BOOLEAN, JS_FALSE) };
184 JS_PUBLIC_DATA(jsval) JSVAL_TRUE = { BUILD_JSVAL(JSVAL_TAG_BOOLEAN, JS_TRUE) };
185 JS_PUBLIC_DATA(jsval) JSVAL_VOID = { BUILD_JSVAL(JSVAL_TAG_UNDEFINED, 0) };
188 /* Make sure that jschar is two bytes unsigned integer */
189 JS_STATIC_ASSERT((jschar)-1 > 0);
190 JS_STATIC_ASSERT(sizeof(jschar) == 2);
199 JS_GetNaNValue(JSContext *cx)
201 return Jsvalify(cx->runtime->NaNValue);
205 JS_GetNegativeInfinityValue(JSContext *cx)
207 return Jsvalify(cx->runtime->negativeInfinityValue);
211 JS_GetPositiveInfinityValue(JSContext *cx)
213 return Jsvalify(cx->runtime->positiveInfinityValue);
217 JS_GetEmptyStringValue(JSContext *cx)
219 return STRING_TO_JSVAL(cx->runtime->emptyString);
222 JS_PUBLIC_API(JSString *)
223 JS_GetEmptyString(JSRuntime *rt)
225 JS_ASSERT(rt->state == JSRTS_UP);
226 return rt->emptyString;
230 TryArgumentFormatter(JSContext *cx, const char **formatp, JSBool fromJS, jsval **vpp, va_list *app)
233 JSArgumentFormatMap *map;
236 for (map = cx->argumentFormatMap; map; map = map->next) {
237 if (!strncmp(format, map->format, map->length)) {
238 *formatp = format + map->length;
239 return map->formatter(cx, format, fromJS, vpp, app);
242 JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_CHAR, format);
246 JS_PUBLIC_API(JSBool)
247 JS_ConvertArguments(JSContext *cx, uintN argc, jsval *argv, const char *format, ...)
252 va_start(ap, format);
253 ok = JS_ConvertArgumentsVA(cx, argc, argv, format, ap);
258 JS_PUBLIC_API(JSBool)
259 JS_ConvertArgumentsVA(JSContext *cx, uintN argc, jsval *argv, const char *format, va_list ap)
270 assertSameCompartment(cx, JSValueArray(argv - 2, argc + 2));
273 while ((c = *format++) != '\0') {
280 if (sp == argv + argc) {
282 fun = js_ValueToFunction(cx, Valueify(&argv[-2]), 0);
285 JS_snprintf(numBuf, sizeof numBuf, "%u", argc);
286 JSAutoByteString funNameBytes;
287 if (const char *name = GetFunctionNameBytes(cx, fun, &funNameBytes)) {
288 JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_MORE_ARGS_NEEDED,
289 name, numBuf, (argc == 1) ? "" : "s");
298 *va_arg(ap, JSBool *) = js_ValueToBoolean(Valueify(*sp));
301 if (!JS_ValueToUint16(cx, *sp, va_arg(ap, uint16 *)))
305 if (!JS_ValueToECMAInt32(cx, *sp, va_arg(ap, int32 *)))
309 if (!JS_ValueToECMAUint32(cx, *sp, va_arg(ap, uint32 *)))
313 if (!JS_ValueToInt32(cx, *sp, va_arg(ap, int32 *)))
317 if (!JS_ValueToNumber(cx, *sp, va_arg(ap, jsdouble *)))
321 if (!JS_ValueToNumber(cx, *sp, &d))
323 *va_arg(ap, jsdouble *) = js_DoubleToInteger(d);
327 str = js_ValueToString(cx, Valueify(*sp));
330 *sp = STRING_TO_JSVAL(str);
332 const jschar *chars = js_GetStringChars(cx, str);
335 *va_arg(ap, const jschar **) = chars;
337 *va_arg(ap, JSString **) = str;
341 if (!js_ValueToObjectOrNull(cx, Valueify(*sp), &obj))
343 *sp = OBJECT_TO_JSVAL(obj);
344 *va_arg(ap, JSObject **) = obj;
347 obj = js_ValueToFunctionObject(cx, Valueify(sp), 0);
350 *sp = OBJECT_TO_JSVAL(obj);
351 *va_arg(ap, JSFunction **) = GET_FUNCTION_PRIVATE(cx, obj);
354 *va_arg(ap, jsval *) = *sp;
360 if (!TryArgumentFormatter(cx, &format, JS_TRUE, &sp,
361 JS_ADDRESSOF_VA_LIST(ap))) {
364 /* NB: the formatter already updated sp, so we continue here. */
372 JS_PUBLIC_API(JSBool)
373 JS_AddArgumentFormatter(JSContext *cx, const char *format, JSArgumentFormatter formatter)
376 JSArgumentFormatMap **mpp, *map;
378 length = strlen(format);
379 mpp = &cx->argumentFormatMap;
380 while ((map = *mpp) != NULL) {
381 /* Insert before any shorter string to match before prefixes. */
382 if (map->length < length)
384 if (map->length == length && !strcmp(map->format, format))
388 map = (JSArgumentFormatMap *) cx->malloc(sizeof *map);
391 map->format = format;
392 map->length = length;
396 map->formatter = formatter;
401 JS_RemoveArgumentFormatter(JSContext *cx, const char *format)
404 JSArgumentFormatMap **mpp, *map;
406 length = strlen(format);
407 mpp = &cx->argumentFormatMap;
408 while ((map = *mpp) != NULL) {
409 if (map->length == length && !strcmp(map->format, format)) {
418 JS_PUBLIC_API(JSBool)
419 JS_ConvertValue(JSContext *cx, jsval v, JSType type, jsval *vp)
427 assertSameCompartment(cx, v);
434 ok = js_ValueToObjectOrNull(cx, Valueify(v), &obj);
436 *vp = OBJECT_TO_JSVAL(obj);
438 case JSTYPE_FUNCTION:
440 obj = js_ValueToFunctionObject(cx, Valueify(vp), JSV2F_SEARCH_STACK);
444 str = js_ValueToString(cx, Valueify(v));
447 *vp = STRING_TO_JSVAL(str);
450 ok = JS_ValueToNumber(cx, v, &d);
452 *vp = DOUBLE_TO_JSVAL(d);
455 *vp = BOOLEAN_TO_JSVAL(js_ValueToBoolean(Valueify(v)));
459 JS_snprintf(numBuf, sizeof numBuf, "%d", (int)type);
460 JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_TYPE, numBuf);
468 JS_PUBLIC_API(JSBool)
469 JS_ValueToObject(JSContext *cx, jsval v, JSObject **objp)
472 assertSameCompartment(cx, v);
473 return js_ValueToObjectOrNull(cx, Valueify(v), objp);
476 JS_PUBLIC_API(JSFunction *)
477 JS_ValueToFunction(JSContext *cx, jsval v)
480 assertSameCompartment(cx, v);
481 return js_ValueToFunction(cx, Valueify(&v), JSV2F_SEARCH_STACK);
484 JS_PUBLIC_API(JSFunction *)
485 JS_ValueToConstructor(JSContext *cx, jsval v)
488 assertSameCompartment(cx, v);
489 return js_ValueToFunction(cx, Valueify(&v), JSV2F_SEARCH_STACK);
492 JS_PUBLIC_API(JSString *)
493 JS_ValueToString(JSContext *cx, jsval v)
496 assertSameCompartment(cx, v);
497 return js_ValueToString(cx, Valueify(v));
500 JS_PUBLIC_API(JSString *)
501 JS_ValueToSource(JSContext *cx, jsval v)
504 assertSameCompartment(cx, v);
505 return js_ValueToSource(cx, Valueify(v));
508 JS_PUBLIC_API(JSBool)
509 JS_ValueToNumber(JSContext *cx, jsval v, jsdouble *dp)
512 assertSameCompartment(cx, v);
514 AutoValueRooter tvr(cx, Valueify(v));
515 return ValueToNumber(cx, tvr.value(), dp);
518 JS_PUBLIC_API(JSBool)
519 JS_DoubleIsInt32(jsdouble d, jsint *ip)
521 return JSDOUBLE_IS_INT32(d, (int32_t *)ip);
524 JS_PUBLIC_API(JSBool)
525 JS_ValueToECMAInt32(JSContext *cx, jsval v, int32 *ip)
528 assertSameCompartment(cx, v);
530 AutoValueRooter tvr(cx, Valueify(v));
531 return ValueToECMAInt32(cx, tvr.value(), (int32_t *)ip);
534 JS_PUBLIC_API(JSBool)
535 JS_ValueToECMAUint32(JSContext *cx, jsval v, uint32 *ip)
538 assertSameCompartment(cx, v);
540 AutoValueRooter tvr(cx, Valueify(v));
541 return ValueToECMAUint32(cx, tvr.value(), (uint32_t *)ip);
544 JS_PUBLIC_API(JSBool)
545 JS_ValueToInt32(JSContext *cx, jsval v, int32 *ip)
548 assertSameCompartment(cx, v);
550 AutoValueRooter tvr(cx, Valueify(v));
551 return ValueToInt32(cx, tvr.value(), (int32_t *)ip);
554 JS_PUBLIC_API(JSBool)
555 JS_ValueToUint16(JSContext *cx, jsval v, uint16 *ip)
558 assertSameCompartment(cx, v);
560 AutoValueRooter tvr(cx, Valueify(v));
561 return ValueToUint16(cx, tvr.value(), (uint16_t *)ip);
564 JS_PUBLIC_API(JSBool)
565 JS_ValueToBoolean(JSContext *cx, jsval v, JSBool *bp)
568 assertSameCompartment(cx, v);
569 *bp = js_ValueToBoolean(Valueify(v));
573 JS_PUBLIC_API(JSType)
574 JS_TypeOfValue(JSContext *cx, jsval v)
577 assertSameCompartment(cx, v);
578 return TypeOfValue(cx, Valueify(v));
581 JS_PUBLIC_API(const char *)
582 JS_GetTypeName(JSContext *cx, JSType type)
584 if ((uintN)type >= (uintN)JSTYPE_LIMIT)
586 return JS_TYPE_STR(type);
589 JS_PUBLIC_API(JSBool)
590 JS_StrictlyEqual(JSContext *cx, jsval v1, jsval v2, JSBool *equal)
592 assertSameCompartment(cx, v1, v2);
593 return StrictlyEqual(cx, Valueify(v1), Valueify(v2), equal);
596 JS_PUBLIC_API(JSBool)
597 JS_SameValue(JSContext *cx, jsval v1, jsval v2, JSBool *same)
599 assertSameCompartment(cx, v1, v2);
600 return SameValue(cx, Valueify(v1), Valueify(v2), same);
603 /************************************************************************/
606 * Has a new runtime ever been created? This flag is used to detect unsafe
607 * changes to js_CStringsAreUTF8 after a runtime has been created, and to
608 * ensure that "first checks" on runtime creation are run only once.
611 static JSBool js_NewRuntimeWasCalled = JS_FALSE;
614 JSRuntime::JSRuntime()
615 : gcChunkAllocator(&defaultGCChunkAllocator)
617 /* Initialize infallibly first, so we can goto bad and JS_DestroyRuntime. */
618 JS_INIT_CLIST(&contextList);
619 JS_INIT_CLIST(&trapList);
620 JS_INIT_CLIST(&watchPointList);
624 JSRuntime::init(uint32 maxbytes)
626 #ifdef JS_METHODJIT_SPEW
631 functionMeterFilename = getenv("JS_FUNCTION_STATFILE");
632 if (functionMeterFilename) {
633 if (!methodReadBarrierCountMap.init())
635 if (!unjoinedFunctionCountMap.init())
638 propTreeStatFilename = getenv("JS_PROPTREE_STATFILE");
639 propTreeDumpFilename = getenv("JS_PROPTREE_DUMPFILE");
642 if (!(atomsCompartment = js_new<JSCompartment>(this)) ||
643 !atomsCompartment->init() ||
644 !compartments.append(atomsCompartment)) {
648 if (!js_InitGC(this, maxbytes) || !js_InitAtomState(this))
651 wrapObjectCallback = js::TransparentObjectWrapper;
654 /* this is asymmetric with JS_ShutDown: */
655 if (!js_SetupLocks(8, 16))
657 rtLock = JS_NEW_LOCK();
660 stateChange = JS_NEW_CONDVAR(gcLock);
663 debuggerLock = JS_NEW_LOCK();
668 debugMode = JS_FALSE;
670 return js_InitThreads(this);
673 JSRuntime::~JSRuntime()
676 /* Don't hurt everyone in leaky ol' Mozilla with a fatal JS_ASSERT! */
677 if (!JS_CLIST_IS_EMPTY(&contextList)) {
678 JSContext *cx, *iter = NULL;
680 while ((cx = js_ContextIterator(this, JS_TRUE, &iter)) != NULL) {
682 "JS API usage error: found live context at %p\n",
687 "JS API usage error: %u context%s left in runtime upon JS_DestroyRuntime.\n",
688 cxcount, (cxcount == 1) ? "" : "s");
692 js_FinishThreads(this);
693 js_FreeRuntimeScriptState(this);
694 js_FinishAtomState(this);
699 JS_DESTROY_LOCK(gcLock);
701 JS_DESTROY_CONDVAR(gcDone);
703 JS_DESTROY_CONDVAR(requestDone);
705 JS_DESTROY_LOCK(rtLock);
707 JS_DESTROY_CONDVAR(stateChange);
709 JS_DESTROY_LOCK(debuggerLock);
713 JS_PUBLIC_API(JSRuntime *)
714 JS_NewRuntime(uint32 maxbytes)
717 if (!js_NewRuntimeWasCalled) {
719 * This code asserts that the numbers associated with the error names
720 * in jsmsg.def are monotonically increasing. It uses values for the
721 * error names enumerated in jscntxt.c. It's not a compile-time check
722 * but it's better than nothing.
725 #define MSG_DEF(name, number, count, exception, format) \
726 JS_ASSERT(name == errorNumber++);
730 #define MSG_DEF(name, number, count, exception, format) \
732 uintN numfmtspecs = 0; \
734 for (fmt = format; *fmt != '\0'; fmt++) { \
735 if (*fmt == '{' && isdigit(fmt[1])) \
738 JS_ASSERT(count == numfmtspecs); \
743 js_NewRuntimeWasCalled = JS_TRUE;
747 void *mem = js_calloc(sizeof(JSRuntime));
751 JSRuntime *rt = new (mem) JSRuntime();
752 if (!rt->init(maxbytes)) {
753 JS_DestroyRuntime(rt);
761 JS_DestroyRuntime(JSRuntime *rt)
769 namespace reprmeter {
770 extern void js_DumpReprMeter();
782 extern void js_DumpOpMeters();
787 reprmeter::js_DumpReprMeter();
796 JS_PUBLIC_API(void *)
797 JS_GetRuntimePrivate(JSRuntime *rt)
803 JS_SetRuntimePrivate(JSRuntime *rt, void *data)
810 StartRequest(JSContext *cx)
812 JSThread *t = cx->thread;
813 JS_ASSERT(CURRENT_THREAD_IS_ME(t));
815 if (t->data.requestDepth) {
816 t->data.requestDepth++;
818 JSRuntime *rt = cx->runtime;
821 /* Wait until the GC is finished. */
822 if (rt->gcThread != cx->thread) {
824 JS_AWAIT_GC_DONE(rt);
827 /* Indicate that a request is running. */
829 t->data.requestDepth = 1;
832 * Adjust rt->interruptCounter to reflect any interrupts added while the
833 * thread was suspended.
835 if (t->data.interruptFlags)
836 JS_ATOMIC_INCREMENT(&rt->interruptCounter);
838 if (rt->requestCount == 1 && rt->activityCallback)
839 rt->activityCallback(rt->activityCallbackArg, true);
844 StopRequest(JSContext *cx)
846 JSThread *t = cx->thread;
847 JS_ASSERT(CURRENT_THREAD_IS_ME(t));
848 JS_ASSERT(t->data.requestDepth != 0);
849 if (t->data.requestDepth != 1) {
850 t->data.requestDepth--;
852 LeaveTrace(cx); /* for GC safety */
854 t->data.conservativeGC.updateForRequestEnd(t->suspendCount);
856 /* Lock before clearing to interlock with ClaimScope, in jslock.c. */
857 JSRuntime *rt = cx->runtime;
860 t->data.requestDepth = 0;
863 * Adjust rt->interruptCounter to reflect any interrupts added while the
864 * thread still had active requests.
866 if (t->data.interruptFlags)
867 JS_ATOMIC_DECREMENT(&rt->interruptCounter);
869 /* Give the GC a chance to run if this was the last request running. */
870 JS_ASSERT(rt->requestCount > 0);
872 if (rt->requestCount == 0) {
873 JS_NOTIFY_REQUEST_DONE(rt);
874 if (rt->activityCallback)
875 rt->activityCallback(rt->activityCallbackArg, false);
879 #endif /* JS_THREADSAFE */
882 JS_BeginRequest(JSContext *cx)
885 cx->outstandingRequests++;
891 JS_EndRequest(JSContext *cx)
894 JS_ASSERT(cx->outstandingRequests != 0);
895 cx->outstandingRequests--;
900 /* Yield to pending GC operations, regardless of request depth */
902 JS_YieldRequest(JSContext *cx)
906 JS_ResumeRequest(cx, JS_SuspendRequest(cx));
910 JS_PUBLIC_API(jsrefcount)
911 JS_SuspendRequest(JSContext *cx)
914 JSThread *t = cx->thread;
915 JS_ASSERT(CURRENT_THREAD_IS_ME(t));
917 jsrefcount saveDepth = t->data.requestDepth;
922 t->data.requestDepth = 1;
931 JS_ResumeRequest(JSContext *cx, jsrefcount saveDepth)
934 JSThread *t = cx->thread;
935 JS_ASSERT(CURRENT_THREAD_IS_ME(t));
938 JS_ASSERT(saveDepth >= 1);
939 JS_ASSERT(!t->data.requestDepth);
940 JS_ASSERT(t->suspendCount);
942 t->data.requestDepth = saveDepth;
947 JS_PUBLIC_API(JSBool)
948 JS_IsInRequest(JSContext *cx)
951 JS_ASSERT(CURRENT_THREAD_IS_ME(cx->thread));
952 return JS_THREAD_DATA(cx)->requestDepth != 0;
959 JS_Lock(JSRuntime *rt)
965 JS_Unlock(JSRuntime *rt)
967 JS_UNLOCK_RUNTIME(rt);
970 JS_PUBLIC_API(JSContextCallback)
971 JS_SetContextCallback(JSRuntime *rt, JSContextCallback cxCallback)
973 JSContextCallback old;
975 old = rt->cxCallback;
976 rt->cxCallback = cxCallback;
980 JS_PUBLIC_API(JSContext *)
981 JS_NewContext(JSRuntime *rt, size_t stackChunkSize)
983 return js_NewContext(rt, stackChunkSize);
987 JS_DestroyContext(JSContext *cx)
989 js_DestroyContext(cx, JSDCM_FORCE_GC);
993 JS_DestroyContextNoGC(JSContext *cx)
995 js_DestroyContext(cx, JSDCM_NO_GC);
999 JS_DestroyContextMaybeGC(JSContext *cx)
1001 js_DestroyContext(cx, JSDCM_MAYBE_GC);
1004 JS_PUBLIC_API(void *)
1005 JS_GetContextPrivate(JSContext *cx)
1011 JS_SetContextPrivate(JSContext *cx, void *data)
1016 JS_PUBLIC_API(JSRuntime *)
1017 JS_GetRuntime(JSContext *cx)
1022 JS_PUBLIC_API(JSContext *)
1023 JS_ContextIterator(JSRuntime *rt, JSContext **iterp)
1025 return js_ContextIterator(rt, JS_TRUE, iterp);
1028 JS_PUBLIC_API(JSVersion)
1029 JS_GetVersion(JSContext *cx)
1031 return VersionNumber(cx->findVersion());
1034 JS_PUBLIC_API(JSVersion)
1035 JS_SetVersion(JSContext *cx, JSVersion newVersion)
1037 JS_ASSERT(VersionIsKnown(newVersion));
1038 JS_ASSERT(!VersionHasFlags(newVersion));
1039 JSVersion newVersionNumber = newVersion;
1042 uintN coptsBefore = cx->getCompileOptions();
1044 JSVersion oldVersion = cx->findVersion();
1045 JSVersion oldVersionNumber = VersionNumber(oldVersion);
1046 if (oldVersionNumber == newVersionNumber)
1047 return oldVersionNumber; /* No override actually occurs! */
1049 /* We no longer support 1.4 or below. */
1050 if (newVersionNumber != JSVERSION_DEFAULT && newVersionNumber <= JSVERSION_1_4)
1051 return oldVersionNumber;
1053 VersionCopyFlags(&newVersion, oldVersion);
1054 cx->maybeOverrideVersion(newVersion);
1055 JS_ASSERT(cx->getCompileOptions() == coptsBefore);
1056 return oldVersionNumber;
1059 static struct v2smap {
1063 {JSVERSION_1_0, "1.0"},
1064 {JSVERSION_1_1, "1.1"},
1065 {JSVERSION_1_2, "1.2"},
1066 {JSVERSION_1_3, "1.3"},
1067 {JSVERSION_1_4, "1.4"},
1068 {JSVERSION_ECMA_3, "ECMAv3"},
1069 {JSVERSION_1_5, "1.5"},
1070 {JSVERSION_1_6, "1.6"},
1071 {JSVERSION_1_7, "1.7"},
1072 {JSVERSION_1_8, "1.8"},
1073 {JSVERSION_ECMA_5, "ECMAv5"},
1074 {JSVERSION_DEFAULT, js_default_str},
1075 {JSVERSION_UNKNOWN, NULL}, /* must be last, NULL is sentinel */
1078 JS_PUBLIC_API(const char *)
1079 JS_VersionToString(JSVersion version)
1083 for (i = 0; v2smap[i].string; i++)
1084 if (v2smap[i].version == version)
1085 return v2smap[i].string;
1089 JS_PUBLIC_API(JSVersion)
1090 JS_StringToVersion(const char *string)
1094 for (i = 0; v2smap[i].string; i++)
1095 if (strcmp(v2smap[i].string, string) == 0)
1096 return v2smap[i].version;
1097 return JSVERSION_UNKNOWN;
1100 JS_PUBLIC_API(uint32)
1101 JS_GetOptions(JSContext *cx)
1104 * Can't check option/version synchronization here.
1105 * We may have been synchronized with a script version that was formerly on
1106 * the stack, but has now been popped.
1108 return cx->allOptions();
1112 SetOptionsCommon(JSContext *cx, uintN options)
1114 JS_ASSERT((options & JSALLOPTION_MASK) == options);
1115 uintN oldopts = cx->allOptions();
1116 uintN newropts = options & JSRUNOPTION_MASK;
1117 uintN newcopts = options & JSCOMPILEOPTION_MASK;
1118 cx->setRunOptions(newropts);
1119 cx->setCompileOptions(newcopts);
1120 cx->updateJITEnabled();
1124 JS_PUBLIC_API(uint32)
1125 JS_SetOptions(JSContext *cx, uint32 options)
1127 AutoLockGC lock(cx->runtime);
1128 return SetOptionsCommon(cx, options);
1131 JS_PUBLIC_API(uint32)
1132 JS_ToggleOptions(JSContext *cx, uint32 options)
1134 AutoLockGC lock(cx->runtime);
1135 uintN oldopts = cx->allOptions();
1136 uintN newopts = oldopts ^ options;
1137 return SetOptionsCommon(cx, newopts);
1140 JS_PUBLIC_API(const char *)
1141 JS_GetImplementationVersion(void)
1143 return "JavaScript-C 1.8.5 2011-03-31";
1146 JS_PUBLIC_API(JSCompartmentCallback)
1147 JS_SetCompartmentCallback(JSRuntime *rt, JSCompartmentCallback callback)
1149 JSCompartmentCallback old = rt->compartmentCallback;
1150 rt->compartmentCallback = callback;
1154 JS_PUBLIC_API(JSWrapObjectCallback)
1155 JS_SetWrapObjectCallbacks(JSRuntime *rt,
1156 JSWrapObjectCallback callback,
1157 JSPreWrapCallback precallback)
1159 JSWrapObjectCallback old = rt->wrapObjectCallback;
1160 rt->wrapObjectCallback = callback;
1161 rt->preWrapObjectCallback = precallback;
1165 JS_PUBLIC_API(JSCrossCompartmentCall *)
1166 JS_EnterCrossCompartmentCall(JSContext *cx, JSObject *target)
1171 AutoCompartment *call = js_new<AutoCompartment>(cx, target);
1174 if (!call->enter()) {
1178 return reinterpret_cast<JSCrossCompartmentCall *>(call);
1181 JS_PUBLIC_API(JSCrossCompartmentCall *)
1182 JS_EnterCrossCompartmentCallScript(JSContext *cx, JSScript *target)
1184 static JSClass dummy_class = {
1186 JSCLASS_GLOBAL_FLAGS,
1187 JS_PropertyStub, JS_PropertyStub,
1188 JS_PropertyStub, JS_StrictPropertyStub,
1189 JS_EnumerateStub, JS_ResolveStub,
1190 JS_ConvertStub, NULL,
1191 JSCLASS_NO_OPTIONAL_MEMBERS
1197 JSObject *scriptObject = target->u.object;
1198 if (!scriptObject) {
1199 SwitchToCompartment sc(cx, target->compartment);
1200 scriptObject = JS_NewGlobalObject(cx, &dummy_class);
1204 return JS_EnterCrossCompartmentCall(cx, scriptObject);
1208 JS_LeaveCrossCompartmentCall(JSCrossCompartmentCall *call)
1210 AutoCompartment *realcall = reinterpret_cast<AutoCompartment *>(call);
1211 CHECK_REQUEST(realcall->context);
1213 js_delete(realcall);
1217 JSAutoEnterCompartment::enter(JSContext *cx, JSObject *target)
1220 if (cx->compartment == target->getCompartment()) {
1221 call = reinterpret_cast<JSCrossCompartmentCall*>(1);
1224 call = JS_EnterCrossCompartmentCall(cx, target);
1225 return call != NULL;
1229 JSAutoEnterCompartment::enterAndIgnoreErrors(JSContext *cx, JSObject *target)
1231 (void) enter(cx, target);
1237 AutoEnterScriptCompartment::enter(JSContext *cx, JSScript *target)
1240 if (cx->compartment == target->compartment) {
1241 call = reinterpret_cast<JSCrossCompartmentCall*>(1);
1244 call = JS_EnterCrossCompartmentCallScript(cx, target);
1245 return call != NULL;
1248 } /* namespace JS */
1250 JS_PUBLIC_API(void *)
1251 JS_SetCompartmentPrivate(JSContext *cx, JSCompartment *compartment, void *data)
1254 void *old = compartment->data;
1255 compartment->data = data;
1259 JS_PUBLIC_API(void *)
1260 JS_GetCompartmentPrivate(JSContext *cx, JSCompartment *compartment)
1263 return compartment->data;
1266 JS_PUBLIC_API(JSBool)
1267 JS_WrapObject(JSContext *cx, JSObject **objp)
1270 return cx->compartment->wrap(cx, objp);
1273 JS_PUBLIC_API(JSBool)
1274 JS_WrapValue(JSContext *cx, jsval *vp)
1277 return cx->compartment->wrap(cx, Valueify(vp));
1280 JS_PUBLIC_API(JSObject *)
1281 JS_TransplantObject(JSContext *cx, JSObject *origobj, JSObject *target)
1283 // This function is called when an object moves between two
1284 // different compartments. In that case, we need to "move" the
1285 // window from origobj's compartment to target's compartment.
1286 JSCompartment *destination = target->getCompartment();
1287 WrapperMap &map = destination->crossCompartmentWrappers;
1288 Value origv = ObjectValue(*origobj);
1291 if (origobj->getCompartment() == destination) {
1292 // If the original object is in the same compartment as the
1293 // destination, then we know that we won't find wrapper in the
1294 // destination's cross compartment map and that the same
1295 // object will continue to work. Note the rare case where
1296 // |origobj == target|. In that case, we can just treat this
1297 // as a same compartment navigation. The effect is to clear
1298 // all of the wrappers and their holders if they have
1299 // them. This would be cleaner as a separate API.
1300 if (origobj != target && !origobj->swap(cx, target))
1303 } else if (WrapperMap::Ptr p = map.lookup(origv)) {
1304 // There might already be a wrapper for the original object in
1305 // the new compartment. If there is, make it the primary outer
1306 // window proxy around the inner (accomplished by swapping
1307 // target's innards with the old, possibly security wrapper,
1309 obj = &p->value.toObject();
1311 if (!obj->swap(cx, target))
1314 // Otherwise, this is going to be our outer window proxy in
1315 // the new compartment.
1319 // Now, iterate through other scopes looking for references to the
1320 // old outer window. They need to be updated to point at the new
1321 // outer window. They also might transition between different
1322 // types of security wrappers based on whether the new compartment
1323 // is same origin with them.
1324 Value targetv = ObjectValue(*obj);
1325 WrapperVector &vector = cx->runtime->compartments;
1326 AutoValueVector toTransplant(cx);
1327 toTransplant.reserve(vector.length());
1329 for (JSCompartment **p = vector.begin(), **end = vector.end(); p != end; ++p) {
1330 WrapperMap &pmap = (*p)->crossCompartmentWrappers;
1331 if (WrapperMap::Ptr wp = pmap.lookup(origv)) {
1332 // We found a wrapper. Remember and root it.
1333 toTransplant.append(wp->value);
1337 for (Value *begin = toTransplant.begin(), *end = toTransplant.end(); begin != end; ++begin) {
1338 JSObject *wobj = &begin->toObject();
1339 JSCompartment *wcompartment = wobj->compartment();
1340 WrapperMap &pmap = wcompartment->crossCompartmentWrappers;
1341 JS_ASSERT(pmap.lookup(origv));
1344 // First, we wrap it in the new compartment. This will return
1346 AutoCompartment ac(cx, wobj);
1347 JSObject *tobj = obj;
1348 if (!ac.enter() || !wcompartment->wrap(cx, &tobj))
1351 // Now, because we need to maintain object identity, we do a
1352 // brain transplant on the old object. At the same time, we
1353 // update the entry in the compartment's wrapper map to point
1354 // to the old wrapper.
1355 JS_ASSERT(tobj != wobj);
1356 if (!wobj->swap(cx, tobj))
1358 pmap.put(targetv, ObjectValue(*wobj));
1361 // Lastly, update the original object to point to the new one.
1362 if (origobj->getCompartment() != destination) {
1363 AutoCompartment ac(cx, origobj);
1364 JSObject *tobj = obj;
1365 if (!ac.enter() || !JS_WrapObject(cx, &tobj))
1367 if (!origobj->swap(cx, tobj))
1369 origobj->getCompartment()->crossCompartmentWrappers.put(targetv, origv);
1376 * The location object is special. There is the location object itself and
1377 * then the location object wrapper. Because there are no direct references to
1378 * the location object itself, we don't want the old obj (|origobj| here) to
1379 * become the new wrapper but the wrapper itself instead. This leads to very
1380 * subtle differences between js_TransplantObjectWithWrapper and
1381 * JS_TransplantObject.
1383 JS_FRIEND_API(JSObject *)
1384 js_TransplantObjectWithWrapper(JSContext *cx,
1386 JSObject *origwrapper,
1387 JSObject *targetobj,
1388 JSObject *targetwrapper)
1391 JSCompartment *destination = targetobj->getCompartment();
1392 WrapperMap &map = destination->crossCompartmentWrappers;
1394 // |origv| is the map entry we're looking up. The map entries are going to
1395 // be for the location object itself.
1396 Value origv = ObjectValue(*origobj);
1398 // There might already be a wrapper for the original object in the new
1400 if (WrapperMap::Ptr p = map.lookup(origv)) {
1401 // There is. Make the existing wrapper a same compartment location
1402 // wrapper (swapping it with the given new wrapper).
1403 obj = &p->value.toObject();
1405 if (!obj->swap(cx, targetwrapper))
1408 // Otherwise, use the passed-in wrapper as the same compartment
1409 // location wrapper.
1410 obj = targetwrapper;
1413 // Now, iterate through other scopes looking for references to the old
1414 // location object. Note that the entries in the maps are for |origobj|
1415 // and not |origwrapper|. They need to be updated to point at the new
1417 Value targetv = ObjectValue(*targetobj);
1418 WrapperVector &vector = cx->runtime->compartments;
1419 AutoValueVector toTransplant(cx);
1420 toTransplant.reserve(vector.length());
1422 for (JSCompartment **p = vector.begin(), **end = vector.end(); p != end; ++p) {
1423 WrapperMap &pmap = (*p)->crossCompartmentWrappers;
1424 if (WrapperMap::Ptr wp = pmap.lookup(origv)) {
1425 // We found a wrapper. Remember and root it.
1426 toTransplant.append(wp->value);
1430 for (Value *begin = toTransplant.begin(), *end = toTransplant.end(); begin != end; ++begin) {
1431 JSObject *wobj = &begin->toObject();
1432 JSCompartment *wcompartment = wobj->compartment();
1433 WrapperMap &pmap = wcompartment->crossCompartmentWrappers;
1434 JS_ASSERT(pmap.lookup(origv));
1437 // First, we wrap it in the new compartment. This will return a
1439 AutoCompartment ac(cx, wobj);
1441 JSObject *tobj = targetobj;
1442 if (!ac.enter() || !wcompartment->wrap(cx, &tobj))
1445 // Now, because we need to maintain object identity, we do a brain
1446 // transplant on the old object. At the same time, we update the
1447 // entry in the compartment's wrapper map to point to the old
1449 JS_ASSERT(tobj != wobj);
1450 if (!wobj->swap(cx, tobj))
1452 pmap.put(targetv, ObjectValue(*wobj));
1455 // Lastly, update the original object to point to the new one. However, as
1456 // mentioned above, we do the transplant on the wrapper, not the object
1457 // itself, since all of the references are to the object itself.
1459 AutoCompartment ac(cx, origobj);
1460 JSObject *tobj = obj;
1461 if (!ac.enter() || !JS_WrapObject(cx, &tobj))
1463 if (!origwrapper->swap(cx, tobj))
1465 origwrapper->getCompartment()->crossCompartmentWrappers.put(targetv,
1466 ObjectValue(*origwrapper));
1472 JS_PUBLIC_API(JSObject *)
1473 JS_GetGlobalObject(JSContext *cx)
1475 return cx->globalObject;
1479 JS_SetGlobalObject(JSContext *cx, JSObject *obj)
1483 cx->globalObject = obj;
1485 cx->resetCompartment();
1488 class AutoResolvingEntry {
1490 AutoResolvingEntry() : entry(NULL) {}
1493 * Returns false on error. But N.B. if obj[id] was already being resolved,
1494 * this is a no-op, and we silently treat that as success.
1496 bool start(JSContext *cx, JSObject *obj, jsid id, uint32 flag) {
1502 bool ok = !!js_StartResolving(cx, &key, flag, &entry);
1503 JS_ASSERT_IF(!ok, !entry);
1507 ~AutoResolvingEntry() {
1509 js_StopResolving(cx, &key, flag, NULL, 0);
1516 JSResolvingEntry *entry;
1520 js_InitFunctionAndObjectClasses(JSContext *cx, JSObject *obj)
1522 JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
1523 JSObject *fun_proto, *obj_proto;
1525 /* If cx has no global object, use obj so prototypes can be found. */
1526 if (!cx->globalObject)
1527 JS_SetGlobalObject(cx, obj);
1529 /* Record Function and Object in cx->resolvingTable. */
1530 AutoResolvingEntry e1, e2;
1531 JSAtom **classAtoms = cx->runtime->atomState.classAtoms;
1532 if (!e1.start(cx, obj, ATOM_TO_JSID(classAtoms[JSProto_Function]), JSRESFLAG_LOOKUP) ||
1533 !e2.start(cx, obj, ATOM_TO_JSID(classAtoms[JSProto_Object]), JSRESFLAG_LOOKUP)) {
1537 /* Initialize the function class first so constructors can be made. */
1538 if (!js_GetClassPrototype(cx, obj, JSProto_Function, &fun_proto))
1541 fun_proto = js_InitFunctionClass(cx, obj);
1547 ctor = JS_GetConstructor(cx, fun_proto);
1550 if (!obj->defineProperty(cx, ATOM_TO_JSID(CLASS_ATOM(cx, Function)),
1551 ObjectValue(*ctor), 0, 0, 0)) {
1556 /* Initialize the object class next so Object.prototype works. */
1557 if (!js_GetClassPrototype(cx, obj, JSProto_Object, &obj_proto))
1560 obj_proto = js_InitObjectClass(cx, obj);
1564 /* Function.prototype and the global object delegate to Object.prototype. */
1565 fun_proto->setProto(obj_proto);
1566 if (!obj->getProto())
1567 obj->setProto(obj_proto);
1572 JS_PUBLIC_API(JSBool)
1573 JS_InitStandardClasses(JSContext *cx, JSObject *obj)
1575 JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
1579 * JS_SetGlobalObject might or might not change cx's compartment, so call
1580 * it before assertSameCompartment. (The API contract is that *after* this,
1581 * cx and obj must be in the same compartment.)
1583 if (!cx->globalObject)
1584 JS_SetGlobalObject(cx, obj);
1585 assertSameCompartment(cx, obj);
1587 /* Define a top-level property 'undefined' with the undefined value. */
1588 JSAtom *atom = cx->runtime->atomState.typeAtoms[JSTYPE_VOID];
1589 if (!obj->defineProperty(cx, ATOM_TO_JSID(atom), UndefinedValue(),
1590 PropertyStub, StrictPropertyStub,
1591 JSPROP_PERMANENT | JSPROP_READONLY)) {
1595 /* Function and Object require cooperative bootstrapping magic. */
1596 if (!js_InitFunctionAndObjectClasses(cx, obj))
1599 /* Initialize the rest of the standard objects and functions. */
1600 return js_InitArrayClass(cx, obj) &&
1601 js_InitBooleanClass(cx, obj) &&
1602 js_InitExceptionClasses(cx, obj) &&
1603 js_InitMathClass(cx, obj) &&
1604 js_InitNumberClass(cx, obj) &&
1605 js_InitJSONClass(cx, obj) &&
1606 js_InitRegExpClass(cx, obj) &&
1607 js_InitStringClass(cx, obj) &&
1608 js_InitTypedArrayClasses(cx, obj) &&
1609 #if JS_HAS_XML_SUPPORT
1610 js_InitXMLClasses(cx, obj) &&
1612 #if JS_HAS_GENERATORS
1613 js_InitIteratorClasses(cx, obj) &&
1615 js_InitDateClass(cx, obj) &&
1616 js_InitProxyClass(cx, obj);
1619 #define CLASP(name) (&js_##name##Class)
1620 #define TYPED_ARRAY_CLASP(type) (&TypedArray::fastClasses[TypedArray::type])
1621 #define EAGER_ATOM(name) ATOM_OFFSET(name), NULL
1622 #define EAGER_CLASS_ATOM(name) CLASS_ATOM_OFFSET(name), NULL
1623 #define EAGER_ATOM_AND_CLASP(name) EAGER_CLASS_ATOM(name), CLASP(name)
1624 #define LAZY_ATOM(name) ATOM_OFFSET(lazy.name), js_##name##_str
1626 typedef struct JSStdName {
1628 size_t atomOffset; /* offset of atom pointer in JSAtomState */
1629 const char *name; /* null if atom is pre-pinned, else name */
1634 StdNameToAtom(JSContext *cx, JSStdName *stdn)
1640 offset = stdn->atomOffset;
1641 atom = OFFSET_TO_ATOM(cx->runtime, offset);
1645 atom = js_Atomize(cx, name, strlen(name), ATOM_PINNED);
1646 OFFSET_TO_ATOM(cx->runtime, offset) = atom;
1653 * Table of class initializers and their atom offsets in rt->atomState.
1654 * If you add a "standard" class, remember to update this table.
1656 static JSStdName standard_class_atoms[] = {
1657 {js_InitFunctionAndObjectClasses, EAGER_ATOM_AND_CLASP(Function)},
1658 {js_InitFunctionAndObjectClasses, EAGER_ATOM_AND_CLASP(Object)},
1659 {js_InitArrayClass, EAGER_ATOM_AND_CLASP(Array)},
1660 {js_InitBooleanClass, EAGER_ATOM_AND_CLASP(Boolean)},
1661 {js_InitDateClass, EAGER_ATOM_AND_CLASP(Date)},
1662 {js_InitMathClass, EAGER_ATOM_AND_CLASP(Math)},
1663 {js_InitNumberClass, EAGER_ATOM_AND_CLASP(Number)},
1664 {js_InitStringClass, EAGER_ATOM_AND_CLASP(String)},
1665 {js_InitExceptionClasses, EAGER_ATOM_AND_CLASP(Error)},
1666 {js_InitRegExpClass, EAGER_ATOM_AND_CLASP(RegExp)},
1667 #if JS_HAS_XML_SUPPORT
1668 {js_InitXMLClass, EAGER_ATOM_AND_CLASP(XML)},
1669 {js_InitNamespaceClass, EAGER_ATOM_AND_CLASP(Namespace)},
1670 {js_InitQNameClass, EAGER_ATOM_AND_CLASP(QName)},
1672 #if JS_HAS_GENERATORS
1673 {js_InitIteratorClasses, EAGER_ATOM_AND_CLASP(StopIteration)},
1675 {js_InitJSONClass, EAGER_ATOM_AND_CLASP(JSON)},
1676 {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(ArrayBuffer), &js::ArrayBuffer::jsclass},
1677 {NULL, 0, NULL, NULL}
1681 * Table of top-level function and constant names and their init functions.
1682 * If you add a "standard" global function or property, remember to update
1685 static JSStdName standard_class_names[] = {
1686 {js_InitObjectClass, EAGER_ATOM(eval), CLASP(Object)},
1688 /* Global properties and functions defined by the Number class. */
1689 {js_InitNumberClass, EAGER_ATOM(NaN), CLASP(Number)},
1690 {js_InitNumberClass, EAGER_ATOM(Infinity), CLASP(Number)},
1691 {js_InitNumberClass, LAZY_ATOM(isNaN), CLASP(Number)},
1692 {js_InitNumberClass, LAZY_ATOM(isFinite), CLASP(Number)},
1693 {js_InitNumberClass, LAZY_ATOM(parseFloat), CLASP(Number)},
1694 {js_InitNumberClass, LAZY_ATOM(parseInt), CLASP(Number)},
1696 /* String global functions. */
1697 {js_InitStringClass, LAZY_ATOM(escape), CLASP(String)},
1698 {js_InitStringClass, LAZY_ATOM(unescape), CLASP(String)},
1699 {js_InitStringClass, LAZY_ATOM(decodeURI), CLASP(String)},
1700 {js_InitStringClass, LAZY_ATOM(encodeURI), CLASP(String)},
1701 {js_InitStringClass, LAZY_ATOM(decodeURIComponent), CLASP(String)},
1702 {js_InitStringClass, LAZY_ATOM(encodeURIComponent), CLASP(String)},
1704 {js_InitStringClass, LAZY_ATOM(uneval), CLASP(String)},
1707 /* Exception constructors. */
1708 {js_InitExceptionClasses, EAGER_CLASS_ATOM(Error), CLASP(Error)},
1709 {js_InitExceptionClasses, EAGER_CLASS_ATOM(InternalError), CLASP(Error)},
1710 {js_InitExceptionClasses, EAGER_CLASS_ATOM(EvalError), CLASP(Error)},
1711 {js_InitExceptionClasses, EAGER_CLASS_ATOM(RangeError), CLASP(Error)},
1712 {js_InitExceptionClasses, EAGER_CLASS_ATOM(ReferenceError), CLASP(Error)},
1713 {js_InitExceptionClasses, EAGER_CLASS_ATOM(SyntaxError), CLASP(Error)},
1714 {js_InitExceptionClasses, EAGER_CLASS_ATOM(TypeError), CLASP(Error)},
1715 {js_InitExceptionClasses, EAGER_CLASS_ATOM(URIError), CLASP(Error)},
1717 #if JS_HAS_XML_SUPPORT
1718 {js_InitXMLClass, LAZY_ATOM(XMLList), CLASP(XML)},
1719 {js_InitXMLClass, LAZY_ATOM(isXMLName), CLASP(XML)},
1722 #if JS_HAS_GENERATORS
1723 {js_InitIteratorClasses, EAGER_ATOM_AND_CLASP(Iterator)},
1724 {js_InitIteratorClasses, EAGER_ATOM_AND_CLASP(Generator)},
1728 {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(ArrayBuffer), &js::ArrayBuffer::jsclass},
1729 {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(Int8Array), TYPED_ARRAY_CLASP(TYPE_INT8)},
1730 {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(Uint8Array), TYPED_ARRAY_CLASP(TYPE_UINT8)},
1731 {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(Int16Array), TYPED_ARRAY_CLASP(TYPE_INT16)},
1732 {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(Uint16Array), TYPED_ARRAY_CLASP(TYPE_UINT16)},
1733 {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(Int32Array), TYPED_ARRAY_CLASP(TYPE_INT32)},
1734 {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(Uint32Array), TYPED_ARRAY_CLASP(TYPE_UINT32)},
1735 {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(Float32Array), TYPED_ARRAY_CLASP(TYPE_FLOAT32)},
1736 {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(Float64Array), TYPED_ARRAY_CLASP(TYPE_FLOAT64)},
1737 {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(Uint8ClampedArray),
1738 TYPED_ARRAY_CLASP(TYPE_UINT8_CLAMPED)},
1740 {js_InitProxyClass, EAGER_ATOM_AND_CLASP(Proxy)},
1742 {NULL, 0, NULL, NULL}
1745 static JSStdName object_prototype_names[] = {
1746 /* Object.prototype properties (global delegates to Object.prototype). */
1747 {js_InitObjectClass, EAGER_ATOM(proto), CLASP(Object)},
1749 {js_InitObjectClass, EAGER_ATOM(toSource), CLASP(Object)},
1751 {js_InitObjectClass, EAGER_ATOM(toString), CLASP(Object)},
1752 {js_InitObjectClass, EAGER_ATOM(toLocaleString), CLASP(Object)},
1753 {js_InitObjectClass, EAGER_ATOM(valueOf), CLASP(Object)},
1754 #if JS_HAS_OBJ_WATCHPOINT
1755 {js_InitObjectClass, LAZY_ATOM(watch), CLASP(Object)},
1756 {js_InitObjectClass, LAZY_ATOM(unwatch), CLASP(Object)},
1758 {js_InitObjectClass, LAZY_ATOM(hasOwnProperty), CLASP(Object)},
1759 {js_InitObjectClass, LAZY_ATOM(isPrototypeOf), CLASP(Object)},
1760 {js_InitObjectClass, LAZY_ATOM(propertyIsEnumerable), CLASP(Object)},
1761 #if OLD_GETTER_SETTER_METHODS
1762 {js_InitObjectClass, LAZY_ATOM(defineGetter), CLASP(Object)},
1763 {js_InitObjectClass, LAZY_ATOM(defineSetter), CLASP(Object)},
1764 {js_InitObjectClass, LAZY_ATOM(lookupGetter), CLASP(Object)},
1765 {js_InitObjectClass, LAZY_ATOM(lookupSetter), CLASP(Object)},
1768 {NULL, 0, NULL, NULL}
1771 JS_PUBLIC_API(JSBool)
1772 JS_ResolveStandardClass(JSContext *cx, JSObject *obj, jsid id, JSBool *resolved)
1781 assertSameCompartment(cx, obj, id);
1782 *resolved = JS_FALSE;
1785 JS_ASSERT(rt->state != JSRTS_DOWN);
1786 if (rt->state == JSRTS_LANDING || !JSID_IS_ATOM(id))
1789 idstr = JSID_TO_STRING(id);
1791 /* Check whether we're resolving 'undefined', and define it if so. */
1792 atom = rt->atomState.typeAtoms[JSTYPE_VOID];
1793 if (idstr == ATOM_TO_STRING(atom)) {
1794 *resolved = JS_TRUE;
1795 return obj->defineProperty(cx, ATOM_TO_JSID(atom), UndefinedValue(),
1796 PropertyStub, StrictPropertyStub,
1797 JSPROP_PERMANENT | JSPROP_READONLY);
1800 /* Try for class constructors/prototypes named by well-known atoms. */
1802 for (i = 0; standard_class_atoms[i].init; i++) {
1803 JS_ASSERT(standard_class_atoms[i].clasp);
1804 atom = OFFSET_TO_ATOM(rt, standard_class_atoms[i].atomOffset);
1805 if (idstr == ATOM_TO_STRING(atom)) {
1806 stdnm = &standard_class_atoms[i];
1812 /* Try less frequently used top-level functions and constants. */
1813 for (i = 0; standard_class_names[i].init; i++) {
1814 JS_ASSERT(standard_class_names[i].clasp);
1815 atom = StdNameToAtom(cx, &standard_class_names[i]);
1818 if (idstr == ATOM_TO_STRING(atom)) {
1819 stdnm = &standard_class_names[i];
1824 if (!stdnm && !obj->getProto()) {
1826 * Try even less frequently used names delegated from the global
1827 * object to Object.prototype, but only if the Object class hasn't
1828 * yet been initialized.
1830 for (i = 0; object_prototype_names[i].init; i++) {
1831 JS_ASSERT(object_prototype_names[i].clasp);
1832 atom = StdNameToAtom(cx, &object_prototype_names[i]);
1835 if (idstr == ATOM_TO_STRING(atom)) {
1836 stdnm = &object_prototype_names[i];
1845 * If this standard class is anonymous, then we don't want to resolve
1848 JS_ASSERT(obj->isGlobal());
1849 if (stdnm->clasp->flags & JSCLASS_IS_ANONYMOUS)
1852 JSProtoKey key = JSCLASS_CACHED_PROTO_KEY(stdnm->clasp);
1853 if (obj->getReservedSlot(key).isObject())
1856 if (!stdnm->init(cx, obj))
1858 *resolved = JS_TRUE;
1863 JS_PUBLIC_API(JSBool)
1864 JS_EnumerateStandardClasses(JSContext *cx, JSObject *obj)
1871 assertSameCompartment(cx, obj);
1874 /* Check whether we need to bind 'undefined' and define it if so. */
1875 atom = rt->atomState.typeAtoms[JSTYPE_VOID];
1876 if (!obj->nativeContains(ATOM_TO_JSID(atom)) &&
1877 !obj->defineProperty(cx, ATOM_TO_JSID(atom), UndefinedValue(),
1878 PropertyStub, StrictPropertyStub,
1879 JSPROP_PERMANENT | JSPROP_READONLY)) {
1883 /* Initialize any classes that have not been resolved yet. */
1884 for (i = 0; standard_class_atoms[i].init; i++) {
1885 atom = OFFSET_TO_ATOM(rt, standard_class_atoms[i].atomOffset);
1886 if (!obj->nativeContains(ATOM_TO_JSID(atom)) &&
1887 !standard_class_atoms[i].init(cx, obj)) {
1898 NewIdArray(JSContext *cx, jsint length)
1903 cx->calloc(offsetof(JSIdArray, vector) + length * sizeof(jsval));
1905 ida->length = length;
1912 * Unlike realloc(3), this function frees ida on failure.
1915 SetIdArrayLength(JSContext *cx, JSIdArray *ida, jsint length)
1919 rida = (JSIdArray *)
1921 offsetof(JSIdArray, vector) + length * sizeof(jsval));
1923 JS_DestroyIdArray(cx, ida);
1925 rida->length = length;
1931 AddAtomToArray(JSContext *cx, JSAtom *atom, JSIdArray *ida, jsint *ip)
1936 length = ida->length;
1938 ida = SetIdArrayLength(cx, ida, JS_MAX(length * 2, 8));
1941 JS_ASSERT(i < ida->length);
1943 ida->vector[i] = ATOM_TO_JSID(atom);
1949 EnumerateIfResolved(JSContext *cx, JSObject *obj, JSAtom *atom, JSIdArray *ida,
1950 jsint *ip, JSBool *foundp)
1952 *foundp = obj->nativeContains(ATOM_TO_JSID(atom));
1954 ida = AddAtomToArray(cx, atom, ida, ip);
1958 JS_PUBLIC_API(JSIdArray *)
1959 JS_EnumerateResolvedStandardClasses(JSContext *cx, JSObject *obj, JSIdArray *ida)
1968 assertSameCompartment(cx, obj, ida);
1973 ida = NewIdArray(cx, 8);
1979 /* Check whether 'undefined' has been resolved and enumerate it if so. */
1980 atom = rt->atomState.typeAtoms[JSTYPE_VOID];
1981 ida = EnumerateIfResolved(cx, obj, atom, ida, &i, &found);
1985 /* Enumerate only classes that *have* been resolved. */
1986 for (j = 0; standard_class_atoms[j].init; j++) {
1987 atom = OFFSET_TO_ATOM(rt, standard_class_atoms[j].atomOffset);
1988 ida = EnumerateIfResolved(cx, obj, atom, ida, &i, &found);
1993 init = standard_class_atoms[j].init;
1995 for (k = 0; standard_class_names[k].init; k++) {
1996 if (standard_class_names[k].init == init) {
1997 atom = StdNameToAtom(cx, &standard_class_names[k]);
1998 ida = AddAtomToArray(cx, atom, ida, &i);
2004 if (init == js_InitObjectClass) {
2005 for (k = 0; object_prototype_names[k].init; k++) {
2006 atom = StdNameToAtom(cx, &object_prototype_names[k]);
2007 ida = AddAtomToArray(cx, atom, ida, &i);
2015 /* Trim to exact length. */
2016 return SetIdArrayLength(cx, ida, i);
2021 #undef EAGER_CLASS_ATOM
2022 #undef EAGER_ATOM_CLASP
2025 JS_PUBLIC_API(JSBool)
2026 JS_GetClassObject(JSContext *cx, JSObject *obj, JSProtoKey key, JSObject **objp)
2029 assertSameCompartment(cx, obj);
2030 return js_GetClassObject(cx, obj, key, objp);
2033 JS_PUBLIC_API(JSObject *)
2034 JS_GetScopeChain(JSContext *cx)
2037 return GetScopeChain(cx);
2040 JS_PUBLIC_API(JSObject *)
2041 JS_GetGlobalForObject(JSContext *cx, JSObject *obj)
2043 assertSameCompartment(cx, obj);
2044 return obj->getGlobal();
2047 JS_PUBLIC_API(JSObject *)
2048 JS_GetGlobalForScopeChain(JSContext *cx)
2051 return GetGlobalForScopeChain(cx);
2054 JS_PUBLIC_API(jsval)
2055 JS_ComputeThis(JSContext *cx, jsval *vp)
2057 assertSameCompartment(cx, JSValueArray(vp, 2));
2058 return BoxThisForVp(cx, Valueify(vp)) ? vp[1] : JSVAL_NULL;
2061 JS_PUBLIC_API(void *)
2062 JS_malloc(JSContext *cx, size_t nbytes)
2064 return cx->malloc(nbytes);
2067 JS_PUBLIC_API(void *)
2068 JS_realloc(JSContext *cx, void *p, size_t nbytes)
2070 return cx->realloc(p, nbytes);
2074 JS_free(JSContext *cx, void *p)
2080 JS_updateMallocCounter(JSContext *cx, size_t nbytes)
2082 return cx->runtime->updateMallocCounter(nbytes);
2085 JS_PUBLIC_API(char *)
2086 JS_strdup(JSContext *cx, const char *s)
2095 return (char *)memcpy(p, s, n);
2098 JS_PUBLIC_API(JSBool)
2099 JS_NewNumberValue(JSContext *cx, jsdouble d, jsval *rval)
2101 d = JS_CANONICALIZE_NAN(d);
2102 Valueify(rval)->setNumber(d);
2108 JS_PUBLIC_API(JSBool)
2109 JS_AddValueRoot(JSContext *cx, jsval *vp)
2112 return js_AddRoot(cx, Valueify(vp), NULL);
2115 JS_PUBLIC_API(JSBool)
2116 JS_AddStringRoot(JSContext *cx, JSString **rp)
2119 return js_AddGCThingRoot(cx, (void **)rp, NULL);
2122 JS_PUBLIC_API(JSBool)
2123 JS_AddObjectRoot(JSContext *cx, JSObject **rp)
2126 return js_AddGCThingRoot(cx, (void **)rp, NULL);
2129 JS_PUBLIC_API(JSBool)
2130 JS_AddGCThingRoot(JSContext *cx, void **rp)
2133 return js_AddGCThingRoot(cx, (void **)rp, NULL);
2136 JS_PUBLIC_API(JSBool)
2137 JS_AddNamedValueRoot(JSContext *cx, jsval *vp, const char *name)
2140 return js_AddRoot(cx, Valueify(vp), name);
2143 JS_PUBLIC_API(JSBool)
2144 JS_AddNamedStringRoot(JSContext *cx, JSString **rp, const char *name)
2147 return js_AddGCThingRoot(cx, (void **)rp, name);
2150 JS_PUBLIC_API(JSBool)
2151 JS_AddNamedObjectRoot(JSContext *cx, JSObject **rp, const char *name)
2154 return js_AddGCThingRoot(cx, (void **)rp, name);
2157 JS_PUBLIC_API(JSBool)
2158 JS_AddNamedGCThingRoot(JSContext *cx, void **rp, const char *name)
2161 return js_AddGCThingRoot(cx, (void **)rp, name);
2164 JS_PUBLIC_API(JSBool)
2165 JS_RemoveValueRoot(JSContext *cx, jsval *vp)
2168 return js_RemoveRoot(cx->runtime, (void *)vp);
2171 JS_PUBLIC_API(JSBool)
2172 JS_RemoveStringRoot(JSContext *cx, JSString **rp)
2175 return js_RemoveRoot(cx->runtime, (void *)rp);
2178 JS_PUBLIC_API(JSBool)
2179 JS_RemoveObjectRoot(JSContext *cx, JSObject **rp)
2182 return js_RemoveRoot(cx->runtime, (void *)rp);
2185 JS_PUBLIC_API(JSBool)
2186 JS_RemoveGCThingRoot(JSContext *cx, void **rp)
2189 return js_RemoveRoot(cx->runtime, (void *)rp);
2192 JS_NEVER_INLINE JS_PUBLIC_API(void)
2193 JS_AnchorPtr(void *p)
2200 JS_DumpNamedRoots(JSRuntime *rt,
2201 void (*dump)(const char *name, void *rp, JSGCRootType type, void *data),
2204 js_DumpNamedRoots(rt, dump, data);
2209 JS_PUBLIC_API(uint32)
2210 JS_MapGCRoots(JSRuntime *rt, JSGCRootMapFun map, void *data)
2212 return js_MapGCRoots(rt, map, data);
2215 JS_PUBLIC_API(JSBool)
2216 JS_LockGCThing(JSContext *cx, void *thing)
2221 ok = js_LockGCThingRT(cx->runtime, thing);
2223 JS_ReportOutOfMemory(cx);
2227 JS_PUBLIC_API(JSBool)
2228 JS_LockGCThingRT(JSRuntime *rt, void *thing)
2230 return js_LockGCThingRT(rt, thing);
2233 JS_PUBLIC_API(JSBool)
2234 JS_UnlockGCThing(JSContext *cx, void *thing)
2237 js_UnlockGCThingRT(cx->runtime, thing);
2241 JS_PUBLIC_API(JSBool)
2242 JS_UnlockGCThingRT(JSRuntime *rt, void *thing)
2244 js_UnlockGCThingRT(rt, thing);
2249 JS_SetExtraGCRoots(JSRuntime *rt, JSTraceDataOp traceOp, void *data)
2251 rt->gcExtraRootsTraceOp = traceOp;
2252 rt->gcExtraRootsData = data;
2256 JS_TraceRuntime(JSTracer *trc)
2262 JS_CallTracer(JSTracer *trc, void *thing, uint32 kind)
2265 MarkKind(trc, thing, kind);
2270 #ifdef HAVE_XPCONNECT
2271 #include "dump_xpc.h"
2275 JS_PrintTraceThingInfo(char *buf, size_t bufsize, JSTracer *trc, void *thing, uint32 kind,
2285 case JSTRACE_OBJECT:
2287 JSObject *obj = (JSObject *)thing;
2288 Class *clasp = obj->getClass();
2291 #ifdef HAVE_XPCONNECT
2292 if (clasp->flags & JSCLASS_PRIVATE_IS_NSISUPPORTS) {
2293 void *privateThing = obj->getPrivate();
2295 const char *xpcClassName = GetXPCObjectClassName(privateThing);
2297 name = xpcClassName;
2304 case JSTRACE_STRING:
2305 name = ((JSString *)thing)->isDependent()
2310 #if JS_HAS_XML_SUPPORT
2322 if (n > bufsize - 1)
2324 memcpy(buf, name, n + 1);
2328 if (details && bufsize > 2) {
2333 case JSTRACE_OBJECT:
2335 JSObject *obj = (JSObject *)thing;
2336 Class *clasp = obj->getClass();
2337 if (clasp == &js_FunctionClass) {
2338 JSFunction *fun = GET_FUNCTION_PRIVATE(trc->context, obj);
2340 JS_snprintf(buf, bufsize, "<newborn>");
2341 } else if (FUN_OBJECT(fun) != obj) {
2342 JS_snprintf(buf, bufsize, "%p", fun);
2345 PutEscapedString(buf, bufsize, ATOM_TO_STRING(fun->atom), 0);
2347 } else if (clasp->flags & JSCLASS_HAS_PRIVATE) {
2348 JS_snprintf(buf, bufsize, "%p", obj->getPrivate());
2350 JS_snprintf(buf, bufsize, "<no private>");
2355 case JSTRACE_STRING:
2357 JSString *str = (JSString *)thing;
2358 if (str->isLinear())
2359 PutEscapedString(buf, bufsize, str->assertIsLinear(), 0);
2361 JS_snprintf(buf, bufsize, "<rope: length %d>", (int)str->length());
2365 #if JS_HAS_XML_SUPPORT
2368 extern const char *js_xml_class_str[];
2369 JSXML *xml = (JSXML *)thing;
2371 JS_snprintf(buf, bufsize, "%s", js_xml_class_str[xml->xml_class]);
2380 buf[bufsize - 1] = '\0';
2383 typedef struct JSHeapDumpNode JSHeapDumpNode;
2385 struct JSHeapDumpNode {
2388 JSHeapDumpNode *next; /* next sibling */
2389 JSHeapDumpNode *parent; /* node with the thing that refer to thing
2391 char edgeName[1]; /* name of the edge from parent->thing
2395 typedef struct JSDumpingTracer {
2397 JSDHashTable visited;
2401 void *thingToIgnore;
2402 JSHeapDumpNode *parentNode;
2403 JSHeapDumpNode **lastNodep;
2408 DumpNotify(JSTracer *trc, void *thing, uint32 kind)
2410 JSDumpingTracer *dtrc;
2412 JSDHashEntryStub *entry;
2413 JSHeapDumpNode *node;
2414 const char *edgeName;
2415 size_t edgeNameSize;
2417 JS_ASSERT(trc->callback == DumpNotify);
2418 dtrc = (JSDumpingTracer *)trc;
2420 if (!dtrc->ok || thing == dtrc->thingToIgnore)
2426 * Check if we have already seen thing unless it is thingToFind to include
2427 * it to the graph each time we reach it and print all live things that
2428 * refer to thingToFind.
2430 * This does not print all possible paths leading to thingToFind since
2431 * when a thing A refers directly or indirectly to thingToFind and A is
2432 * present several times in the graph, we will print only the first path
2433 * leading to A and thingToFind, other ways to reach A will be ignored.
2435 if (dtrc->thingToFind != thing) {
2437 * The startThing check allows to avoid putting startThing into the
2438 * hash table before tracing startThing in JS_DumpHeap.
2440 if (thing == dtrc->startThing)
2442 entry = (JSDHashEntryStub *)
2443 JS_DHashTableOperate(&dtrc->visited, thing, JS_DHASH_ADD);
2445 JS_ReportOutOfMemory(cx);
2446 dtrc->ok = JS_FALSE;
2454 if (dtrc->base.debugPrinter) {
2455 dtrc->base.debugPrinter(trc, dtrc->buffer, sizeof(dtrc->buffer));
2456 edgeName = dtrc->buffer;
2457 } else if (dtrc->base.debugPrintIndex != (size_t)-1) {
2458 JS_snprintf(dtrc->buffer, sizeof(dtrc->buffer), "%s[%lu]",
2459 (const char *)dtrc->base.debugPrintArg,
2460 dtrc->base.debugPrintIndex);
2461 edgeName = dtrc->buffer;
2463 edgeName = (const char*)dtrc->base.debugPrintArg;
2466 edgeNameSize = strlen(edgeName) + 1;
2467 node = (JSHeapDumpNode *) js_malloc(offsetof(JSHeapDumpNode, edgeName) + edgeNameSize);
2469 dtrc->ok = JS_FALSE;
2473 node->thing = thing;
2476 node->parent = dtrc->parentNode;
2477 memcpy(node->edgeName, edgeName, edgeNameSize);
2479 JS_ASSERT(!*dtrc->lastNodep);
2480 *dtrc->lastNodep = node;
2481 dtrc->lastNodep = &node->next;
2484 /* Dump node and the chain that leads to thing it contains. */
2486 DumpNode(JSDumpingTracer *dtrc, FILE* fp, JSHeapDumpNode *node)
2488 JSHeapDumpNode *prev, *following;
2491 enum { MAX_PARENTS_TO_PRINT = 10 };
2493 JS_PrintTraceThingInfo(dtrc->buffer, sizeof dtrc->buffer,
2494 &dtrc->base, node->thing, node->kind, JS_TRUE);
2495 if (fprintf(fp, "%p %-22s via ", node->thing, dtrc->buffer) < 0)
2499 * We need to print the parent chain in the reverse order. To do it in
2500 * O(N) time where N is the chain length we first reverse the chain while
2501 * searching for the top and then print each node while restoring the
2504 chainLimit = MAX_PARENTS_TO_PRINT;
2507 following = node->parent;
2508 node->parent = prev;
2513 if (chainLimit == 0) {
2514 if (fputs("...", fp) < 0)
2525 /* Loop must continue even when !ok to restore the parent chain. */
2528 /* Print edge from some runtime root or startThing. */
2529 if (fputs(node->edgeName, fp) < 0)
2532 JS_PrintTraceThingInfo(dtrc->buffer, sizeof dtrc->buffer,
2533 &dtrc->base, prev->thing, prev->kind,
2535 if (fprintf(fp, "(%p %s).%s",
2536 prev->thing, dtrc->buffer, node->edgeName) < 0) {
2541 following = node->parent;
2542 node->parent = prev;
2547 return ok && putc('\n', fp) >= 0;
2550 JS_PUBLIC_API(JSBool)
2551 JS_DumpHeap(JSContext *cx, FILE *fp, void* startThing, uint32 startKind,
2552 void *thingToFind, size_t maxDepth, void *thingToIgnore)
2554 JSDumpingTracer dtrc;
2555 JSHeapDumpNode *node, *children, *next, *parent;
2557 JSBool thingToFindWasTraced;
2562 JS_TRACER_INIT(&dtrc.base, cx, DumpNotify);
2563 if (!JS_DHashTableInit(&dtrc.visited, JS_DHashGetStubOps(),
2564 NULL, sizeof(JSDHashEntryStub),
2565 JS_DHASH_DEFAULT_CAPACITY(100))) {
2566 JS_ReportOutOfMemory(cx);
2570 dtrc.startThing = startThing;
2571 dtrc.thingToFind = thingToFind;
2572 dtrc.thingToIgnore = thingToIgnore;
2573 dtrc.parentNode = NULL;
2575 dtrc.lastNodep = &node;
2577 JS_ASSERT(startKind == 0);
2578 TraceRuntime(&dtrc.base);
2580 JS_TraceChildren(&dtrc.base, startThing, startKind);
2587 thingToFindWasTraced = thingToFind && thingToFind == startThing;
2590 * Loop must continue even when !dtrc.ok to free all nodes allocated
2594 if (thingToFind == NULL || thingToFind == node->thing)
2595 dtrc.ok = DumpNode(&dtrc, fp, node);
2597 /* Descend into children. */
2600 (thingToFind != node->thing || !thingToFindWasTraced)) {
2601 dtrc.parentNode = node;
2603 dtrc.lastNodep = &children;
2604 JS_TraceChildren(&dtrc.base, node->thing, node->kind);
2605 if (thingToFind == node->thing)
2606 thingToFindWasTraced = JS_TRUE;
2607 if (children != NULL) {
2615 /* Move to next or parents next and free the node. */
2618 parent = node->parent;
2625 JS_ASSERT(depth > 1);
2632 JS_ASSERT(depth == 1);
2633 JS_DHashTableFinish(&dtrc.visited);
2640 JS_MarkGCThing(JSContext *cx, jsval v, const char *name, void *arg)
2644 trc = (JSTracer *)arg;
2646 trc = cx->runtime->gcMarkingTracer;
2648 JS_ASSERT(trc == cx->runtime->gcMarkingTracer);
2650 #ifdef JS_THREADSAFE
2651 JS_ASSERT(cx->runtime->gcThread == trc->context->thread);
2653 MarkValue(trc, Valueify(v), name ? name : "unknown");
2656 extern JS_PUBLIC_API(JSBool)
2657 JS_IsGCMarkingTracer(JSTracer *trc)
2659 return IS_GC_MARKING_TRACER(trc);
2663 JS_GC(JSContext *cx)
2667 /* Don't nuke active arenas if executing or compiling. */
2668 if (cx->tempPool.current == &cx->tempPool.first)
2669 JS_FinishArenaPool(&cx->tempPool);
2670 js_GC(cx, NULL, GC_NORMAL);
2674 JS_MaybeGC(JSContext *cx)
2678 /* Don't nuke active arenas if executing or compiling. */
2679 if (cx->tempPool.current == &cx->tempPool.first)
2680 JS_FinishArenaPool(&cx->tempPool);
2685 JS_PUBLIC_API(JSGCCallback)
2686 JS_SetGCCallback(JSContext *cx, JSGCCallback cb)
2689 return JS_SetGCCallbackRT(cx->runtime, cb);
2692 JS_PUBLIC_API(JSGCCallback)
2693 JS_SetGCCallbackRT(JSRuntime *rt, JSGCCallback cb)
2697 oldcb = rt->gcCallback;
2698 rt->gcCallback = cb;
2702 JS_PUBLIC_API(JSBool)
2703 JS_IsAboutToBeFinalized(JSContext *cx, void *thing)
2706 JS_ASSERT(!cx->runtime->gcMarkingTracer);
2707 return IsAboutToBeFinalized(cx, thing);
2711 JS_SetGCParameter(JSRuntime *rt, JSGCParamKey key, uint32 value)
2714 case JSGC_MAX_BYTES:
2715 rt->gcMaxBytes = value;
2717 case JSGC_MAX_MALLOC_BYTES:
2718 rt->setGCMaxMallocBytes(value);
2720 case JSGC_STACKPOOL_LIFESPAN:
2721 rt->gcEmptyArenaPoolLifespan = value;
2724 rt->gcMode = JSGCMode(value);
2725 JS_ASSERT(rt->gcMode == JSGC_MODE_GLOBAL ||
2726 rt->gcMode == JSGC_MODE_COMPARTMENT);
2729 JS_ASSERT(key == JSGC_TRIGGER_FACTOR);
2730 JS_ASSERT(value >= 100);
2731 rt->setGCTriggerFactor(value);
2736 JS_PUBLIC_API(uint32)
2737 JS_GetGCParameter(JSRuntime *rt, JSGCParamKey key)
2740 case JSGC_MAX_BYTES:
2741 return rt->gcMaxBytes;
2742 case JSGC_MAX_MALLOC_BYTES:
2743 return rt->gcMaxMallocBytes;
2744 case JSGC_STACKPOOL_LIFESPAN:
2745 return rt->gcEmptyArenaPoolLifespan;
2746 case JSGC_TRIGGER_FACTOR:
2747 return rt->gcTriggerFactor;
2751 return uint32(rt->gcMode);
2752 case JSGC_UNUSED_CHUNKS:
2753 return uint32(rt->gcChunksWaitingToExpire);
2755 JS_ASSERT(key == JSGC_NUMBER);
2756 return rt->gcNumber;
2761 JS_SetGCParameterForThread(JSContext *cx, JSGCParamKey key, uint32 value)
2763 JS_ASSERT(key == JSGC_MAX_CODE_CACHE_BYTES);
2765 SetMaxCodeCacheBytes(cx, value);
2769 JS_PUBLIC_API(uint32)
2770 JS_GetGCParameterForThread(JSContext *cx, JSGCParamKey key)
2772 JS_ASSERT(key == JSGC_MAX_CODE_CACHE_BYTES);
2774 return JS_THREAD_DATA(cx)->maxCodeCacheBytes;
2781 JS_FlushCaches(JSContext *cx)
2784 FlushJITCache(cx, &cx->compartment->traceMonitor);
2789 JS_AddExternalStringFinalizer(JSStringFinalizeOp finalizer)
2791 return JSExternalString::changeFinalizer(NULL, finalizer);
2795 JS_RemoveExternalStringFinalizer(JSStringFinalizeOp finalizer)
2797 return JSExternalString::changeFinalizer(finalizer, NULL);
2800 JS_PUBLIC_API(JSString *)
2801 JS_NewExternalString(JSContext *cx, jschar *chars, size_t length, intN type)
2804 JS_ASSERT(uintN(type) < JSExternalString::TYPE_LIMIT);
2806 JSExternalString *str = js_NewGCExternalString(cx, uintN(type));
2809 str->initFlat(chars, length);
2810 str->externalStringType = type;
2811 cx->runtime->updateMallocCounter((length + 1) * sizeof(jschar));
2816 JS_GetExternalStringGCType(JSRuntime *rt, JSString *str)
2819 * No need to test this in js_GetExternalStringGCType, which asserts its
2820 * inverse instead of wasting cycles on testing a condition we can ensure
2821 * by auditing in-VM calls to the js_... helper.
2823 if (JSString::isStatic(str))
2826 return js_GetExternalStringGCType(str);
2830 JS_SetThreadStackLimit(JSContext *cx, jsuword limitAddr)
2832 #if JS_STACK_GROWTH_DIRECTION > 0
2834 limitAddr = jsuword(-1);
2836 cx->stackLimit = limitAddr;
2840 JS_SetNativeStackQuota(JSContext *cx, size_t stackSize)
2842 #ifdef JS_THREADSAFE
2843 JS_ASSERT(cx->thread);
2846 #if JS_STACK_GROWTH_DIRECTION > 0
2847 if (stackSize == 0) {
2848 cx->stackLimit = jsuword(-1);
2850 jsuword stackBase = reinterpret_cast<jsuword>(JS_THREAD_DATA(cx)->nativeStackBase);
2851 JS_ASSERT(stackBase <= size_t(-1) - stackSize);
2852 cx->stackLimit = stackBase + stackSize - 1;
2855 if (stackSize == 0) {
2858 jsuword stackBase = reinterpret_cast<jsuword>(JS_THREAD_DATA(cx)->nativeStackBase);
2859 JS_ASSERT(stackBase >= stackSize);
2860 cx->stackLimit = stackBase - (stackSize - 1);
2866 JS_SetScriptStackQuota(JSContext *cx, size_t quota)
2868 cx->scriptStackQuota = quota;
2871 /************************************************************************/
2874 JS_DestroyIdArray(JSContext *cx, JSIdArray *ida)
2879 JS_PUBLIC_API(JSBool)
2880 JS_ValueToId(JSContext *cx, jsval v, jsid *idp)
2883 assertSameCompartment(cx, v);
2884 return ValueToId(cx, Valueify(v), idp);
2887 JS_PUBLIC_API(JSBool)
2888 JS_IdToValue(JSContext *cx, jsid id, jsval *vp)
2891 *vp = IdToJsval(id);
2892 assertSameCompartment(cx, *vp);
2896 JS_PUBLIC_API(JSBool)
2897 JS_PropertyStub(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
2902 JS_PUBLIC_API(JSBool)
2903 JS_StrictPropertyStub(JSContext *cx, JSObject *obj, jsid id, JSBool strict, jsval *vp)
2908 JS_PUBLIC_API(JSBool)
2909 JS_EnumerateStub(JSContext *cx, JSObject *obj)
2914 JS_PUBLIC_API(JSBool)
2915 JS_ResolveStub(JSContext *cx, JSObject *obj, jsid id)
2920 JS_PUBLIC_API(JSBool)
2921 JS_ConvertStub(JSContext *cx, JSObject *obj, JSType type, jsval *vp)
2923 JS_ASSERT(type != JSTYPE_OBJECT && type != JSTYPE_FUNCTION);
2924 return js_TryValueOf(cx, obj, type, Valueify(vp));
2928 JS_FinalizeStub(JSContext *cx, JSObject *obj)
2931 JS_PUBLIC_API(JSObject *)
2932 JS_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto,
2933 JSClass *clasp, JSNative constructor, uintN nargs,
2934 JSPropertySpec *ps, JSFunctionSpec *fs,
2935 JSPropertySpec *static_ps, JSFunctionSpec *static_fs)
2938 assertSameCompartment(cx, obj, parent_proto);
2939 return js_InitClass(cx, obj, parent_proto, Valueify(clasp),
2940 Valueify(constructor), nargs,
2941 ps, fs, static_ps, static_fs);
2944 #ifdef JS_THREADSAFE
2945 JS_PUBLIC_API(JSClass *)
2946 JS_GetClass(JSContext *cx, JSObject *obj)
2948 return Jsvalify(obj->getClass());
2951 JS_PUBLIC_API(JSClass *)
2952 JS_GetClass(JSObject *obj)
2954 return Jsvalify(obj->getClass());
2958 JS_PUBLIC_API(JSBool)
2959 JS_InstanceOf(JSContext *cx, JSObject *obj, JSClass *clasp, jsval *argv)
2962 assertSameCompartment(cx, obj);
2963 return InstanceOf(cx, obj, Valueify(clasp), Valueify(argv));
2966 JS_PUBLIC_API(JSBool)
2967 JS_HasInstance(JSContext *cx, JSObject *obj, jsval v, JSBool *bp)
2969 assertSameCompartment(cx, obj, v);
2970 return HasInstance(cx, obj, Valueify(&v), bp);
2973 JS_PUBLIC_API(void *)
2974 JS_GetPrivate(JSContext *cx, JSObject *obj)
2976 return obj->getPrivate();
2979 JS_PUBLIC_API(JSBool)
2980 JS_SetPrivate(JSContext *cx, JSObject *obj, void *data)
2982 obj->setPrivate(data);
2986 JS_PUBLIC_API(void *)
2987 JS_GetInstancePrivate(JSContext *cx, JSObject *obj, JSClass *clasp, jsval *argv)
2989 if (!InstanceOf(cx, obj, Valueify(clasp), Valueify(argv)))
2991 return obj->getPrivate();
2994 JS_PUBLIC_API(JSObject *)
2995 JS_GetPrototype(JSContext *cx, JSObject *obj)
3000 assertSameCompartment(cx, obj);
3001 proto = obj->getProto();
3003 /* Beware ref to dead object (we may be called from obj's finalizer). */
3004 return proto && proto->map ? proto : NULL;
3007 JS_PUBLIC_API(JSBool)
3008 JS_SetPrototype(JSContext *cx, JSObject *obj, JSObject *proto)
3011 assertSameCompartment(cx, obj, proto);
3012 return SetProto(cx, obj, proto, JS_FALSE);
3015 JS_PUBLIC_API(JSObject *)
3016 JS_GetParent(JSContext *cx, JSObject *obj)
3018 assertSameCompartment(cx, obj);
3019 JSObject *parent = obj->getParent();
3021 /* Beware ref to dead object (we may be called from obj's finalizer). */
3022 return parent && parent->map ? parent : NULL;
3025 JS_PUBLIC_API(JSBool)
3026 JS_SetParent(JSContext *cx, JSObject *obj, JSObject *parent)
3029 JS_ASSERT(parent || !obj->getParent());
3030 assertSameCompartment(cx, obj, parent);
3031 obj->setParent(parent);
3035 JS_PUBLIC_API(JSObject *)
3036 JS_GetConstructor(JSContext *cx, JSObject *proto)
3041 assertSameCompartment(cx, proto);
3043 JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
3045 if (!proto->getProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.constructorAtom), &cval))
3049 if (!IsFunctionObject(cval, &funobj)) {
3050 JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NO_CONSTRUCTOR,
3051 proto->getClass()->name);
3054 return &cval.toObject();
3057 JS_PUBLIC_API(JSBool)
3058 JS_GetObjectId(JSContext *cx, JSObject *obj, jsid *idp)
3060 assertSameCompartment(cx, obj);
3061 *idp = OBJECT_TO_JSID(obj);
3065 JS_PUBLIC_API(JSObject *)
3066 JS_NewGlobalObject(JSContext *cx, JSClass *clasp)
3068 JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
3070 JS_ASSERT(clasp->flags & JSCLASS_IS_GLOBAL);
3071 JSObject *obj = NewNonFunction<WithProto::Given>(cx, Valueify(clasp), NULL, NULL);
3075 obj->syncSpecialEquality();
3077 /* Construct a regexp statics object for this global object. */
3078 JSObject *res = regexp_statics_construct(cx, obj);
3080 !js_SetReservedSlot(cx, obj, JSRESERVED_GLOBAL_REGEXP_STATICS, ObjectValue(*res)) ||
3081 !js_SetReservedSlot(cx, obj, JSRESERVED_GLOBAL_FLAGS, Int32Value(0))) {
3088 JS_PUBLIC_API(JSObject *)
3089 JS_NewCompartmentAndGlobalObject(JSContext *cx, JSClass *clasp, JSPrincipals *principals)
3092 JSCompartment *compartment = NewCompartment(cx, principals);
3096 JSCompartment *saved = cx->compartment;
3097 cx->compartment = compartment;
3098 JSObject *obj = JS_NewGlobalObject(cx, clasp);
3099 cx->compartment = saved;
3104 JS_PUBLIC_API(JSObject *)
3105 JS_NewObject(JSContext *cx, JSClass *jsclasp, JSObject *proto, JSObject *parent)
3107 JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
3109 assertSameCompartment(cx, proto, parent);
3111 Class *clasp = Valueify(jsclasp);
3113 clasp = &js_ObjectClass; /* default class is Object */
3115 JS_ASSERT(clasp != &js_FunctionClass);
3116 JS_ASSERT(!(clasp->flags & JSCLASS_IS_GLOBAL));
3118 JSObject *obj = NewNonFunction<WithProto::Class>(cx, clasp, proto, parent);
3120 obj->syncSpecialEquality();
3122 JS_ASSERT_IF(obj, obj->getParent());
3126 JS_PUBLIC_API(JSObject *)
3127 JS_NewObjectWithGivenProto(JSContext *cx, JSClass *jsclasp, JSObject *proto, JSObject *parent)
3129 JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
3131 assertSameCompartment(cx, proto, parent);
3133 Class *clasp = Valueify(jsclasp);
3135 clasp = &js_ObjectClass; /* default class is Object */
3137 JS_ASSERT(clasp != &js_FunctionClass);
3138 JS_ASSERT(!(clasp->flags & JSCLASS_IS_GLOBAL));
3140 JSObject *obj = NewNonFunction<WithProto::Given>(cx, clasp, proto, parent);
3142 obj->syncSpecialEquality();
3146 JS_PUBLIC_API(JSObject *)
3147 JS_NewObjectForConstructor(JSContext *cx, const jsval *vp)
3150 assertSameCompartment(cx, *vp);
3152 return js_CreateThis(cx, JSVAL_TO_OBJECT(*vp));
3155 JS_PUBLIC_API(JSBool)
3156 JS_IsExtensible(JSObject *obj)
3158 return obj->isExtensible();
3161 JS_PUBLIC_API(JSBool)
3162 JS_FreezeObject(JSContext *cx, JSObject *obj)
3165 assertSameCompartment(cx, obj);
3167 return obj->freeze(cx);
3170 JS_PUBLIC_API(JSBool)
3171 JS_DeepFreezeObject(JSContext *cx, JSObject *obj)
3174 assertSameCompartment(cx, obj);
3176 /* Assume that non-extensible objects are already deep-frozen, to avoid divergence. */
3177 if (!obj->isExtensible())
3180 if (!obj->freeze(cx))
3183 /* Walk slots in obj and if any value is a non-null object, seal it. */
3184 for (uint32 i = 0, n = obj->slotSpan(); i < n; ++i) {
3185 const Value &v = obj->getSlot(i);
3186 if (v.isPrimitive())
3188 if (!JS_DeepFreezeObject(cx, &v.toObject()))
3195 JS_PUBLIC_API(JSObject *)
3196 JS_ConstructObject(JSContext *cx, JSClass *jsclasp, JSObject *proto, JSObject *parent)
3199 assertSameCompartment(cx, proto, parent);
3200 Class *clasp = Valueify(jsclasp);
3202 clasp = &js_ObjectClass; /* default class is Object */
3203 return js_ConstructObject(cx, clasp, proto, parent, 0, NULL);
3206 JS_PUBLIC_API(JSObject *)
3207 JS_ConstructObjectWithArguments(JSContext *cx, JSClass *jsclasp, JSObject *proto,
3208 JSObject *parent, uintN argc, jsval *argv)
3211 assertSameCompartment(cx, proto, parent, JSValueArray(argv, argc));
3212 Class *clasp = Valueify(jsclasp);
3214 clasp = &js_ObjectClass; /* default class is Object */
3215 return js_ConstructObject(cx, clasp, proto, parent, argc, Valueify(argv));
3219 LookupPropertyById(JSContext *cx, JSObject *obj, jsid id, uintN flags,
3220 JSObject **objp, JSProperty **propp)
3223 assertSameCompartment(cx, obj, id);
3225 JSAutoResolveFlags rf(cx, flags);
3226 id = js_CheckForStringIndex(id);
3227 return obj->lookupProperty(cx, id, objp, propp);
3230 #define AUTO_NAMELEN(s,n) (((n) == (size_t)-1) ? js_strlen(s) : (n))
3233 LookupResult(JSContext *cx, JSObject *obj, JSObject *obj2, jsid id,
3234 JSProperty *prop, Value *vp)
3237 /* XXX bad API: no way to tell "not defined" from "void value" */
3242 if (obj2->isNative()) {
3243 Shape *shape = (Shape *) prop;
3245 if (shape->isMethod()) {
3246 AutoShapeRooter root(cx, shape);
3247 vp->setObject(shape->methodObject());
3248 return !!obj2->methodReadBarrier(cx, *shape, vp);
3251 /* Peek at the native property's slot value, without doing a Get. */
3252 if (obj2->containsSlot(shape->slot)) {
3253 *vp = obj2->nativeGetSlot(shape->slot);
3257 if (obj2->isDenseArray())
3258 return js_GetDenseArrayElementValue(cx, obj2, id, vp);
3259 if (obj2->isProxy()) {
3260 AutoPropertyDescriptorRooter desc(cx);
3261 if (!JSProxy::getPropertyDescriptor(cx, obj2, id, false, &desc))
3263 if (!(desc.attrs & JSPROP_SHARED)) {
3270 /* XXX bad API: no way to return "defined but value unknown" */
3271 vp->setBoolean(true);
3275 JS_PUBLIC_API(JSBool)
3276 JS_LookupPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
3280 return LookupPropertyById(cx, obj, id, JSRESOLVE_QUALIFIED, &obj2, &prop) &&
3281 LookupResult(cx, obj, obj2, id, prop, Valueify(vp));
3284 JS_PUBLIC_API(JSBool)
3285 JS_LookupElement(JSContext *cx, JSObject *obj, jsint index, jsval *vp)
3287 return JS_LookupPropertyById(cx, obj, INT_TO_JSID(index), vp);
3290 JS_PUBLIC_API(JSBool)
3291 JS_LookupProperty(JSContext *cx, JSObject *obj, const char *name, jsval *vp)
3293 JSAtom *atom = js_Atomize(cx, name, strlen(name), 0);
3294 return atom && JS_LookupPropertyById(cx, obj, ATOM_TO_JSID(atom), vp);
3297 JS_PUBLIC_API(JSBool)
3298 JS_LookupUCProperty(JSContext *cx, JSObject *obj, const jschar *name, size_t namelen, jsval *vp)
3300 JSAtom *atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0);
3301 return atom && JS_LookupPropertyById(cx, obj, ATOM_TO_JSID(atom), vp);
3304 JS_PUBLIC_API(JSBool)
3305 JS_LookupPropertyWithFlagsById(JSContext *cx, JSObject *obj, jsid id, uintN flags,
3306 JSObject **objp, jsval *vp)
3312 assertSameCompartment(cx, obj, id);
3313 ok = obj->isNative()
3314 ? js_LookupPropertyWithFlags(cx, obj, id, flags, objp, &prop) >= 0
3315 : obj->lookupProperty(cx, id, objp, &prop);
3316 return ok && LookupResult(cx, obj, *objp, id, prop, Valueify(vp));
3319 JS_PUBLIC_API(JSBool)
3320 JS_LookupPropertyWithFlags(JSContext *cx, JSObject *obj, const char *name, uintN flags, jsval *vp)
3323 JSAtom *atom = js_Atomize(cx, name, strlen(name), 0);
3324 return atom && JS_LookupPropertyWithFlagsById(cx, obj, ATOM_TO_JSID(atom), flags, &obj2, vp);
3327 JS_PUBLIC_API(JSBool)
3328 JS_HasPropertyById(JSContext *cx, JSObject *obj, jsid id, JSBool *foundp)
3332 JSBool ok = LookupPropertyById(cx, obj, id, JSRESOLVE_QUALIFIED | JSRESOLVE_DETECTING,
3334 *foundp = (prop != NULL);
3338 JS_PUBLIC_API(JSBool)
3339 JS_HasElement(JSContext *cx, JSObject *obj, jsint index, JSBool *foundp)
3341 return JS_HasPropertyById(cx, obj, INT_TO_JSID(index), foundp);
3344 JS_PUBLIC_API(JSBool)
3345 JS_HasProperty(JSContext *cx, JSObject *obj, const char *name, JSBool *foundp)
3347 JSAtom *atom = js_Atomize(cx, name, strlen(name), 0);
3348 return atom && JS_HasPropertyById(cx, obj, ATOM_TO_JSID(atom), foundp);
3351 JS_PUBLIC_API(JSBool)
3352 JS_HasUCProperty(JSContext *cx, JSObject *obj, const jschar *name, size_t namelen, JSBool *foundp)
3354 JSAtom *atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0);
3355 return atom && JS_HasPropertyById(cx, obj, ATOM_TO_JSID(atom), foundp);
3358 JS_PUBLIC_API(JSBool)
3359 JS_AlreadyHasOwnPropertyById(JSContext *cx, JSObject *obj, jsid id, JSBool *foundp)
3362 assertSameCompartment(cx, obj, id);
3364 if (!obj->isNative()) {
3368 if (!LookupPropertyById(cx, obj, id, JSRESOLVE_QUALIFIED | JSRESOLVE_DETECTING,
3372 *foundp = (obj == obj2);
3376 *foundp = obj->nativeContains(id);
3380 JS_PUBLIC_API(JSBool)
3381 JS_AlreadyHasOwnElement(JSContext *cx, JSObject *obj, jsint index, JSBool *foundp)
3383 return JS_AlreadyHasOwnPropertyById(cx, obj, INT_TO_JSID(index), foundp);
3386 JS_PUBLIC_API(JSBool)
3387 JS_AlreadyHasOwnProperty(JSContext *cx, JSObject *obj, const char *name, JSBool *foundp)
3389 JSAtom *atom = js_Atomize(cx, name, strlen(name), 0);
3390 return atom && JS_AlreadyHasOwnPropertyById(cx, obj, ATOM_TO_JSID(atom), foundp);
3393 JS_PUBLIC_API(JSBool)
3394 JS_AlreadyHasOwnUCProperty(JSContext *cx, JSObject *obj, const jschar *name, size_t namelen,
3397 JSAtom *atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0);
3398 return atom && JS_AlreadyHasOwnPropertyById(cx, obj, ATOM_TO_JSID(atom), foundp);
3402 DefinePropertyById(JSContext *cx, JSObject *obj, jsid id, const Value &value,
3403 PropertyOp getter, StrictPropertyOp setter, uintN attrs,
3404 uintN flags, intN tinyid)
3407 assertSameCompartment(cx, obj, id, value,
3408 (attrs & JSPROP_GETTER)
3409 ? JS_FUNC_TO_DATA_PTR(JSObject *, getter)
3411 (attrs & JSPROP_SETTER)
3412 ? JS_FUNC_TO_DATA_PTR(JSObject *, setter)
3415 JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED | JSRESOLVE_DECLARING);
3416 if (flags != 0 && obj->isNative()) {
3417 return !!js_DefineNativeProperty(cx, obj, id, value, getter, setter,
3418 attrs, flags, tinyid, NULL);
3420 return obj->defineProperty(cx, id, value, getter, setter, attrs);
3423 JS_PUBLIC_API(JSBool)
3424 JS_DefinePropertyById(JSContext *cx, JSObject *obj, jsid id, jsval value,
3425 JSPropertyOp getter, JSStrictPropertyOp setter, uintN attrs)
3427 return DefinePropertyById(cx, obj, id, Valueify(value), Valueify(getter),
3428 Valueify(setter), attrs, 0, 0);
3431 JS_PUBLIC_API(JSBool)
3432 JS_DefineElement(JSContext *cx, JSObject *obj, jsint index, jsval value,
3433 JSPropertyOp getter, JSStrictPropertyOp setter, uintN attrs)
3435 return DefinePropertyById(cx, obj, INT_TO_JSID(index), Valueify(value),
3436 Valueify(getter), Valueify(setter), attrs, 0, 0);
3440 DefineProperty(JSContext *cx, JSObject *obj, const char *name, const Value &value,
3441 PropertyOp getter, StrictPropertyOp setter, uintN attrs,
3442 uintN flags, intN tinyid)
3447 if (attrs & JSPROP_INDEX) {
3448 id = INT_TO_JSID(intptr_t(name));
3450 attrs &= ~JSPROP_INDEX;
3452 atom = js_Atomize(cx, name, strlen(name), 0);
3455 id = ATOM_TO_JSID(atom);
3457 return DefinePropertyById(cx, obj, id, value, getter, setter, attrs, flags, tinyid);
3460 JS_PUBLIC_API(JSBool)
3461 JS_DefineProperty(JSContext *cx, JSObject *obj, const char *name, jsval value,
3462 JSPropertyOp getter, JSStrictPropertyOp setter, uintN attrs)
3464 return DefineProperty(cx, obj, name, Valueify(value), Valueify(getter),
3465 Valueify(setter), attrs, 0, 0);
3468 JS_PUBLIC_API(JSBool)
3469 JS_DefinePropertyWithTinyId(JSContext *cx, JSObject *obj, const char *name, int8 tinyid,
3470 jsval value, JSPropertyOp getter, JSStrictPropertyOp setter, uintN attrs)
3472 return DefineProperty(cx, obj, name, Valueify(value), Valueify(getter),
3473 Valueify(setter), attrs, Shape::HAS_SHORTID, tinyid);
3477 DefineUCProperty(JSContext *cx, JSObject *obj, const jschar *name, size_t namelen,
3478 const Value &value, PropertyOp getter, StrictPropertyOp setter, uintN attrs,
3479 uintN flags, intN tinyid)
3481 JSAtom *atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0);
3482 return atom && DefinePropertyById(cx, obj, ATOM_TO_JSID(atom), value, getter, setter, attrs,
3486 JS_PUBLIC_API(JSBool)
3487 JS_DefineUCProperty(JSContext *cx, JSObject *obj, const jschar *name, size_t namelen,
3488 jsval value, JSPropertyOp getter, JSStrictPropertyOp setter, uintN attrs)
3490 return DefineUCProperty(cx, obj, name, namelen, Valueify(value),
3491 Valueify(getter), Valueify(setter), attrs, 0, 0);
3494 JS_PUBLIC_API(JSBool)
3495 JS_DefineUCPropertyWithTinyId(JSContext *cx, JSObject *obj, const jschar *name, size_t namelen,
3496 int8 tinyid, jsval value,
3497 JSPropertyOp getter, JSStrictPropertyOp setter, uintN attrs)
3499 return DefineUCProperty(cx, obj, name, namelen, Valueify(value), Valueify(getter),
3500 Valueify(setter), attrs, Shape::HAS_SHORTID, tinyid);
3503 JS_PUBLIC_API(JSBool)
3504 JS_DefineOwnProperty(JSContext *cx, JSObject *obj, jsid id, jsval descriptor, JSBool *bp)
3507 assertSameCompartment(cx, obj, id, descriptor);
3508 return js_DefineOwnProperty(cx, obj, id, Valueify(descriptor), bp);
3511 JS_PUBLIC_API(JSObject *)
3512 JS_DefineObject(JSContext *cx, JSObject *obj, const char *name, JSClass *jsclasp,
3513 JSObject *proto, uintN attrs)
3516 assertSameCompartment(cx, obj, proto);
3518 Class *clasp = Valueify(jsclasp);
3520 clasp = &js_ObjectClass; /* default class is Object */
3522 JSObject *nobj = NewObject<WithProto::Class>(cx, clasp, proto, obj);
3526 nobj->syncSpecialEquality();
3528 if (!DefineProperty(cx, obj, name, ObjectValue(*nobj), NULL, NULL, attrs, 0, 0))
3534 JS_PUBLIC_API(JSBool)
3535 JS_DefineConstDoubles(JSContext *cx, JSObject *obj, JSConstDoubleSpec *cds)
3541 for (ok = JS_TRUE; cds->name; cds++) {
3542 Value value = DoubleValue(cds->dval);
3545 attrs = JSPROP_READONLY | JSPROP_PERMANENT;
3546 ok = DefineProperty(cx, obj, cds->name, value, NULL, NULL, attrs, 0, 0);
3553 JS_PUBLIC_API(JSBool)
3554 JS_DefineProperties(JSContext *cx, JSObject *obj, JSPropertySpec *ps)
3558 for (ok = true; ps->name; ps++) {
3559 ok = DefineProperty(cx, obj, ps->name, UndefinedValue(),
3560 Valueify(ps->getter), Valueify(ps->setter),
3561 ps->flags, Shape::HAS_SHORTID, ps->tinyid);
3568 JS_PUBLIC_API(JSBool)
3569 JS_AliasProperty(JSContext *cx, JSObject *obj, const char *name, const char *alias)
3577 assertSameCompartment(cx, obj);
3579 JSAtom *atom = js_Atomize(cx, name, strlen(name), 0);
3582 if (!LookupPropertyById(cx, obj, ATOM_TO_JSID(atom), JSRESOLVE_QUALIFIED, &obj2, &prop))
3585 js_ReportIsNotDefined(cx, name);
3588 if (obj2 != obj || !obj->isNative()) {
3589 JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_ALIAS,
3590 alias, name, obj2->getClass()->name);
3593 atom = js_Atomize(cx, alias, strlen(alias), 0);
3597 shape = (Shape *)prop;
3598 ok = (js_AddNativeProperty(cx, obj, ATOM_TO_JSID(atom),
3599 shape->getter(), shape->setter(), shape->slot,
3600 shape->attributes(), shape->getFlags() | Shape::ALIAS,
3607 JS_PUBLIC_API(JSBool)
3608 JS_AliasElement(JSContext *cx, JSObject *obj, const char *name, jsint alias)
3615 assertSameCompartment(cx, obj);
3617 JSAtom *atom = js_Atomize(cx, name, strlen(name), 0);
3620 if (!LookupPropertyById(cx, obj, ATOM_TO_JSID(atom), JSRESOLVE_QUALIFIED, &obj2, &prop))
3623 js_ReportIsNotDefined(cx, name);
3626 if (obj2 != obj || !obj->isNative()) {
3628 JS_snprintf(numBuf, sizeof numBuf, "%ld", (long)alias);
3629 JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_ALIAS,
3630 numBuf, name, obj2->getClass()->name);
3633 shape = (Shape *)prop;
3634 return js_AddNativeProperty(cx, obj, INT_TO_JSID(alias),
3635 shape->getter(), shape->setter(), shape->slot,
3636 shape->attributes(), shape->getFlags() | Shape::ALIAS,
3642 GetPropertyDescriptorById(JSContext *cx, JSObject *obj, jsid id, uintN flags,
3643 JSBool own, PropertyDescriptor *desc)
3648 if (!LookupPropertyById(cx, obj, id, flags, &obj2, &prop))
3651 if (!prop || (own && obj != obj2)) {
3654 desc->getter = NULL;
3655 desc->setter = NULL;
3656 desc->value.setUndefined();
3661 if (obj2->isNative()) {
3662 Shape *shape = (Shape *) prop;
3663 desc->attrs = shape->attributes();
3665 if (shape->isMethod()) {
3666 desc->getter = PropertyStub;
3667 desc->setter = StrictPropertyStub;
3668 desc->value.setObject(shape->methodObject());
3670 desc->getter = shape->getter();
3671 desc->setter = shape->setter();
3672 if (obj2->containsSlot(shape->slot))
3673 desc->value = obj2->nativeGetSlot(shape->slot);
3675 desc->value.setUndefined();
3678 if (obj2->isProxy()) {
3679 JSAutoResolveFlags rf(cx, flags);
3681 ? JSProxy::getOwnPropertyDescriptor(cx, obj2, id, false, desc)
3682 : JSProxy::getPropertyDescriptor(cx, obj2, id, false, desc);
3684 if (!obj2->getAttributes(cx, id, &desc->attrs))
3686 desc->getter = NULL;
3687 desc->setter = NULL;
3688 desc->value.setUndefined();
3693 JS_PUBLIC_API(JSBool)
3694 JS_GetPropertyDescriptorById(JSContext *cx, JSObject *obj, jsid id, uintN flags,
3695 JSPropertyDescriptor *desc)
3697 return GetPropertyDescriptorById(cx, obj, id, flags, JS_FALSE, Valueify(desc));
3700 JS_PUBLIC_API(JSBool)
3701 JS_GetPropertyAttrsGetterAndSetterById(JSContext *cx, JSObject *obj, jsid id,
3702 uintN *attrsp, JSBool *foundp,
3703 JSPropertyOp *getterp, JSStrictPropertyOp *setterp)
3705 PropertyDescriptor desc;
3706 if (!GetPropertyDescriptorById(cx, obj, id, JSRESOLVE_QUALIFIED, JS_FALSE, &desc))
3709 *attrsp = desc.attrs;
3710 *foundp = (desc.obj != NULL);
3712 *getterp = Jsvalify(desc.getter);
3714 *setterp = Jsvalify(desc.setter);
3718 JS_PUBLIC_API(JSBool)
3719 JS_GetPropertyAttributes(JSContext *cx, JSObject *obj, const char *name,
3720 uintN *attrsp, JSBool *foundp)
3722 JSAtom *atom = js_Atomize(cx, name, strlen(name), 0);
3723 return atom && JS_GetPropertyAttrsGetterAndSetterById(cx, obj, ATOM_TO_JSID(atom),
3724 attrsp, foundp, NULL, NULL);
3727 JS_PUBLIC_API(JSBool)
3728 JS_GetUCPropertyAttributes(JSContext *cx, JSObject *obj, const jschar *name, size_t namelen,
3729 uintN *attrsp, JSBool *foundp)
3731 JSAtom *atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0);
3732 return atom && JS_GetPropertyAttrsGetterAndSetterById(cx, obj, ATOM_TO_JSID(atom),
3733 attrsp, foundp, NULL, NULL);
3736 JS_PUBLIC_API(JSBool)
3737 JS_GetPropertyAttrsGetterAndSetter(JSContext *cx, JSObject *obj, const char *name,
3738 uintN *attrsp, JSBool *foundp,
3739 JSPropertyOp *getterp, JSStrictPropertyOp *setterp)
3741 JSAtom *atom = js_Atomize(cx, name, strlen(name), 0);
3742 return atom && JS_GetPropertyAttrsGetterAndSetterById(cx, obj, ATOM_TO_JSID(atom),
3743 attrsp, foundp, getterp, setterp);
3746 JS_PUBLIC_API(JSBool)
3747 JS_GetUCPropertyAttrsGetterAndSetter(JSContext *cx, JSObject *obj,
3748 const jschar *name, size_t namelen,
3749 uintN *attrsp, JSBool *foundp,
3750 JSPropertyOp *getterp, JSStrictPropertyOp *setterp)
3752 JSAtom *atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0);
3753 return atom && JS_GetPropertyAttrsGetterAndSetterById(cx, obj, ATOM_TO_JSID(atom),
3754 attrsp, foundp, getterp, setterp);
3757 JS_PUBLIC_API(JSBool)
3758 JS_GetOwnPropertyDescriptor(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
3761 return js_GetOwnPropertyDescriptor(cx, obj, id, Valueify(vp));
3765 SetPropertyAttributesById(JSContext *cx, JSObject *obj, jsid id, uintN attrs, JSBool *foundp)
3770 if (!LookupPropertyById(cx, obj, id, JSRESOLVE_QUALIFIED, &obj2, &prop))
3772 if (!prop || obj != obj2) {
3776 JSBool ok = obj->isNative()
3777 ? js_SetNativeAttributes(cx, obj, (Shape *) prop, attrs)
3778 : obj->setAttributes(cx, id, &attrs);
3784 JS_PUBLIC_API(JSBool)
3785 JS_SetPropertyAttributes(JSContext *cx, JSObject *obj, const char *name,
3786 uintN attrs, JSBool *foundp)
3788 JSAtom *atom = js_Atomize(cx, name, strlen(name), 0);
3789 return atom && SetPropertyAttributesById(cx, obj, ATOM_TO_JSID(atom), attrs, foundp);
3792 JS_PUBLIC_API(JSBool)
3793 JS_SetUCPropertyAttributes(JSContext *cx, JSObject *obj, const jschar *name, size_t namelen,
3794 uintN attrs, JSBool *foundp)
3796 JSAtom *atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0);
3797 return atom && SetPropertyAttributesById(cx, obj, ATOM_TO_JSID(atom), attrs, foundp);
3800 JS_PUBLIC_API(JSBool)
3801 JS_GetPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
3804 assertSameCompartment(cx, obj, id);
3805 JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
3806 return obj->getProperty(cx, id, Valueify(vp));
3809 JS_PUBLIC_API(JSBool)
3810 JS_GetPropertyByIdDefault(JSContext *cx, JSObject *obj, jsid id, jsval def, jsval *vp)
3812 return GetPropertyDefault(cx, obj, id, Valueify(def), Valueify(vp));
3815 JS_PUBLIC_API(JSBool)
3816 JS_GetElement(JSContext *cx, JSObject *obj, jsint index, jsval *vp)
3818 return JS_GetPropertyById(cx, obj, INT_TO_JSID(index), vp);
3821 JS_PUBLIC_API(JSBool)
3822 JS_GetProperty(JSContext *cx, JSObject *obj, const char *name, jsval *vp)
3824 JSAtom *atom = js_Atomize(cx, name, strlen(name), 0);
3825 return atom && JS_GetPropertyById(cx, obj, ATOM_TO_JSID(atom), vp);
3828 JS_PUBLIC_API(JSBool)
3829 JS_GetPropertyDefault(JSContext *cx, JSObject *obj, const char *name, jsval def, jsval *vp)
3831 JSAtom *atom = js_Atomize(cx, name, strlen(name), 0);
3832 return atom && JS_GetPropertyByIdDefault(cx, obj, ATOM_TO_JSID(atom), def, vp);
3835 JS_PUBLIC_API(JSBool)
3836 JS_GetUCProperty(JSContext *cx, JSObject *obj, const jschar *name, size_t namelen, jsval *vp)
3838 JSAtom *atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0);
3839 return atom && JS_GetPropertyById(cx, obj, ATOM_TO_JSID(atom), vp);
3842 JS_PUBLIC_API(JSBool)
3843 JS_GetMethodById(JSContext *cx, JSObject *obj, jsid id, JSObject **objp, jsval *vp)
3846 assertSameCompartment(cx, obj, id);
3847 if (!js_GetMethod(cx, obj, id, JSGET_METHOD_BARRIER, Valueify(vp)))
3854 JS_PUBLIC_API(JSBool)
3855 JS_GetMethod(JSContext *cx, JSObject *obj, const char *name, JSObject **objp, jsval *vp)
3857 JSAtom *atom = js_Atomize(cx, name, strlen(name), 0);
3858 return atom && JS_GetMethodById(cx, obj, ATOM_TO_JSID(atom), objp, vp);
3861 JS_PUBLIC_API(JSBool)
3862 JS_SetPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
3865 assertSameCompartment(cx, obj, id);
3866 JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED | JSRESOLVE_ASSIGNING);
3867 return obj->setProperty(cx, id, Valueify(vp), false);
3870 JS_PUBLIC_API(JSBool)
3871 JS_SetElement(JSContext *cx, JSObject *obj, jsint index, jsval *vp)
3873 return JS_SetPropertyById(cx, obj, INT_TO_JSID(index), vp);
3876 JS_PUBLIC_API(JSBool)
3877 JS_SetProperty(JSContext *cx, JSObject *obj, const char *name, jsval *vp)
3879 JSAtom *atom = js_Atomize(cx, name, strlen(name), 0);
3880 return atom && JS_SetPropertyById(cx, obj, ATOM_TO_JSID(atom), vp);
3883 JS_PUBLIC_API(JSBool)
3884 JS_SetUCProperty(JSContext *cx, JSObject *obj, const jschar *name, size_t namelen, jsval *vp)
3886 JSAtom *atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0);
3887 return atom && JS_SetPropertyById(cx, obj, ATOM_TO_JSID(atom), vp);
3890 JS_PUBLIC_API(JSBool)
3891 JS_DeletePropertyById2(JSContext *cx, JSObject *obj, jsid id, jsval *rval)
3894 assertSameCompartment(cx, obj, id);
3895 JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
3896 return obj->deleteProperty(cx, id, Valueify(rval), false);
3899 JS_PUBLIC_API(JSBool)
3900 JS_DeleteElement2(JSContext *cx, JSObject *obj, jsint index, jsval *rval)
3902 return JS_DeletePropertyById2(cx, obj, INT_TO_JSID(index), rval);
3905 JS_PUBLIC_API(JSBool)
3906 JS_DeleteProperty2(JSContext *cx, JSObject *obj, const char *name, jsval *rval)
3908 JSAtom *atom = js_Atomize(cx, name, strlen(name), 0);
3909 return atom && JS_DeletePropertyById2(cx, obj, ATOM_TO_JSID(atom), rval);
3912 JS_PUBLIC_API(JSBool)
3913 JS_DeleteUCProperty2(JSContext *cx, JSObject *obj, const jschar *name, size_t namelen, jsval *rval)
3915 JSAtom *atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0);
3916 return atom && JS_DeletePropertyById2(cx, obj, ATOM_TO_JSID(atom), rval);
3919 JS_PUBLIC_API(JSBool)
3920 JS_DeletePropertyById(JSContext *cx, JSObject *obj, jsid id)
3923 return JS_DeletePropertyById2(cx, obj, id, &junk);
3926 JS_PUBLIC_API(JSBool)
3927 JS_DeleteElement(JSContext *cx, JSObject *obj, jsint index)
3930 return JS_DeleteElement2(cx, obj, index, &junk);
3933 JS_PUBLIC_API(JSBool)
3934 JS_DeleteProperty(JSContext *cx, JSObject *obj, const char *name)
3937 return JS_DeleteProperty2(cx, obj, name, &junk);
3941 JS_ClearScope(JSContext *cx, JSObject *obj)
3944 assertSameCompartment(cx, obj);
3946 JSFinalizeOp clearOp = obj->getOps()->clear;
3950 if (obj->isNative())
3951 js_ClearNative(cx, obj);
3953 /* Clear cached class objects on the global object. */
3954 if (obj->isGlobal()) {
3955 /* This can return false but that doesn't mean it failed. */
3958 for (int key = JSProto_Null; key < JSProto_LIMIT * 3; key++)
3959 JS_SetReservedSlot(cx, obj, key, JSVAL_VOID);
3961 /* Clear regexp statics. */
3962 RegExpStatics::extractFrom(obj)->clear();
3964 /* Clear the CSP eval-is-allowed cache. */
3965 JS_SetReservedSlot(cx, obj, JSRESERVED_GLOBAL_EVAL_ALLOWED, JSVAL_VOID);
3968 * Mark global as cleared. If we try to execute any compile-and-go
3969 * scripts from here on, we will throw.
3971 int32 flags = obj->getReservedSlot(JSRESERVED_GLOBAL_FLAGS).toInt32();
3972 flags |= JSGLOBAL_FLAGS_CLEARED;
3973 JS_SetReservedSlot(cx, obj, JSRESERVED_GLOBAL_FLAGS, Jsvalify(Int32Value(flags)));
3979 JS_PUBLIC_API(JSIdArray *)
3980 JS_Enumerate(JSContext *cx, JSObject *obj)
3983 assertSameCompartment(cx, obj);
3985 AutoIdVector props(cx);
3987 if (!GetPropertyNames(cx, obj, JSITER_OWNONLY, &props) || !VectorToIdArray(cx, props, &ida))
3989 for (size_t n = 0; n < size_t(ida->length); ++n)
3990 JS_ASSERT(js_CheckForStringIndex(ida->vector[n]) == ida->vector[n]);
3995 * XXX reverse iterator for properties, unreverse and meld with jsinterp.c's
3996 * prop_iterator_class somehow...
3997 * + preserve the obj->enumerate API while optimizing the native object case
3998 * + native case here uses a Shape *, but that iterates in reverse!
3999 * + so we make non-native match, by reverse-iterating after JS_Enumerating
4001 const uint32 JSSLOT_ITER_INDEX = 0;
4004 prop_iter_finalize(JSContext *cx, JSObject *obj)
4006 void *pdata = obj->getPrivate();
4010 if (obj->getSlot(JSSLOT_ITER_INDEX).toInt32() >= 0) {
4011 /* Non-native case: destroy the ida enumerated when obj was created. */
4012 JSIdArray *ida = (JSIdArray *) pdata;
4013 JS_DestroyIdArray(cx, ida);
4018 prop_iter_trace(JSTracer *trc, JSObject *obj)
4020 void *pdata = obj->getPrivate();
4024 if (obj->getSlot(JSSLOT_ITER_INDEX).toInt32() < 0) {
4025 /* Native case: just mark the next property to visit. */
4026 ((Shape *) pdata)->trace(trc);
4028 /* Non-native case: mark each id in the JSIdArray private. */
4029 JSIdArray *ida = (JSIdArray *) pdata;
4030 MarkIdRange(trc, ida->length, ida->vector, "prop iter");
4034 static Class prop_iter_class = {
4036 JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(1) |
4037 JSCLASS_MARK_IS_TRACE,
4038 PropertyStub, /* addProperty */
4039 PropertyStub, /* delProperty */
4040 PropertyStub, /* getProperty */
4041 StrictPropertyStub, /* setProperty */
4046 NULL, /* reserved0 */
4047 NULL, /* checkAccess */
4049 NULL, /* construct */
4050 NULL, /* xdrObject */
4051 NULL, /* hasInstance */
4052 JS_CLASS_TRACE(prop_iter_trace)
4055 JS_PUBLIC_API(JSObject *)
4056 JS_NewPropertyIterator(JSContext *cx, JSObject *obj)
4064 assertSameCompartment(cx, obj);
4065 iterobj = NewNonFunction<WithProto::Class>(cx, &prop_iter_class, NULL, obj);
4069 if (obj->isNative()) {
4070 /* Native case: start with the last property in obj. */
4071 pdata = obj->lastProperty();
4075 * Non-native case: enumerate a JSIdArray and keep it via private.
4077 * Note: we have to make sure that we root obj around the call to
4078 * JS_Enumerate to protect against multiple allocations under it.
4080 AutoObjectRooter tvr(cx, iterobj);
4081 ida = JS_Enumerate(cx, obj);
4085 index = ida->length;
4088 /* iterobj cannot escape to other threads here. */
4089 iterobj->setPrivate(const_cast<void *>(pdata));
4090 iterobj->getSlotRef(JSSLOT_ITER_INDEX).setInt32(index);
4094 JS_PUBLIC_API(JSBool)
4095 JS_NextProperty(JSContext *cx, JSObject *iterobj, jsid *idp)
4102 assertSameCompartment(cx, iterobj);
4103 i = iterobj->getSlot(JSSLOT_ITER_INDEX).toInt32();
4105 /* Native case: private data is a property tree node pointer. */
4106 JS_ASSERT(iterobj->getParent()->isNative());
4107 shape = (Shape *) iterobj->getPrivate();
4109 while (shape->previous() && (!shape->enumerable() || shape->isAlias()))
4110 shape = shape->previous();
4112 if (!shape->previous()) {
4113 JS_ASSERT(JSID_IS_EMPTY(shape->id));
4116 iterobj->setPrivate(const_cast<Shape *>(shape->previous()));
4120 /* Non-native case: use the ida enumerated when iterobj was created. */
4121 ida = (JSIdArray *) iterobj->getPrivate();
4122 JS_ASSERT(i <= ida->length);
4123 STATIC_ASSUME(i <= ida->length);
4127 *idp = ida->vector[--i];
4128 iterobj->setSlot(JSSLOT_ITER_INDEX, Int32Value(i));
4134 JS_PUBLIC_API(JSBool)
4135 JS_GetReservedSlot(JSContext *cx, JSObject *obj, uint32 index, jsval *vp)
4138 assertSameCompartment(cx, obj);
4139 return js_GetReservedSlot(cx, obj, index, Valueify(vp));
4142 JS_PUBLIC_API(JSBool)
4143 JS_SetReservedSlot(JSContext *cx, JSObject *obj, uint32 index, jsval v)
4146 assertSameCompartment(cx, obj, v);
4147 return js_SetReservedSlot(cx, obj, index, Valueify(v));
4150 JS_PUBLIC_API(JSObject *)
4151 JS_NewArrayObject(JSContext *cx, jsint length, jsval *vector)
4153 JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
4155 /* NB: jsuint cast does ToUint32. */
4156 assertSameCompartment(cx, JSValueArray(vector, vector ? (jsuint)length : 0));
4157 return NewDenseCopiedArray(cx, (jsuint)length, Valueify(vector));
4160 JS_PUBLIC_API(JSBool)
4161 JS_IsArrayObject(JSContext *cx, JSObject *obj)
4163 assertSameCompartment(cx, obj);
4164 return obj->isArray() ||
4165 (obj->isWrapper() && JSWrapper::wrappedObject(obj)->isArray());
4168 JS_PUBLIC_API(JSBool)
4169 JS_GetArrayLength(JSContext *cx, JSObject *obj, jsuint *lengthp)
4172 assertSameCompartment(cx, obj);
4173 return js_GetLengthProperty(cx, obj, lengthp);
4176 JS_PUBLIC_API(JSBool)
4177 JS_SetArrayLength(JSContext *cx, JSObject *obj, jsuint length)
4180 assertSameCompartment(cx, obj);
4181 return js_SetLengthProperty(cx, obj, length);
4184 JS_PUBLIC_API(JSBool)
4185 JS_HasArrayLength(JSContext *cx, JSObject *obj, jsuint *lengthp)
4188 assertSameCompartment(cx, obj);
4189 return js_HasLengthProperty(cx, obj, lengthp);
4192 JS_PUBLIC_API(JSBool)
4193 JS_CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
4194 jsval *vp, uintN *attrsp)
4197 assertSameCompartment(cx, obj, id);
4198 return CheckAccess(cx, obj, id, mode, Valueify(vp), attrsp);
4201 #ifdef JS_THREADSAFE
4202 JS_PUBLIC_API(jsrefcount)
4203 JS_HoldPrincipals(JSContext *cx, JSPrincipals *principals)
4205 return JS_ATOMIC_INCREMENT(&principals->refcount);
4208 JS_PUBLIC_API(jsrefcount)
4209 JS_DropPrincipals(JSContext *cx, JSPrincipals *principals)
4211 jsrefcount rc = JS_ATOMIC_DECREMENT(&principals->refcount);
4213 principals->destroy(cx, principals);
4218 JS_PUBLIC_API(JSSecurityCallbacks *)
4219 JS_SetRuntimeSecurityCallbacks(JSRuntime *rt, JSSecurityCallbacks *callbacks)
4221 JSSecurityCallbacks *oldcallbacks;
4223 oldcallbacks = rt->securityCallbacks;
4224 rt->securityCallbacks = callbacks;
4225 return oldcallbacks;
4228 JS_PUBLIC_API(JSSecurityCallbacks *)
4229 JS_GetRuntimeSecurityCallbacks(JSRuntime *rt)
4231 return rt->securityCallbacks;
4234 JS_PUBLIC_API(JSSecurityCallbacks *)
4235 JS_SetContextSecurityCallbacks(JSContext *cx, JSSecurityCallbacks *callbacks)
4237 JSSecurityCallbacks *oldcallbacks;
4239 oldcallbacks = cx->securityCallbacks;
4240 cx->securityCallbacks = callbacks;
4241 return oldcallbacks;
4244 JS_PUBLIC_API(JSSecurityCallbacks *)
4245 JS_GetSecurityCallbacks(JSContext *cx)
4247 return cx->securityCallbacks
4248 ? cx->securityCallbacks
4249 : cx->runtime->securityCallbacks;
4252 JS_PUBLIC_API(JSFunction *)
4253 JS_NewFunction(JSContext *cx, JSNative native, uintN nargs, uintN flags,
4254 JSObject *parent, const char *name)
4256 JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
4260 assertSameCompartment(cx, parent);
4265 atom = js_Atomize(cx, name, strlen(name), 0);
4269 return js_NewFunction(cx, NULL, Valueify(native), nargs, flags, parent, atom);
4272 JS_PUBLIC_API(JSFunction *)
4273 JS_NewFunctionById(JSContext *cx, JSNative native, uintN nargs, uintN flags, JSObject *parent,
4276 JS_ASSERT(JSID_IS_STRING(id));
4277 JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
4279 assertSameCompartment(cx, parent);
4281 return js_NewFunction(cx, NULL, Valueify(native), nargs, flags, parent, JSID_TO_ATOM(id));
4284 JS_PUBLIC_API(JSObject *)
4285 JS_CloneFunctionObject(JSContext *cx, JSObject *funobj, JSObject *parent)
4288 assertSameCompartment(cx, parent); // XXX no funobj for now
4291 parent = GetScopeChain(cx, cx->fp());
4293 parent = cx->globalObject;
4297 if (funobj->getClass() != &js_FunctionClass) {
4299 * We cannot clone this object, so fail (we used to return funobj, bad
4300 * idea, but we changed incompatibly to teach any abusers a lesson!).
4302 Value v = ObjectValue(*funobj);
4303 js_ReportIsNotFunction(cx, &v, 0);
4307 JSFunction *fun = GET_FUNCTION_PRIVATE(cx, funobj);
4308 if (!FUN_FLAT_CLOSURE(fun))
4309 return CloneFunctionObject(cx, fun, parent);
4312 * A flat closure carries its own environment, so why clone it? In case
4313 * someone wants to mutate its fixed slots or add ad-hoc properties. API
4314 * compatibility suggests we not return funobj and let callers mutate the
4315 * returned object at will.
4317 * But it's worse than that: API compatibility according to the test for
4318 * bug 300079 requires we get "upvars" from parent and its ancestors! So
4319 * we do that (grudgingly!). The scope chain ancestors are searched as if
4320 * they were activations, respecting the skip field in each upvar's cookie
4321 * but looking up the property by name instead of frame slot.
4323 JSObject *clone = js_AllocFlatClosure(cx, fun, parent);
4327 JSUpvarArray *uva = fun->u.i.script->upvars();
4328 uint32 i = uva->length;
4331 for (Shape::Range r(fun->script()->bindings.lastUpvar()); i-- != 0; r.popFront()) {
4332 JSObject *obj = parent;
4333 int skip = uva->vector[i].level();
4334 while (--skip > 0) {
4336 JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
4337 JSMSG_BAD_CLONE_FUNOBJ_SCOPE);
4340 obj = obj->getParent();
4343 if (!obj->getProperty(cx, r.front().id, clone->getFlatClosureUpvars() + i))
4350 JS_PUBLIC_API(JSObject *)
4351 JS_GetFunctionObject(JSFunction *fun)
4353 return FUN_OBJECT(fun);
4356 JS_PUBLIC_API(JSString *)
4357 JS_GetFunctionId(JSFunction *fun)
4359 return fun->atom ? ATOM_TO_STRING(fun->atom) : NULL;
4362 JS_PUBLIC_API(uintN)
4363 JS_GetFunctionFlags(JSFunction *fun)
4368 JS_PUBLIC_API(uint16)
4369 JS_GetFunctionArity(JSFunction *fun)
4374 JS_PUBLIC_API(JSBool)
4375 JS_ObjectIsFunction(JSContext *cx, JSObject *obj)
4377 return obj->getClass() == &js_FunctionClass;
4380 JS_PUBLIC_API(JSBool)
4381 JS_ObjectIsCallable(JSContext *cx, JSObject *obj)
4383 return obj->isCallable();
4387 js_generic_native_method_dispatcher(JSContext *cx, uintN argc, Value *vp)
4389 JSFunctionSpec *fs = (JSFunctionSpec *) vp->toObject().getReservedSlot(0).toPrivate();
4390 JS_ASSERT((fs->flags & JSFUN_GENERIC_NATIVE) != 0);
4393 js_ReportMissingArg(cx, *vp, 0);
4398 * Copy all actual (argc) arguments down over our |this| parameter, vp[1],
4399 * which is almost always the class constructor object, e.g. Array. Then
4400 * call the corresponding prototype native method with our first argument
4403 memmove(vp + 1, vp + 2, argc * sizeof(jsval));
4405 /* Clear the last parameter in case too few arguments were passed. */
4406 vp[2 + --argc].setUndefined();
4410 (fs->flags & JSFUN_TRCINFO)
4411 ? JS_FUNC_TO_DATA_PTR(JSNativeTraceInfo *, fs->call)->native
4415 return native(cx, argc, vp);
4418 JS_PUBLIC_API(JSBool)
4419 JS_DefineFunctions(JSContext *cx, JSObject *obj, JSFunctionSpec *fs)
4421 JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
4427 assertSameCompartment(cx, obj);
4429 for (; fs->name; fs++) {
4433 * Define a generic arity N+1 static method for the arity N prototype
4434 * method if flags contains JSFUN_GENERIC_NATIVE.
4436 if (flags & JSFUN_GENERIC_NATIVE) {
4438 ctor = JS_GetConstructor(cx, obj);
4443 flags &= ~JSFUN_GENERIC_NATIVE;
4444 fun = JS_DefineFunction(cx, ctor, fs->name,
4445 Jsvalify(js_generic_native_method_dispatcher),
4447 flags & ~JSFUN_TRCINFO);
4452 * As jsapi.h notes, fs must point to storage that lives as long
4453 * as fun->object lives.
4455 Value priv = PrivateValue(fs);
4456 if (!js_SetReservedSlot(cx, FUN_OBJECT(fun), 0, priv))
4460 fun = JS_DefineFunction(cx, obj, fs->name, fs->call, fs->nargs, flags);
4467 JS_PUBLIC_API(JSFunction *)
4468 JS_DefineFunction(JSContext *cx, JSObject *obj, const char *name, JSNative call,
4469 uintN nargs, uintN attrs)
4471 JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
4473 assertSameCompartment(cx, obj);
4474 JSAtom *atom = js_Atomize(cx, name, strlen(name), 0);
4477 return js_DefineFunction(cx, obj, ATOM_TO_JSID(atom), Valueify(call), nargs, attrs);
4480 JS_PUBLIC_API(JSFunction *)
4481 JS_DefineUCFunction(JSContext *cx, JSObject *obj,
4482 const jschar *name, size_t namelen, JSNative call,
4483 uintN nargs, uintN attrs)
4485 JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
4487 assertSameCompartment(cx, obj);
4488 JSAtom *atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0);
4491 return js_DefineFunction(cx, obj, ATOM_TO_JSID(atom), Valueify(call), nargs, attrs);
4494 extern JS_PUBLIC_API(JSFunction *)
4495 JS_DefineFunctionById(JSContext *cx, JSObject *obj, jsid id, JSNative call,
4496 uintN nargs, uintN attrs)
4498 JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
4500 assertSameCompartment(cx, obj);
4501 return js_DefineFunction(cx, obj, id, Valueify(call), nargs, attrs);
4505 LAST_FRAME_EXCEPTION_CHECK(JSContext *cx, bool result)
4507 if (!result && !cx->hasRunOption(JSOPTION_DONT_REPORT_UNCAUGHT))
4508 js_ReportUncaughtException(cx);
4512 LAST_FRAME_CHECKS(JSContext *cx, bool result)
4514 if (!JS_IsRunning(cx)) {
4515 LAST_FRAME_EXCEPTION_CHECK(cx, result);
4519 inline static uint32
4520 JS_OPTIONS_TO_TCFLAGS(JSContext *cx)
4522 return (cx->hasRunOption(JSOPTION_COMPILE_N_GO) ? TCF_COMPILE_N_GO : 0) |
4523 (cx->hasRunOption(JSOPTION_NO_SCRIPT_RVAL) ? TCF_NO_SCRIPT_RVAL : 0);
4527 CompileUCScriptForPrincipalsCommon(JSContext *cx, JSObject *obj, JSPrincipals *principals,
4528 const jschar *chars, size_t length,
4529 const char *filename, uintN lineno, JSVersion version)
4531 JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
4533 assertSameCompartment(cx, obj, principals);
4535 uint32 tcflags = JS_OPTIONS_TO_TCFLAGS(cx) | TCF_NEED_MUTABLE_SCRIPT;
4536 JSScript *script = Compiler::compileScript(cx, obj, NULL, principals, tcflags,
4537 chars, length, filename, lineno, version);
4538 JSObject *scriptObj = NULL;
4540 scriptObj = js_NewScriptObject(cx, script);
4542 js_DestroyScript(cx, script);
4544 LAST_FRAME_CHECKS(cx, scriptObj);
4548 extern JS_PUBLIC_API(JSObject *)
4549 JS_CompileUCScriptForPrincipalsVersion(JSContext *cx, JSObject *obj,
4550 JSPrincipals *principals,
4551 const jschar *chars, size_t length,
4552 const char *filename, uintN lineno,
4555 AutoVersionAPI avi(cx, version);
4556 return CompileUCScriptForPrincipalsCommon(cx, obj, principals, chars, length, filename, lineno,
4560 JS_PUBLIC_API(JSObject *)
4561 JS_CompileUCScriptForPrincipals(JSContext *cx, JSObject *obj, JSPrincipals *principals,
4562 const jschar *chars, size_t length,
4563 const char *filename, uintN lineno)
4565 return CompileUCScriptForPrincipalsCommon(cx, obj, principals, chars, length, filename, lineno,
4569 JS_PUBLIC_API(JSObject *)
4570 JS_CompileUCScript(JSContext *cx, JSObject *obj, const jschar *chars, size_t length,
4571 const char *filename, uintN lineno)
4573 JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
4574 return JS_CompileUCScriptForPrincipals(cx, obj, NULL, chars, length, filename, lineno);
4577 JS_PUBLIC_API(JSObject *)
4578 JS_CompileScriptForPrincipalsVersion(JSContext *cx, JSObject *obj,
4579 JSPrincipals *principals,
4580 const char *bytes, size_t length,
4581 const char *filename, uintN lineno,
4584 AutoVersionAPI ava(cx, version);
4585 return JS_CompileScriptForPrincipals(cx, obj, principals, bytes, length, filename, lineno);
4588 JS_PUBLIC_API(JSObject *)
4589 JS_CompileScriptForPrincipals(JSContext *cx, JSObject *obj,
4590 JSPrincipals *principals,
4591 const char *bytes, size_t length,
4592 const char *filename, uintN lineno)
4594 JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
4597 jschar *chars = js_InflateString(cx, bytes, &length);
4600 JSObject *scriptObj =
4601 JS_CompileUCScriptForPrincipals(cx, obj, principals, chars, length, filename, lineno);
4606 JS_PUBLIC_API(JSObject *)
4607 JS_CompileScript(JSContext *cx, JSObject *obj, const char *bytes, size_t length,
4608 const char *filename, uintN lineno)
4610 JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
4611 return JS_CompileScriptForPrincipals(cx, obj, NULL, bytes, length, filename, lineno);
4614 JS_PUBLIC_API(JSBool)
4615 JS_BufferIsCompilableUnit(JSContext *cx, JSObject *obj, const char *bytes, size_t length)
4619 JSExceptionState *exnState;
4620 JSErrorReporter older;
4623 assertSameCompartment(cx, obj);
4624 chars = js_InflateString(cx, bytes, &length);
4629 * Return true on any out-of-memory error, so our caller doesn't try to
4630 * collect more buffered source.
4633 exnState = JS_SaveExceptionState(cx);
4636 if (parser.init(chars, length, NULL, 1, cx->findVersion())) {
4637 older = JS_SetErrorReporter(cx, NULL);
4638 if (!parser.parse(obj) &&
4639 parser.tokenStream.isUnexpectedEOF()) {
4641 * We ran into an error. If it was because we ran out of
4642 * source, we return false so our caller knows to try to
4643 * collect more buffered source.
4647 JS_SetErrorReporter(cx, older);
4651 JS_RestoreExceptionState(cx, exnState);
4655 /* Use the fastest available getc. */
4656 #if defined(HAVE_GETC_UNLOCKED)
4657 # define fast_getc getc_unlocked
4658 #elif defined(HAVE__GETC_NOLOCK)
4659 # define fast_getc _getc_nolock
4661 # define fast_getc getc
4665 CompileFileHelper(JSContext *cx, JSObject *obj, JSPrincipals *principals,
4666 const char* filename, FILE *fp)
4669 int ok = fstat(fileno(fp), &st);
4674 size_t len = st.st_size;
4678 /* Read in the whole file, then compile it. */
4680 JS_ASSERT(len == 0);
4681 len = 8; /* start with a small buffer, expand as necessary */
4683 bool hitEOF = false;
4686 jschar* tmpbuf = (jschar *) js_realloc(buf, len * sizeof(jschar));
4699 buf[i++] = (jschar) (unsigned char) c;
4703 buf = (jschar *) js_malloc(len * sizeof(jschar));
4708 while ((c = fast_getc(fp)) != EOF)
4709 buf[i++] = (jschar) (unsigned char) c;
4712 JS_ASSERT(i <= len);
4714 uint32 tcflags = JS_OPTIONS_TO_TCFLAGS(cx) | TCF_NEED_MUTABLE_SCRIPT;
4715 script = Compiler::compileScript(cx, obj, NULL, principals, tcflags, buf, len, filename, 1,
4721 JSObject *scriptObj = js_NewScriptObject(cx, script);
4723 js_DestroyScript(cx, script);
4728 JS_PUBLIC_API(JSObject *)
4729 JS_CompileFile(JSContext *cx, JSObject *obj, const char *filename)
4731 JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
4734 assertSameCompartment(cx, obj);
4735 JSObject *scriptObj = NULL;
4738 if (!filename || strcmp(filename, "-") == 0) {
4741 fp = fopen(filename, "r");
4743 JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_OPEN,
4744 filename, "No such file or directory");
4749 scriptObj = CompileFileHelper(cx, obj, NULL, filename, fp);
4754 LAST_FRAME_CHECKS(cx, scriptObj);
4758 JS_PUBLIC_API(JSObject *)
4759 JS_CompileFileHandleForPrincipals(JSContext *cx, JSObject *obj, const char *filename,
4760 FILE *file, JSPrincipals *principals)
4762 JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
4765 assertSameCompartment(cx, obj, principals);
4766 JSObject *scriptObj = CompileFileHelper(cx, obj, principals, filename, file);
4767 LAST_FRAME_CHECKS(cx, scriptObj);
4771 JS_PUBLIC_API(JSObject *)
4772 JS_CompileFileHandleForPrincipalsVersion(JSContext *cx, JSObject *obj, const char *filename,
4773 FILE *file, JSPrincipals *principals, JSVersion version)
4775 AutoVersionAPI ava(cx, version);
4776 return JS_CompileFileHandleForPrincipals(cx, obj, filename, file, principals);
4779 JS_PUBLIC_API(JSObject *)
4780 JS_CompileFileHandle(JSContext *cx, JSObject *obj, const char *filename, FILE *file)
4782 JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
4783 return JS_CompileFileHandleForPrincipals(cx, obj, filename, file, NULL);
4786 JS_PUBLIC_API(JSScript *)
4787 JS_GetScriptFromObject(JSObject *scriptObj)
4789 JS_ASSERT(scriptObj->isScript());
4791 return (JSScript *) scriptObj->getPrivate();
4795 CompileUCFunctionForPrincipalsCommon(JSContext *cx, JSObject *obj,
4796 JSPrincipals *principals, const char *name,
4797 uintN nargs, const char **argnames,
4798 const jschar *chars, size_t length,
4799 const char *filename, uintN lineno, JSVersion version)
4801 JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
4803 JSAtom *funAtom, *argAtom;
4807 assertSameCompartment(cx, obj, principals);
4811 funAtom = js_Atomize(cx, name, strlen(name), 0);
4818 fun = js_NewFunction(cx, NULL, NULL, 0, JSFUN_INTERPRETED, obj, funAtom);
4823 AutoObjectRooter tvr(cx, FUN_OBJECT(fun));
4824 MUST_FLOW_THROUGH("out");
4826 Bindings bindings(cx);
4827 AutoBindingsRooter root(cx, bindings);
4828 for (i = 0; i < nargs; i++) {
4829 argAtom = js_Atomize(cx, argnames[i], strlen(argnames[i]), 0);
4836 if (!bindings.addArgument(cx, argAtom, &dummy)) {
4842 if (!Compiler::compileFunctionBody(cx, fun, principals, &bindings,
4843 chars, length, filename, lineno, version)) {
4848 if (obj && funAtom &&
4849 !obj->defineProperty(cx, ATOM_TO_JSID(funAtom), ObjectValue(*fun),
4850 NULL, NULL, JSPROP_ENUMERATE)) {
4854 #ifdef JS_SCOPE_DEPTH_METER
4856 JSObject *pobj = obj;
4859 while ((pobj = pobj->getParent()) != NULL)
4861 JS_BASIC_STATS_ACCUM(&cx->runtime->hostenvScopeDepthStats, depth);
4867 LAST_FRAME_CHECKS(cx, fun);
4870 JS_PUBLIC_API(JSFunction *)
4871 JS_CompileUCFunctionForPrincipalsVersion(JSContext *cx, JSObject *obj,
4872 JSPrincipals *principals, const char *name,
4873 uintN nargs, const char **argnames,
4874 const jschar *chars, size_t length,
4875 const char *filename, uintN lineno,
4878 AutoVersionAPI avi(cx, version);
4879 return CompileUCFunctionForPrincipalsCommon(cx, obj, principals, name, nargs, argnames, chars,
4880 length, filename, lineno, avi.version());
4883 JS_PUBLIC_API(JSFunction *)
4884 JS_CompileUCFunctionForPrincipals(JSContext *cx, JSObject *obj,
4885 JSPrincipals *principals, const char *name,
4886 uintN nargs, const char **argnames,
4887 const jschar *chars, size_t length,
4888 const char *filename, uintN lineno)
4890 return CompileUCFunctionForPrincipalsCommon(cx, obj, principals, name, nargs, argnames, chars,
4891 length, filename, lineno, cx->findVersion());
4894 JS_PUBLIC_API(JSFunction *)
4895 JS_CompileUCFunction(JSContext *cx, JSObject *obj, const char *name,
4896 uintN nargs, const char **argnames,
4897 const jschar *chars, size_t length,
4898 const char *filename, uintN lineno)
4900 JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
4901 return JS_CompileUCFunctionForPrincipals(cx, obj, NULL, name, nargs, argnames,
4902 chars, length, filename, lineno);
4905 JS_PUBLIC_API(JSFunction *)
4906 JS_CompileFunctionForPrincipals(JSContext *cx, JSObject *obj,
4907 JSPrincipals *principals, const char *name,
4908 uintN nargs, const char **argnames,
4909 const char *bytes, size_t length,
4910 const char *filename, uintN lineno)
4912 JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
4913 jschar *chars = js_InflateString(cx, bytes, &length);
4916 JSFunction *fun = JS_CompileUCFunctionForPrincipals(cx, obj, principals, name,
4917 nargs, argnames, chars, length,
4923 JS_PUBLIC_API(JSFunction *)
4924 JS_CompileFunction(JSContext *cx, JSObject *obj, const char *name,
4925 uintN nargs, const char **argnames,
4926 const char *bytes, size_t length,
4927 const char *filename, uintN lineno)
4929 JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
4930 return JS_CompileFunctionForPrincipals(cx, obj, NULL, name, nargs, argnames, bytes, length,
4934 JS_PUBLIC_API(JSString *)
4935 JS_DecompileScript(JSContext *cx, JSScript *script, const char *name, uintN indent)
4937 JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
4943 if (cx->compartment != script->compartment)
4944 CompartmentChecker::fail(cx->compartment, script->compartment);
4946 jp = js_NewPrinter(cx, name, NULL,
4947 indent & ~JS_DONT_PRETTY_PRINT,
4948 !(indent & JS_DONT_PRETTY_PRINT),
4952 if (js_DecompileScript(jp, script))
4953 str = js_GetPrinterOutput(jp);
4956 js_DestroyPrinter(jp);
4960 JS_PUBLIC_API(JSString *)
4961 JS_DecompileScriptObject(JSContext *cx, JSObject *scriptObj, const char *name, uintN indent)
4963 return JS_DecompileScript(cx, scriptObj->getScript(), name, indent);
4966 JS_PUBLIC_API(JSString *)
4967 JS_DecompileFunction(JSContext *cx, JSFunction *fun, uintN indent)
4969 JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
4971 assertSameCompartment(cx, fun);
4972 return js_DecompileToString(cx, "JS_DecompileFunction", fun,
4973 indent & ~JS_DONT_PRETTY_PRINT,
4974 !(indent & JS_DONT_PRETTY_PRINT),
4975 false, false, js_DecompileFunction);
4978 JS_PUBLIC_API(JSString *)
4979 JS_DecompileFunctionBody(JSContext *cx, JSFunction *fun, uintN indent)
4981 JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
4983 assertSameCompartment(cx, fun);
4984 return js_DecompileToString(cx, "JS_DecompileFunctionBody", fun,
4985 indent & ~JS_DONT_PRETTY_PRINT,
4986 !(indent & JS_DONT_PRETTY_PRINT),
4987 false, false, js_DecompileFunctionBody);
4990 JS_PUBLIC_API(JSBool)
4991 JS_ExecuteScript(JSContext *cx, JSObject *obj, JSObject *scriptObj, jsval *rval)
4993 JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
4996 assertSameCompartment(cx, obj, scriptObj);
4998 JSBool ok = Execute(cx, obj, scriptObj->getScript(), NULL, 0, Valueify(rval));
4999 LAST_FRAME_CHECKS(cx, ok);
5003 JS_PUBLIC_API(JSBool)
5004 JS_ExecuteScriptVersion(JSContext *cx, JSObject *obj, JSObject *scriptObj, jsval *rval,
5007 AutoVersionAPI ava(cx, version);
5008 return JS_ExecuteScript(cx, obj, scriptObj, rval);
5012 EvaluateUCScriptForPrincipalsCommon(JSContext *cx, JSObject *obj,
5013 JSPrincipals *principals,
5014 const jschar *chars, uintN length,
5015 const char *filename, uintN lineno,
5016 jsval *rval, JSVersion compileVersion)
5018 JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
5021 JSScript *script = Compiler::compileScript(cx, obj, NULL, principals,
5023 ? TCF_COMPILE_N_GO | TCF_NO_SCRIPT_RVAL
5025 chars, length, filename, lineno, compileVersion);
5027 LAST_FRAME_CHECKS(cx, script);
5030 JS_ASSERT(script->getVersion() == compileVersion);
5031 bool ok = Execute(cx, obj, script, NULL, 0, Valueify(rval));
5032 LAST_FRAME_CHECKS(cx, ok);
5033 js_DestroyScript(cx, script);
5038 JS_PUBLIC_API(JSBool)
5039 JS_EvaluateUCScriptForPrincipalsVersion(JSContext *cx, JSObject *obj,
5040 JSPrincipals *principals,
5041 const jschar *chars, uintN length,
5042 const char *filename, uintN lineno,
5043 jsval *rval, JSVersion version)
5045 AutoVersionAPI avi(cx, version);
5046 return EvaluateUCScriptForPrincipalsCommon(cx, obj, principals, chars, length,
5047 filename, lineno, rval, avi.version());
5050 JS_PUBLIC_API(JSBool)
5051 JS_EvaluateUCScriptForPrincipals(JSContext *cx, JSObject *obj,
5052 JSPrincipals *principals,
5053 const jschar *chars, uintN length,
5054 const char *filename, uintN lineno,
5057 return EvaluateUCScriptForPrincipalsCommon(cx, obj, principals, chars, length,
5058 filename, lineno, rval, cx->findVersion());
5061 JS_PUBLIC_API(JSBool)
5062 JS_EvaluateUCScript(JSContext *cx, JSObject *obj, const jschar *chars, uintN length,
5063 const char *filename, uintN lineno, jsval *rval)
5065 JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
5066 return JS_EvaluateUCScriptForPrincipals(cx, obj, NULL, chars, length, filename, lineno, rval);
5069 /* Ancient uintN nbytes is part of API/ABI, so use size_t length local. */
5070 JS_PUBLIC_API(JSBool)
5071 JS_EvaluateScriptForPrincipals(JSContext *cx, JSObject *obj, JSPrincipals *principals,
5072 const char *bytes, uintN nbytes,
5073 const char *filename, uintN lineno, jsval *rval)
5075 JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
5076 size_t length = nbytes;
5077 jschar *chars = js_InflateString(cx, bytes, &length);
5080 JSBool ok = JS_EvaluateUCScriptForPrincipals(cx, obj, principals, chars, length,
5081 filename, lineno, rval);
5086 JS_PUBLIC_API(JSBool)
5087 JS_EvaluateScriptForPrincipalsVersion(JSContext *cx, JSObject *obj, JSPrincipals *principals,
5088 const char *bytes, uintN nbytes,
5089 const char *filename, uintN lineno, jsval *rval, JSVersion version)
5091 AutoVersionAPI avi(cx, version);
5092 return JS_EvaluateScriptForPrincipals(cx, obj, principals, bytes, nbytes, filename, lineno,
5096 JS_PUBLIC_API(JSBool)
5097 JS_EvaluateScript(JSContext *cx, JSObject *obj, const char *bytes, uintN nbytes,
5098 const char *filename, uintN lineno, jsval *rval)
5100 JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
5101 return JS_EvaluateScriptForPrincipals(cx, obj, NULL, bytes, nbytes, filename, lineno, rval);
5104 JS_PUBLIC_API(JSBool)
5105 JS_CallFunction(JSContext *cx, JSObject *obj, JSFunction *fun, uintN argc, jsval *argv,
5108 JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
5110 assertSameCompartment(cx, obj, fun, JSValueArray(argv, argc));
5111 JSBool ok = ExternalInvoke(cx, ObjectOrNullValue(obj), ObjectValue(*fun), argc,
5112 Valueify(argv), Valueify(rval));
5113 LAST_FRAME_CHECKS(cx, ok);
5117 JS_PUBLIC_API(JSBool)
5118 JS_CallFunctionName(JSContext *cx, JSObject *obj, const char *name, uintN argc, jsval *argv,
5121 JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
5123 assertSameCompartment(cx, obj, JSValueArray(argv, argc));
5125 AutoValueRooter tvr(cx);
5126 JSAtom *atom = js_Atomize(cx, name, strlen(name), 0);
5129 js_GetMethod(cx, obj, ATOM_TO_JSID(atom), JSGET_NO_METHOD_BARRIER, tvr.addr()) &&
5130 ExternalInvoke(cx, ObjectOrNullValue(obj), tvr.value(), argc, Valueify(argv),
5132 LAST_FRAME_CHECKS(cx, ok);
5136 JS_PUBLIC_API(JSBool)
5137 JS_CallFunctionValue(JSContext *cx, JSObject *obj, jsval fval, uintN argc, jsval *argv,
5140 JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
5143 assertSameCompartment(cx, obj, fval, JSValueArray(argv, argc));
5144 JSBool ok = ExternalInvoke(cx, ObjectOrNullValue(obj), Valueify(fval), argc, Valueify(argv),
5146 LAST_FRAME_CHECKS(cx, ok);
5153 Call(JSContext *cx, jsval thisv, jsval fval, uintN argc, jsval *argv, jsval *rval)
5158 assertSameCompartment(cx, thisv, fval, JSValueArray(argv, argc));
5159 ok = ExternalInvoke(cx, Valueify(thisv), Valueify(fval), argc, Valueify(argv), Valueify(rval));
5160 LAST_FRAME_CHECKS(cx, ok);
5166 JS_PUBLIC_API(JSObject *)
5167 JS_New(JSContext *cx, JSObject *ctor, uintN argc, jsval *argv)
5170 assertSameCompartment(cx, ctor, JSValueArray(argv, argc));
5172 // This is not a simple variation of JS_CallFunctionValue because JSOP_NEW
5173 // is not a simple variation of JSOP_CALL. We have to determine what class
5174 // of object to create, create it, and clamp the return value to an object,
5175 // among other details. js_InvokeConstructor does the hard work.
5176 InvokeArgsGuard args;
5177 if (!cx->stack().pushInvokeArgs(cx, argc, &args))
5180 args.callee().setObject(*ctor);
5181 args.thisv().setNull();
5182 memcpy(args.argv(), argv, argc * sizeof(jsval));
5184 bool ok = InvokeConstructor(cx, args);
5186 JSObject *obj = NULL;
5188 if (args.rval().isObject()) {
5189 obj = &args.rval().toObject();
5192 * Although constructors may return primitives (via proxies), this
5193 * API is asking for an object, so we report an error.
5195 JSAutoByteString bytes;
5196 if (js_ValueToPrintable(cx, args.rval(), &bytes)) {
5197 JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_NEW_RESULT,
5203 LAST_FRAME_CHECKS(cx, ok);
5207 JS_PUBLIC_API(JSOperationCallback)
5208 JS_SetOperationCallback(JSContext *cx, JSOperationCallback callback)
5210 #ifdef JS_THREADSAFE
5211 JS_ASSERT(CURRENT_THREAD_IS_ME(cx->thread));
5213 JSOperationCallback old = cx->operationCallback;
5214 cx->operationCallback = callback;
5218 JS_PUBLIC_API(JSOperationCallback)
5219 JS_GetOperationCallback(JSContext *cx)
5221 return cx->operationCallback;
5225 JS_TriggerOperationCallback(JSContext *cx)
5227 #ifdef JS_THREADSAFE
5228 AutoLockGC lock(cx->runtime);
5230 TriggerOperationCallback(cx);
5234 JS_TriggerAllOperationCallbacks(JSRuntime *rt)
5236 #ifdef JS_THREADSAFE
5237 AutoLockGC lock(rt);
5239 TriggerAllOperationCallbacks(rt);
5242 JS_PUBLIC_API(JSBool)
5243 JS_IsRunning(JSContext *cx)
5246 * The use of cx->fp below is safe. Rationale: Here we don't care if the
5247 * interpreter state is stale. We just want to know if there *is* any
5248 * interpreter state.
5250 VOUCH_DOES_NOT_REQUIRE_STACK();
5253 JS_ASSERT_IF(JS_ON_TRACE(cx) && JS_TRACE_MONITOR_ON_TRACE(cx)->tracecx == cx, cx->hasfp());
5255 JSStackFrame *fp = cx->maybefp();
5256 while (fp && fp->isDummyFrame())
5261 JS_PUBLIC_API(JSStackFrame *)
5262 JS_SaveFrameChain(JSContext *cx)
5265 JSStackFrame *fp = js_GetTopStackFrame(cx);
5268 cx->saveActiveSegment();
5273 JS_RestoreFrameChain(JSContext *cx, JSStackFrame *fp)
5276 JS_ASSERT_NOT_ON_TRACE(cx);
5277 JS_ASSERT(!cx->hasfp());
5280 cx->restoreSegment();
5283 /************************************************************************/
5284 JS_PUBLIC_API(JSString *)
5285 JS_NewStringCopyN(JSContext *cx, const char *s, size_t n)
5288 return js_NewStringCopyN(cx, s, n);
5291 JS_PUBLIC_API(JSString *)
5292 JS_NewStringCopyZ(JSContext *cx, const char *s)
5300 return cx->runtime->emptyString;
5302 js = js_InflateString(cx, s, &n);
5305 str = js_NewString(cx, js, n);
5311 JS_PUBLIC_API(JSBool)
5312 JS_StringHasBeenInterned(JSString *str)
5314 return str->isAtomized();
5317 JS_PUBLIC_API(JSString *)
5318 JS_InternJSString(JSContext *cx, JSString *str)
5321 JSAtom *atom = js_AtomizeString(cx, str, 0);
5324 return ATOM_TO_STRING(atom);
5327 JS_PUBLIC_API(JSString *)
5328 JS_InternString(JSContext *cx, const char *s)
5333 atom = js_Atomize(cx, s, strlen(s), ATOM_INTERNED);
5336 return ATOM_TO_STRING(atom);
5339 JS_PUBLIC_API(JSString *)
5340 JS_NewUCString(JSContext *cx, jschar *chars, size_t length)
5343 return js_NewString(cx, chars, length);
5346 JS_PUBLIC_API(JSString *)
5347 JS_NewUCStringCopyN(JSContext *cx, const jschar *s, size_t n)
5350 return js_NewStringCopyN(cx, s, n);
5353 JS_PUBLIC_API(JSString *)
5354 JS_NewUCStringCopyZ(JSContext *cx, const jschar *s)
5358 return cx->runtime->emptyString;
5359 return js_NewStringCopyZ(cx, s);
5362 JS_PUBLIC_API(JSString *)
5363 JS_InternUCStringN(JSContext *cx, const jschar *s, size_t length)
5368 atom = js_AtomizeChars(cx, s, length, ATOM_INTERNED);
5371 return ATOM_TO_STRING(atom);
5374 JS_PUBLIC_API(JSString *)
5375 JS_InternUCString(JSContext *cx, const jschar *s)
5377 return JS_InternUCStringN(cx, s, js_strlen(s));
5380 JS_PUBLIC_API(size_t)
5381 JS_GetStringLength(JSString *str)
5383 return str->length();
5386 JS_PUBLIC_API(const jschar *)
5387 JS_GetStringCharsZ(JSContext *cx, JSString *str)
5390 assertSameCompartment(cx, str);
5391 return str->getCharsZ(cx);
5394 JS_PUBLIC_API(const jschar *)
5395 JS_GetStringCharsZAndLength(JSContext *cx, JSString *str, size_t *plength)
5398 assertSameCompartment(cx, str);
5399 *plength = str->length();
5400 return str->getCharsZ(cx);
5403 JS_PUBLIC_API(const jschar *)
5404 JS_GetStringCharsAndLength(JSContext *cx, JSString *str, size_t *plength)
5407 assertSameCompartment(cx, str);
5408 *plength = str->length();
5409 return str->getChars(cx);
5412 JS_PUBLIC_API(const jschar *)
5413 JS_GetInternedStringChars(JSString *str)
5415 JS_ASSERT(str->isAtomized());
5416 return str->flatChars();
5419 JS_PUBLIC_API(const jschar *)
5420 JS_GetInternedStringCharsAndLength(JSString *str, size_t *plength)
5422 JS_ASSERT(str->isAtomized());
5423 *plength = str->flatLength();
5424 return str->flatChars();
5427 extern JS_PUBLIC_API(JSFlatString *)
5428 JS_FlattenString(JSContext *cx, JSString *str)
5431 assertSameCompartment(cx, str);
5432 return str->getCharsZ(cx) ? (JSFlatString *)str : NULL;
5435 extern JS_PUBLIC_API(const jschar *)
5436 JS_GetFlatStringChars(JSFlatString *str)
5438 return str->chars();
5441 JS_PUBLIC_API(JSBool)
5442 JS_CompareStrings(JSContext *cx, JSString *str1, JSString *str2, int32 *result)
5444 return CompareStrings(cx, str1, str2, result);
5447 JS_PUBLIC_API(JSBool)
5448 JS_StringEqualsAscii(JSContext *cx, JSString *str, const char *asciiBytes, JSBool *match)
5450 JSLinearString *linearStr = str->ensureLinear(cx);
5453 *match = StringEqualsAscii(linearStr, asciiBytes);
5457 JS_PUBLIC_API(JSBool)
5458 JS_FlatStringEqualsAscii(JSFlatString *str, const char *asciiBytes)
5460 return StringEqualsAscii(str, asciiBytes);
5463 JS_PUBLIC_API(size_t)
5464 JS_PutEscapedFlatString(char *buffer, size_t size, JSFlatString *str, char quote)
5466 return PutEscapedString(buffer, size, str, quote);
5469 JS_PUBLIC_API(size_t)
5470 JS_PutEscapedString(JSContext *cx, char *buffer, size_t size, JSString *str, char quote)
5472 JSLinearString *linearStr = str->ensureLinear(cx);
5475 return PutEscapedString(buffer, size, linearStr, quote);
5478 JS_PUBLIC_API(JSBool)
5479 JS_FileEscapedString(FILE *fp, JSString *str, char quote)
5481 JSLinearString *linearStr = str->ensureLinear(NULL);
5482 return linearStr && FileEscapedString(fp, linearStr, quote);
5485 JS_PUBLIC_API(JSString *)
5486 JS_NewGrowableString(JSContext *cx, jschar *chars, size_t length)
5489 return js_NewString(cx, chars, length);
5492 JS_PUBLIC_API(JSString *)
5493 JS_NewDependentString(JSContext *cx, JSString *str, size_t start, size_t length)
5496 return js_NewDependentString(cx, str, start, length);
5499 JS_PUBLIC_API(JSString *)
5500 JS_ConcatStrings(JSContext *cx, JSString *left, JSString *right)
5503 return js_ConcatStrings(cx, left, right);
5506 JS_PUBLIC_API(const jschar *)
5507 JS_UndependString(JSContext *cx, JSString *str)
5510 return str->getCharsZ(cx);
5513 JS_PUBLIC_API(JSBool)
5514 JS_MakeStringImmutable(JSContext *cx, JSString *str)
5517 return js_MakeStringImmutable(cx, str);
5520 JS_PUBLIC_API(JSBool)
5521 JS_EncodeCharacters(JSContext *cx, const jschar *src, size_t srclen, char *dst, size_t *dstlenp)
5525 n = js_GetDeflatedStringLength(cx, src, srclen);
5526 if (n == (size_t)-1) {
5534 return js_DeflateStringToBuffer(cx, src, srclen, dst, dstlenp);
5537 JS_PUBLIC_API(JSBool)
5538 JS_DecodeBytes(JSContext *cx, const char *src, size_t srclen, jschar *dst, size_t *dstlenp)
5540 return js_InflateStringToBuffer(cx, src, srclen, dst, dstlenp);
5543 JS_PUBLIC_API(char *)
5544 JS_EncodeString(JSContext *cx, JSString *str)
5546 const jschar *chars = str->getChars(cx);
5549 return js_DeflateString(cx, chars, str->length());
5552 JS_PUBLIC_API(size_t)
5553 JS_GetStringEncodingLength(JSContext *cx, JSString *str)
5555 const jschar *chars = str->getChars(cx);
5558 return js_GetDeflatedStringLength(cx, chars, str->length());
5561 JS_PUBLIC_API(size_t)
5562 JS_EncodeStringToBuffer(JSString *str, char *buffer, size_t length)
5565 * FIXME bug 612141 - fix js_DeflateStringToBuffer interface so the result
5566 * would allow to distinguish between insufficient buffer and encoding
5569 size_t writtenLength = length;
5570 const jschar *chars = str->getChars(NULL);
5573 if (js_DeflateStringToBuffer(NULL, chars, str->length(), buffer, &writtenLength)) {
5574 JS_ASSERT(writtenLength <= length);
5575 return writtenLength;
5577 JS_ASSERT(writtenLength <= length);
5578 size_t necessaryLength = js_GetDeflatedStringLength(NULL, chars, str->length());
5579 if (necessaryLength == size_t(-1))
5581 if (writtenLength != length) {
5582 /* Make sure that the buffer contains only valid UTF-8 sequences. */
5583 JS_ASSERT(js_CStringsAreUTF8);
5584 PodZero(buffer + writtenLength, length - writtenLength);
5586 return necessaryLength;
5589 JS_PUBLIC_API(JSBool)
5590 JS_Stringify(JSContext *cx, jsval *vp, JSObject *replacer, jsval space,
5591 JSONWriteCallback callback, void *data)
5594 assertSameCompartment(cx, replacer, space);
5595 StringBuffer sb(cx);
5596 if (!js_Stringify(cx, Valueify(vp), replacer, Valueify(space), sb))
5598 return callback(sb.begin(), sb.length(), data);
5601 JS_PUBLIC_API(JSBool)
5602 JS_TryJSON(JSContext *cx, jsval *vp)
5605 assertSameCompartment(cx, *vp);
5606 return js_TryJSON(cx, Valueify(vp));
5609 JS_PUBLIC_API(JSONParser *)
5610 JS_BeginJSONParse(JSContext *cx, jsval *vp)
5613 return js_BeginJSONParse(cx, Valueify(vp));
5616 JS_PUBLIC_API(JSBool)
5617 JS_ConsumeJSONText(JSContext *cx, JSONParser *jp, const jschar *data, uint32 len)
5620 return js_ConsumeJSONText(cx, jp, data, len);
5623 JS_PUBLIC_API(JSBool)
5624 JS_FinishJSONParse(JSContext *cx, JSONParser *jp, jsval reviver)
5627 assertSameCompartment(cx, reviver);
5628 return js_FinishJSONParse(cx, jp, Valueify(reviver));
5631 JS_PUBLIC_API(JSBool)
5632 JS_ReadStructuredClone(JSContext *cx, const uint64 *buf, size_t nbytes,
5633 uint32 version, jsval *vp,
5634 const JSStructuredCloneCallbacks *optionalCallbacks,
5637 if (version > JS_STRUCTURED_CLONE_VERSION) {
5638 JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_CLONE_VERSION);
5641 const JSStructuredCloneCallbacks *callbacks =
5644 cx->runtime->structuredCloneCallbacks;
5645 return ReadStructuredClone(cx, buf, nbytes, Valueify(vp), callbacks, closure);
5648 JS_PUBLIC_API(JSBool)
5649 JS_WriteStructuredClone(JSContext *cx, jsval v, uint64 **bufp, size_t *nbytesp,
5650 const JSStructuredCloneCallbacks *optionalCallbacks,
5653 const JSStructuredCloneCallbacks *callbacks =
5656 cx->runtime->structuredCloneCallbacks;
5657 return WriteStructuredClone(cx, Valueify(v), (uint64_t **) bufp, nbytesp,
5658 callbacks, closure);
5661 JS_PUBLIC_API(JSBool)
5662 JS_StructuredClone(JSContext *cx, jsval v, jsval *vp,
5663 ReadStructuredCloneOp optionalReadOp,
5664 const JSStructuredCloneCallbacks *optionalCallbacks,
5667 const JSStructuredCloneCallbacks *callbacks =
5670 cx->runtime->structuredCloneCallbacks;
5671 JSAutoStructuredCloneBuffer buf;
5672 return buf.write(cx, v, callbacks, closure) &&
5673 buf.read(vp, cx, callbacks, closure);
5677 JS_SetStructuredCloneCallbacks(JSRuntime *rt, const JSStructuredCloneCallbacks *callbacks)
5679 rt->structuredCloneCallbacks = callbacks;
5682 JS_PUBLIC_API(JSBool)
5683 JS_ReadUint32Pair(JSStructuredCloneReader *r, uint32 *p1, uint32 *p2)
5685 return r->input().readPair((uint32_t *) p1, (uint32_t *) p2);
5688 JS_PUBLIC_API(JSBool)
5689 JS_ReadBytes(JSStructuredCloneReader *r, void *p, size_t len)
5691 return r->input().readBytes(p, len);
5694 JS_PUBLIC_API(JSBool)
5695 JS_WriteUint32Pair(JSStructuredCloneWriter *w, uint32 tag, uint32 data)
5697 return w->output().writePair(tag, data);
5700 JS_PUBLIC_API(JSBool)
5701 JS_WriteBytes(JSStructuredCloneWriter *w, const void *p, size_t len)
5703 return w->output().writeBytes(p, len);
5707 * The following determines whether C Strings are to be treated as UTF-8
5708 * or ISO-8859-1. For correct operation, it must be set prior to the
5709 * first call to JS_NewRuntime.
5711 #ifndef JS_C_STRINGS_ARE_UTF8
5712 JSBool js_CStringsAreUTF8 = JS_FALSE;
5715 JS_PUBLIC_API(JSBool)
5716 JS_CStringsAreUTF8()
5718 return js_CStringsAreUTF8;
5722 JS_SetCStringsAreUTF8()
5724 JS_ASSERT(!js_NewRuntimeWasCalled);
5726 #ifndef JS_C_STRINGS_ARE_UTF8
5727 js_CStringsAreUTF8 = JS_TRUE;
5731 /************************************************************************/
5734 JS_ReportError(JSContext *cx, const char *format, ...)
5738 va_start(ap, format);
5739 js_ReportErrorVA(cx, JSREPORT_ERROR, format, ap);
5744 JS_ReportErrorNumber(JSContext *cx, JSErrorCallback errorCallback,
5745 void *userRef, const uintN errorNumber, ...)
5749 va_start(ap, errorNumber);
5750 js_ReportErrorNumberVA(cx, JSREPORT_ERROR, errorCallback, userRef,
5751 errorNumber, JS_TRUE, ap);
5756 JS_ReportErrorNumberUC(JSContext *cx, JSErrorCallback errorCallback,
5757 void *userRef, const uintN errorNumber, ...)
5761 va_start(ap, errorNumber);
5762 js_ReportErrorNumberVA(cx, JSREPORT_ERROR, errorCallback, userRef,
5763 errorNumber, JS_FALSE, ap);
5767 JS_PUBLIC_API(JSBool)
5768 JS_ReportWarning(JSContext *cx, const char *format, ...)
5773 va_start(ap, format);
5774 ok = js_ReportErrorVA(cx, JSREPORT_WARNING, format, ap);
5779 JS_PUBLIC_API(JSBool)
5780 JS_ReportErrorFlagsAndNumber(JSContext *cx, uintN flags,
5781 JSErrorCallback errorCallback, void *userRef,
5782 const uintN errorNumber, ...)
5787 va_start(ap, errorNumber);
5788 ok = js_ReportErrorNumberVA(cx, flags, errorCallback, userRef,
5789 errorNumber, JS_TRUE, ap);
5794 JS_PUBLIC_API(JSBool)
5795 JS_ReportErrorFlagsAndNumberUC(JSContext *cx, uintN flags,
5796 JSErrorCallback errorCallback, void *userRef,
5797 const uintN errorNumber, ...)
5802 va_start(ap, errorNumber);
5803 ok = js_ReportErrorNumberVA(cx, flags, errorCallback, userRef,
5804 errorNumber, JS_FALSE, ap);
5810 JS_ReportOutOfMemory(JSContext *cx)
5812 js_ReportOutOfMemory(cx);
5816 JS_ReportAllocationOverflow(JSContext *cx)
5818 js_ReportAllocationOverflow(cx);
5821 JS_PUBLIC_API(JSErrorReporter)
5822 JS_SetErrorReporter(JSContext *cx, JSErrorReporter er)
5824 JSErrorReporter older;
5826 older = cx->errorReporter;
5827 cx->errorReporter = er;
5831 /************************************************************************/
5836 JS_PUBLIC_API(JSObject *)
5837 JS_NewDateObject(JSContext *cx, int year, int mon, int mday, int hour, int min, int sec)
5840 return js_NewDateObject(cx, year, mon, mday, hour, min, sec);
5843 JS_PUBLIC_API(JSObject *)
5844 JS_NewDateObjectMsec(JSContext *cx, jsdouble msec)
5847 return js_NewDateObjectMsec(cx, msec);
5850 JS_PUBLIC_API(JSBool)
5851 JS_ObjectIsDate(JSContext *cx, JSObject *obj)
5854 return obj->isDate();
5857 /************************************************************************/
5860 * Regular Expressions.
5862 JS_PUBLIC_API(JSObject *)
5863 JS_NewRegExpObject(JSContext *cx, JSObject *obj, char *bytes, size_t length, uintN flags)
5866 jschar *chars = js_InflateString(cx, bytes, &length);
5869 RegExpStatics *res = RegExpStatics::extractFrom(obj);
5870 JSObject *reobj = RegExp::createObject(cx, res, chars, length, flags);
5875 JS_PUBLIC_API(JSObject *)
5876 JS_NewUCRegExpObject(JSContext *cx, JSObject *obj, jschar *chars, size_t length, uintN flags)
5879 RegExpStatics *res = RegExpStatics::extractFrom(obj);
5880 return RegExp::createObject(cx, res, chars, length, flags);
5884 JS_SetRegExpInput(JSContext *cx, JSObject *obj, JSString *input, JSBool multiline)
5887 assertSameCompartment(cx, input);
5889 RegExpStatics::extractFrom(obj)->reset(input, !!multiline);
5893 JS_ClearRegExpStatics(JSContext *cx, JSObject *obj)
5898 RegExpStatics::extractFrom(obj)->clear();
5901 JS_PUBLIC_API(JSBool)
5902 JS_ExecuteRegExp(JSContext *cx, JSObject *obj, JSObject *reobj, jschar *chars, size_t length,
5903 size_t *indexp, JSBool test, jsval *rval)
5907 RegExp *re = RegExp::extractFrom(reobj);
5911 JSString *str = js_NewStringCopyN(cx, chars, length);
5915 return re->execute(cx, RegExpStatics::extractFrom(obj), str, indexp, test, Valueify(rval));
5918 JS_PUBLIC_API(JSObject *)
5919 JS_NewRegExpObjectNoStatics(JSContext *cx, char *bytes, size_t length, uintN flags)
5922 jschar *chars = js_InflateString(cx, bytes, &length);
5925 JSObject *obj = RegExp::createObjectNoStatics(cx, chars, length, flags);
5930 JS_PUBLIC_API(JSObject *)
5931 JS_NewUCRegExpObjectNoStatics(JSContext *cx, jschar *chars, size_t length, uintN flags)
5934 return RegExp::createObjectNoStatics(cx, chars, length, flags);
5937 JS_PUBLIC_API(JSBool)
5938 JS_ExecuteRegExpNoStatics(JSContext *cx, JSObject *obj, jschar *chars, size_t length,
5939 size_t *indexp, JSBool test, jsval *rval)
5943 RegExp *re = RegExp::extractFrom(obj);
5947 JSString *str = js_NewStringCopyN(cx, chars, length);
5951 return re->executeNoStatics(cx, str, indexp, test, Valueify(rval));
5954 /************************************************************************/
5957 JS_SetLocaleCallbacks(JSContext *cx, JSLocaleCallbacks *callbacks)
5959 cx->localeCallbacks = callbacks;
5962 JS_PUBLIC_API(JSLocaleCallbacks *)
5963 JS_GetLocaleCallbacks(JSContext *cx)
5965 return cx->localeCallbacks;
5968 /************************************************************************/
5970 JS_PUBLIC_API(JSBool)
5971 JS_IsExceptionPending(JSContext *cx)
5973 return (JSBool) cx->isExceptionPending();
5976 JS_PUBLIC_API(JSBool)
5977 JS_GetPendingException(JSContext *cx, jsval *vp)
5980 if (!cx->isExceptionPending())
5982 Valueify(*vp) = cx->getPendingException();
5983 assertSameCompartment(cx, *vp);
5988 JS_SetPendingException(JSContext *cx, jsval v)
5991 assertSameCompartment(cx, v);
5992 cx->setPendingException(Valueify(v));
5996 JS_ClearPendingException(JSContext *cx)
5998 cx->clearPendingException();
6001 JS_PUBLIC_API(JSBool)
6002 JS_ReportPendingException(JSContext *cx)
6010 * Set cx->generatingError to suppress the standard error-to-exception
6011 * conversion done by all {js,JS}_Report* functions except for OOM. The
6012 * cx->generatingError flag was added to suppress recursive divergence
6013 * under js_ErrorToException, but it serves for our purposes here too.
6015 save = cx->generatingError;
6016 cx->generatingError = JS_TRUE;
6017 ok = js_ReportUncaughtException(cx);
6018 cx->generatingError = save;
6022 struct JSExceptionState {
6027 JS_PUBLIC_API(JSExceptionState *)
6028 JS_SaveExceptionState(JSContext *cx)
6030 JSExceptionState *state;
6033 state = (JSExceptionState *) cx->malloc(sizeof(JSExceptionState));
6035 state->throwing = JS_GetPendingException(cx, &state->exception);
6036 if (state->throwing && JSVAL_IS_GCTHING(state->exception))
6037 js_AddRoot(cx, Valueify(&state->exception), "JSExceptionState.exception");
6043 JS_RestoreExceptionState(JSContext *cx, JSExceptionState *state)
6047 if (state->throwing)
6048 JS_SetPendingException(cx, state->exception);
6050 JS_ClearPendingException(cx);
6051 JS_DropExceptionState(cx, state);
6056 JS_DropExceptionState(JSContext *cx, JSExceptionState *state)
6060 if (state->throwing && JSVAL_IS_GCTHING(state->exception)) {
6061 assertSameCompartment(cx, state->exception);
6062 JS_RemoveValueRoot(cx, &state->exception);
6068 JS_PUBLIC_API(JSErrorReport *)
6069 JS_ErrorFromException(JSContext *cx, jsval v)
6072 assertSameCompartment(cx, v);
6073 return js_ErrorFromException(cx, v);
6076 JS_PUBLIC_API(JSBool)
6077 JS_ThrowReportedError(JSContext *cx, const char *message,
6078 JSErrorReport *reportp)
6080 return JS_IsRunning(cx) &&
6081 js_ErrorToException(cx, message, reportp, NULL, NULL);
6084 JS_PUBLIC_API(JSBool)
6085 JS_ThrowStopIteration(JSContext *cx)
6087 return js_ThrowStopIteration(cx);
6091 * Get the owning thread id of a context. Returns 0 if the context is not
6092 * owned by any thread.
6094 JS_PUBLIC_API(jsword)
6095 JS_GetContextThread(JSContext *cx)
6097 #ifdef JS_THREADSAFE
6098 return reinterpret_cast<jsword>(JS_THREAD_ID(cx));
6105 * Set the current thread as the owning thread of a context. Returns the
6106 * old owning thread id, or -1 if the operation failed.
6108 JS_PUBLIC_API(jsword)
6109 JS_SetContextThread(JSContext *cx)
6111 #ifdef JS_THREADSAFE
6112 JS_ASSERT(!cx->outstandingRequests);
6114 JS_ASSERT(CURRENT_THREAD_IS_ME(cx->thread));
6115 return reinterpret_cast<jsword>(cx->thread->id);
6118 if (!js_InitContextThread(cx)) {
6119 js_ReportOutOfMemory(cx);
6123 /* Here the GC lock is still held after js_InitContextThread took it. */
6124 JS_UNLOCK_GC(cx->runtime);
6129 JS_PUBLIC_API(jsword)
6130 JS_ClearContextThread(JSContext *cx)
6132 #ifdef JS_THREADSAFE
6134 * cx must have exited all requests it entered and, if cx is associated
6135 * with a thread, this must be called only from that thread. If not, this
6136 * is a harmless no-op.
6138 JS_ASSERT(cx->outstandingRequests == 0);
6139 JSThread *t = cx->thread;
6142 JS_ASSERT(CURRENT_THREAD_IS_ME(t));
6145 * We must not race with a GC that accesses cx->thread for all threads,
6148 JSRuntime *rt = cx->runtime;
6149 AutoLockGC lock(rt);
6151 js_ClearContextThread(cx);
6152 JS_ASSERT_IF(JS_CLIST_IS_EMPTY(&t->contextList), !t->data.requestDepth);
6155 * We can access t->id as long as the GC lock is held and we cannot race
6156 * with the GC that may delete t.
6158 return reinterpret_cast<jsword>(t->id);
6166 JS_SetGCZeal(JSContext *cx, uint8 zeal)
6168 cx->runtime->gcZeal = zeal;
6172 /************************************************************************/
6174 #if !defined(STATIC_EXPORTABLE_JS_API) && !defined(STATIC_JS_API) && defined(XP_WIN) && !defined (WINCE)
6179 * Initialization routine for the JS DLL.
6181 BOOL WINAPI DllMain (HINSTANCE hDLL, DWORD dwReason, LPVOID lpReserved)