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"
87 #include "jsstaticcheck.h"
89 #include "jswrapper.h"
90 #include "jstypedarray.h"
92 #include "jsatominlines.h"
93 #include "jscntxtinlines.h"
94 #include "jsinterpinlines.h"
95 #include "jsobjinlines.h"
96 #include "jsscopeinlines.h"
97 #include "jscntxtinlines.h"
98 #include "jsregexpinlines.h"
99 #include "jsscriptinlines.h"
100 #include "jsstrinlines.h"
101 #include "assembler/wtf/Platform.h"
104 #include "assembler/jit/ExecutableAllocator.h"
105 #include "methodjit/Logging.h"
108 #if JS_HAS_XML_SUPPORT
113 using namespace js::gc
;
115 static JSClass dummy_class
= {
117 JSCLASS_GLOBAL_FLAGS
,
118 JS_PropertyStub
, JS_PropertyStub
,
119 JS_PropertyStub
, JS_StrictPropertyStub
,
120 JS_EnumerateStub
, JS_ResolveStub
,
121 JS_ConvertStub
, NULL
,
122 JSCLASS_NO_OPTIONAL_MEMBERS
126 * This class is a version-establising barrier at the head of a VM entry or
127 * re-entry. It ensures that:
129 * - |newVersion| is the starting (default) version used for the context.
130 * - The starting version state is not an override.
131 * - Overrides in the VM session are not propagated to the caller.
135 JSContext
* const cx
;
136 JSVersion oldDefaultVersion
;
137 bool oldHasVersionOverride
;
138 JSVersion oldVersionOverride
;
140 uintN oldCompileOptions
;
142 JSVersion newVersion
;
145 explicit AutoVersionAPI(JSContext
*cx
, JSVersion newVersion
)
147 oldDefaultVersion(cx
->getDefaultVersion()),
148 oldHasVersionOverride(cx
->isVersionOverridden()),
149 oldVersionOverride(oldHasVersionOverride
? cx
->findVersion() : JSVERSION_UNKNOWN
)
151 , oldCompileOptions(cx
->getCompileOptions())
155 * Note: ANONFUNFIX in newVersion is ignored for backwards
156 * compatibility, must be set via JS_SetOptions. (Because of this, we
157 * inherit the current ANONFUNFIX setting from the options.
159 VersionSetAnonFunFix(&newVersion
, OptionsHasAnonFunFix(cx
->getCompileOptions()));
160 this->newVersion
= newVersion
;
161 cx
->clearVersionOverride();
162 cx
->setDefaultVersion(newVersion
);
166 cx
->setDefaultVersion(oldDefaultVersion
);
167 if (oldHasVersionOverride
)
168 cx
->overrideVersion(oldVersionOverride
);
170 cx
->clearVersionOverride();
171 JS_ASSERT(oldCompileOptions
== cx
->getCompileOptions());
174 /* The version that this scoped-entity establishes. */
175 JSVersion
version() const { return newVersion
; }
178 #ifdef HAVE_VA_LIST_AS_ARRAY
179 #define JS_ADDRESSOF_VA_LIST(ap) ((va_list *)(ap))
181 #define JS_ADDRESSOF_VA_LIST(ap) (&(ap))
184 #ifdef JS_USE_JSVAL_JSID_STRUCT_TYPES
185 JS_PUBLIC_DATA(jsid
) JS_DEFAULT_XML_NAMESPACE_ID
= { size_t(JSID_TYPE_DEFAULT_XML_NAMESPACE
) };
186 JS_PUBLIC_DATA(jsid
) JSID_VOID
= { size_t(JSID_TYPE_VOID
) };
187 JS_PUBLIC_DATA(jsid
) JSID_EMPTY
= { size_t(JSID_TYPE_OBJECT
) };
190 #ifdef JS_USE_JSVAL_JSID_STRUCT_TYPES
191 JS_PUBLIC_DATA(jsval
) JSVAL_NULL
= { BUILD_JSVAL(JSVAL_TAG_NULL
, 0) };
192 JS_PUBLIC_DATA(jsval
) JSVAL_ZERO
= { BUILD_JSVAL(JSVAL_TAG_INT32
, 0) };
193 JS_PUBLIC_DATA(jsval
) JSVAL_ONE
= { BUILD_JSVAL(JSVAL_TAG_INT32
, 1) };
194 JS_PUBLIC_DATA(jsval
) JSVAL_FALSE
= { BUILD_JSVAL(JSVAL_TAG_BOOLEAN
, JS_FALSE
) };
195 JS_PUBLIC_DATA(jsval
) JSVAL_TRUE
= { BUILD_JSVAL(JSVAL_TAG_BOOLEAN
, JS_TRUE
) };
196 JS_PUBLIC_DATA(jsval
) JSVAL_VOID
= { BUILD_JSVAL(JSVAL_TAG_UNDEFINED
, 0) };
199 /* Make sure that jschar is two bytes unsigned integer */
200 JS_STATIC_ASSERT((jschar
)-1 > 0);
201 JS_STATIC_ASSERT(sizeof(jschar
) == 2);
210 JS_GetNaNValue(JSContext
*cx
)
212 return Jsvalify(cx
->runtime
->NaNValue
);
216 JS_GetNegativeInfinityValue(JSContext
*cx
)
218 return Jsvalify(cx
->runtime
->negativeInfinityValue
);
222 JS_GetPositiveInfinityValue(JSContext
*cx
)
224 return Jsvalify(cx
->runtime
->positiveInfinityValue
);
228 JS_GetEmptyStringValue(JSContext
*cx
)
230 return STRING_TO_JSVAL(cx
->runtime
->emptyString
);
233 JS_PUBLIC_API(JSString
*)
234 JS_GetEmptyString(JSRuntime
*rt
)
236 JS_ASSERT(rt
->state
== JSRTS_UP
);
237 return rt
->emptyString
;
241 TryArgumentFormatter(JSContext
*cx
, const char **formatp
, JSBool fromJS
, jsval
**vpp
, va_list *app
)
244 JSArgumentFormatMap
*map
;
247 for (map
= cx
->argumentFormatMap
; map
; map
= map
->next
) {
248 if (!strncmp(format
, map
->format
, map
->length
)) {
249 *formatp
= format
+ map
->length
;
250 return map
->formatter(cx
, format
, fromJS
, vpp
, app
);
253 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_BAD_CHAR
, format
);
257 JS_PUBLIC_API(JSBool
)
258 JS_ConvertArguments(JSContext
*cx
, uintN argc
, jsval
*argv
, const char *format
, ...)
263 va_start(ap
, format
);
264 ok
= JS_ConvertArgumentsVA(cx
, argc
, argv
, format
, ap
);
269 JS_PUBLIC_API(JSBool
)
270 JS_ConvertArgumentsVA(JSContext
*cx
, uintN argc
, jsval
*argv
, const char *format
, va_list ap
)
281 assertSameCompartment(cx
, JSValueArray(argv
- 2, argc
+ 2));
284 while ((c
= *format
++) != '\0') {
291 if (sp
== argv
+ argc
) {
293 fun
= js_ValueToFunction(cx
, Valueify(&argv
[-2]), 0);
296 JS_snprintf(numBuf
, sizeof numBuf
, "%u", argc
);
297 JSAutoByteString funNameBytes
;
298 if (const char *name
= GetFunctionNameBytes(cx
, fun
, &funNameBytes
)) {
299 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_MORE_ARGS_NEEDED
,
300 name
, numBuf
, (argc
== 1) ? "" : "s");
309 *va_arg(ap
, JSBool
*) = js_ValueToBoolean(Valueify(*sp
));
312 if (!JS_ValueToUint16(cx
, *sp
, va_arg(ap
, uint16
*)))
316 if (!JS_ValueToECMAInt32(cx
, *sp
, va_arg(ap
, int32
*)))
320 if (!JS_ValueToECMAUint32(cx
, *sp
, va_arg(ap
, uint32
*)))
324 if (!JS_ValueToInt32(cx
, *sp
, va_arg(ap
, int32
*)))
328 if (!JS_ValueToNumber(cx
, *sp
, va_arg(ap
, jsdouble
*)))
332 if (!JS_ValueToNumber(cx
, *sp
, &d
))
334 *va_arg(ap
, jsdouble
*) = js_DoubleToInteger(d
);
338 str
= js_ValueToString(cx
, Valueify(*sp
));
341 *sp
= STRING_TO_JSVAL(str
);
343 const jschar
*chars
= js_GetStringChars(cx
, str
);
346 *va_arg(ap
, const jschar
**) = chars
;
348 *va_arg(ap
, JSString
**) = str
;
352 if (!js_ValueToObjectOrNull(cx
, Valueify(*sp
), &obj
))
354 *sp
= OBJECT_TO_JSVAL(obj
);
355 *va_arg(ap
, JSObject
**) = obj
;
358 obj
= js_ValueToFunctionObject(cx
, Valueify(sp
), 0);
361 *sp
= OBJECT_TO_JSVAL(obj
);
362 *va_arg(ap
, JSFunction
**) = GET_FUNCTION_PRIVATE(cx
, obj
);
365 *va_arg(ap
, jsval
*) = *sp
;
371 if (!TryArgumentFormatter(cx
, &format
, JS_TRUE
, &sp
,
372 JS_ADDRESSOF_VA_LIST(ap
))) {
375 /* NB: the formatter already updated sp, so we continue here. */
383 JS_PUBLIC_API(JSBool
)
384 JS_AddArgumentFormatter(JSContext
*cx
, const char *format
, JSArgumentFormatter formatter
)
387 JSArgumentFormatMap
**mpp
, *map
;
389 length
= strlen(format
);
390 mpp
= &cx
->argumentFormatMap
;
391 while ((map
= *mpp
) != NULL
) {
392 /* Insert before any shorter string to match before prefixes. */
393 if (map
->length
< length
)
395 if (map
->length
== length
&& !strcmp(map
->format
, format
))
399 map
= (JSArgumentFormatMap
*) cx
->malloc(sizeof *map
);
402 map
->format
= format
;
403 map
->length
= length
;
407 map
->formatter
= formatter
;
412 JS_RemoveArgumentFormatter(JSContext
*cx
, const char *format
)
415 JSArgumentFormatMap
**mpp
, *map
;
417 length
= strlen(format
);
418 mpp
= &cx
->argumentFormatMap
;
419 while ((map
= *mpp
) != NULL
) {
420 if (map
->length
== length
&& !strcmp(map
->format
, format
)) {
429 JS_PUBLIC_API(JSBool
)
430 JS_ConvertValue(JSContext
*cx
, jsval v
, JSType type
, jsval
*vp
)
438 assertSameCompartment(cx
, v
);
445 ok
= js_ValueToObjectOrNull(cx
, Valueify(v
), &obj
);
447 *vp
= OBJECT_TO_JSVAL(obj
);
449 case JSTYPE_FUNCTION
:
451 obj
= js_ValueToFunctionObject(cx
, Valueify(vp
), JSV2F_SEARCH_STACK
);
455 str
= js_ValueToString(cx
, Valueify(v
));
458 *vp
= STRING_TO_JSVAL(str
);
461 ok
= JS_ValueToNumber(cx
, v
, &d
);
463 *vp
= DOUBLE_TO_JSVAL(d
);
466 *vp
= BOOLEAN_TO_JSVAL(js_ValueToBoolean(Valueify(v
)));
470 JS_snprintf(numBuf
, sizeof numBuf
, "%d", (int)type
);
471 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_BAD_TYPE
, numBuf
);
479 JS_PUBLIC_API(JSBool
)
480 JS_ValueToObject(JSContext
*cx
, jsval v
, JSObject
**objp
)
483 assertSameCompartment(cx
, v
);
484 return js_ValueToObjectOrNull(cx
, Valueify(v
), objp
);
487 JS_PUBLIC_API(JSFunction
*)
488 JS_ValueToFunction(JSContext
*cx
, jsval v
)
491 assertSameCompartment(cx
, v
);
492 return js_ValueToFunction(cx
, Valueify(&v
), JSV2F_SEARCH_STACK
);
495 JS_PUBLIC_API(JSFunction
*)
496 JS_ValueToConstructor(JSContext
*cx
, jsval v
)
499 assertSameCompartment(cx
, v
);
500 return js_ValueToFunction(cx
, Valueify(&v
), JSV2F_SEARCH_STACK
);
503 JS_PUBLIC_API(JSString
*)
504 JS_ValueToString(JSContext
*cx
, jsval v
)
507 assertSameCompartment(cx
, v
);
508 return js_ValueToString(cx
, Valueify(v
));
511 JS_PUBLIC_API(JSString
*)
512 JS_ValueToSource(JSContext
*cx
, jsval v
)
515 assertSameCompartment(cx
, v
);
516 return js_ValueToSource(cx
, Valueify(v
));
519 JS_PUBLIC_API(JSBool
)
520 JS_ValueToNumber(JSContext
*cx
, jsval v
, jsdouble
*dp
)
523 assertSameCompartment(cx
, v
);
525 AutoValueRooter
tvr(cx
, Valueify(v
));
526 return ValueToNumber(cx
, tvr
.value(), dp
);
529 JS_PUBLIC_API(JSBool
)
530 JS_DoubleIsInt32(jsdouble d
, jsint
*ip
)
532 return JSDOUBLE_IS_INT32(d
, (int32_t *)ip
);
535 JS_PUBLIC_API(JSBool
)
536 JS_ValueToECMAInt32(JSContext
*cx
, jsval v
, int32
*ip
)
539 assertSameCompartment(cx
, v
);
541 AutoValueRooter
tvr(cx
, Valueify(v
));
542 return ValueToECMAInt32(cx
, tvr
.value(), (int32_t *)ip
);
545 JS_PUBLIC_API(JSBool
)
546 JS_ValueToECMAUint32(JSContext
*cx
, jsval v
, uint32
*ip
)
549 assertSameCompartment(cx
, v
);
551 AutoValueRooter
tvr(cx
, Valueify(v
));
552 return ValueToECMAUint32(cx
, tvr
.value(), (uint32_t *)ip
);
555 JS_PUBLIC_API(JSBool
)
556 JS_ValueToInt32(JSContext
*cx
, jsval v
, int32
*ip
)
559 assertSameCompartment(cx
, v
);
561 AutoValueRooter
tvr(cx
, Valueify(v
));
562 return ValueToInt32(cx
, tvr
.value(), (int32_t *)ip
);
565 JS_PUBLIC_API(JSBool
)
566 JS_ValueToUint16(JSContext
*cx
, jsval v
, uint16
*ip
)
569 assertSameCompartment(cx
, v
);
571 AutoValueRooter
tvr(cx
, Valueify(v
));
572 return ValueToUint16(cx
, tvr
.value(), (uint16_t *)ip
);
575 JS_PUBLIC_API(JSBool
)
576 JS_ValueToBoolean(JSContext
*cx
, jsval v
, JSBool
*bp
)
579 assertSameCompartment(cx
, v
);
580 *bp
= js_ValueToBoolean(Valueify(v
));
584 JS_PUBLIC_API(JSType
)
585 JS_TypeOfValue(JSContext
*cx
, jsval v
)
588 assertSameCompartment(cx
, v
);
589 return TypeOfValue(cx
, Valueify(v
));
592 JS_PUBLIC_API(const char *)
593 JS_GetTypeName(JSContext
*cx
, JSType type
)
595 if ((uintN
)type
>= (uintN
)JSTYPE_LIMIT
)
597 return JS_TYPE_STR(type
);
600 JS_PUBLIC_API(JSBool
)
601 JS_StrictlyEqual(JSContext
*cx
, jsval v1
, jsval v2
, JSBool
*equal
)
603 assertSameCompartment(cx
, v1
, v2
);
604 return StrictlyEqual(cx
, Valueify(v1
), Valueify(v2
), equal
);
607 JS_PUBLIC_API(JSBool
)
608 JS_SameValue(JSContext
*cx
, jsval v1
, jsval v2
, JSBool
*same
)
610 assertSameCompartment(cx
, v1
, v2
);
611 return SameValue(cx
, Valueify(v1
), Valueify(v2
), same
);
614 /************************************************************************/
617 * Has a new runtime ever been created? This flag is used to detect unsafe
618 * changes to js_CStringsAreUTF8 after a runtime has been created, and to
619 * ensure that "first checks" on runtime creation are run only once.
622 static JSBool js_NewRuntimeWasCalled
= JS_FALSE
;
625 JSRuntime::JSRuntime()
626 : gcChunkAllocator(&defaultGCChunkAllocator
)
628 /* Initialize infallibly first, so we can goto bad and JS_DestroyRuntime. */
629 JS_INIT_CLIST(&contextList
);
630 JS_INIT_CLIST(&trapList
);
631 JS_INIT_CLIST(&watchPointList
);
635 JSRuntime::init(uint32 maxbytes
)
637 #ifdef JS_METHODJIT_SPEW
642 functionMeterFilename
= getenv("JS_FUNCTION_STATFILE");
643 if (functionMeterFilename
) {
644 if (!methodReadBarrierCountMap
.init())
646 if (!unjoinedFunctionCountMap
.init())
649 propTreeStatFilename
= getenv("JS_PROPTREE_STATFILE");
650 propTreeDumpFilename
= getenv("JS_PROPTREE_DUMPFILE");
653 if (!(atomsCompartment
= js_new
<JSCompartment
>(this)) ||
654 !atomsCompartment
->init() ||
655 !compartments
.append(atomsCompartment
)) {
659 if (!js_InitGC(this, maxbytes
) || !js_InitAtomState(this))
662 wrapObjectCallback
= js::TransparentObjectWrapper
;
665 /* this is asymmetric with JS_ShutDown: */
666 if (!js_SetupLocks(8, 16))
668 rtLock
= JS_NEW_LOCK();
671 stateChange
= JS_NEW_CONDVAR(gcLock
);
674 debuggerLock
= JS_NEW_LOCK();
679 debugMode
= JS_FALSE
;
681 return js_InitThreads(this);
684 JSRuntime::~JSRuntime()
687 /* Don't hurt everyone in leaky ol' Mozilla with a fatal JS_ASSERT! */
688 if (!JS_CLIST_IS_EMPTY(&contextList
)) {
689 JSContext
*cx
, *iter
= NULL
;
691 while ((cx
= js_ContextIterator(this, JS_TRUE
, &iter
)) != NULL
) {
693 "JS API usage error: found live context at %p\n",
698 "JS API usage error: %u context%s left in runtime upon JS_DestroyRuntime.\n",
699 cxcount
, (cxcount
== 1) ? "" : "s");
703 js_FinishThreads(this);
704 js_FreeRuntimeScriptState(this);
705 js_FinishAtomState(this);
710 JS_DESTROY_LOCK(gcLock
);
712 JS_DESTROY_CONDVAR(gcDone
);
714 JS_DESTROY_CONDVAR(requestDone
);
716 JS_DESTROY_LOCK(rtLock
);
718 JS_DESTROY_CONDVAR(stateChange
);
720 JS_DESTROY_LOCK(debuggerLock
);
724 JS_PUBLIC_API(JSRuntime
*)
725 JS_NewRuntime(uint32 maxbytes
)
728 if (!js_NewRuntimeWasCalled
) {
730 * This code asserts that the numbers associated with the error names
731 * in jsmsg.def are monotonically increasing. It uses values for the
732 * error names enumerated in jscntxt.c. It's not a compile-time check
733 * but it's better than nothing.
736 #define MSG_DEF(name, number, count, exception, format) \
737 JS_ASSERT(name == errorNumber++);
741 #define MSG_DEF(name, number, count, exception, format) \
743 uintN numfmtspecs = 0; \
745 for (fmt = format; *fmt != '\0'; fmt++) { \
746 if (*fmt == '{' && isdigit(fmt[1])) \
749 JS_ASSERT(count == numfmtspecs); \
754 js_NewRuntimeWasCalled
= JS_TRUE
;
758 void *mem
= js_calloc(sizeof(JSRuntime
));
762 JSRuntime
*rt
= new (mem
) JSRuntime();
763 if (!rt
->init(maxbytes
)) {
764 JS_DestroyRuntime(rt
);
772 JS_DestroyRuntime(JSRuntime
*rt
)
780 namespace reprmeter
{
781 extern void js_DumpReprMeter();
793 extern void js_DumpOpMeters();
798 reprmeter::js_DumpReprMeter();
807 JS_PUBLIC_API(void *)
808 JS_GetRuntimePrivate(JSRuntime
*rt
)
814 JS_SetRuntimePrivate(JSRuntime
*rt
, void *data
)
821 StartRequest(JSContext
*cx
)
823 JSThread
*t
= cx
->thread
;
824 JS_ASSERT(CURRENT_THREAD_IS_ME(t
));
826 if (t
->data
.requestDepth
) {
827 t
->data
.requestDepth
++;
829 JSRuntime
*rt
= cx
->runtime
;
832 /* Wait until the GC is finished. */
833 if (rt
->gcThread
!= cx
->thread
) {
835 JS_AWAIT_GC_DONE(rt
);
838 /* Indicate that a request is running. */
840 t
->data
.requestDepth
= 1;
843 * Adjust rt->interruptCounter to reflect any interrupts added while the
844 * thread was suspended.
846 if (t
->data
.interruptFlags
)
847 JS_ATOMIC_INCREMENT(&rt
->interruptCounter
);
849 if (rt
->requestCount
== 1 && rt
->activityCallback
)
850 rt
->activityCallback(rt
->activityCallbackArg
, true);
855 StopRequest(JSContext
*cx
)
857 JSThread
*t
= cx
->thread
;
858 JS_ASSERT(CURRENT_THREAD_IS_ME(t
));
859 JS_ASSERT(t
->data
.requestDepth
!= 0);
860 if (t
->data
.requestDepth
!= 1) {
861 t
->data
.requestDepth
--;
863 LeaveTrace(cx
); /* for GC safety */
865 t
->data
.conservativeGC
.updateForRequestEnd(t
->suspendCount
);
867 /* Lock before clearing to interlock with ClaimScope, in jslock.c. */
868 JSRuntime
*rt
= cx
->runtime
;
871 t
->data
.requestDepth
= 0;
874 * Adjust rt->interruptCounter to reflect any interrupts added while the
875 * thread still had active requests.
877 if (t
->data
.interruptFlags
)
878 JS_ATOMIC_DECREMENT(&rt
->interruptCounter
);
880 /* Give the GC a chance to run if this was the last request running. */
881 JS_ASSERT(rt
->requestCount
> 0);
883 if (rt
->requestCount
== 0) {
884 JS_NOTIFY_REQUEST_DONE(rt
);
885 if (rt
->activityCallback
)
886 rt
->activityCallback(rt
->activityCallbackArg
, false);
890 #endif /* JS_THREADSAFE */
893 JS_BeginRequest(JSContext
*cx
)
896 cx
->outstandingRequests
++;
902 JS_EndRequest(JSContext
*cx
)
905 JS_ASSERT(cx
->outstandingRequests
!= 0);
906 cx
->outstandingRequests
--;
911 /* Yield to pending GC operations, regardless of request depth */
913 JS_YieldRequest(JSContext
*cx
)
917 JS_ResumeRequest(cx
, JS_SuspendRequest(cx
));
921 JS_PUBLIC_API(jsrefcount
)
922 JS_SuspendRequest(JSContext
*cx
)
925 JSThread
*t
= cx
->thread
;
926 JS_ASSERT(CURRENT_THREAD_IS_ME(t
));
928 jsrefcount saveDepth
= t
->data
.requestDepth
;
933 t
->data
.requestDepth
= 1;
942 JS_ResumeRequest(JSContext
*cx
, jsrefcount saveDepth
)
945 JSThread
*t
= cx
->thread
;
946 JS_ASSERT(CURRENT_THREAD_IS_ME(t
));
949 JS_ASSERT(saveDepth
>= 1);
950 JS_ASSERT(!t
->data
.requestDepth
);
951 JS_ASSERT(t
->suspendCount
);
953 t
->data
.requestDepth
= saveDepth
;
958 JS_PUBLIC_API(JSBool
)
959 JS_IsInRequest(JSContext
*cx
)
962 JS_ASSERT(CURRENT_THREAD_IS_ME(cx
->thread
));
963 return JS_THREAD_DATA(cx
)->requestDepth
!= 0;
970 JS_Lock(JSRuntime
*rt
)
976 JS_Unlock(JSRuntime
*rt
)
978 JS_UNLOCK_RUNTIME(rt
);
981 JS_PUBLIC_API(JSContextCallback
)
982 JS_SetContextCallback(JSRuntime
*rt
, JSContextCallback cxCallback
)
984 JSContextCallback old
;
986 old
= rt
->cxCallback
;
987 rt
->cxCallback
= cxCallback
;
991 JS_PUBLIC_API(JSContext
*)
992 JS_NewContext(JSRuntime
*rt
, size_t stackChunkSize
)
994 return js_NewContext(rt
, stackChunkSize
);
998 JS_DestroyContext(JSContext
*cx
)
1000 js_DestroyContext(cx
, JSDCM_FORCE_GC
);
1004 JS_DestroyContextNoGC(JSContext
*cx
)
1006 js_DestroyContext(cx
, JSDCM_NO_GC
);
1010 JS_DestroyContextMaybeGC(JSContext
*cx
)
1012 js_DestroyContext(cx
, JSDCM_MAYBE_GC
);
1015 JS_PUBLIC_API(void *)
1016 JS_GetContextPrivate(JSContext
*cx
)
1022 JS_SetContextPrivate(JSContext
*cx
, void *data
)
1027 JS_PUBLIC_API(JSRuntime
*)
1028 JS_GetRuntime(JSContext
*cx
)
1033 JS_PUBLIC_API(JSContext
*)
1034 JS_ContextIterator(JSRuntime
*rt
, JSContext
**iterp
)
1036 return js_ContextIterator(rt
, JS_TRUE
, iterp
);
1039 JS_PUBLIC_API(JSVersion
)
1040 JS_GetVersion(JSContext
*cx
)
1042 return VersionNumber(cx
->findVersion());
1045 JS_PUBLIC_API(JSVersion
)
1046 JS_SetVersion(JSContext
*cx
, JSVersion newVersion
)
1048 JS_ASSERT(VersionIsKnown(newVersion
));
1049 JS_ASSERT(!VersionHasFlags(newVersion
));
1050 JSVersion newVersionNumber
= newVersion
;
1053 uintN coptsBefore
= cx
->getCompileOptions();
1055 JSVersion oldVersion
= cx
->findVersion();
1056 JSVersion oldVersionNumber
= VersionNumber(oldVersion
);
1057 if (oldVersionNumber
== newVersionNumber
)
1058 return oldVersionNumber
; /* No override actually occurs! */
1060 /* We no longer support 1.4 or below. */
1061 if (newVersionNumber
!= JSVERSION_DEFAULT
&& newVersionNumber
<= JSVERSION_1_4
)
1062 return oldVersionNumber
;
1064 VersionCopyFlags(&newVersion
, oldVersion
);
1065 cx
->maybeOverrideVersion(newVersion
);
1066 JS_ASSERT(cx
->getCompileOptions() == coptsBefore
);
1067 return oldVersionNumber
;
1070 static struct v2smap
{
1074 {JSVERSION_1_0
, "1.0"},
1075 {JSVERSION_1_1
, "1.1"},
1076 {JSVERSION_1_2
, "1.2"},
1077 {JSVERSION_1_3
, "1.3"},
1078 {JSVERSION_1_4
, "1.4"},
1079 {JSVERSION_ECMA_3
, "ECMAv3"},
1080 {JSVERSION_1_5
, "1.5"},
1081 {JSVERSION_1_6
, "1.6"},
1082 {JSVERSION_1_7
, "1.7"},
1083 {JSVERSION_1_8
, "1.8"},
1084 {JSVERSION_ECMA_5
, "ECMAv5"},
1085 {JSVERSION_DEFAULT
, js_default_str
},
1086 {JSVERSION_UNKNOWN
, NULL
}, /* must be last, NULL is sentinel */
1089 JS_PUBLIC_API(const char *)
1090 JS_VersionToString(JSVersion version
)
1094 for (i
= 0; v2smap
[i
].string
; i
++)
1095 if (v2smap
[i
].version
== version
)
1096 return v2smap
[i
].string
;
1100 JS_PUBLIC_API(JSVersion
)
1101 JS_StringToVersion(const char *string
)
1105 for (i
= 0; v2smap
[i
].string
; i
++)
1106 if (strcmp(v2smap
[i
].string
, string
) == 0)
1107 return v2smap
[i
].version
;
1108 return JSVERSION_UNKNOWN
;
1111 JS_PUBLIC_API(uint32
)
1112 JS_GetOptions(JSContext
*cx
)
1115 * Can't check option/version synchronization here.
1116 * We may have been synchronized with a script version that was formerly on
1117 * the stack, but has now been popped.
1119 return cx
->allOptions();
1123 SetOptionsCommon(JSContext
*cx
, uintN options
)
1125 JS_ASSERT((options
& JSALLOPTION_MASK
) == options
);
1126 uintN oldopts
= cx
->allOptions();
1127 uintN newropts
= options
& JSRUNOPTION_MASK
;
1128 uintN newcopts
= options
& JSCOMPILEOPTION_MASK
;
1129 cx
->setRunOptions(newropts
);
1130 cx
->setCompileOptions(newcopts
);
1131 cx
->updateJITEnabled();
1135 JS_PUBLIC_API(uint32
)
1136 JS_SetOptions(JSContext
*cx
, uint32 options
)
1138 AutoLockGC
lock(cx
->runtime
);
1139 return SetOptionsCommon(cx
, options
);
1142 JS_PUBLIC_API(uint32
)
1143 JS_ToggleOptions(JSContext
*cx
, uint32 options
)
1145 AutoLockGC
lock(cx
->runtime
);
1146 uintN oldopts
= cx
->allOptions();
1147 uintN newopts
= oldopts
^ options
;
1148 return SetOptionsCommon(cx
, newopts
);
1151 JS_PUBLIC_API(const char *)
1152 JS_GetImplementationVersion(void)
1154 return "JavaScript-C 1.8.0 pre-release 1 2007-10-03";
1157 JS_PUBLIC_API(JSCompartmentCallback
)
1158 JS_SetCompartmentCallback(JSRuntime
*rt
, JSCompartmentCallback callback
)
1160 JSCompartmentCallback old
= rt
->compartmentCallback
;
1161 rt
->compartmentCallback
= callback
;
1165 JS_PUBLIC_API(JSWrapObjectCallback
)
1166 JS_SetWrapObjectCallbacks(JSRuntime
*rt
,
1167 JSWrapObjectCallback callback
,
1168 JSPreWrapCallback precallback
)
1170 JSWrapObjectCallback old
= rt
->wrapObjectCallback
;
1171 rt
->wrapObjectCallback
= callback
;
1172 rt
->preWrapObjectCallback
= precallback
;
1176 JS_PUBLIC_API(JSCrossCompartmentCall
*)
1177 JS_EnterCrossCompartmentCall(JSContext
*cx
, JSObject
*target
)
1182 AutoCompartment
*call
= js_new
<AutoCompartment
>(cx
, target
);
1185 if (!call
->enter()) {
1189 return reinterpret_cast<JSCrossCompartmentCall
*>(call
);
1192 JS_PUBLIC_API(JSCrossCompartmentCall
*)
1193 JS_EnterCrossCompartmentCallScript(JSContext
*cx
, JSScript
*target
)
1198 JSObject
*scriptObject
= target
->u
.object
;
1199 if (!scriptObject
) {
1200 SwitchToCompartment
sc(cx
, target
->compartment
);
1201 scriptObject
= JS_NewGlobalObject(cx
, &dummy_class
);
1205 return JS_EnterCrossCompartmentCall(cx
, scriptObject
);
1209 JS_LeaveCrossCompartmentCall(JSCrossCompartmentCall
*call
)
1211 AutoCompartment
*realcall
= reinterpret_cast<AutoCompartment
*>(call
);
1212 CHECK_REQUEST(realcall
->context
);
1214 js_delete(realcall
);
1218 JSAutoEnterCompartment::enter(JSContext
*cx
, JSObject
*target
)
1221 if (cx
->compartment
== target
->getCompartment()) {
1222 call
= reinterpret_cast<JSCrossCompartmentCall
*>(1);
1225 call
= JS_EnterCrossCompartmentCall(cx
, target
);
1226 return call
!= NULL
;
1230 JSAutoEnterCompartment::enter(JSContext
*cx
, JSScript
*target
)
1233 if (cx
->compartment
== target
->compartment
) {
1234 call
= reinterpret_cast<JSCrossCompartmentCall
*>(1);
1237 call
= JS_EnterCrossCompartmentCallScript(cx
, target
);
1238 return call
!= NULL
;
1242 JSAutoEnterCompartment::enterAndIgnoreErrors(JSContext
*cx
, JSObject
*target
)
1244 (void) enter(cx
, target
);
1247 JS_PUBLIC_API(void *)
1248 JS_SetCompartmentPrivate(JSContext
*cx
, JSCompartment
*compartment
, void *data
)
1251 void *old
= compartment
->data
;
1252 compartment
->data
= data
;
1256 JS_PUBLIC_API(void *)
1257 JS_GetCompartmentPrivate(JSContext
*cx
, JSCompartment
*compartment
)
1260 return compartment
->data
;
1263 JS_PUBLIC_API(JSBool
)
1264 JS_WrapObject(JSContext
*cx
, JSObject
**objp
)
1267 return cx
->compartment
->wrap(cx
, objp
);
1270 JS_PUBLIC_API(JSBool
)
1271 JS_WrapValue(JSContext
*cx
, jsval
*vp
)
1274 return cx
->compartment
->wrap(cx
, Valueify(vp
));
1277 JS_PUBLIC_API(JSObject
*)
1278 JS_TransplantObject(JSContext
*cx
, JSObject
*origobj
, JSObject
*target
)
1280 // This function is called when an object moves between two
1281 // different compartments. In that case, we need to "move" the
1282 // window from origobj's compartment to target's compartment.
1283 JSCompartment
*destination
= target
->getCompartment();
1284 WrapperMap
&map
= destination
->crossCompartmentWrappers
;
1285 Value origv
= ObjectValue(*origobj
);
1288 if (origobj
->getCompartment() == destination
) {
1289 // If the original object is in the same compartment as the
1290 // destination, then we know that we won't find wrapper in the
1291 // destination's cross compartment map and that the same
1292 // object will continue to work. Note the rare case where
1293 // |origobj == target|. In that case, we can just treat this
1294 // as a same compartment navigation. The effect is to clear
1295 // all of the wrappers and their holders if they have
1296 // them. This would be cleaner as a separate API.
1297 if (origobj
!= target
&& !origobj
->swap(cx
, target
))
1300 } else if (WrapperMap::Ptr p
= map
.lookup(origv
)) {
1301 // There might already be a wrapper for the original object in
1302 // the new compartment. If there is, make it the primary outer
1303 // window proxy around the inner (accomplished by swapping
1304 // target's innards with the old, possibly security wrapper,
1306 obj
= &p
->value
.toObject();
1308 if (!obj
->swap(cx
, target
))
1311 // Otherwise, this is going to be our outer window proxy in
1312 // the new compartment.
1316 // Now, iterate through other scopes looking for references to the
1317 // old outer window. They need to be updated to point at the new
1318 // outer window. They also might transition between different
1319 // types of security wrappers based on whether the new compartment
1320 // is same origin with them.
1321 Value targetv
= ObjectValue(*obj
);
1322 WrapperVector
&vector
= cx
->runtime
->compartments
;
1323 AutoValueVector
toTransplant(cx
);
1324 toTransplant
.reserve(vector
.length());
1326 for (JSCompartment
**p
= vector
.begin(), **end
= vector
.end(); p
!= end
; ++p
) {
1327 WrapperMap
&pmap
= (*p
)->crossCompartmentWrappers
;
1328 if (WrapperMap::Ptr wp
= pmap
.lookup(origv
)) {
1329 // We found a wrapper. Remember and root it.
1330 toTransplant
.append(wp
->value
);
1334 for (Value
*begin
= toTransplant
.begin(), *end
= toTransplant
.end(); begin
!= end
; ++begin
) {
1335 JSObject
*wobj
= &begin
->toObject();
1336 JSCompartment
*wcompartment
= wobj
->compartment();
1337 WrapperMap
&pmap
= wcompartment
->crossCompartmentWrappers
;
1338 JS_ASSERT(pmap
.lookup(origv
));
1341 // First, we wrap it in the new compartment. This will return
1343 AutoCompartment
ac(cx
, wobj
);
1344 JSObject
*tobj
= obj
;
1345 if (!ac
.enter() || !wcompartment
->wrap(cx
, &tobj
))
1348 // Now, because we need to maintain object identity, we do a
1349 // brain transplant on the old object. At the same time, we
1350 // update the entry in the compartment's wrapper map to point
1351 // to the old wrapper.
1352 JS_ASSERT(tobj
!= wobj
);
1353 if (!wobj
->swap(cx
, tobj
))
1355 pmap
.put(targetv
, ObjectValue(*wobj
));
1358 // Lastly, update the original object to point to the new one.
1359 if (origobj
->getCompartment() != destination
) {
1360 AutoCompartment
ac(cx
, origobj
);
1361 JSObject
*tobj
= obj
;
1362 if (!ac
.enter() || !JS_WrapObject(cx
, &tobj
))
1364 if (!origobj
->swap(cx
, tobj
))
1366 origobj
->getCompartment()->crossCompartmentWrappers
.put(targetv
, origv
);
1372 JS_PUBLIC_API(JSObject
*)
1373 JS_GetGlobalObject(JSContext
*cx
)
1375 return cx
->globalObject
;
1379 JS_SetGlobalObject(JSContext
*cx
, JSObject
*obj
)
1383 cx
->globalObject
= obj
;
1385 cx
->resetCompartment();
1388 class AutoResolvingEntry
{
1390 AutoResolvingEntry() : entry(NULL
) {}
1393 * Returns false on error. But N.B. if obj[id] was already being resolved,
1394 * this is a no-op, and we silently treat that as success.
1396 bool start(JSContext
*cx
, JSObject
*obj
, jsid id
, uint32 flag
) {
1402 bool ok
= !!js_StartResolving(cx
, &key
, flag
, &entry
);
1403 JS_ASSERT_IF(!ok
, !entry
);
1407 ~AutoResolvingEntry() {
1409 js_StopResolving(cx
, &key
, flag
, NULL
, 0);
1416 JSResolvingEntry
*entry
;
1420 js_InitFunctionAndObjectClasses(JSContext
*cx
, JSObject
*obj
)
1422 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
1423 JSObject
*fun_proto
, *obj_proto
;
1425 /* If cx has no global object, use obj so prototypes can be found. */
1426 if (!cx
->globalObject
)
1427 JS_SetGlobalObject(cx
, obj
);
1429 /* Record Function and Object in cx->resolvingTable. */
1430 AutoResolvingEntry e1
, e2
;
1431 JSAtom
**classAtoms
= cx
->runtime
->atomState
.classAtoms
;
1432 if (!e1
.start(cx
, obj
, ATOM_TO_JSID(classAtoms
[JSProto_Function
]), JSRESFLAG_LOOKUP
) ||
1433 !e2
.start(cx
, obj
, ATOM_TO_JSID(classAtoms
[JSProto_Object
]), JSRESFLAG_LOOKUP
)) {
1437 /* Initialize the function class first so constructors can be made. */
1438 if (!js_GetClassPrototype(cx
, obj
, JSProto_Function
, &fun_proto
))
1441 fun_proto
= js_InitFunctionClass(cx
, obj
);
1447 ctor
= JS_GetConstructor(cx
, fun_proto
);
1450 obj
->defineProperty(cx
, ATOM_TO_JSID(CLASS_ATOM(cx
, Function
)),
1451 ObjectValue(*ctor
), 0, 0, 0);
1454 /* Initialize the object class next so Object.prototype works. */
1455 if (!js_GetClassPrototype(cx
, obj
, JSProto_Object
, &obj_proto
))
1458 obj_proto
= js_InitObjectClass(cx
, obj
);
1462 /* Function.prototype and the global object delegate to Object.prototype. */
1463 fun_proto
->setProto(obj_proto
);
1464 if (!obj
->getProto())
1465 obj
->setProto(obj_proto
);
1470 JS_PUBLIC_API(JSBool
)
1471 JS_InitStandardClasses(JSContext
*cx
, JSObject
*obj
)
1473 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
1477 * JS_SetGlobalObject might or might not change cx's compartment, so call
1478 * it before assertSameCompartment. (The API contract is that *after* this,
1479 * cx and obj must be in the same compartment.)
1481 if (!cx
->globalObject
)
1482 JS_SetGlobalObject(cx
, obj
);
1483 assertSameCompartment(cx
, obj
);
1485 /* Define a top-level property 'undefined' with the undefined value. */
1486 JSAtom
*atom
= cx
->runtime
->atomState
.typeAtoms
[JSTYPE_VOID
];
1487 if (!obj
->defineProperty(cx
, ATOM_TO_JSID(atom
), UndefinedValue(),
1488 PropertyStub
, StrictPropertyStub
,
1489 JSPROP_PERMANENT
| JSPROP_READONLY
)) {
1493 /* Function and Object require cooperative bootstrapping magic. */
1494 if (!js_InitFunctionAndObjectClasses(cx
, obj
))
1497 /* Initialize the rest of the standard objects and functions. */
1498 return js_InitArrayClass(cx
, obj
) &&
1499 js_InitBooleanClass(cx
, obj
) &&
1500 js_InitExceptionClasses(cx
, obj
) &&
1501 js_InitMathClass(cx
, obj
) &&
1502 js_InitNumberClass(cx
, obj
) &&
1503 js_InitJSONClass(cx
, obj
) &&
1504 js_InitRegExpClass(cx
, obj
) &&
1505 js_InitStringClass(cx
, obj
) &&
1506 js_InitTypedArrayClasses(cx
, obj
) &&
1507 #if JS_HAS_XML_SUPPORT
1508 js_InitXMLClasses(cx
, obj
) &&
1510 #if JS_HAS_GENERATORS
1511 js_InitIteratorClasses(cx
, obj
) &&
1513 js_InitDateClass(cx
, obj
) &&
1514 js_InitProxyClass(cx
, obj
);
1517 #define CLASP(name) (&js_##name##Class)
1518 #define TYPED_ARRAY_CLASP(type) (&TypedArray::fastClasses[TypedArray::type])
1519 #define EAGER_ATOM(name) ATOM_OFFSET(name), NULL
1520 #define EAGER_CLASS_ATOM(name) CLASS_ATOM_OFFSET(name), NULL
1521 #define EAGER_ATOM_AND_CLASP(name) EAGER_CLASS_ATOM(name), CLASP(name)
1522 #define LAZY_ATOM(name) ATOM_OFFSET(lazy.name), js_##name##_str
1524 typedef struct JSStdName
{
1526 size_t atomOffset
; /* offset of atom pointer in JSAtomState */
1527 const char *name
; /* null if atom is pre-pinned, else name */
1532 StdNameToAtom(JSContext
*cx
, JSStdName
*stdn
)
1538 offset
= stdn
->atomOffset
;
1539 atom
= OFFSET_TO_ATOM(cx
->runtime
, offset
);
1543 atom
= js_Atomize(cx
, name
, strlen(name
), ATOM_PINNED
);
1544 OFFSET_TO_ATOM(cx
->runtime
, offset
) = atom
;
1551 * Table of class initializers and their atom offsets in rt->atomState.
1552 * If you add a "standard" class, remember to update this table.
1554 static JSStdName standard_class_atoms
[] = {
1555 {js_InitFunctionAndObjectClasses
, EAGER_ATOM_AND_CLASP(Function
)},
1556 {js_InitFunctionAndObjectClasses
, EAGER_ATOM_AND_CLASP(Object
)},
1557 {js_InitArrayClass
, EAGER_ATOM_AND_CLASP(Array
)},
1558 {js_InitBooleanClass
, EAGER_ATOM_AND_CLASP(Boolean
)},
1559 {js_InitDateClass
, EAGER_ATOM_AND_CLASP(Date
)},
1560 {js_InitMathClass
, EAGER_ATOM_AND_CLASP(Math
)},
1561 {js_InitNumberClass
, EAGER_ATOM_AND_CLASP(Number
)},
1562 {js_InitStringClass
, EAGER_ATOM_AND_CLASP(String
)},
1563 {js_InitExceptionClasses
, EAGER_ATOM_AND_CLASP(Error
)},
1564 {js_InitRegExpClass
, EAGER_ATOM_AND_CLASP(RegExp
)},
1565 #if JS_HAS_XML_SUPPORT
1566 {js_InitXMLClass
, EAGER_ATOM_AND_CLASP(XML
)},
1567 {js_InitNamespaceClass
, EAGER_ATOM_AND_CLASP(Namespace
)},
1568 {js_InitQNameClass
, EAGER_ATOM_AND_CLASP(QName
)},
1570 #if JS_HAS_GENERATORS
1571 {js_InitIteratorClasses
, EAGER_ATOM_AND_CLASP(StopIteration
)},
1573 {js_InitJSONClass
, EAGER_ATOM_AND_CLASP(JSON
)},
1574 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(ArrayBuffer
), &js::ArrayBuffer::jsclass
},
1575 {NULL
, 0, NULL
, NULL
}
1579 * Table of top-level function and constant names and their init functions.
1580 * If you add a "standard" global function or property, remember to update
1583 static JSStdName standard_class_names
[] = {
1584 {js_InitObjectClass
, EAGER_ATOM(eval
), CLASP(Object
)},
1586 /* Global properties and functions defined by the Number class. */
1587 {js_InitNumberClass
, EAGER_ATOM(NaN
), CLASP(Number
)},
1588 {js_InitNumberClass
, EAGER_ATOM(Infinity
), CLASP(Number
)},
1589 {js_InitNumberClass
, LAZY_ATOM(isNaN
), CLASP(Number
)},
1590 {js_InitNumberClass
, LAZY_ATOM(isFinite
), CLASP(Number
)},
1591 {js_InitNumberClass
, LAZY_ATOM(parseFloat
), CLASP(Number
)},
1592 {js_InitNumberClass
, LAZY_ATOM(parseInt
), CLASP(Number
)},
1594 /* String global functions. */
1595 {js_InitStringClass
, LAZY_ATOM(escape
), CLASP(String
)},
1596 {js_InitStringClass
, LAZY_ATOM(unescape
), CLASP(String
)},
1597 {js_InitStringClass
, LAZY_ATOM(decodeURI
), CLASP(String
)},
1598 {js_InitStringClass
, LAZY_ATOM(encodeURI
), CLASP(String
)},
1599 {js_InitStringClass
, LAZY_ATOM(decodeURIComponent
), CLASP(String
)},
1600 {js_InitStringClass
, LAZY_ATOM(encodeURIComponent
), CLASP(String
)},
1602 {js_InitStringClass
, LAZY_ATOM(uneval
), CLASP(String
)},
1605 /* Exception constructors. */
1606 {js_InitExceptionClasses
, EAGER_CLASS_ATOM(Error
), CLASP(Error
)},
1607 {js_InitExceptionClasses
, EAGER_CLASS_ATOM(InternalError
), CLASP(Error
)},
1608 {js_InitExceptionClasses
, EAGER_CLASS_ATOM(EvalError
), CLASP(Error
)},
1609 {js_InitExceptionClasses
, EAGER_CLASS_ATOM(RangeError
), CLASP(Error
)},
1610 {js_InitExceptionClasses
, EAGER_CLASS_ATOM(ReferenceError
), CLASP(Error
)},
1611 {js_InitExceptionClasses
, EAGER_CLASS_ATOM(SyntaxError
), CLASP(Error
)},
1612 {js_InitExceptionClasses
, EAGER_CLASS_ATOM(TypeError
), CLASP(Error
)},
1613 {js_InitExceptionClasses
, EAGER_CLASS_ATOM(URIError
), CLASP(Error
)},
1615 #if JS_HAS_XML_SUPPORT
1616 {js_InitXMLClass
, LAZY_ATOM(XMLList
), CLASP(XML
)},
1617 {js_InitXMLClass
, LAZY_ATOM(isXMLName
), CLASP(XML
)},
1620 #if JS_HAS_GENERATORS
1621 {js_InitIteratorClasses
, EAGER_ATOM_AND_CLASP(Iterator
)},
1622 {js_InitIteratorClasses
, EAGER_ATOM_AND_CLASP(Generator
)},
1626 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(ArrayBuffer
), &js::ArrayBuffer::jsclass
},
1627 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(Int8Array
), TYPED_ARRAY_CLASP(TYPE_INT8
)},
1628 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(Uint8Array
), TYPED_ARRAY_CLASP(TYPE_UINT8
)},
1629 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(Int16Array
), TYPED_ARRAY_CLASP(TYPE_INT16
)},
1630 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(Uint16Array
), TYPED_ARRAY_CLASP(TYPE_UINT16
)},
1631 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(Int32Array
), TYPED_ARRAY_CLASP(TYPE_INT32
)},
1632 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(Uint32Array
), TYPED_ARRAY_CLASP(TYPE_UINT32
)},
1633 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(Float32Array
), TYPED_ARRAY_CLASP(TYPE_FLOAT32
)},
1634 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(Float64Array
), TYPED_ARRAY_CLASP(TYPE_FLOAT64
)},
1635 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(Uint8ClampedArray
),
1636 TYPED_ARRAY_CLASP(TYPE_UINT8_CLAMPED
)},
1638 {js_InitProxyClass
, EAGER_ATOM_AND_CLASP(Proxy
)},
1640 {NULL
, 0, NULL
, NULL
}
1643 static JSStdName object_prototype_names
[] = {
1644 /* Object.prototype properties (global delegates to Object.prototype). */
1645 {js_InitObjectClass
, EAGER_ATOM(proto
), CLASP(Object
)},
1647 {js_InitObjectClass
, EAGER_ATOM(toSource
), CLASP(Object
)},
1649 {js_InitObjectClass
, EAGER_ATOM(toString
), CLASP(Object
)},
1650 {js_InitObjectClass
, EAGER_ATOM(toLocaleString
), CLASP(Object
)},
1651 {js_InitObjectClass
, EAGER_ATOM(valueOf
), CLASP(Object
)},
1652 #if JS_HAS_OBJ_WATCHPOINT
1653 {js_InitObjectClass
, LAZY_ATOM(watch
), CLASP(Object
)},
1654 {js_InitObjectClass
, LAZY_ATOM(unwatch
), CLASP(Object
)},
1656 {js_InitObjectClass
, LAZY_ATOM(hasOwnProperty
), CLASP(Object
)},
1657 {js_InitObjectClass
, LAZY_ATOM(isPrototypeOf
), CLASP(Object
)},
1658 {js_InitObjectClass
, LAZY_ATOM(propertyIsEnumerable
), CLASP(Object
)},
1659 #if OLD_GETTER_SETTER_METHODS
1660 {js_InitObjectClass
, LAZY_ATOM(defineGetter
), CLASP(Object
)},
1661 {js_InitObjectClass
, LAZY_ATOM(defineSetter
), CLASP(Object
)},
1662 {js_InitObjectClass
, LAZY_ATOM(lookupGetter
), CLASP(Object
)},
1663 {js_InitObjectClass
, LAZY_ATOM(lookupSetter
), CLASP(Object
)},
1666 {NULL
, 0, NULL
, NULL
}
1669 JS_PUBLIC_API(JSBool
)
1670 JS_ResolveStandardClass(JSContext
*cx
, JSObject
*obj
, jsid id
, JSBool
*resolved
)
1679 assertSameCompartment(cx
, obj
, id
);
1680 *resolved
= JS_FALSE
;
1683 JS_ASSERT(rt
->state
!= JSRTS_DOWN
);
1684 if (rt
->state
== JSRTS_LANDING
|| !JSID_IS_ATOM(id
))
1687 idstr
= JSID_TO_STRING(id
);
1689 /* Check whether we're resolving 'undefined', and define it if so. */
1690 atom
= rt
->atomState
.typeAtoms
[JSTYPE_VOID
];
1691 if (idstr
== ATOM_TO_STRING(atom
)) {
1692 *resolved
= JS_TRUE
;
1693 return obj
->defineProperty(cx
, ATOM_TO_JSID(atom
), UndefinedValue(),
1694 PropertyStub
, StrictPropertyStub
,
1695 JSPROP_PERMANENT
| JSPROP_READONLY
);
1698 /* Try for class constructors/prototypes named by well-known atoms. */
1700 for (i
= 0; standard_class_atoms
[i
].init
; i
++) {
1701 JS_ASSERT(standard_class_atoms
[i
].clasp
);
1702 atom
= OFFSET_TO_ATOM(rt
, standard_class_atoms
[i
].atomOffset
);
1703 if (idstr
== ATOM_TO_STRING(atom
)) {
1704 stdnm
= &standard_class_atoms
[i
];
1710 /* Try less frequently used top-level functions and constants. */
1711 for (i
= 0; standard_class_names
[i
].init
; i
++) {
1712 JS_ASSERT(standard_class_names
[i
].clasp
);
1713 atom
= StdNameToAtom(cx
, &standard_class_names
[i
]);
1716 if (idstr
== ATOM_TO_STRING(atom
)) {
1717 stdnm
= &standard_class_names
[i
];
1722 if (!stdnm
&& !obj
->getProto()) {
1724 * Try even less frequently used names delegated from the global
1725 * object to Object.prototype, but only if the Object class hasn't
1726 * yet been initialized.
1728 for (i
= 0; object_prototype_names
[i
].init
; i
++) {
1729 JS_ASSERT(object_prototype_names
[i
].clasp
);
1730 atom
= StdNameToAtom(cx
, &object_prototype_names
[i
]);
1733 if (idstr
== ATOM_TO_STRING(atom
)) {
1734 stdnm
= &object_prototype_names
[i
];
1743 * If this standard class is anonymous, then we don't want to resolve
1746 JS_ASSERT(obj
->isGlobal());
1747 if (stdnm
->clasp
->flags
& JSCLASS_IS_ANONYMOUS
)
1750 JSProtoKey key
= JSCLASS_CACHED_PROTO_KEY(stdnm
->clasp
);
1751 if (obj
->getReservedSlot(key
).isObject())
1754 if (!stdnm
->init(cx
, obj
))
1756 *resolved
= JS_TRUE
;
1761 JS_PUBLIC_API(JSBool
)
1762 JS_EnumerateStandardClasses(JSContext
*cx
, JSObject
*obj
)
1769 assertSameCompartment(cx
, obj
);
1772 /* Check whether we need to bind 'undefined' and define it if so. */
1773 atom
= rt
->atomState
.typeAtoms
[JSTYPE_VOID
];
1774 if (!obj
->nativeContains(ATOM_TO_JSID(atom
)) &&
1775 !obj
->defineProperty(cx
, ATOM_TO_JSID(atom
), UndefinedValue(),
1776 PropertyStub
, StrictPropertyStub
,
1777 JSPROP_PERMANENT
| JSPROP_READONLY
)) {
1781 /* Initialize any classes that have not been resolved yet. */
1782 for (i
= 0; standard_class_atoms
[i
].init
; i
++) {
1783 atom
= OFFSET_TO_ATOM(rt
, standard_class_atoms
[i
].atomOffset
);
1784 if (!obj
->nativeContains(ATOM_TO_JSID(atom
)) &&
1785 !standard_class_atoms
[i
].init(cx
, obj
)) {
1796 NewIdArray(JSContext
*cx
, jsint length
)
1801 cx
->calloc(offsetof(JSIdArray
, vector
) + length
* sizeof(jsval
));
1803 ida
->length
= length
;
1810 * Unlike realloc(3), this function frees ida on failure.
1813 SetIdArrayLength(JSContext
*cx
, JSIdArray
*ida
, jsint length
)
1817 rida
= (JSIdArray
*)
1819 offsetof(JSIdArray
, vector
) + length
* sizeof(jsval
));
1821 JS_DestroyIdArray(cx
, ida
);
1823 rida
->length
= length
;
1829 AddAtomToArray(JSContext
*cx
, JSAtom
*atom
, JSIdArray
*ida
, jsint
*ip
)
1834 length
= ida
->length
;
1836 ida
= SetIdArrayLength(cx
, ida
, JS_MAX(length
* 2, 8));
1839 JS_ASSERT(i
< ida
->length
);
1841 ida
->vector
[i
] = ATOM_TO_JSID(atom
);
1847 EnumerateIfResolved(JSContext
*cx
, JSObject
*obj
, JSAtom
*atom
, JSIdArray
*ida
,
1848 jsint
*ip
, JSBool
*foundp
)
1850 *foundp
= obj
->nativeContains(ATOM_TO_JSID(atom
));
1852 ida
= AddAtomToArray(cx
, atom
, ida
, ip
);
1856 JS_PUBLIC_API(JSIdArray
*)
1857 JS_EnumerateResolvedStandardClasses(JSContext
*cx
, JSObject
*obj
, JSIdArray
*ida
)
1866 assertSameCompartment(cx
, obj
, ida
);
1871 ida
= NewIdArray(cx
, 8);
1877 /* Check whether 'undefined' has been resolved and enumerate it if so. */
1878 atom
= rt
->atomState
.typeAtoms
[JSTYPE_VOID
];
1879 ida
= EnumerateIfResolved(cx
, obj
, atom
, ida
, &i
, &found
);
1883 /* Enumerate only classes that *have* been resolved. */
1884 for (j
= 0; standard_class_atoms
[j
].init
; j
++) {
1885 atom
= OFFSET_TO_ATOM(rt
, standard_class_atoms
[j
].atomOffset
);
1886 ida
= EnumerateIfResolved(cx
, obj
, atom
, ida
, &i
, &found
);
1891 init
= standard_class_atoms
[j
].init
;
1893 for (k
= 0; standard_class_names
[k
].init
; k
++) {
1894 if (standard_class_names
[k
].init
== init
) {
1895 atom
= StdNameToAtom(cx
, &standard_class_names
[k
]);
1896 ida
= AddAtomToArray(cx
, atom
, ida
, &i
);
1902 if (init
== js_InitObjectClass
) {
1903 for (k
= 0; object_prototype_names
[k
].init
; k
++) {
1904 atom
= StdNameToAtom(cx
, &object_prototype_names
[k
]);
1905 ida
= AddAtomToArray(cx
, atom
, ida
, &i
);
1913 /* Trim to exact length. */
1914 return SetIdArrayLength(cx
, ida
, i
);
1919 #undef EAGER_CLASS_ATOM
1920 #undef EAGER_ATOM_CLASP
1923 JS_PUBLIC_API(JSBool
)
1924 JS_GetClassObject(JSContext
*cx
, JSObject
*obj
, JSProtoKey key
, JSObject
**objp
)
1927 assertSameCompartment(cx
, obj
);
1928 return js_GetClassObject(cx
, obj
, key
, objp
);
1931 JS_PUBLIC_API(JSObject
*)
1932 JS_GetScopeChain(JSContext
*cx
)
1935 return GetScopeChain(cx
);
1938 JS_PUBLIC_API(JSObject
*)
1939 JS_GetGlobalForObject(JSContext
*cx
, JSObject
*obj
)
1941 assertSameCompartment(cx
, obj
);
1942 return obj
->getGlobal();
1945 JS_PUBLIC_API(JSObject
*)
1946 JS_GetGlobalForScopeChain(JSContext
*cx
)
1949 return GetGlobalForScopeChain(cx
);
1952 JS_PUBLIC_API(jsval
)
1953 JS_ComputeThis(JSContext
*cx
, jsval
*vp
)
1955 assertSameCompartment(cx
, JSValueArray(vp
, 2));
1956 return BoxThisForVp(cx
, Valueify(vp
)) ? vp
[1] : JSVAL_NULL
;
1959 JS_PUBLIC_API(void *)
1960 JS_malloc(JSContext
*cx
, size_t nbytes
)
1962 return cx
->malloc(nbytes
);
1965 JS_PUBLIC_API(void *)
1966 JS_realloc(JSContext
*cx
, void *p
, size_t nbytes
)
1968 return cx
->realloc(p
, nbytes
);
1972 JS_free(JSContext
*cx
, void *p
)
1978 JS_updateMallocCounter(JSContext
*cx
, size_t nbytes
)
1980 return cx
->runtime
->updateMallocCounter(nbytes
);
1983 JS_PUBLIC_API(char *)
1984 JS_strdup(JSContext
*cx
, const char *s
)
1993 return (char *)memcpy(p
, s
, n
);
1996 JS_PUBLIC_API(JSBool
)
1997 JS_NewNumberValue(JSContext
*cx
, jsdouble d
, jsval
*rval
)
1999 d
= JS_CANONICALIZE_NAN(d
);
2000 Valueify(rval
)->setNumber(d
);
2006 JS_PUBLIC_API(JSBool
)
2007 JS_AddValueRoot(JSContext
*cx
, jsval
*vp
)
2010 return js_AddRoot(cx
, Valueify(vp
), NULL
);
2013 JS_PUBLIC_API(JSBool
)
2014 JS_AddStringRoot(JSContext
*cx
, JSString
**rp
)
2017 return js_AddGCThingRoot(cx
, (void **)rp
, NULL
);
2020 JS_PUBLIC_API(JSBool
)
2021 JS_AddObjectRoot(JSContext
*cx
, JSObject
**rp
)
2024 return js_AddGCThingRoot(cx
, (void **)rp
, NULL
);
2027 JS_PUBLIC_API(JSBool
)
2028 JS_AddGCThingRoot(JSContext
*cx
, void **rp
)
2031 return js_AddGCThingRoot(cx
, (void **)rp
, NULL
);
2034 JS_PUBLIC_API(JSBool
)
2035 JS_AddNamedValueRoot(JSContext
*cx
, jsval
*vp
, const char *name
)
2038 return js_AddRoot(cx
, Valueify(vp
), name
);
2041 JS_PUBLIC_API(JSBool
)
2042 JS_AddNamedStringRoot(JSContext
*cx
, JSString
**rp
, const char *name
)
2045 return js_AddGCThingRoot(cx
, (void **)rp
, name
);
2048 JS_PUBLIC_API(JSBool
)
2049 JS_AddNamedObjectRoot(JSContext
*cx
, JSObject
**rp
, const char *name
)
2052 return js_AddGCThingRoot(cx
, (void **)rp
, name
);
2055 JS_PUBLIC_API(JSBool
)
2056 JS_AddNamedGCThingRoot(JSContext
*cx
, void **rp
, const char *name
)
2059 return js_AddGCThingRoot(cx
, (void **)rp
, name
);
2062 JS_PUBLIC_API(JSBool
)
2063 JS_RemoveValueRoot(JSContext
*cx
, jsval
*vp
)
2066 return js_RemoveRoot(cx
->runtime
, (void *)vp
);
2069 JS_PUBLIC_API(JSBool
)
2070 JS_RemoveStringRoot(JSContext
*cx
, JSString
**rp
)
2073 return js_RemoveRoot(cx
->runtime
, (void *)rp
);
2076 JS_PUBLIC_API(JSBool
)
2077 JS_RemoveObjectRoot(JSContext
*cx
, JSObject
**rp
)
2080 return js_RemoveRoot(cx
->runtime
, (void *)rp
);
2083 JS_PUBLIC_API(JSBool
)
2084 JS_RemoveGCThingRoot(JSContext
*cx
, void **rp
)
2087 return js_RemoveRoot(cx
->runtime
, (void *)rp
);
2093 JS_DumpNamedRoots(JSRuntime
*rt
,
2094 void (*dump
)(const char *name
, void *rp
, JSGCRootType type
, void *data
),
2097 js_DumpNamedRoots(rt
, dump
, data
);
2102 JS_PUBLIC_API(uint32
)
2103 JS_MapGCRoots(JSRuntime
*rt
, JSGCRootMapFun map
, void *data
)
2105 return js_MapGCRoots(rt
, map
, data
);
2108 JS_PUBLIC_API(JSBool
)
2109 JS_LockGCThing(JSContext
*cx
, void *thing
)
2114 ok
= js_LockGCThingRT(cx
->runtime
, thing
);
2116 JS_ReportOutOfMemory(cx
);
2120 JS_PUBLIC_API(JSBool
)
2121 JS_LockGCThingRT(JSRuntime
*rt
, void *thing
)
2123 return js_LockGCThingRT(rt
, thing
);
2126 JS_PUBLIC_API(JSBool
)
2127 JS_UnlockGCThing(JSContext
*cx
, void *thing
)
2130 js_UnlockGCThingRT(cx
->runtime
, thing
);
2134 JS_PUBLIC_API(JSBool
)
2135 JS_UnlockGCThingRT(JSRuntime
*rt
, void *thing
)
2137 js_UnlockGCThingRT(rt
, thing
);
2142 JS_SetExtraGCRoots(JSRuntime
*rt
, JSTraceDataOp traceOp
, void *data
)
2144 rt
->gcExtraRootsTraceOp
= traceOp
;
2145 rt
->gcExtraRootsData
= data
;
2149 JS_TraceRuntime(JSTracer
*trc
)
2155 JS_CallTracer(JSTracer
*trc
, void *thing
, uint32 kind
)
2158 MarkKind(trc
, thing
, kind
);
2163 #ifdef HAVE_XPCONNECT
2164 #include "dump_xpc.h"
2168 JS_PrintTraceThingInfo(char *buf
, size_t bufsize
, JSTracer
*trc
, void *thing
, uint32 kind
,
2178 case JSTRACE_OBJECT
:
2180 JSObject
*obj
= (JSObject
*)thing
;
2181 Class
*clasp
= obj
->getClass();
2184 #ifdef HAVE_XPCONNECT
2185 if (clasp
->flags
& JSCLASS_PRIVATE_IS_NSISUPPORTS
) {
2186 void *privateThing
= obj
->getPrivate();
2188 const char *xpcClassName
= GetXPCObjectClassName(privateThing
);
2190 name
= xpcClassName
;
2197 case JSTRACE_STRING
:
2198 name
= ((JSString
*)thing
)->isDependent()
2203 #if JS_HAS_XML_SUPPORT
2215 if (n
> bufsize
- 1)
2217 memcpy(buf
, name
, n
+ 1);
2221 if (details
&& bufsize
> 2) {
2226 case JSTRACE_OBJECT
:
2228 JSObject
*obj
= (JSObject
*)thing
;
2229 Class
*clasp
= obj
->getClass();
2230 if (clasp
== &js_FunctionClass
) {
2231 JSFunction
*fun
= GET_FUNCTION_PRIVATE(trc
->context
, obj
);
2233 JS_snprintf(buf
, bufsize
, "<newborn>");
2234 } else if (FUN_OBJECT(fun
) != obj
) {
2235 JS_snprintf(buf
, bufsize
, "%p", fun
);
2238 PutEscapedString(buf
, bufsize
, ATOM_TO_STRING(fun
->atom
), 0);
2240 } else if (clasp
->flags
& JSCLASS_HAS_PRIVATE
) {
2241 JS_snprintf(buf
, bufsize
, "%p", obj
->getPrivate());
2243 JS_snprintf(buf
, bufsize
, "<no private>");
2248 case JSTRACE_STRING
:
2250 JSString
*str
= (JSString
*)thing
;
2251 if (str
->isLinear())
2252 PutEscapedString(buf
, bufsize
, str
->assertIsLinear(), 0);
2254 JS_snprintf(buf
, bufsize
, "<rope: length %d>", (int)str
->length());
2258 #if JS_HAS_XML_SUPPORT
2261 extern const char *js_xml_class_str
[];
2262 JSXML
*xml
= (JSXML
*)thing
;
2264 JS_snprintf(buf
, bufsize
, "%s", js_xml_class_str
[xml
->xml_class
]);
2273 buf
[bufsize
- 1] = '\0';
2276 typedef struct JSHeapDumpNode JSHeapDumpNode
;
2278 struct JSHeapDumpNode
{
2281 JSHeapDumpNode
*next
; /* next sibling */
2282 JSHeapDumpNode
*parent
; /* node with the thing that refer to thing
2284 char edgeName
[1]; /* name of the edge from parent->thing
2288 typedef struct JSDumpingTracer
{
2290 JSDHashTable visited
;
2294 void *thingToIgnore
;
2295 JSHeapDumpNode
*parentNode
;
2296 JSHeapDumpNode
**lastNodep
;
2301 DumpNotify(JSTracer
*trc
, void *thing
, uint32 kind
)
2303 JSDumpingTracer
*dtrc
;
2305 JSDHashEntryStub
*entry
;
2306 JSHeapDumpNode
*node
;
2307 const char *edgeName
;
2308 size_t edgeNameSize
;
2310 JS_ASSERT(trc
->callback
== DumpNotify
);
2311 dtrc
= (JSDumpingTracer
*)trc
;
2313 if (!dtrc
->ok
|| thing
== dtrc
->thingToIgnore
)
2319 * Check if we have already seen thing unless it is thingToFind to include
2320 * it to the graph each time we reach it and print all live things that
2321 * refer to thingToFind.
2323 * This does not print all possible paths leading to thingToFind since
2324 * when a thing A refers directly or indirectly to thingToFind and A is
2325 * present several times in the graph, we will print only the first path
2326 * leading to A and thingToFind, other ways to reach A will be ignored.
2328 if (dtrc
->thingToFind
!= thing
) {
2330 * The startThing check allows to avoid putting startThing into the
2331 * hash table before tracing startThing in JS_DumpHeap.
2333 if (thing
== dtrc
->startThing
)
2335 entry
= (JSDHashEntryStub
*)
2336 JS_DHashTableOperate(&dtrc
->visited
, thing
, JS_DHASH_ADD
);
2338 JS_ReportOutOfMemory(cx
);
2339 dtrc
->ok
= JS_FALSE
;
2347 if (dtrc
->base
.debugPrinter
) {
2348 dtrc
->base
.debugPrinter(trc
, dtrc
->buffer
, sizeof(dtrc
->buffer
));
2349 edgeName
= dtrc
->buffer
;
2350 } else if (dtrc
->base
.debugPrintIndex
!= (size_t)-1) {
2351 JS_snprintf(dtrc
->buffer
, sizeof(dtrc
->buffer
), "%s[%lu]",
2352 (const char *)dtrc
->base
.debugPrintArg
,
2353 dtrc
->base
.debugPrintIndex
);
2354 edgeName
= dtrc
->buffer
;
2356 edgeName
= (const char*)dtrc
->base
.debugPrintArg
;
2359 edgeNameSize
= strlen(edgeName
) + 1;
2360 node
= (JSHeapDumpNode
*) js_malloc(offsetof(JSHeapDumpNode
, edgeName
) + edgeNameSize
);
2362 dtrc
->ok
= JS_FALSE
;
2366 node
->thing
= thing
;
2369 node
->parent
= dtrc
->parentNode
;
2370 memcpy(node
->edgeName
, edgeName
, edgeNameSize
);
2372 JS_ASSERT(!*dtrc
->lastNodep
);
2373 *dtrc
->lastNodep
= node
;
2374 dtrc
->lastNodep
= &node
->next
;
2377 /* Dump node and the chain that leads to thing it contains. */
2379 DumpNode(JSDumpingTracer
*dtrc
, FILE* fp
, JSHeapDumpNode
*node
)
2381 JSHeapDumpNode
*prev
, *following
;
2384 enum { MAX_PARENTS_TO_PRINT
= 10 };
2386 JS_PrintTraceThingInfo(dtrc
->buffer
, sizeof dtrc
->buffer
,
2387 &dtrc
->base
, node
->thing
, node
->kind
, JS_TRUE
);
2388 if (fprintf(fp
, "%p %-22s via ", node
->thing
, dtrc
->buffer
) < 0)
2392 * We need to print the parent chain in the reverse order. To do it in
2393 * O(N) time where N is the chain length we first reverse the chain while
2394 * searching for the top and then print each node while restoring the
2397 chainLimit
= MAX_PARENTS_TO_PRINT
;
2400 following
= node
->parent
;
2401 node
->parent
= prev
;
2406 if (chainLimit
== 0) {
2407 if (fputs("...", fp
) < 0)
2418 /* Loop must continue even when !ok to restore the parent chain. */
2421 /* Print edge from some runtime root or startThing. */
2422 if (fputs(node
->edgeName
, fp
) < 0)
2425 JS_PrintTraceThingInfo(dtrc
->buffer
, sizeof dtrc
->buffer
,
2426 &dtrc
->base
, prev
->thing
, prev
->kind
,
2428 if (fprintf(fp
, "(%p %s).%s",
2429 prev
->thing
, dtrc
->buffer
, node
->edgeName
) < 0) {
2434 following
= node
->parent
;
2435 node
->parent
= prev
;
2440 return ok
&& putc('\n', fp
) >= 0;
2443 JS_PUBLIC_API(JSBool
)
2444 JS_DumpHeap(JSContext
*cx
, FILE *fp
, void* startThing
, uint32 startKind
,
2445 void *thingToFind
, size_t maxDepth
, void *thingToIgnore
)
2447 JSDumpingTracer dtrc
;
2448 JSHeapDumpNode
*node
, *children
, *next
, *parent
;
2450 JSBool thingToFindWasTraced
;
2455 JS_TRACER_INIT(&dtrc
.base
, cx
, DumpNotify
);
2456 if (!JS_DHashTableInit(&dtrc
.visited
, JS_DHashGetStubOps(),
2457 NULL
, sizeof(JSDHashEntryStub
),
2458 JS_DHASH_DEFAULT_CAPACITY(100))) {
2459 JS_ReportOutOfMemory(cx
);
2463 dtrc
.startThing
= startThing
;
2464 dtrc
.thingToFind
= thingToFind
;
2465 dtrc
.thingToIgnore
= thingToIgnore
;
2466 dtrc
.parentNode
= NULL
;
2468 dtrc
.lastNodep
= &node
;
2470 JS_ASSERT(startKind
== 0);
2471 TraceRuntime(&dtrc
.base
);
2473 JS_TraceChildren(&dtrc
.base
, startThing
, startKind
);
2480 thingToFindWasTraced
= thingToFind
&& thingToFind
== startThing
;
2483 * Loop must continue even when !dtrc.ok to free all nodes allocated
2487 if (thingToFind
== NULL
|| thingToFind
== node
->thing
)
2488 dtrc
.ok
= DumpNode(&dtrc
, fp
, node
);
2490 /* Descend into children. */
2493 (thingToFind
!= node
->thing
|| !thingToFindWasTraced
)) {
2494 dtrc
.parentNode
= node
;
2496 dtrc
.lastNodep
= &children
;
2497 JS_TraceChildren(&dtrc
.base
, node
->thing
, node
->kind
);
2498 if (thingToFind
== node
->thing
)
2499 thingToFindWasTraced
= JS_TRUE
;
2500 if (children
!= NULL
) {
2508 /* Move to next or parents next and free the node. */
2511 parent
= node
->parent
;
2518 JS_ASSERT(depth
> 1);
2525 JS_ASSERT(depth
== 1);
2526 JS_DHashTableFinish(&dtrc
.visited
);
2533 JS_MarkGCThing(JSContext
*cx
, jsval v
, const char *name
, void *arg
)
2537 trc
= (JSTracer
*)arg
;
2539 trc
= cx
->runtime
->gcMarkingTracer
;
2541 JS_ASSERT(trc
== cx
->runtime
->gcMarkingTracer
);
2543 #ifdef JS_THREADSAFE
2544 JS_ASSERT(cx
->runtime
->gcThread
== trc
->context
->thread
);
2546 MarkValue(trc
, Valueify(v
), name
? name
: "unknown");
2549 extern JS_PUBLIC_API(JSBool
)
2550 JS_IsGCMarkingTracer(JSTracer
*trc
)
2552 return IS_GC_MARKING_TRACER(trc
);
2556 JS_GC(JSContext
*cx
)
2560 /* Don't nuke active arenas if executing or compiling. */
2561 if (cx
->tempPool
.current
== &cx
->tempPool
.first
)
2562 JS_FinishArenaPool(&cx
->tempPool
);
2563 js_GC(cx
, NULL
, GC_NORMAL
);
2567 JS_MaybeGC(JSContext
*cx
)
2571 /* Don't nuke active arenas if executing or compiling. */
2572 if (cx
->tempPool
.current
== &cx
->tempPool
.first
)
2573 JS_FinishArenaPool(&cx
->tempPool
);
2578 JS_PUBLIC_API(JSGCCallback
)
2579 JS_SetGCCallback(JSContext
*cx
, JSGCCallback cb
)
2582 return JS_SetGCCallbackRT(cx
->runtime
, cb
);
2585 JS_PUBLIC_API(JSGCCallback
)
2586 JS_SetGCCallbackRT(JSRuntime
*rt
, JSGCCallback cb
)
2590 oldcb
= rt
->gcCallback
;
2591 rt
->gcCallback
= cb
;
2595 JS_PUBLIC_API(JSBool
)
2596 JS_IsAboutToBeFinalized(JSContext
*cx
, void *thing
)
2599 JS_ASSERT(!cx
->runtime
->gcMarkingTracer
);
2600 return IsAboutToBeFinalized(cx
, thing
);
2604 JS_SetGCParameter(JSRuntime
*rt
, JSGCParamKey key
, uint32 value
)
2607 case JSGC_MAX_BYTES
:
2608 rt
->gcMaxBytes
= value
;
2610 case JSGC_MAX_MALLOC_BYTES
:
2611 rt
->setGCMaxMallocBytes(value
);
2613 case JSGC_STACKPOOL_LIFESPAN
:
2614 rt
->gcEmptyArenaPoolLifespan
= value
;
2617 rt
->gcMode
= JSGCMode(value
);
2618 JS_ASSERT(rt
->gcMode
== JSGC_MODE_GLOBAL
||
2619 rt
->gcMode
== JSGC_MODE_COMPARTMENT
);
2622 JS_ASSERT(key
== JSGC_TRIGGER_FACTOR
);
2623 JS_ASSERT(value
>= 100);
2624 rt
->setGCTriggerFactor(value
);
2629 JS_PUBLIC_API(uint32
)
2630 JS_GetGCParameter(JSRuntime
*rt
, JSGCParamKey key
)
2633 case JSGC_MAX_BYTES
:
2634 return rt
->gcMaxBytes
;
2635 case JSGC_MAX_MALLOC_BYTES
:
2636 return rt
->gcMaxMallocBytes
;
2637 case JSGC_STACKPOOL_LIFESPAN
:
2638 return rt
->gcEmptyArenaPoolLifespan
;
2639 case JSGC_TRIGGER_FACTOR
:
2640 return rt
->gcTriggerFactor
;
2644 return uint32(rt
->gcMode
);
2646 JS_ASSERT(key
== JSGC_NUMBER
);
2647 return rt
->gcNumber
;
2652 JS_SetGCParameterForThread(JSContext
*cx
, JSGCParamKey key
, uint32 value
)
2654 JS_ASSERT(key
== JSGC_MAX_CODE_CACHE_BYTES
);
2656 SetMaxCodeCacheBytes(cx
, value
);
2660 JS_PUBLIC_API(uint32
)
2661 JS_GetGCParameterForThread(JSContext
*cx
, JSGCParamKey key
)
2663 JS_ASSERT(key
== JSGC_MAX_CODE_CACHE_BYTES
);
2665 return JS_THREAD_DATA(cx
)->maxCodeCacheBytes
;
2672 JS_FlushCaches(JSContext
*cx
)
2675 FlushJITCache(cx
, &cx
->compartment
->traceMonitor
);
2680 JS_AddExternalStringFinalizer(JSStringFinalizeOp finalizer
)
2682 return JSExternalString::changeFinalizer(NULL
, finalizer
);
2686 JS_RemoveExternalStringFinalizer(JSStringFinalizeOp finalizer
)
2688 return JSExternalString::changeFinalizer(finalizer
, NULL
);
2691 JS_PUBLIC_API(JSString
*)
2692 JS_NewExternalString(JSContext
*cx
, jschar
*chars
, size_t length
, intN type
)
2695 JS_ASSERT(uintN(type
) < JSExternalString::TYPE_LIMIT
);
2697 JSExternalString
*str
= js_NewGCExternalString(cx
, uintN(type
));
2700 str
->initFlat(chars
, length
);
2701 str
->externalStringType
= type
;
2702 cx
->runtime
->updateMallocCounter((length
+ 1) * sizeof(jschar
));
2707 JS_GetExternalStringGCType(JSRuntime
*rt
, JSString
*str
)
2710 * No need to test this in js_GetExternalStringGCType, which asserts its
2711 * inverse instead of wasting cycles on testing a condition we can ensure
2712 * by auditing in-VM calls to the js_... helper.
2714 if (JSString::isStatic(str
))
2717 return js_GetExternalStringGCType(str
);
2721 JS_SetThreadStackLimit(JSContext
*cx
, jsuword limitAddr
)
2723 #if JS_STACK_GROWTH_DIRECTION > 0
2725 limitAddr
= jsuword(-1);
2727 cx
->stackLimit
= limitAddr
;
2731 JS_SetNativeStackQuota(JSContext
*cx
, size_t stackSize
)
2733 #ifdef JS_THREADSAFE
2734 JS_ASSERT(cx
->thread
);
2737 #if JS_STACK_GROWTH_DIRECTION > 0
2738 if (stackSize
== 0) {
2739 cx
->stackLimit
= jsuword(-1);
2741 jsuword stackBase
= reinterpret_cast<jsuword
>(JS_THREAD_DATA(cx
)->nativeStackBase
);
2742 JS_ASSERT(stackBase
<= size_t(-1) - stackSize
);
2743 cx
->stackLimit
= stackBase
+ stackSize
- 1;
2746 if (stackSize
== 0) {
2749 jsuword stackBase
= reinterpret_cast<jsuword
>(JS_THREAD_DATA(cx
)->nativeStackBase
);
2750 JS_ASSERT(stackBase
>= stackSize
);
2751 cx
->stackLimit
= stackBase
- (stackSize
- 1);
2757 JS_SetScriptStackQuota(JSContext
*cx
, size_t quota
)
2759 cx
->scriptStackQuota
= quota
;
2762 /************************************************************************/
2765 JS_DestroyIdArray(JSContext
*cx
, JSIdArray
*ida
)
2770 JS_PUBLIC_API(JSBool
)
2771 JS_ValueToId(JSContext
*cx
, jsval v
, jsid
*idp
)
2774 assertSameCompartment(cx
, v
);
2775 return ValueToId(cx
, Valueify(v
), idp
);
2778 JS_PUBLIC_API(JSBool
)
2779 JS_IdToValue(JSContext
*cx
, jsid id
, jsval
*vp
)
2782 *vp
= IdToJsval(id
);
2783 assertSameCompartment(cx
, *vp
);
2787 JS_PUBLIC_API(JSBool
)
2788 JS_PropertyStub(JSContext
*cx
, JSObject
*obj
, jsid id
, jsval
*vp
)
2793 JS_PUBLIC_API(JSBool
)
2794 JS_StrictPropertyStub(JSContext
*cx
, JSObject
*obj
, jsid id
, JSBool strict
, jsval
*vp
)
2799 JS_PUBLIC_API(JSBool
)
2800 JS_EnumerateStub(JSContext
*cx
, JSObject
*obj
)
2805 JS_PUBLIC_API(JSBool
)
2806 JS_ResolveStub(JSContext
*cx
, JSObject
*obj
, jsid id
)
2811 JS_PUBLIC_API(JSBool
)
2812 JS_ConvertStub(JSContext
*cx
, JSObject
*obj
, JSType type
, jsval
*vp
)
2814 JS_ASSERT(type
!= JSTYPE_OBJECT
&& type
!= JSTYPE_FUNCTION
);
2815 return js_TryValueOf(cx
, obj
, type
, Valueify(vp
));
2819 JS_FinalizeStub(JSContext
*cx
, JSObject
*obj
)
2822 JS_PUBLIC_API(JSObject
*)
2823 JS_InitClass(JSContext
*cx
, JSObject
*obj
, JSObject
*parent_proto
,
2824 JSClass
*clasp
, JSNative constructor
, uintN nargs
,
2825 JSPropertySpec
*ps
, JSFunctionSpec
*fs
,
2826 JSPropertySpec
*static_ps
, JSFunctionSpec
*static_fs
)
2829 assertSameCompartment(cx
, obj
, parent_proto
);
2830 return js_InitClass(cx
, obj
, parent_proto
, Valueify(clasp
),
2831 Valueify(constructor
), nargs
,
2832 ps
, fs
, static_ps
, static_fs
);
2835 #ifdef JS_THREADSAFE
2836 JS_PUBLIC_API(JSClass
*)
2837 JS_GetClass(JSContext
*cx
, JSObject
*obj
)
2839 return Jsvalify(obj
->getClass());
2842 JS_PUBLIC_API(JSClass
*)
2843 JS_GetClass(JSObject
*obj
)
2845 return Jsvalify(obj
->getClass());
2849 JS_PUBLIC_API(JSBool
)
2850 JS_InstanceOf(JSContext
*cx
, JSObject
*obj
, JSClass
*clasp
, jsval
*argv
)
2853 assertSameCompartment(cx
, obj
);
2854 return InstanceOf(cx
, obj
, Valueify(clasp
), Valueify(argv
));
2857 JS_PUBLIC_API(JSBool
)
2858 JS_HasInstance(JSContext
*cx
, JSObject
*obj
, jsval v
, JSBool
*bp
)
2860 assertSameCompartment(cx
, obj
, v
);
2861 return HasInstance(cx
, obj
, Valueify(&v
), bp
);
2864 JS_PUBLIC_API(void *)
2865 JS_GetPrivate(JSContext
*cx
, JSObject
*obj
)
2867 return obj
->getPrivate();
2870 JS_PUBLIC_API(JSBool
)
2871 JS_SetPrivate(JSContext
*cx
, JSObject
*obj
, void *data
)
2873 obj
->setPrivate(data
);
2877 JS_PUBLIC_API(void *)
2878 JS_GetInstancePrivate(JSContext
*cx
, JSObject
*obj
, JSClass
*clasp
, jsval
*argv
)
2880 if (!InstanceOf(cx
, obj
, Valueify(clasp
), Valueify(argv
)))
2882 return obj
->getPrivate();
2885 JS_PUBLIC_API(JSObject
*)
2886 JS_GetPrototype(JSContext
*cx
, JSObject
*obj
)
2891 assertSameCompartment(cx
, obj
);
2892 proto
= obj
->getProto();
2894 /* Beware ref to dead object (we may be called from obj's finalizer). */
2895 return proto
&& proto
->map
? proto
: NULL
;
2898 JS_PUBLIC_API(JSBool
)
2899 JS_SetPrototype(JSContext
*cx
, JSObject
*obj
, JSObject
*proto
)
2902 assertSameCompartment(cx
, obj
, proto
);
2903 return SetProto(cx
, obj
, proto
, JS_FALSE
);
2906 JS_PUBLIC_API(JSObject
*)
2907 JS_GetParent(JSContext
*cx
, JSObject
*obj
)
2909 assertSameCompartment(cx
, obj
);
2910 JSObject
*parent
= obj
->getParent();
2912 /* Beware ref to dead object (we may be called from obj's finalizer). */
2913 return parent
&& parent
->map
? parent
: NULL
;
2916 JS_PUBLIC_API(JSBool
)
2917 JS_SetParent(JSContext
*cx
, JSObject
*obj
, JSObject
*parent
)
2920 JS_ASSERT(parent
|| !obj
->getParent());
2921 assertSameCompartment(cx
, obj
, parent
);
2922 obj
->setParent(parent
);
2926 JS_PUBLIC_API(JSObject
*)
2927 JS_GetConstructor(JSContext
*cx
, JSObject
*proto
)
2932 assertSameCompartment(cx
, proto
);
2934 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
);
2936 if (!proto
->getProperty(cx
, ATOM_TO_JSID(cx
->runtime
->atomState
.constructorAtom
), &cval
))
2940 if (!IsFunctionObject(cval
, &funobj
)) {
2941 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_NO_CONSTRUCTOR
,
2942 proto
->getClass()->name
);
2945 return &cval
.toObject();
2948 JS_PUBLIC_API(JSBool
)
2949 JS_GetObjectId(JSContext
*cx
, JSObject
*obj
, jsid
*idp
)
2951 assertSameCompartment(cx
, obj
);
2952 *idp
= OBJECT_TO_JSID(obj
);
2956 JS_PUBLIC_API(JSObject
*)
2957 JS_NewGlobalObject(JSContext
*cx
, JSClass
*clasp
)
2959 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
2961 JS_ASSERT(clasp
->flags
& JSCLASS_IS_GLOBAL
);
2962 JSObject
*obj
= NewNonFunction
<WithProto::Given
>(cx
, Valueify(clasp
), NULL
, NULL
);
2966 obj
->syncSpecialEquality();
2968 /* Construct a regexp statics object for this global object. */
2969 JSObject
*res
= regexp_statics_construct(cx
, obj
);
2971 !js_SetReservedSlot(cx
, obj
, JSRESERVED_GLOBAL_REGEXP_STATICS
, ObjectValue(*res
)) ||
2972 !js_SetReservedSlot(cx
, obj
, JSRESERVED_GLOBAL_FLAGS
, Int32Value(0))) {
2979 JS_PUBLIC_API(JSObject
*)
2980 JS_NewCompartmentAndGlobalObject(JSContext
*cx
, JSClass
*clasp
, JSPrincipals
*principals
)
2983 JSCompartment
*compartment
= NewCompartment(cx
, principals
);
2987 JSCompartment
*saved
= cx
->compartment
;
2988 cx
->compartment
= compartment
;
2989 JSObject
*obj
= JS_NewGlobalObject(cx
, clasp
);
2990 cx
->compartment
= saved
;
2995 JS_PUBLIC_API(JSObject
*)
2996 JS_NewObject(JSContext
*cx
, JSClass
*jsclasp
, JSObject
*proto
, JSObject
*parent
)
2998 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
3000 assertSameCompartment(cx
, proto
, parent
);
3002 Class
*clasp
= Valueify(jsclasp
);
3004 clasp
= &js_ObjectClass
; /* default class is Object */
3006 JS_ASSERT(clasp
!= &js_FunctionClass
);
3007 JS_ASSERT(!(clasp
->flags
& JSCLASS_IS_GLOBAL
));
3009 JSObject
*obj
= NewNonFunction
<WithProto::Class
>(cx
, clasp
, proto
, parent
);
3011 obj
->syncSpecialEquality();
3013 JS_ASSERT_IF(obj
, obj
->getParent());
3017 JS_PUBLIC_API(JSObject
*)
3018 JS_NewObjectWithGivenProto(JSContext
*cx
, JSClass
*jsclasp
, JSObject
*proto
, JSObject
*parent
)
3020 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
3022 assertSameCompartment(cx
, proto
, parent
);
3024 Class
*clasp
= Valueify(jsclasp
);
3026 clasp
= &js_ObjectClass
; /* default class is Object */
3028 JS_ASSERT(clasp
!= &js_FunctionClass
);
3029 JS_ASSERT(!(clasp
->flags
& JSCLASS_IS_GLOBAL
));
3031 JSObject
*obj
= NewNonFunction
<WithProto::Given
>(cx
, clasp
, proto
, parent
);
3033 obj
->syncSpecialEquality();
3037 JS_PUBLIC_API(JSObject
*)
3038 JS_NewObjectForConstructor(JSContext
*cx
, const jsval
*vp
)
3041 assertSameCompartment(cx
, *vp
);
3043 return js_CreateThis(cx
, JSVAL_TO_OBJECT(*vp
));
3046 JS_PUBLIC_API(JSBool
)
3047 JS_IsExtensible(JSObject
*obj
)
3049 return obj
->isExtensible();
3052 JS_PUBLIC_API(JSBool
)
3053 JS_FreezeObject(JSContext
*cx
, JSObject
*obj
)
3056 assertSameCompartment(cx
, obj
);
3058 return obj
->freeze(cx
);
3061 JS_PUBLIC_API(JSBool
)
3062 JS_DeepFreezeObject(JSContext
*cx
, JSObject
*obj
)
3065 assertSameCompartment(cx
, obj
);
3067 /* Assume that non-extensible objects are already deep-frozen, to avoid divergence. */
3068 if (!obj
->isExtensible())
3071 if (!obj
->freeze(cx
))
3074 /* Walk slots in obj and if any value is a non-null object, seal it. */
3075 for (uint32 i
= 0, n
= obj
->slotSpan(); i
< n
; ++i
) {
3076 const Value
&v
= obj
->getSlot(i
);
3077 if (v
.isPrimitive())
3079 if (!JS_DeepFreezeObject(cx
, &v
.toObject()))
3086 JS_PUBLIC_API(JSObject
*)
3087 JS_ConstructObject(JSContext
*cx
, JSClass
*jsclasp
, JSObject
*proto
, JSObject
*parent
)
3090 assertSameCompartment(cx
, proto
, parent
);
3091 Class
*clasp
= Valueify(jsclasp
);
3093 clasp
= &js_ObjectClass
; /* default class is Object */
3094 return js_ConstructObject(cx
, clasp
, proto
, parent
, 0, NULL
);
3097 JS_PUBLIC_API(JSObject
*)
3098 JS_ConstructObjectWithArguments(JSContext
*cx
, JSClass
*jsclasp
, JSObject
*proto
,
3099 JSObject
*parent
, uintN argc
, jsval
*argv
)
3102 assertSameCompartment(cx
, proto
, parent
, JSValueArray(argv
, argc
));
3103 Class
*clasp
= Valueify(jsclasp
);
3105 clasp
= &js_ObjectClass
; /* default class is Object */
3106 return js_ConstructObject(cx
, clasp
, proto
, parent
, argc
, Valueify(argv
));
3110 LookupPropertyById(JSContext
*cx
, JSObject
*obj
, jsid id
, uintN flags
,
3111 JSObject
**objp
, JSProperty
**propp
)
3114 assertSameCompartment(cx
, obj
, id
);
3116 JSAutoResolveFlags
rf(cx
, flags
);
3117 id
= js_CheckForStringIndex(id
);
3118 return obj
->lookupProperty(cx
, id
, objp
, propp
);
3121 #define AUTO_NAMELEN(s,n) (((n) == (size_t)-1) ? js_strlen(s) : (n))
3124 LookupResult(JSContext
*cx
, JSObject
*obj
, JSObject
*obj2
, jsid id
,
3125 JSProperty
*prop
, Value
*vp
)
3128 /* XXX bad API: no way to tell "not defined" from "void value" */
3133 if (obj2
->isNative()) {
3134 Shape
*shape
= (Shape
*) prop
;
3136 if (shape
->isMethod()) {
3137 AutoShapeRooter
root(cx
, shape
);
3138 vp
->setObject(shape
->methodObject());
3139 return !!obj2
->methodReadBarrier(cx
, *shape
, vp
);
3142 /* Peek at the native property's slot value, without doing a Get. */
3143 if (obj2
->containsSlot(shape
->slot
)) {
3144 *vp
= obj2
->nativeGetSlot(shape
->slot
);
3148 if (obj2
->isDenseArray())
3149 return js_GetDenseArrayElementValue(cx
, obj2
, id
, vp
);
3150 if (obj2
->isProxy()) {
3151 AutoPropertyDescriptorRooter
desc(cx
);
3152 if (!JSProxy::getPropertyDescriptor(cx
, obj2
, id
, false, &desc
))
3154 if (!(desc
.attrs
& JSPROP_SHARED
)) {
3161 /* XXX bad API: no way to return "defined but value unknown" */
3162 vp
->setBoolean(true);
3166 JS_PUBLIC_API(JSBool
)
3167 JS_LookupPropertyById(JSContext
*cx
, JSObject
*obj
, jsid id
, jsval
*vp
)
3171 return LookupPropertyById(cx
, obj
, id
, JSRESOLVE_QUALIFIED
, &obj2
, &prop
) &&
3172 LookupResult(cx
, obj
, obj2
, id
, prop
, Valueify(vp
));
3175 JS_PUBLIC_API(JSBool
)
3176 JS_LookupElement(JSContext
*cx
, JSObject
*obj
, jsint index
, jsval
*vp
)
3178 return JS_LookupPropertyById(cx
, obj
, INT_TO_JSID(index
), vp
);
3181 JS_PUBLIC_API(JSBool
)
3182 JS_LookupProperty(JSContext
*cx
, JSObject
*obj
, const char *name
, jsval
*vp
)
3184 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3185 return atom
&& JS_LookupPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), vp
);
3188 JS_PUBLIC_API(JSBool
)
3189 JS_LookupUCProperty(JSContext
*cx
, JSObject
*obj
, const jschar
*name
, size_t namelen
, jsval
*vp
)
3191 JSAtom
*atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
3192 return atom
&& JS_LookupPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), vp
);
3195 JS_PUBLIC_API(JSBool
)
3196 JS_LookupPropertyWithFlagsById(JSContext
*cx
, JSObject
*obj
, jsid id
, uintN flags
,
3197 JSObject
**objp
, jsval
*vp
)
3203 assertSameCompartment(cx
, obj
, id
);
3204 ok
= obj
->isNative()
3205 ? js_LookupPropertyWithFlags(cx
, obj
, id
, flags
, objp
, &prop
) >= 0
3206 : obj
->lookupProperty(cx
, id
, objp
, &prop
);
3207 return ok
&& LookupResult(cx
, obj
, *objp
, id
, prop
, Valueify(vp
));
3210 JS_PUBLIC_API(JSBool
)
3211 JS_LookupPropertyWithFlags(JSContext
*cx
, JSObject
*obj
, const char *name
, uintN flags
, jsval
*vp
)
3214 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3215 return atom
&& JS_LookupPropertyWithFlagsById(cx
, obj
, ATOM_TO_JSID(atom
), flags
, &obj2
, vp
);
3218 JS_PUBLIC_API(JSBool
)
3219 JS_HasPropertyById(JSContext
*cx
, JSObject
*obj
, jsid id
, JSBool
*foundp
)
3223 JSBool ok
= LookupPropertyById(cx
, obj
, id
, JSRESOLVE_QUALIFIED
| JSRESOLVE_DETECTING
,
3225 *foundp
= (prop
!= NULL
);
3229 JS_PUBLIC_API(JSBool
)
3230 JS_HasElement(JSContext
*cx
, JSObject
*obj
, jsint index
, JSBool
*foundp
)
3232 return JS_HasPropertyById(cx
, obj
, INT_TO_JSID(index
), foundp
);
3235 JS_PUBLIC_API(JSBool
)
3236 JS_HasProperty(JSContext
*cx
, JSObject
*obj
, const char *name
, JSBool
*foundp
)
3238 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3239 return atom
&& JS_HasPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), foundp
);
3242 JS_PUBLIC_API(JSBool
)
3243 JS_HasUCProperty(JSContext
*cx
, JSObject
*obj
, const jschar
*name
, size_t namelen
, JSBool
*foundp
)
3245 JSAtom
*atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
3246 return atom
&& JS_HasPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), foundp
);
3249 JS_PUBLIC_API(JSBool
)
3250 JS_AlreadyHasOwnPropertyById(JSContext
*cx
, JSObject
*obj
, jsid id
, JSBool
*foundp
)
3253 assertSameCompartment(cx
, obj
, id
);
3255 if (!obj
->isNative()) {
3259 if (!LookupPropertyById(cx
, obj
, id
, JSRESOLVE_QUALIFIED
| JSRESOLVE_DETECTING
,
3263 *foundp
= (obj
== obj2
);
3267 *foundp
= obj
->nativeContains(id
);
3271 JS_PUBLIC_API(JSBool
)
3272 JS_AlreadyHasOwnElement(JSContext
*cx
, JSObject
*obj
, jsint index
, JSBool
*foundp
)
3274 return JS_AlreadyHasOwnPropertyById(cx
, obj
, INT_TO_JSID(index
), foundp
);
3277 JS_PUBLIC_API(JSBool
)
3278 JS_AlreadyHasOwnProperty(JSContext
*cx
, JSObject
*obj
, const char *name
, JSBool
*foundp
)
3280 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3281 return atom
&& JS_AlreadyHasOwnPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), foundp
);
3284 JS_PUBLIC_API(JSBool
)
3285 JS_AlreadyHasOwnUCProperty(JSContext
*cx
, JSObject
*obj
, const jschar
*name
, size_t namelen
,
3288 JSAtom
*atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
3289 return atom
&& JS_AlreadyHasOwnPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), foundp
);
3293 DefinePropertyById(JSContext
*cx
, JSObject
*obj
, jsid id
, const Value
&value
,
3294 PropertyOp getter
, StrictPropertyOp setter
, uintN attrs
,
3295 uintN flags
, intN tinyid
)
3298 assertSameCompartment(cx
, obj
, id
, value
,
3299 (attrs
& JSPROP_GETTER
)
3300 ? JS_FUNC_TO_DATA_PTR(JSObject
*, getter
)
3302 (attrs
& JSPROP_SETTER
)
3303 ? JS_FUNC_TO_DATA_PTR(JSObject
*, setter
)
3306 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
| JSRESOLVE_DECLARING
);
3307 if (flags
!= 0 && obj
->isNative()) {
3308 return !!js_DefineNativeProperty(cx
, obj
, id
, value
, getter
, setter
,
3309 attrs
, flags
, tinyid
, NULL
);
3311 return obj
->defineProperty(cx
, id
, value
, getter
, setter
, attrs
);
3314 JS_PUBLIC_API(JSBool
)
3315 JS_DefinePropertyById(JSContext
*cx
, JSObject
*obj
, jsid id
, jsval value
,
3316 JSPropertyOp getter
, JSStrictPropertyOp setter
, uintN attrs
)
3318 return DefinePropertyById(cx
, obj
, id
, Valueify(value
), Valueify(getter
),
3319 Valueify(setter
), attrs
, 0, 0);
3322 JS_PUBLIC_API(JSBool
)
3323 JS_DefineElement(JSContext
*cx
, JSObject
*obj
, jsint index
, jsval value
,
3324 JSPropertyOp getter
, JSStrictPropertyOp setter
, uintN attrs
)
3326 return DefinePropertyById(cx
, obj
, INT_TO_JSID(index
), Valueify(value
),
3327 Valueify(getter
), Valueify(setter
), attrs
, 0, 0);
3331 DefineProperty(JSContext
*cx
, JSObject
*obj
, const char *name
, const Value
&value
,
3332 PropertyOp getter
, StrictPropertyOp setter
, uintN attrs
,
3333 uintN flags
, intN tinyid
)
3338 if (attrs
& JSPROP_INDEX
) {
3339 id
= INT_TO_JSID(intptr_t(name
));
3341 attrs
&= ~JSPROP_INDEX
;
3343 atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3346 id
= ATOM_TO_JSID(atom
);
3348 return DefinePropertyById(cx
, obj
, id
, value
, getter
, setter
, attrs
, flags
, tinyid
);
3351 JS_PUBLIC_API(JSBool
)
3352 JS_DefineProperty(JSContext
*cx
, JSObject
*obj
, const char *name
, jsval value
,
3353 JSPropertyOp getter
, JSStrictPropertyOp setter
, uintN attrs
)
3355 return DefineProperty(cx
, obj
, name
, Valueify(value
), Valueify(getter
),
3356 Valueify(setter
), attrs
, 0, 0);
3359 JS_PUBLIC_API(JSBool
)
3360 JS_DefinePropertyWithTinyId(JSContext
*cx
, JSObject
*obj
, const char *name
, int8 tinyid
,
3361 jsval value
, JSPropertyOp getter
, JSStrictPropertyOp setter
, uintN attrs
)
3363 return DefineProperty(cx
, obj
, name
, Valueify(value
), Valueify(getter
),
3364 Valueify(setter
), attrs
, Shape::HAS_SHORTID
, tinyid
);
3368 DefineUCProperty(JSContext
*cx
, JSObject
*obj
, const jschar
*name
, size_t namelen
,
3369 const Value
&value
, PropertyOp getter
, StrictPropertyOp setter
, uintN attrs
,
3370 uintN flags
, intN tinyid
)
3372 JSAtom
*atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
3373 return atom
&& DefinePropertyById(cx
, obj
, ATOM_TO_JSID(atom
), value
, getter
, setter
, attrs
,
3377 JS_PUBLIC_API(JSBool
)
3378 JS_DefineUCProperty(JSContext
*cx
, JSObject
*obj
, const jschar
*name
, size_t namelen
,
3379 jsval value
, JSPropertyOp getter
, JSStrictPropertyOp setter
, uintN attrs
)
3381 return DefineUCProperty(cx
, obj
, name
, namelen
, Valueify(value
),
3382 Valueify(getter
), Valueify(setter
), attrs
, 0, 0);
3385 JS_PUBLIC_API(JSBool
)
3386 JS_DefineUCPropertyWithTinyId(JSContext
*cx
, JSObject
*obj
, const jschar
*name
, size_t namelen
,
3387 int8 tinyid
, jsval value
,
3388 JSPropertyOp getter
, JSStrictPropertyOp setter
, uintN attrs
)
3390 return DefineUCProperty(cx
, obj
, name
, namelen
, Valueify(value
), Valueify(getter
),
3391 Valueify(setter
), attrs
, Shape::HAS_SHORTID
, tinyid
);
3394 JS_PUBLIC_API(JSBool
)
3395 JS_DefineOwnProperty(JSContext
*cx
, JSObject
*obj
, jsid id
, jsval descriptor
, JSBool
*bp
)
3398 assertSameCompartment(cx
, obj
, id
, descriptor
);
3399 return js_DefineOwnProperty(cx
, obj
, id
, Valueify(descriptor
), bp
);
3402 JS_PUBLIC_API(JSObject
*)
3403 JS_DefineObject(JSContext
*cx
, JSObject
*obj
, const char *name
, JSClass
*jsclasp
,
3404 JSObject
*proto
, uintN attrs
)
3407 assertSameCompartment(cx
, obj
, proto
);
3409 Class
*clasp
= Valueify(jsclasp
);
3411 clasp
= &js_ObjectClass
; /* default class is Object */
3413 JSObject
*nobj
= NewObject
<WithProto::Class
>(cx
, clasp
, proto
, obj
);
3417 nobj
->syncSpecialEquality();
3419 if (!DefineProperty(cx
, obj
, name
, ObjectValue(*nobj
), NULL
, NULL
, attrs
, 0, 0))
3425 JS_PUBLIC_API(JSBool
)
3426 JS_DefineConstDoubles(JSContext
*cx
, JSObject
*obj
, JSConstDoubleSpec
*cds
)
3432 for (ok
= JS_TRUE
; cds
->name
; cds
++) {
3433 Value value
= DoubleValue(cds
->dval
);
3436 attrs
= JSPROP_READONLY
| JSPROP_PERMANENT
;
3437 ok
= DefineProperty(cx
, obj
, cds
->name
, value
, NULL
, NULL
, attrs
, 0, 0);
3444 JS_PUBLIC_API(JSBool
)
3445 JS_DefineProperties(JSContext
*cx
, JSObject
*obj
, JSPropertySpec
*ps
)
3449 for (ok
= true; ps
->name
; ps
++) {
3450 ok
= DefineProperty(cx
, obj
, ps
->name
, UndefinedValue(),
3451 Valueify(ps
->getter
), Valueify(ps
->setter
),
3452 ps
->flags
, Shape::HAS_SHORTID
, ps
->tinyid
);
3459 JS_PUBLIC_API(JSBool
)
3460 JS_AliasProperty(JSContext
*cx
, JSObject
*obj
, const char *name
, const char *alias
)
3468 assertSameCompartment(cx
, obj
);
3470 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3473 if (!LookupPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), JSRESOLVE_QUALIFIED
, &obj2
, &prop
))
3476 js_ReportIsNotDefined(cx
, name
);
3479 if (obj2
!= obj
|| !obj
->isNative()) {
3480 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_CANT_ALIAS
,
3481 alias
, name
, obj2
->getClass()->name
);
3484 atom
= js_Atomize(cx
, alias
, strlen(alias
), 0);
3488 shape
= (Shape
*)prop
;
3489 ok
= (js_AddNativeProperty(cx
, obj
, ATOM_TO_JSID(atom
),
3490 shape
->getter(), shape
->setter(), shape
->slot
,
3491 shape
->attributes(), shape
->getFlags() | Shape::ALIAS
,
3498 JS_PUBLIC_API(JSBool
)
3499 JS_AliasElement(JSContext
*cx
, JSObject
*obj
, const char *name
, jsint alias
)
3506 assertSameCompartment(cx
, obj
);
3508 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3511 if (!LookupPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), JSRESOLVE_QUALIFIED
, &obj2
, &prop
))
3514 js_ReportIsNotDefined(cx
, name
);
3517 if (obj2
!= obj
|| !obj
->isNative()) {
3519 JS_snprintf(numBuf
, sizeof numBuf
, "%ld", (long)alias
);
3520 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_CANT_ALIAS
,
3521 numBuf
, name
, obj2
->getClass()->name
);
3524 shape
= (Shape
*)prop
;
3525 return js_AddNativeProperty(cx
, obj
, INT_TO_JSID(alias
),
3526 shape
->getter(), shape
->setter(), shape
->slot
,
3527 shape
->attributes(), shape
->getFlags() | Shape::ALIAS
,
3533 GetPropertyDescriptorById(JSContext
*cx
, JSObject
*obj
, jsid id
, uintN flags
,
3534 JSBool own
, PropertyDescriptor
*desc
)
3539 if (!LookupPropertyById(cx
, obj
, id
, flags
, &obj2
, &prop
))
3542 if (!prop
|| (own
&& obj
!= obj2
)) {
3545 desc
->getter
= NULL
;
3546 desc
->setter
= NULL
;
3547 desc
->value
.setUndefined();
3552 if (obj2
->isNative()) {
3553 Shape
*shape
= (Shape
*) prop
;
3554 desc
->attrs
= shape
->attributes();
3556 if (shape
->isMethod()) {
3557 desc
->getter
= PropertyStub
;
3558 desc
->setter
= StrictPropertyStub
;
3559 desc
->value
.setObject(shape
->methodObject());
3561 desc
->getter
= shape
->getter();
3562 desc
->setter
= shape
->setter();
3563 if (obj2
->containsSlot(shape
->slot
))
3564 desc
->value
= obj2
->nativeGetSlot(shape
->slot
);
3566 desc
->value
.setUndefined();
3569 if (obj2
->isProxy()) {
3570 JSAutoResolveFlags
rf(cx
, flags
);
3572 ? JSProxy::getOwnPropertyDescriptor(cx
, obj2
, id
, false, desc
)
3573 : JSProxy::getPropertyDescriptor(cx
, obj2
, id
, false, desc
);
3575 if (!obj2
->getAttributes(cx
, id
, &desc
->attrs
))
3577 desc
->getter
= NULL
;
3578 desc
->setter
= NULL
;
3579 desc
->value
.setUndefined();
3584 JS_PUBLIC_API(JSBool
)
3585 JS_GetPropertyDescriptorById(JSContext
*cx
, JSObject
*obj
, jsid id
, uintN flags
,
3586 JSPropertyDescriptor
*desc
)
3588 return GetPropertyDescriptorById(cx
, obj
, id
, flags
, JS_FALSE
, Valueify(desc
));
3591 JS_PUBLIC_API(JSBool
)
3592 JS_GetPropertyAttrsGetterAndSetterById(JSContext
*cx
, JSObject
*obj
, jsid id
,
3593 uintN
*attrsp
, JSBool
*foundp
,
3594 JSPropertyOp
*getterp
, JSStrictPropertyOp
*setterp
)
3596 PropertyDescriptor desc
;
3597 if (!GetPropertyDescriptorById(cx
, obj
, id
, JSRESOLVE_QUALIFIED
, JS_FALSE
, &desc
))
3600 *attrsp
= desc
.attrs
;
3601 *foundp
= (desc
.obj
!= NULL
);
3603 *getterp
= Jsvalify(desc
.getter
);
3605 *setterp
= Jsvalify(desc
.setter
);
3609 JS_PUBLIC_API(JSBool
)
3610 JS_GetPropertyAttributes(JSContext
*cx
, JSObject
*obj
, const char *name
,
3611 uintN
*attrsp
, JSBool
*foundp
)
3613 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3614 return atom
&& JS_GetPropertyAttrsGetterAndSetterById(cx
, obj
, ATOM_TO_JSID(atom
),
3615 attrsp
, foundp
, NULL
, NULL
);
3618 JS_PUBLIC_API(JSBool
)
3619 JS_GetUCPropertyAttributes(JSContext
*cx
, JSObject
*obj
, const jschar
*name
, size_t namelen
,
3620 uintN
*attrsp
, JSBool
*foundp
)
3622 JSAtom
*atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
3623 return atom
&& JS_GetPropertyAttrsGetterAndSetterById(cx
, obj
, ATOM_TO_JSID(atom
),
3624 attrsp
, foundp
, NULL
, NULL
);
3627 JS_PUBLIC_API(JSBool
)
3628 JS_GetPropertyAttrsGetterAndSetter(JSContext
*cx
, JSObject
*obj
, const char *name
,
3629 uintN
*attrsp
, JSBool
*foundp
,
3630 JSPropertyOp
*getterp
, JSStrictPropertyOp
*setterp
)
3632 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3633 return atom
&& JS_GetPropertyAttrsGetterAndSetterById(cx
, obj
, ATOM_TO_JSID(atom
),
3634 attrsp
, foundp
, getterp
, setterp
);
3637 JS_PUBLIC_API(JSBool
)
3638 JS_GetUCPropertyAttrsGetterAndSetter(JSContext
*cx
, JSObject
*obj
,
3639 const jschar
*name
, size_t namelen
,
3640 uintN
*attrsp
, JSBool
*foundp
,
3641 JSPropertyOp
*getterp
, JSStrictPropertyOp
*setterp
)
3643 JSAtom
*atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
3644 return atom
&& JS_GetPropertyAttrsGetterAndSetterById(cx
, obj
, ATOM_TO_JSID(atom
),
3645 attrsp
, foundp
, getterp
, setterp
);
3648 JS_PUBLIC_API(JSBool
)
3649 JS_GetOwnPropertyDescriptor(JSContext
*cx
, JSObject
*obj
, jsid id
, jsval
*vp
)
3652 return js_GetOwnPropertyDescriptor(cx
, obj
, id
, Valueify(vp
));
3656 SetPropertyAttributesById(JSContext
*cx
, JSObject
*obj
, jsid id
, uintN attrs
, JSBool
*foundp
)
3661 if (!LookupPropertyById(cx
, obj
, id
, JSRESOLVE_QUALIFIED
, &obj2
, &prop
))
3663 if (!prop
|| obj
!= obj2
) {
3667 JSBool ok
= obj
->isNative()
3668 ? js_SetNativeAttributes(cx
, obj
, (Shape
*) prop
, attrs
)
3669 : obj
->setAttributes(cx
, id
, &attrs
);
3675 JS_PUBLIC_API(JSBool
)
3676 JS_SetPropertyAttributes(JSContext
*cx
, JSObject
*obj
, const char *name
,
3677 uintN attrs
, JSBool
*foundp
)
3679 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3680 return atom
&& SetPropertyAttributesById(cx
, obj
, ATOM_TO_JSID(atom
), attrs
, foundp
);
3683 JS_PUBLIC_API(JSBool
)
3684 JS_SetUCPropertyAttributes(JSContext
*cx
, JSObject
*obj
, const jschar
*name
, size_t namelen
,
3685 uintN attrs
, JSBool
*foundp
)
3687 JSAtom
*atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
3688 return atom
&& SetPropertyAttributesById(cx
, obj
, ATOM_TO_JSID(atom
), attrs
, foundp
);
3691 JS_PUBLIC_API(JSBool
)
3692 JS_GetPropertyById(JSContext
*cx
, JSObject
*obj
, jsid id
, jsval
*vp
)
3695 assertSameCompartment(cx
, obj
, id
);
3696 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
);
3697 return obj
->getProperty(cx
, id
, Valueify(vp
));
3700 JS_PUBLIC_API(JSBool
)
3701 JS_GetPropertyByIdDefault(JSContext
*cx
, JSObject
*obj
, jsid id
, jsval def
, jsval
*vp
)
3703 return GetPropertyDefault(cx
, obj
, id
, Valueify(def
), Valueify(vp
));
3706 JS_PUBLIC_API(JSBool
)
3707 JS_GetElement(JSContext
*cx
, JSObject
*obj
, jsint index
, jsval
*vp
)
3709 return JS_GetPropertyById(cx
, obj
, INT_TO_JSID(index
), vp
);
3712 JS_PUBLIC_API(JSBool
)
3713 JS_GetProperty(JSContext
*cx
, JSObject
*obj
, const char *name
, jsval
*vp
)
3715 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3716 return atom
&& JS_GetPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), vp
);
3719 JS_PUBLIC_API(JSBool
)
3720 JS_GetPropertyDefault(JSContext
*cx
, JSObject
*obj
, const char *name
, jsval def
, jsval
*vp
)
3722 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3723 return atom
&& JS_GetPropertyByIdDefault(cx
, obj
, ATOM_TO_JSID(atom
), def
, vp
);
3726 JS_PUBLIC_API(JSBool
)
3727 JS_GetUCProperty(JSContext
*cx
, JSObject
*obj
, const jschar
*name
, size_t namelen
, jsval
*vp
)
3729 JSAtom
*atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
3730 return atom
&& JS_GetPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), vp
);
3733 JS_PUBLIC_API(JSBool
)
3734 JS_GetMethodById(JSContext
*cx
, JSObject
*obj
, jsid id
, JSObject
**objp
, jsval
*vp
)
3737 assertSameCompartment(cx
, obj
, id
);
3738 if (!js_GetMethod(cx
, obj
, id
, JSGET_METHOD_BARRIER
, Valueify(vp
)))
3745 JS_PUBLIC_API(JSBool
)
3746 JS_GetMethod(JSContext
*cx
, JSObject
*obj
, const char *name
, JSObject
**objp
, jsval
*vp
)
3748 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3749 return atom
&& JS_GetMethodById(cx
, obj
, ATOM_TO_JSID(atom
), objp
, vp
);
3752 JS_PUBLIC_API(JSBool
)
3753 JS_SetPropertyById(JSContext
*cx
, JSObject
*obj
, jsid id
, jsval
*vp
)
3756 assertSameCompartment(cx
, obj
, id
);
3757 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
| JSRESOLVE_ASSIGNING
);
3758 return obj
->setProperty(cx
, id
, Valueify(vp
), false);
3761 JS_PUBLIC_API(JSBool
)
3762 JS_SetElement(JSContext
*cx
, JSObject
*obj
, jsint index
, jsval
*vp
)
3764 return JS_SetPropertyById(cx
, obj
, INT_TO_JSID(index
), vp
);
3767 JS_PUBLIC_API(JSBool
)
3768 JS_SetProperty(JSContext
*cx
, JSObject
*obj
, const char *name
, jsval
*vp
)
3770 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3771 return atom
&& JS_SetPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), vp
);
3774 JS_PUBLIC_API(JSBool
)
3775 JS_SetUCProperty(JSContext
*cx
, JSObject
*obj
, const jschar
*name
, size_t namelen
, jsval
*vp
)
3777 JSAtom
*atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
3778 return atom
&& JS_SetPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), vp
);
3781 JS_PUBLIC_API(JSBool
)
3782 JS_DeletePropertyById2(JSContext
*cx
, JSObject
*obj
, jsid id
, jsval
*rval
)
3785 assertSameCompartment(cx
, obj
, id
);
3786 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
);
3787 return obj
->deleteProperty(cx
, id
, Valueify(rval
), false);
3790 JS_PUBLIC_API(JSBool
)
3791 JS_DeleteElement2(JSContext
*cx
, JSObject
*obj
, jsint index
, jsval
*rval
)
3793 return JS_DeletePropertyById2(cx
, obj
, INT_TO_JSID(index
), rval
);
3796 JS_PUBLIC_API(JSBool
)
3797 JS_DeleteProperty2(JSContext
*cx
, JSObject
*obj
, const char *name
, jsval
*rval
)
3799 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3800 return atom
&& JS_DeletePropertyById2(cx
, obj
, ATOM_TO_JSID(atom
), rval
);
3803 JS_PUBLIC_API(JSBool
)
3804 JS_DeleteUCProperty2(JSContext
*cx
, JSObject
*obj
, const jschar
*name
, size_t namelen
, jsval
*rval
)
3806 JSAtom
*atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
3807 return atom
&& JS_DeletePropertyById2(cx
, obj
, ATOM_TO_JSID(atom
), rval
);
3810 JS_PUBLIC_API(JSBool
)
3811 JS_DeletePropertyById(JSContext
*cx
, JSObject
*obj
, jsid id
)
3814 return JS_DeletePropertyById2(cx
, obj
, id
, &junk
);
3817 JS_PUBLIC_API(JSBool
)
3818 JS_DeleteElement(JSContext
*cx
, JSObject
*obj
, jsint index
)
3821 return JS_DeleteElement2(cx
, obj
, index
, &junk
);
3824 JS_PUBLIC_API(JSBool
)
3825 JS_DeleteProperty(JSContext
*cx
, JSObject
*obj
, const char *name
)
3828 return JS_DeleteProperty2(cx
, obj
, name
, &junk
);
3832 JS_ClearScope(JSContext
*cx
, JSObject
*obj
)
3835 assertSameCompartment(cx
, obj
);
3837 JSFinalizeOp clearOp
= obj
->getOps()->clear
;
3841 if (obj
->isNative())
3842 js_ClearNative(cx
, obj
);
3844 /* Clear cached class objects on the global object. */
3845 if (obj
->isGlobal()) {
3846 /* This can return false but that doesn't mean it failed. */
3849 for (int key
= JSProto_Null
; key
< JSProto_LIMIT
* 3; key
++)
3850 JS_SetReservedSlot(cx
, obj
, key
, JSVAL_VOID
);
3852 /* Clear regexp statics. */
3853 RegExpStatics::extractFrom(obj
)->clear();
3855 /* Clear the CSP eval-is-allowed cache. */
3856 JS_SetReservedSlot(cx
, obj
, JSRESERVED_GLOBAL_EVAL_ALLOWED
, JSVAL_VOID
);
3859 * Mark global as cleared. If we try to execute any compile-and-go
3860 * scripts from here on, we will throw.
3862 int32 flags
= obj
->getReservedSlot(JSRESERVED_GLOBAL_FLAGS
).toInt32();
3863 flags
|= JSGLOBAL_FLAGS_CLEARED
;
3864 JS_SetReservedSlot(cx
, obj
, JSRESERVED_GLOBAL_FLAGS
, Jsvalify(Int32Value(flags
)));
3870 JS_PUBLIC_API(JSIdArray
*)
3871 JS_Enumerate(JSContext
*cx
, JSObject
*obj
)
3874 assertSameCompartment(cx
, obj
);
3876 AutoIdVector
props(cx
);
3878 if (!GetPropertyNames(cx
, obj
, JSITER_OWNONLY
, &props
) || !VectorToIdArray(cx
, props
, &ida
))
3880 for (size_t n
= 0; n
< size_t(ida
->length
); ++n
)
3881 JS_ASSERT(js_CheckForStringIndex(ida
->vector
[n
]) == ida
->vector
[n
]);
3886 * XXX reverse iterator for properties, unreverse and meld with jsinterp.c's
3887 * prop_iterator_class somehow...
3888 * + preserve the obj->enumerate API while optimizing the native object case
3889 * + native case here uses a Shape *, but that iterates in reverse!
3890 * + so we make non-native match, by reverse-iterating after JS_Enumerating
3892 const uint32 JSSLOT_ITER_INDEX
= 0;
3895 prop_iter_finalize(JSContext
*cx
, JSObject
*obj
)
3897 void *pdata
= obj
->getPrivate();
3901 if (obj
->getSlot(JSSLOT_ITER_INDEX
).toInt32() >= 0) {
3902 /* Non-native case: destroy the ida enumerated when obj was created. */
3903 JSIdArray
*ida
= (JSIdArray
*) pdata
;
3904 JS_DestroyIdArray(cx
, ida
);
3909 prop_iter_trace(JSTracer
*trc
, JSObject
*obj
)
3911 void *pdata
= obj
->getPrivate();
3915 if (obj
->getSlot(JSSLOT_ITER_INDEX
).toInt32() < 0) {
3916 /* Native case: just mark the next property to visit. */
3917 ((Shape
*) pdata
)->trace(trc
);
3919 /* Non-native case: mark each id in the JSIdArray private. */
3920 JSIdArray
*ida
= (JSIdArray
*) pdata
;
3921 MarkIdRange(trc
, ida
->length
, ida
->vector
, "prop iter");
3925 static Class prop_iter_class
= {
3927 JSCLASS_HAS_PRIVATE
| JSCLASS_HAS_RESERVED_SLOTS(1) |
3928 JSCLASS_MARK_IS_TRACE
,
3929 PropertyStub
, /* addProperty */
3930 PropertyStub
, /* delProperty */
3931 PropertyStub
, /* getProperty */
3932 StrictPropertyStub
, /* setProperty */
3937 NULL
, /* reserved0 */
3938 NULL
, /* checkAccess */
3940 NULL
, /* construct */
3941 NULL
, /* xdrObject */
3942 NULL
, /* hasInstance */
3943 JS_CLASS_TRACE(prop_iter_trace
)
3946 JS_PUBLIC_API(JSObject
*)
3947 JS_NewPropertyIterator(JSContext
*cx
, JSObject
*obj
)
3955 assertSameCompartment(cx
, obj
);
3956 iterobj
= NewNonFunction
<WithProto::Class
>(cx
, &prop_iter_class
, NULL
, obj
);
3960 if (obj
->isNative()) {
3961 /* Native case: start with the last property in obj. */
3962 pdata
= obj
->lastProperty();
3966 * Non-native case: enumerate a JSIdArray and keep it via private.
3968 * Note: we have to make sure that we root obj around the call to
3969 * JS_Enumerate to protect against multiple allocations under it.
3971 AutoObjectRooter
tvr(cx
, iterobj
);
3972 ida
= JS_Enumerate(cx
, obj
);
3976 index
= ida
->length
;
3979 /* iterobj cannot escape to other threads here. */
3980 iterobj
->setPrivate(const_cast<void *>(pdata
));
3981 iterobj
->getSlotRef(JSSLOT_ITER_INDEX
).setInt32(index
);
3985 JS_PUBLIC_API(JSBool
)
3986 JS_NextProperty(JSContext
*cx
, JSObject
*iterobj
, jsid
*idp
)
3993 assertSameCompartment(cx
, iterobj
);
3994 i
= iterobj
->getSlot(JSSLOT_ITER_INDEX
).toInt32();
3996 /* Native case: private data is a property tree node pointer. */
3997 JS_ASSERT(iterobj
->getParent()->isNative());
3998 shape
= (Shape
*) iterobj
->getPrivate();
4000 while (shape
->previous() && (!shape
->enumerable() || shape
->isAlias()))
4001 shape
= shape
->previous();
4003 if (!shape
->previous()) {
4004 JS_ASSERT(JSID_IS_EMPTY(shape
->id
));
4007 iterobj
->setPrivate(const_cast<Shape
*>(shape
->previous()));
4011 /* Non-native case: use the ida enumerated when iterobj was created. */
4012 ida
= (JSIdArray
*) iterobj
->getPrivate();
4013 JS_ASSERT(i
<= ida
->length
);
4014 STATIC_ASSUME(i
<= ida
->length
);
4018 *idp
= ida
->vector
[--i
];
4019 iterobj
->setSlot(JSSLOT_ITER_INDEX
, Int32Value(i
));
4025 JS_PUBLIC_API(JSBool
)
4026 JS_GetReservedSlot(JSContext
*cx
, JSObject
*obj
, uint32 index
, jsval
*vp
)
4029 assertSameCompartment(cx
, obj
);
4030 return js_GetReservedSlot(cx
, obj
, index
, Valueify(vp
));
4033 JS_PUBLIC_API(JSBool
)
4034 JS_SetReservedSlot(JSContext
*cx
, JSObject
*obj
, uint32 index
, jsval v
)
4037 assertSameCompartment(cx
, obj
, v
);
4038 return js_SetReservedSlot(cx
, obj
, index
, Valueify(v
));
4041 JS_PUBLIC_API(JSObject
*)
4042 JS_NewArrayObject(JSContext
*cx
, jsint length
, jsval
*vector
)
4044 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
4046 /* NB: jsuint cast does ToUint32. */
4047 assertSameCompartment(cx
, JSValueArray(vector
, vector
? (jsuint
)length
: 0));
4048 return NewDenseCopiedArray(cx
, (jsuint
)length
, Valueify(vector
));
4051 JS_PUBLIC_API(JSBool
)
4052 JS_IsArrayObject(JSContext
*cx
, JSObject
*obj
)
4054 assertSameCompartment(cx
, obj
);
4055 return obj
->isArray() ||
4056 (obj
->isWrapper() && JSWrapper::wrappedObject(obj
)->isArray());
4059 JS_PUBLIC_API(JSBool
)
4060 JS_GetArrayLength(JSContext
*cx
, JSObject
*obj
, jsuint
*lengthp
)
4063 assertSameCompartment(cx
, obj
);
4064 return js_GetLengthProperty(cx
, obj
, lengthp
);
4067 JS_PUBLIC_API(JSBool
)
4068 JS_SetArrayLength(JSContext
*cx
, JSObject
*obj
, jsuint length
)
4071 assertSameCompartment(cx
, obj
);
4072 return js_SetLengthProperty(cx
, obj
, length
);
4075 JS_PUBLIC_API(JSBool
)
4076 JS_HasArrayLength(JSContext
*cx
, JSObject
*obj
, jsuint
*lengthp
)
4079 assertSameCompartment(cx
, obj
);
4080 return js_HasLengthProperty(cx
, obj
, lengthp
);
4083 JS_PUBLIC_API(JSBool
)
4084 JS_CheckAccess(JSContext
*cx
, JSObject
*obj
, jsid id
, JSAccessMode mode
,
4085 jsval
*vp
, uintN
*attrsp
)
4088 assertSameCompartment(cx
, obj
, id
);
4089 return CheckAccess(cx
, obj
, id
, mode
, Valueify(vp
), attrsp
);
4092 #ifdef JS_THREADSAFE
4093 JS_PUBLIC_API(jsrefcount
)
4094 JS_HoldPrincipals(JSContext
*cx
, JSPrincipals
*principals
)
4096 return JS_ATOMIC_INCREMENT(&principals
->refcount
);
4099 JS_PUBLIC_API(jsrefcount
)
4100 JS_DropPrincipals(JSContext
*cx
, JSPrincipals
*principals
)
4102 jsrefcount rc
= JS_ATOMIC_DECREMENT(&principals
->refcount
);
4104 principals
->destroy(cx
, principals
);
4109 JS_PUBLIC_API(JSSecurityCallbacks
*)
4110 JS_SetRuntimeSecurityCallbacks(JSRuntime
*rt
, JSSecurityCallbacks
*callbacks
)
4112 JSSecurityCallbacks
*oldcallbacks
;
4114 oldcallbacks
= rt
->securityCallbacks
;
4115 rt
->securityCallbacks
= callbacks
;
4116 return oldcallbacks
;
4119 JS_PUBLIC_API(JSSecurityCallbacks
*)
4120 JS_GetRuntimeSecurityCallbacks(JSRuntime
*rt
)
4122 return rt
->securityCallbacks
;
4125 JS_PUBLIC_API(JSSecurityCallbacks
*)
4126 JS_SetContextSecurityCallbacks(JSContext
*cx
, JSSecurityCallbacks
*callbacks
)
4128 JSSecurityCallbacks
*oldcallbacks
;
4130 oldcallbacks
= cx
->securityCallbacks
;
4131 cx
->securityCallbacks
= callbacks
;
4132 return oldcallbacks
;
4135 JS_PUBLIC_API(JSSecurityCallbacks
*)
4136 JS_GetSecurityCallbacks(JSContext
*cx
)
4138 return cx
->securityCallbacks
4139 ? cx
->securityCallbacks
4140 : cx
->runtime
->securityCallbacks
;
4143 JS_PUBLIC_API(JSFunction
*)
4144 JS_NewFunction(JSContext
*cx
, JSNative native
, uintN nargs
, uintN flags
,
4145 JSObject
*parent
, const char *name
)
4147 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
4151 assertSameCompartment(cx
, parent
);
4156 atom
= js_Atomize(cx
, name
, strlen(name
), 0);
4160 return js_NewFunction(cx
, NULL
, Valueify(native
), nargs
, flags
, parent
, atom
);
4163 JS_PUBLIC_API(JSFunction
*)
4164 JS_NewFunctionById(JSContext
*cx
, JSNative native
, uintN nargs
, uintN flags
, JSObject
*parent
,
4167 JS_ASSERT(JSID_IS_STRING(id
));
4168 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
4170 assertSameCompartment(cx
, parent
);
4172 return js_NewFunction(cx
, NULL
, Valueify(native
), nargs
, flags
, parent
, JSID_TO_ATOM(id
));
4175 JS_PUBLIC_API(JSObject
*)
4176 JS_CloneFunctionObject(JSContext
*cx
, JSObject
*funobj
, JSObject
*parent
)
4179 assertSameCompartment(cx
, parent
); // XXX no funobj for now
4182 parent
= GetScopeChain(cx
, cx
->fp());
4184 parent
= cx
->globalObject
;
4188 if (funobj
->getClass() != &js_FunctionClass
) {
4190 * We cannot clone this object, so fail (we used to return funobj, bad
4191 * idea, but we changed incompatibly to teach any abusers a lesson!).
4193 Value v
= ObjectValue(*funobj
);
4194 js_ReportIsNotFunction(cx
, &v
, 0);
4198 JSFunction
*fun
= GET_FUNCTION_PRIVATE(cx
, funobj
);
4199 if (!FUN_FLAT_CLOSURE(fun
))
4200 return CloneFunctionObject(cx
, fun
, parent
);
4203 * A flat closure carries its own environment, so why clone it? In case
4204 * someone wants to mutate its fixed slots or add ad-hoc properties. API
4205 * compatibility suggests we not return funobj and let callers mutate the
4206 * returned object at will.
4208 * But it's worse than that: API compatibility according to the test for
4209 * bug 300079 requires we get "upvars" from parent and its ancestors! So
4210 * we do that (grudgingly!). The scope chain ancestors are searched as if
4211 * they were activations, respecting the skip field in each upvar's cookie
4212 * but looking up the property by name instead of frame slot.
4214 JSObject
*clone
= js_AllocFlatClosure(cx
, fun
, parent
);
4218 JSUpvarArray
*uva
= fun
->u
.i
.script
->upvars();
4219 uint32 i
= uva
->length
;
4222 for (Shape::Range
r(fun
->script()->bindings
.lastUpvar()); i
-- != 0; r
.popFront()) {
4223 JSObject
*obj
= parent
;
4224 int skip
= uva
->vector
[i
].level();
4225 while (--skip
> 0) {
4227 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
,
4228 JSMSG_BAD_CLONE_FUNOBJ_SCOPE
);
4231 obj
= obj
->getParent();
4234 if (!obj
->getProperty(cx
, r
.front().id
, clone
->getFlatClosureUpvars() + i
))
4241 JS_PUBLIC_API(JSObject
*)
4242 JS_GetFunctionObject(JSFunction
*fun
)
4244 return FUN_OBJECT(fun
);
4247 JS_PUBLIC_API(JSString
*)
4248 JS_GetFunctionId(JSFunction
*fun
)
4250 return fun
->atom
? ATOM_TO_STRING(fun
->atom
) : NULL
;
4253 JS_PUBLIC_API(uintN
)
4254 JS_GetFunctionFlags(JSFunction
*fun
)
4259 JS_PUBLIC_API(uint16
)
4260 JS_GetFunctionArity(JSFunction
*fun
)
4265 JS_PUBLIC_API(JSBool
)
4266 JS_ObjectIsFunction(JSContext
*cx
, JSObject
*obj
)
4268 return obj
->getClass() == &js_FunctionClass
;
4271 JS_PUBLIC_API(JSBool
)
4272 JS_ObjectIsCallable(JSContext
*cx
, JSObject
*obj
)
4274 return obj
->isCallable();
4278 js_generic_native_method_dispatcher(JSContext
*cx
, uintN argc
, Value
*vp
)
4280 JSFunctionSpec
*fs
= (JSFunctionSpec
*) vp
->toObject().getReservedSlot(0).toPrivate();
4281 JS_ASSERT((fs
->flags
& JSFUN_GENERIC_NATIVE
) != 0);
4284 js_ReportMissingArg(cx
, *vp
, 0);
4289 * Copy all actual (argc) arguments down over our |this| parameter, vp[1],
4290 * which is almost always the class constructor object, e.g. Array. Then
4291 * call the corresponding prototype native method with our first argument
4294 memmove(vp
+ 1, vp
+ 2, argc
* sizeof(jsval
));
4296 /* Clear the last parameter in case too few arguments were passed. */
4297 vp
[2 + --argc
].setUndefined();
4301 (fs
->flags
& JSFUN_TRCINFO
)
4302 ? JS_FUNC_TO_DATA_PTR(JSNativeTraceInfo
*, fs
->call
)->native
4306 return native(cx
, argc
, vp
);
4309 JS_PUBLIC_API(JSBool
)
4310 JS_DefineFunctions(JSContext
*cx
, JSObject
*obj
, JSFunctionSpec
*fs
)
4312 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
4318 assertSameCompartment(cx
, obj
);
4320 for (; fs
->name
; fs
++) {
4324 * Define a generic arity N+1 static method for the arity N prototype
4325 * method if flags contains JSFUN_GENERIC_NATIVE.
4327 if (flags
& JSFUN_GENERIC_NATIVE
) {
4329 ctor
= JS_GetConstructor(cx
, obj
);
4334 flags
&= ~JSFUN_GENERIC_NATIVE
;
4335 fun
= JS_DefineFunction(cx
, ctor
, fs
->name
,
4336 Jsvalify(js_generic_native_method_dispatcher
),
4338 flags
& ~JSFUN_TRCINFO
);
4343 * As jsapi.h notes, fs must point to storage that lives as long
4344 * as fun->object lives.
4346 Value priv
= PrivateValue(fs
);
4347 if (!js_SetReservedSlot(cx
, FUN_OBJECT(fun
), 0, priv
))
4351 fun
= JS_DefineFunction(cx
, obj
, fs
->name
, fs
->call
, fs
->nargs
, flags
);
4358 JS_PUBLIC_API(JSFunction
*)
4359 JS_DefineFunction(JSContext
*cx
, JSObject
*obj
, const char *name
, JSNative call
,
4360 uintN nargs
, uintN attrs
)
4362 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
4364 assertSameCompartment(cx
, obj
);
4365 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
4368 return js_DefineFunction(cx
, obj
, ATOM_TO_JSID(atom
), Valueify(call
), nargs
, attrs
);
4371 JS_PUBLIC_API(JSFunction
*)
4372 JS_DefineUCFunction(JSContext
*cx
, JSObject
*obj
,
4373 const jschar
*name
, size_t namelen
, JSNative call
,
4374 uintN nargs
, uintN attrs
)
4376 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
4378 assertSameCompartment(cx
, obj
);
4379 JSAtom
*atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
4382 return js_DefineFunction(cx
, obj
, ATOM_TO_JSID(atom
), Valueify(call
), nargs
, attrs
);
4385 extern JS_PUBLIC_API(JSFunction
*)
4386 JS_DefineFunctionById(JSContext
*cx
, JSObject
*obj
, jsid id
, JSNative call
,
4387 uintN nargs
, uintN attrs
)
4389 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
4391 assertSameCompartment(cx
, obj
);
4392 return js_DefineFunction(cx
, obj
, id
, Valueify(call
), nargs
, attrs
);
4396 LAST_FRAME_EXCEPTION_CHECK(JSContext
*cx
, bool result
)
4398 if (!result
&& !cx
->hasRunOption(JSOPTION_DONT_REPORT_UNCAUGHT
))
4399 js_ReportUncaughtException(cx
);
4403 LAST_FRAME_CHECKS(JSContext
*cx
, bool result
)
4405 if (!JS_IsRunning(cx
)) {
4406 LAST_FRAME_EXCEPTION_CHECK(cx
, result
);
4410 inline static uint32
4411 JS_OPTIONS_TO_TCFLAGS(JSContext
*cx
)
4413 return (cx
->hasRunOption(JSOPTION_COMPILE_N_GO
) ? TCF_COMPILE_N_GO
: 0) |
4414 (cx
->hasRunOption(JSOPTION_NO_SCRIPT_RVAL
) ? TCF_NO_SCRIPT_RVAL
: 0);
4418 CompileUCScriptForPrincipalsCommon(JSContext
*cx
, JSObject
*obj
, JSPrincipals
*principals
,
4419 const jschar
*chars
, size_t length
,
4420 const char *filename
, uintN lineno
, JSVersion version
)
4422 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
4424 assertSameCompartment(cx
, obj
, principals
);
4426 uint32 tcflags
= JS_OPTIONS_TO_TCFLAGS(cx
) | TCF_NEED_MUTABLE_SCRIPT
;
4427 JSScript
*script
= Compiler::compileScript(cx
, obj
, NULL
, principals
, tcflags
,
4428 chars
, length
, filename
, lineno
, version
);
4429 if (script
&& !js_NewScriptObject(cx
, script
)) {
4430 js_DestroyScript(cx
, script
);
4433 LAST_FRAME_CHECKS(cx
, script
);
4437 extern JS_PUBLIC_API(JSScript
*)
4438 JS_CompileUCScriptForPrincipalsVersion(JSContext
*cx
, JSObject
*obj
,
4439 JSPrincipals
*principals
,
4440 const jschar
*chars
, size_t length
,
4441 const char *filename
, uintN lineno
,
4444 AutoVersionAPI
avi(cx
, version
);
4445 return CompileUCScriptForPrincipalsCommon(cx
, obj
, principals
, chars
, length
, filename
, lineno
,
4449 JS_PUBLIC_API(JSScript
*)
4450 JS_CompileUCScriptForPrincipals(JSContext
*cx
, JSObject
*obj
, JSPrincipals
*principals
,
4451 const jschar
*chars
, size_t length
,
4452 const char *filename
, uintN lineno
)
4454 return CompileUCScriptForPrincipalsCommon(cx
, obj
, principals
, chars
, length
, filename
, lineno
,
4458 JS_PUBLIC_API(JSScript
*)
4459 JS_CompileUCScript(JSContext
*cx
, JSObject
*obj
, const jschar
*chars
, size_t length
,
4460 const char *filename
, uintN lineno
)
4462 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
4463 return JS_CompileUCScriptForPrincipals(cx
, obj
, NULL
, chars
, length
, filename
, lineno
);
4466 JS_PUBLIC_API(JSScript
*)
4467 JS_CompileScriptForPrincipalsVersion(JSContext
*cx
, JSObject
*obj
,
4468 JSPrincipals
*principals
,
4469 const char *bytes
, size_t length
,
4470 const char *filename
, uintN lineno
,
4473 AutoVersionAPI
ava(cx
, version
);
4474 return JS_CompileScriptForPrincipals(cx
, obj
, principals
, bytes
, length
, filename
, lineno
);
4477 JS_PUBLIC_API(JSScript
*)
4478 JS_CompileScriptForPrincipals(JSContext
*cx
, JSObject
*obj
,
4479 JSPrincipals
*principals
,
4480 const char *bytes
, size_t length
,
4481 const char *filename
, uintN lineno
)
4483 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
4486 jschar
*chars
= js_InflateString(cx
, bytes
, &length
);
4489 JSScript
*script
= JS_CompileUCScriptForPrincipals(cx
, obj
, principals
, chars
, length
, filename
, lineno
);
4494 JS_PUBLIC_API(JSScript
*)
4495 JS_CompileScript(JSContext
*cx
, JSObject
*obj
, const char *bytes
, size_t length
,
4496 const char *filename
, uintN lineno
)
4498 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
4499 return JS_CompileScriptForPrincipals(cx
, obj
, NULL
, bytes
, length
, filename
, lineno
);
4502 JS_PUBLIC_API(JSBool
)
4503 JS_BufferIsCompilableUnit(JSContext
*cx
, JSObject
*obj
, const char *bytes
, size_t length
)
4507 JSExceptionState
*exnState
;
4508 JSErrorReporter older
;
4511 assertSameCompartment(cx
, obj
);
4512 chars
= js_InflateString(cx
, bytes
, &length
);
4517 * Return true on any out-of-memory error, so our caller doesn't try to
4518 * collect more buffered source.
4521 exnState
= JS_SaveExceptionState(cx
);
4524 if (parser
.init(chars
, length
, NULL
, 1, cx
->findVersion())) {
4525 older
= JS_SetErrorReporter(cx
, NULL
);
4526 if (!parser
.parse(obj
) &&
4527 parser
.tokenStream
.isUnexpectedEOF()) {
4529 * We ran into an error. If it was because we ran out of
4530 * source, we return false so our caller knows to try to
4531 * collect more buffered source.
4535 JS_SetErrorReporter(cx
, older
);
4539 JS_RestoreExceptionState(cx
, exnState
);
4543 /* Use the fastest available getc. */
4544 #if defined(HAVE_GETC_UNLOCKED)
4545 # define fast_getc getc_unlocked
4546 #elif defined(HAVE__GETC_NOLOCK)
4547 # define fast_getc _getc_nolock
4549 # define fast_getc getc
4553 CompileFileHelper(JSContext
*cx
, JSObject
*obj
, JSPrincipals
*principals
, uint32 tcflags
,
4554 const char* filename
, FILE *fp
)
4557 int ok
= fstat(fileno(fp
), &st
);
4562 size_t len
= st
.st_size
;
4566 /* Read in the whole file, then compile it. */
4568 JS_ASSERT(len
== 0);
4569 len
= 8; /* start with a small buffer, expand as necessary */
4571 bool hitEOF
= false;
4574 jschar
* tmpbuf
= (jschar
*) cx
->realloc(buf
, len
* sizeof(jschar
));
4587 buf
[i
++] = (jschar
) (unsigned char) c
;
4591 buf
= (jschar
*) cx
->malloc(len
* sizeof(jschar
));
4596 while ((c
= fast_getc(fp
)) != EOF
)
4597 buf
[i
++] = (jschar
) (unsigned char) c
;
4600 JS_ASSERT(i
<= len
);
4602 script
= Compiler::compileScript(cx
, obj
, NULL
, principals
, tcflags
, buf
, len
, filename
, 1,
4608 JS_PUBLIC_API(JSScript
*)
4609 JS_CompileFile(JSContext
*cx
, JSObject
*obj
, const char *filename
)
4611 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
4617 assertSameCompartment(cx
, obj
);
4618 if (!filename
|| strcmp(filename
, "-") == 0) {
4621 fp
= fopen(filename
, "r");
4623 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_CANT_OPEN
,
4624 filename
, "No such file or directory");
4629 tcflags
= JS_OPTIONS_TO_TCFLAGS(cx
) | TCF_NEED_MUTABLE_SCRIPT
;
4630 script
= CompileFileHelper(cx
, obj
, NULL
, tcflags
, filename
, fp
);
4634 if (script
&& !js_NewScriptObject(cx
, script
)) {
4635 js_DestroyScript(cx
, script
);
4638 LAST_FRAME_CHECKS(cx
, script
);
4642 JS_PUBLIC_API(JSScript
*)
4643 JS_CompileFileHandleForPrincipals(JSContext
*cx
, JSObject
*obj
, const char *filename
, FILE *file
,
4644 JSPrincipals
*principals
)
4646 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
4651 assertSameCompartment(cx
, obj
, principals
);
4652 tcflags
= JS_OPTIONS_TO_TCFLAGS(cx
) | TCF_NEED_MUTABLE_SCRIPT
;
4653 script
= CompileFileHelper(cx
, obj
, principals
, tcflags
, filename
, file
);
4655 if (script
&& !js_NewScriptObject(cx
, script
)) {
4656 js_DestroyScript(cx
, script
);
4659 LAST_FRAME_CHECKS(cx
, script
);
4663 JS_PUBLIC_API(JSScript
*)
4664 JS_CompileFileHandleForPrincipalsVersion(JSContext
*cx
, JSObject
*obj
, const char *filename
,
4665 FILE *file
, JSPrincipals
*principals
, JSVersion version
)
4667 AutoVersionAPI
ava(cx
, version
);
4668 return JS_CompileFileHandleForPrincipals(cx
, obj
, filename
, file
, principals
);
4671 JS_PUBLIC_API(JSScript
*)
4672 JS_CompileFileHandle(JSContext
*cx
, JSObject
*obj
, const char *filename
, FILE *file
)
4674 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
4675 return JS_CompileFileHandleForPrincipals(cx
, obj
, filename
, file
, NULL
);
4678 JS_PUBLIC_API(JSObject
*)
4679 JS_NewScriptObject(JSContext
*cx
, JSScript
*script
)
4681 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
4683 assertSameCompartment(cx
, script
);
4685 return NewNonFunction
<WithProto::Class
>(cx
, &js_ScriptClass
, NULL
, NULL
);
4688 * This function should only ever be applied to JSScripts that had
4689 * script objects allocated for them when they were created, as
4690 * described in the comment for JSScript::u.object.
4692 JS_ASSERT(script
->u
.object
);
4693 return script
->u
.object
;
4696 JS_PUBLIC_API(JSObject
*)
4697 JS_GetScriptObject(JSScript
*script
)
4700 * This function should only ever be applied to JSScripts that had
4701 * script objects allocated for them when they were created, as
4702 * described in the comment for JSScript::u.object.
4704 JS_ASSERT(script
->u
.object
);
4705 return script
->u
.object
;
4709 JS_DestroyScript(JSContext
*cx
, JSScript
*script
)
4714 * Originally, JSScript lifetimes were managed explicitly, and this function
4715 * was used to free a JSScript. Now, this function does nothing, and the
4716 * garbage collector manages JSScripts; you must root the JSScript's script
4717 * object (obtained via JS_GetScriptObject) to keep it alive.
4719 * However, since the script objects have taken over this responsibility, it
4720 * follows that every script passed here must have a script object.
4722 JS_ASSERT(script
->u
.object
);
4726 CompileUCFunctionForPrincipalsCommon(JSContext
*cx
, JSObject
*obj
,
4727 JSPrincipals
*principals
, const char *name
,
4728 uintN nargs
, const char **argnames
,
4729 const jschar
*chars
, size_t length
,
4730 const char *filename
, uintN lineno
, JSVersion version
)
4732 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
4734 JSAtom
*funAtom
, *argAtom
;
4738 assertSameCompartment(cx
, obj
, principals
);
4742 funAtom
= js_Atomize(cx
, name
, strlen(name
), 0);
4749 fun
= js_NewFunction(cx
, NULL
, NULL
, 0, JSFUN_INTERPRETED
, obj
, funAtom
);
4754 AutoObjectRooter
tvr(cx
, FUN_OBJECT(fun
));
4755 MUST_FLOW_THROUGH("out");
4757 Bindings
bindings(cx
);
4758 AutoBindingsRooter
root(cx
, bindings
);
4759 for (i
= 0; i
< nargs
; i
++) {
4760 argAtom
= js_Atomize(cx
, argnames
[i
], strlen(argnames
[i
]), 0);
4767 if (!bindings
.addArgument(cx
, argAtom
, &dummy
)) {
4773 if (!Compiler::compileFunctionBody(cx
, fun
, principals
, &bindings
,
4774 chars
, length
, filename
, lineno
, version
)) {
4779 if (obj
&& funAtom
&&
4780 !obj
->defineProperty(cx
, ATOM_TO_JSID(funAtom
), ObjectValue(*fun
),
4781 NULL
, NULL
, JSPROP_ENUMERATE
)) {
4785 #ifdef JS_SCOPE_DEPTH_METER
4787 JSObject
*pobj
= obj
;
4790 while ((pobj
= pobj
->getParent()) != NULL
)
4792 JS_BASIC_STATS_ACCUM(&cx
->runtime
->hostenvScopeDepthStats
, depth
);
4798 LAST_FRAME_CHECKS(cx
, fun
);
4801 JS_PUBLIC_API(JSFunction
*)
4802 JS_CompileUCFunctionForPrincipalsVersion(JSContext
*cx
, JSObject
*obj
,
4803 JSPrincipals
*principals
, const char *name
,
4804 uintN nargs
, const char **argnames
,
4805 const jschar
*chars
, size_t length
,
4806 const char *filename
, uintN lineno
,
4809 AutoVersionAPI
avi(cx
, version
);
4810 return CompileUCFunctionForPrincipalsCommon(cx
, obj
, principals
, name
, nargs
, argnames
, chars
,
4811 length
, filename
, lineno
, avi
.version());
4814 JS_PUBLIC_API(JSFunction
*)
4815 JS_CompileUCFunctionForPrincipals(JSContext
*cx
, JSObject
*obj
,
4816 JSPrincipals
*principals
, const char *name
,
4817 uintN nargs
, const char **argnames
,
4818 const jschar
*chars
, size_t length
,
4819 const char *filename
, uintN lineno
)
4821 return CompileUCFunctionForPrincipalsCommon(cx
, obj
, principals
, name
, nargs
, argnames
, chars
,
4822 length
, filename
, lineno
, cx
->findVersion());
4825 JS_PUBLIC_API(JSFunction
*)
4826 JS_CompileUCFunction(JSContext
*cx
, JSObject
*obj
, const char *name
,
4827 uintN nargs
, const char **argnames
,
4828 const jschar
*chars
, size_t length
,
4829 const char *filename
, uintN lineno
)
4831 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
4832 return JS_CompileUCFunctionForPrincipals(cx
, obj
, NULL
, name
, nargs
, argnames
,
4833 chars
, length
, filename
, lineno
);
4836 JS_PUBLIC_API(JSFunction
*)
4837 JS_CompileFunctionForPrincipals(JSContext
*cx
, JSObject
*obj
,
4838 JSPrincipals
*principals
, const char *name
,
4839 uintN nargs
, const char **argnames
,
4840 const char *bytes
, size_t length
,
4841 const char *filename
, uintN lineno
)
4843 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
4844 jschar
*chars
= js_InflateString(cx
, bytes
, &length
);
4847 JSFunction
*fun
= JS_CompileUCFunctionForPrincipals(cx
, obj
, principals
, name
,
4848 nargs
, argnames
, chars
, length
,
4854 JS_PUBLIC_API(JSFunction
*)
4855 JS_CompileFunction(JSContext
*cx
, JSObject
*obj
, const char *name
,
4856 uintN nargs
, const char **argnames
,
4857 const char *bytes
, size_t length
,
4858 const char *filename
, uintN lineno
)
4860 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
4861 return JS_CompileFunctionForPrincipals(cx
, obj
, NULL
, name
, nargs
, argnames
, bytes
, length
,
4865 JS_PUBLIC_API(JSString
*)
4866 JS_DecompileScript(JSContext
*cx
, JSScript
*script
, const char *name
, uintN indent
)
4868 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
4874 if (cx
->compartment
!= script
->compartment
)
4875 CompartmentChecker::fail(cx
->compartment
, script
->compartment
);
4877 jp
= js_NewPrinter(cx
, name
, NULL
,
4878 indent
& ~JS_DONT_PRETTY_PRINT
,
4879 !(indent
& JS_DONT_PRETTY_PRINT
),
4883 if (js_DecompileScript(jp
, script
))
4884 str
= js_GetPrinterOutput(jp
);
4887 js_DestroyPrinter(jp
);
4891 JS_PUBLIC_API(JSString
*)
4892 JS_DecompileFunction(JSContext
*cx
, JSFunction
*fun
, uintN indent
)
4894 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
4896 assertSameCompartment(cx
, fun
);
4897 return js_DecompileToString(cx
, "JS_DecompileFunction", fun
,
4898 indent
& ~JS_DONT_PRETTY_PRINT
,
4899 !(indent
& JS_DONT_PRETTY_PRINT
),
4900 false, false, js_DecompileFunction
);
4903 JS_PUBLIC_API(JSString
*)
4904 JS_DecompileFunctionBody(JSContext
*cx
, JSFunction
*fun
, uintN indent
)
4906 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
4908 assertSameCompartment(cx
, fun
);
4909 return js_DecompileToString(cx
, "JS_DecompileFunctionBody", fun
,
4910 indent
& ~JS_DONT_PRETTY_PRINT
,
4911 !(indent
& JS_DONT_PRETTY_PRINT
),
4912 false, false, js_DecompileFunctionBody
);
4915 JS_PUBLIC_API(JSBool
)
4916 JS_ExecuteScript(JSContext
*cx
, JSObject
*obj
, JSScript
*script
, jsval
*rval
)
4918 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
4922 assertSameCompartment(cx
, obj
, script
);
4923 /* This should receive only scripts handed out via the JSAPI. */
4924 JS_ASSERT(script
->u
.object
);
4925 ok
= Execute(cx
, obj
, script
, NULL
, 0, Valueify(rval
));
4926 LAST_FRAME_CHECKS(cx
, ok
);
4930 JS_PUBLIC_API(JSBool
)
4931 JS_ExecuteScriptVersion(JSContext
*cx
, JSObject
*obj
, JSScript
*script
, jsval
*rval
,
4934 AutoVersionAPI
ava(cx
, version
);
4935 return JS_ExecuteScript(cx
, obj
, script
, rval
);
4939 EvaluateUCScriptForPrincipalsCommon(JSContext
*cx
, JSObject
*obj
,
4940 JSPrincipals
*principals
,
4941 const jschar
*chars
, uintN length
,
4942 const char *filename
, uintN lineno
,
4943 jsval
*rval
, JSVersion compileVersion
)
4945 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
4948 JSScript
*script
= Compiler::compileScript(cx
, obj
, NULL
, principals
,
4950 ? TCF_COMPILE_N_GO
| TCF_NO_SCRIPT_RVAL
4952 chars
, length
, filename
, lineno
, compileVersion
);
4954 LAST_FRAME_CHECKS(cx
, script
);
4957 JS_ASSERT(script
->getVersion() == compileVersion
);
4958 bool ok
= Execute(cx
, obj
, script
, NULL
, 0, Valueify(rval
));
4959 LAST_FRAME_CHECKS(cx
, ok
);
4960 js_DestroyScript(cx
, script
);
4965 JS_PUBLIC_API(JSBool
)
4966 JS_EvaluateUCScriptForPrincipalsVersion(JSContext
*cx
, JSObject
*obj
,
4967 JSPrincipals
*principals
,
4968 const jschar
*chars
, uintN length
,
4969 const char *filename
, uintN lineno
,
4970 jsval
*rval
, JSVersion version
)
4972 AutoVersionAPI
avi(cx
, version
);
4973 return EvaluateUCScriptForPrincipalsCommon(cx
, obj
, principals
, chars
, length
,
4974 filename
, lineno
, rval
, avi
.version());
4977 JS_PUBLIC_API(JSBool
)
4978 JS_EvaluateUCScriptForPrincipals(JSContext
*cx
, JSObject
*obj
,
4979 JSPrincipals
*principals
,
4980 const jschar
*chars
, uintN length
,
4981 const char *filename
, uintN lineno
,
4984 return EvaluateUCScriptForPrincipalsCommon(cx
, obj
, principals
, chars
, length
,
4985 filename
, lineno
, rval
, cx
->findVersion());
4988 JS_PUBLIC_API(JSBool
)
4989 JS_EvaluateUCScript(JSContext
*cx
, JSObject
*obj
, const jschar
*chars
, uintN length
,
4990 const char *filename
, uintN lineno
, jsval
*rval
)
4992 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
4993 return JS_EvaluateUCScriptForPrincipals(cx
, obj
, NULL
, chars
, length
, filename
, lineno
, rval
);
4996 /* Ancient uintN nbytes is part of API/ABI, so use size_t length local. */
4997 JS_PUBLIC_API(JSBool
)
4998 JS_EvaluateScriptForPrincipals(JSContext
*cx
, JSObject
*obj
, JSPrincipals
*principals
,
4999 const char *bytes
, uintN nbytes
,
5000 const char *filename
, uintN lineno
, jsval
*rval
)
5002 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
5003 size_t length
= nbytes
;
5004 jschar
*chars
= js_InflateString(cx
, bytes
, &length
);
5007 JSBool ok
= JS_EvaluateUCScriptForPrincipals(cx
, obj
, principals
, chars
, length
,
5008 filename
, lineno
, rval
);
5013 JS_PUBLIC_API(JSBool
)
5014 JS_EvaluateScriptForPrincipalsVersion(JSContext
*cx
, JSObject
*obj
, JSPrincipals
*principals
,
5015 const char *bytes
, uintN nbytes
,
5016 const char *filename
, uintN lineno
, jsval
*rval
, JSVersion version
)
5018 AutoVersionAPI
avi(cx
, version
);
5019 return JS_EvaluateScriptForPrincipals(cx
, obj
, principals
, bytes
, nbytes
, filename
, lineno
,
5023 JS_PUBLIC_API(JSBool
)
5024 JS_EvaluateScript(JSContext
*cx
, JSObject
*obj
, const char *bytes
, uintN nbytes
,
5025 const char *filename
, uintN lineno
, jsval
*rval
)
5027 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
5028 return JS_EvaluateScriptForPrincipals(cx
, obj
, NULL
, bytes
, nbytes
, filename
, lineno
, rval
);
5031 JS_PUBLIC_API(JSBool
)
5032 JS_CallFunction(JSContext
*cx
, JSObject
*obj
, JSFunction
*fun
, uintN argc
, jsval
*argv
,
5035 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
5037 assertSameCompartment(cx
, obj
, fun
, JSValueArray(argv
, argc
));
5038 JSBool ok
= ExternalInvoke(cx
, ObjectOrNullValue(obj
), ObjectValue(*fun
), argc
,
5039 Valueify(argv
), Valueify(rval
));
5040 LAST_FRAME_CHECKS(cx
, ok
);
5044 JS_PUBLIC_API(JSBool
)
5045 JS_CallFunctionName(JSContext
*cx
, JSObject
*obj
, const char *name
, uintN argc
, jsval
*argv
,
5048 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
5050 assertSameCompartment(cx
, obj
, JSValueArray(argv
, argc
));
5052 AutoValueRooter
tvr(cx
);
5053 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
5056 js_GetMethod(cx
, obj
, ATOM_TO_JSID(atom
), JSGET_NO_METHOD_BARRIER
, tvr
.addr()) &&
5057 ExternalInvoke(cx
, ObjectOrNullValue(obj
), tvr
.value(), argc
, Valueify(argv
),
5059 LAST_FRAME_CHECKS(cx
, ok
);
5063 JS_PUBLIC_API(JSBool
)
5064 JS_CallFunctionValue(JSContext
*cx
, JSObject
*obj
, jsval fval
, uintN argc
, jsval
*argv
,
5067 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
5070 assertSameCompartment(cx
, obj
, fval
, JSValueArray(argv
, argc
));
5071 JSBool ok
= ExternalInvoke(cx
, ObjectOrNullValue(obj
), Valueify(fval
), argc
, Valueify(argv
),
5073 LAST_FRAME_CHECKS(cx
, ok
);
5080 Call(JSContext
*cx
, jsval thisv
, jsval fval
, uintN argc
, jsval
*argv
, jsval
*rval
)
5085 assertSameCompartment(cx
, thisv
, fval
, JSValueArray(argv
, argc
));
5086 ok
= ExternalInvoke(cx
, Valueify(thisv
), Valueify(fval
), argc
, Valueify(argv
), Valueify(rval
));
5087 LAST_FRAME_CHECKS(cx
, ok
);
5093 JS_PUBLIC_API(JSObject
*)
5094 JS_New(JSContext
*cx
, JSObject
*ctor
, uintN argc
, jsval
*argv
)
5097 assertSameCompartment(cx
, ctor
, JSValueArray(argv
, argc
));
5099 // This is not a simple variation of JS_CallFunctionValue because JSOP_NEW
5100 // is not a simple variation of JSOP_CALL. We have to determine what class
5101 // of object to create, create it, and clamp the return value to an object,
5102 // among other details. js_InvokeConstructor does the hard work.
5103 InvokeArgsGuard args
;
5104 if (!cx
->stack().pushInvokeArgs(cx
, argc
, &args
))
5107 args
.callee().setObject(*ctor
);
5108 args
.thisv().setNull();
5109 memcpy(args
.argv(), argv
, argc
* sizeof(jsval
));
5111 bool ok
= InvokeConstructor(cx
, args
);
5113 JSObject
*obj
= NULL
;
5115 if (args
.rval().isObject()) {
5116 obj
= &args
.rval().toObject();
5119 * Although constructors may return primitives (via proxies), this
5120 * API is asking for an object, so we report an error.
5122 JSAutoByteString bytes
;
5123 if (js_ValueToPrintable(cx
, args
.rval(), &bytes
)) {
5124 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_BAD_NEW_RESULT
,
5130 LAST_FRAME_CHECKS(cx
, ok
);
5134 JS_PUBLIC_API(JSOperationCallback
)
5135 JS_SetOperationCallback(JSContext
*cx
, JSOperationCallback callback
)
5137 #ifdef JS_THREADSAFE
5138 JS_ASSERT(CURRENT_THREAD_IS_ME(cx
->thread
));
5140 JSOperationCallback old
= cx
->operationCallback
;
5141 cx
->operationCallback
= callback
;
5145 JS_PUBLIC_API(JSOperationCallback
)
5146 JS_GetOperationCallback(JSContext
*cx
)
5148 return cx
->operationCallback
;
5152 JS_TriggerOperationCallback(JSContext
*cx
)
5154 #ifdef JS_THREADSAFE
5155 AutoLockGC
lock(cx
->runtime
);
5157 TriggerOperationCallback(cx
);
5161 JS_TriggerAllOperationCallbacks(JSRuntime
*rt
)
5163 #ifdef JS_THREADSAFE
5164 AutoLockGC
lock(rt
);
5166 TriggerAllOperationCallbacks(rt
);
5169 JS_PUBLIC_API(JSBool
)
5170 JS_IsRunning(JSContext
*cx
)
5173 * The use of cx->fp below is safe. Rationale: Here we don't care if the
5174 * interpreter state is stale. We just want to know if there *is* any
5175 * interpreter state.
5177 VOUCH_DOES_NOT_REQUIRE_STACK();
5180 JS_ASSERT_IF(JS_ON_TRACE(cx
) && JS_TRACE_MONITOR_ON_TRACE(cx
)->tracecx
== cx
, cx
->hasfp());
5182 JSStackFrame
*fp
= cx
->maybefp();
5183 while (fp
&& fp
->isDummyFrame())
5188 JS_PUBLIC_API(JSStackFrame
*)
5189 JS_SaveFrameChain(JSContext
*cx
)
5192 JSStackFrame
*fp
= js_GetTopStackFrame(cx
);
5195 cx
->saveActiveSegment();
5200 JS_RestoreFrameChain(JSContext
*cx
, JSStackFrame
*fp
)
5203 JS_ASSERT_NOT_ON_TRACE(cx
);
5204 JS_ASSERT(!cx
->hasfp());
5207 cx
->restoreSegment();
5210 /************************************************************************/
5211 JS_PUBLIC_API(JSString
*)
5212 JS_NewStringCopyN(JSContext
*cx
, const char *s
, size_t n
)
5215 return js_NewStringCopyN(cx
, s
, n
);
5218 JS_PUBLIC_API(JSString
*)
5219 JS_NewStringCopyZ(JSContext
*cx
, const char *s
)
5227 return cx
->runtime
->emptyString
;
5229 js
= js_InflateString(cx
, s
, &n
);
5232 str
= js_NewString(cx
, js
, n
);
5238 JS_PUBLIC_API(JSBool
)
5239 JS_StringHasBeenInterned(JSString
*str
)
5241 return str
->isAtomized();
5244 JS_PUBLIC_API(JSString
*)
5245 JS_InternJSString(JSContext
*cx
, JSString
*str
)
5248 JSAtom
*atom
= js_AtomizeString(cx
, str
, 0);
5251 return ATOM_TO_STRING(atom
);
5254 JS_PUBLIC_API(JSString
*)
5255 JS_InternString(JSContext
*cx
, const char *s
)
5260 atom
= js_Atomize(cx
, s
, strlen(s
), ATOM_INTERNED
);
5263 return ATOM_TO_STRING(atom
);
5266 JS_PUBLIC_API(JSString
*)
5267 JS_NewUCString(JSContext
*cx
, jschar
*chars
, size_t length
)
5270 return js_NewString(cx
, chars
, length
);
5273 JS_PUBLIC_API(JSString
*)
5274 JS_NewUCStringCopyN(JSContext
*cx
, const jschar
*s
, size_t n
)
5277 return js_NewStringCopyN(cx
, s
, n
);
5280 JS_PUBLIC_API(JSString
*)
5281 JS_NewUCStringCopyZ(JSContext
*cx
, const jschar
*s
)
5285 return cx
->runtime
->emptyString
;
5286 return js_NewStringCopyZ(cx
, s
);
5289 JS_PUBLIC_API(JSString
*)
5290 JS_InternUCStringN(JSContext
*cx
, const jschar
*s
, size_t length
)
5295 atom
= js_AtomizeChars(cx
, s
, length
, ATOM_INTERNED
);
5298 return ATOM_TO_STRING(atom
);
5301 JS_PUBLIC_API(JSString
*)
5302 JS_InternUCString(JSContext
*cx
, const jschar
*s
)
5304 return JS_InternUCStringN(cx
, s
, js_strlen(s
));
5307 JS_PUBLIC_API(size_t)
5308 JS_GetStringLength(JSString
*str
)
5310 return str
->length();
5313 JS_PUBLIC_API(const jschar
*)
5314 JS_GetStringCharsZ(JSContext
*cx
, JSString
*str
)
5317 assertSameCompartment(cx
, str
);
5318 return str
->getCharsZ(cx
);
5321 JS_PUBLIC_API(const jschar
*)
5322 JS_GetStringCharsZAndLength(JSContext
*cx
, JSString
*str
, size_t *plength
)
5325 assertSameCompartment(cx
, str
);
5326 *plength
= str
->length();
5327 return str
->getCharsZ(cx
);
5330 JS_PUBLIC_API(const jschar
*)
5331 JS_GetStringCharsAndLength(JSContext
*cx
, JSString
*str
, size_t *plength
)
5334 assertSameCompartment(cx
, str
);
5335 *plength
= str
->length();
5336 return str
->getChars(cx
);
5339 JS_PUBLIC_API(const jschar
*)
5340 JS_GetInternedStringChars(JSString
*str
)
5342 JS_ASSERT(str
->isAtomized());
5343 return str
->flatChars();
5346 JS_PUBLIC_API(const jschar
*)
5347 JS_GetInternedStringCharsAndLength(JSString
*str
, size_t *plength
)
5349 JS_ASSERT(str
->isAtomized());
5350 *plength
= str
->flatLength();
5351 return str
->flatChars();
5354 extern JS_PUBLIC_API(JSFlatString
*)
5355 JS_FlattenString(JSContext
*cx
, JSString
*str
)
5358 assertSameCompartment(cx
, str
);
5359 return str
->getCharsZ(cx
) ? (JSFlatString
*)str
: NULL
;
5362 extern JS_PUBLIC_API(const jschar
*)
5363 JS_GetFlatStringChars(JSFlatString
*str
)
5365 return str
->chars();
5368 JS_PUBLIC_API(JSBool
)
5369 JS_CompareStrings(JSContext
*cx
, JSString
*str1
, JSString
*str2
, int32
*result
)
5371 return CompareStrings(cx
, str1
, str2
, result
);
5374 JS_PUBLIC_API(JSBool
)
5375 JS_StringEqualsAscii(JSContext
*cx
, JSString
*str
, const char *asciiBytes
, JSBool
*match
)
5377 JSLinearString
*linearStr
= str
->ensureLinear(cx
);
5380 *match
= StringEqualsAscii(linearStr
, asciiBytes
);
5384 JS_PUBLIC_API(JSBool
)
5385 JS_FlatStringEqualsAscii(JSFlatString
*str
, const char *asciiBytes
)
5387 return StringEqualsAscii(str
, asciiBytes
);
5390 JS_PUBLIC_API(size_t)
5391 JS_PutEscapedFlatString(char *buffer
, size_t size
, JSFlatString
*str
, char quote
)
5393 return PutEscapedString(buffer
, size
, str
, quote
);
5396 JS_PUBLIC_API(size_t)
5397 JS_PutEscapedString(JSContext
*cx
, char *buffer
, size_t size
, JSString
*str
, char quote
)
5399 JSLinearString
*linearStr
= str
->ensureLinear(cx
);
5402 return PutEscapedString(buffer
, size
, linearStr
, quote
);
5405 JS_PUBLIC_API(JSBool
)
5406 JS_FileEscapedString(FILE *fp
, JSString
*str
, char quote
)
5408 JSLinearString
*linearStr
= str
->ensureLinear(NULL
);
5409 return linearStr
&& FileEscapedString(fp
, linearStr
, quote
);
5412 JS_PUBLIC_API(JSString
*)
5413 JS_NewGrowableString(JSContext
*cx
, jschar
*chars
, size_t length
)
5416 return js_NewString(cx
, chars
, length
);
5419 JS_PUBLIC_API(JSString
*)
5420 JS_NewDependentString(JSContext
*cx
, JSString
*str
, size_t start
, size_t length
)
5423 return js_NewDependentString(cx
, str
, start
, length
);
5426 JS_PUBLIC_API(JSString
*)
5427 JS_ConcatStrings(JSContext
*cx
, JSString
*left
, JSString
*right
)
5430 return js_ConcatStrings(cx
, left
, right
);
5433 JS_PUBLIC_API(const jschar
*)
5434 JS_UndependString(JSContext
*cx
, JSString
*str
)
5437 return str
->getCharsZ(cx
);
5440 JS_PUBLIC_API(JSBool
)
5441 JS_MakeStringImmutable(JSContext
*cx
, JSString
*str
)
5444 return js_MakeStringImmutable(cx
, str
);
5447 JS_PUBLIC_API(JSBool
)
5448 JS_EncodeCharacters(JSContext
*cx
, const jschar
*src
, size_t srclen
, char *dst
, size_t *dstlenp
)
5452 n
= js_GetDeflatedStringLength(cx
, src
, srclen
);
5453 if (n
== (size_t)-1) {
5461 return js_DeflateStringToBuffer(cx
, src
, srclen
, dst
, dstlenp
);
5464 JS_PUBLIC_API(JSBool
)
5465 JS_DecodeBytes(JSContext
*cx
, const char *src
, size_t srclen
, jschar
*dst
, size_t *dstlenp
)
5467 return js_InflateStringToBuffer(cx
, src
, srclen
, dst
, dstlenp
);
5470 JS_PUBLIC_API(char *)
5471 JS_EncodeString(JSContext
*cx
, JSString
*str
)
5473 const jschar
*chars
= str
->getChars(cx
);
5476 return js_DeflateString(cx
, chars
, str
->length());
5479 JS_PUBLIC_API(size_t)
5480 JS_GetStringEncodingLength(JSContext
*cx
, JSString
*str
)
5482 const jschar
*chars
= str
->getChars(cx
);
5485 return js_GetDeflatedStringLength(cx
, chars
, str
->length());
5488 JS_PUBLIC_API(size_t)
5489 JS_EncodeStringToBuffer(JSString
*str
, char *buffer
, size_t length
)
5492 * FIXME bug 612141 - fix js_DeflateStringToBuffer interface so the result
5493 * would allow to distinguish between insufficient buffer and encoding
5496 size_t writtenLength
= length
;
5497 const jschar
*chars
= str
->getChars(NULL
);
5500 if (js_DeflateStringToBuffer(NULL
, chars
, str
->length(), buffer
, &writtenLength
)) {
5501 JS_ASSERT(writtenLength
<= length
);
5502 return writtenLength
;
5504 JS_ASSERT(writtenLength
<= length
);
5505 size_t necessaryLength
= js_GetDeflatedStringLength(NULL
, chars
, str
->length());
5506 if (necessaryLength
== size_t(-1))
5508 if (writtenLength
!= length
) {
5509 /* Make sure that the buffer contains only valid UTF-8 sequences. */
5510 JS_ASSERT(js_CStringsAreUTF8
);
5511 PodZero(buffer
+ writtenLength
, length
- writtenLength
);
5513 return necessaryLength
;
5516 JS_PUBLIC_API(JSBool
)
5517 JS_Stringify(JSContext
*cx
, jsval
*vp
, JSObject
*replacer
, jsval space
,
5518 JSONWriteCallback callback
, void *data
)
5521 assertSameCompartment(cx
, replacer
, space
);
5522 StringBuffer
sb(cx
);
5523 if (!js_Stringify(cx
, Valueify(vp
), replacer
, Valueify(space
), sb
))
5525 return callback(sb
.begin(), sb
.length(), data
);
5528 JS_PUBLIC_API(JSBool
)
5529 JS_TryJSON(JSContext
*cx
, jsval
*vp
)
5532 assertSameCompartment(cx
, *vp
);
5533 return js_TryJSON(cx
, Valueify(vp
));
5536 JS_PUBLIC_API(JSONParser
*)
5537 JS_BeginJSONParse(JSContext
*cx
, jsval
*vp
)
5540 return js_BeginJSONParse(cx
, Valueify(vp
));
5543 JS_PUBLIC_API(JSBool
)
5544 JS_ConsumeJSONText(JSContext
*cx
, JSONParser
*jp
, const jschar
*data
, uint32 len
)
5547 return js_ConsumeJSONText(cx
, jp
, data
, len
);
5550 JS_PUBLIC_API(JSBool
)
5551 JS_FinishJSONParse(JSContext
*cx
, JSONParser
*jp
, jsval reviver
)
5554 assertSameCompartment(cx
, reviver
);
5555 return js_FinishJSONParse(cx
, jp
, Valueify(reviver
));
5558 JS_PUBLIC_API(JSBool
)
5559 JS_ReadStructuredClone(JSContext
*cx
, const uint64
*buf
, size_t nbytes
,
5560 uint32 version
, jsval
*vp
,
5561 const JSStructuredCloneCallbacks
*optionalCallbacks
,
5564 if (version
> JS_STRUCTURED_CLONE_VERSION
) {
5565 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_BAD_CLONE_VERSION
);
5568 const JSStructuredCloneCallbacks
*callbacks
=
5571 cx
->runtime
->structuredCloneCallbacks
;
5572 return ReadStructuredClone(cx
, buf
, nbytes
, Valueify(vp
), callbacks
, closure
);
5575 JS_PUBLIC_API(JSBool
)
5576 JS_WriteStructuredClone(JSContext
*cx
, jsval v
, uint64
**bufp
, size_t *nbytesp
,
5577 const JSStructuredCloneCallbacks
*optionalCallbacks
,
5580 const JSStructuredCloneCallbacks
*callbacks
=
5583 cx
->runtime
->structuredCloneCallbacks
;
5584 return WriteStructuredClone(cx
, Valueify(v
), (uint64_t **) bufp
, nbytesp
,
5585 callbacks
, closure
);
5588 JS_PUBLIC_API(JSBool
)
5589 JS_StructuredClone(JSContext
*cx
, jsval v
, jsval
*vp
,
5590 ReadStructuredCloneOp optionalReadOp
,
5591 const JSStructuredCloneCallbacks
*optionalCallbacks
,
5594 const JSStructuredCloneCallbacks
*callbacks
=
5597 cx
->runtime
->structuredCloneCallbacks
;
5598 JSAutoStructuredCloneBuffer buf
;
5599 return buf
.write(cx
, v
, callbacks
, closure
) &&
5600 buf
.read(vp
, cx
, callbacks
, closure
);
5604 JS_SetStructuredCloneCallbacks(JSRuntime
*rt
, const JSStructuredCloneCallbacks
*callbacks
)
5606 rt
->structuredCloneCallbacks
= callbacks
;
5609 JS_PUBLIC_API(JSBool
)
5610 JS_ReadUint32Pair(JSStructuredCloneReader
*r
, uint32
*p1
, uint32
*p2
)
5612 return r
->input().readPair((uint32_t *) p1
, (uint32_t *) p2
);
5615 JS_PUBLIC_API(JSBool
)
5616 JS_ReadBytes(JSStructuredCloneReader
*r
, void *p
, size_t len
)
5618 return r
->input().readBytes(p
, len
);
5621 JS_PUBLIC_API(JSBool
)
5622 JS_WriteUint32Pair(JSStructuredCloneWriter
*w
, uint32 tag
, uint32 data
)
5624 return w
->output().writePair(tag
, data
);
5627 JS_PUBLIC_API(JSBool
)
5628 JS_WriteBytes(JSStructuredCloneWriter
*w
, const void *p
, size_t len
)
5630 return w
->output().writeBytes(p
, len
);
5634 * The following determines whether C Strings are to be treated as UTF-8
5635 * or ISO-8859-1. For correct operation, it must be set prior to the
5636 * first call to JS_NewRuntime.
5638 #ifndef JS_C_STRINGS_ARE_UTF8
5639 JSBool js_CStringsAreUTF8
= JS_FALSE
;
5642 JS_PUBLIC_API(JSBool
)
5643 JS_CStringsAreUTF8()
5645 return js_CStringsAreUTF8
;
5649 JS_SetCStringsAreUTF8()
5651 JS_ASSERT(!js_NewRuntimeWasCalled
);
5653 #ifndef JS_C_STRINGS_ARE_UTF8
5654 js_CStringsAreUTF8
= JS_TRUE
;
5658 /************************************************************************/
5661 JS_ReportError(JSContext
*cx
, const char *format
, ...)
5665 va_start(ap
, format
);
5666 js_ReportErrorVA(cx
, JSREPORT_ERROR
, format
, ap
);
5671 JS_ReportErrorNumber(JSContext
*cx
, JSErrorCallback errorCallback
,
5672 void *userRef
, const uintN errorNumber
, ...)
5676 va_start(ap
, errorNumber
);
5677 js_ReportErrorNumberVA(cx
, JSREPORT_ERROR
, errorCallback
, userRef
,
5678 errorNumber
, JS_TRUE
, ap
);
5683 JS_ReportErrorNumberUC(JSContext
*cx
, JSErrorCallback errorCallback
,
5684 void *userRef
, const uintN errorNumber
, ...)
5688 va_start(ap
, errorNumber
);
5689 js_ReportErrorNumberVA(cx
, JSREPORT_ERROR
, errorCallback
, userRef
,
5690 errorNumber
, JS_FALSE
, ap
);
5694 JS_PUBLIC_API(JSBool
)
5695 JS_ReportWarning(JSContext
*cx
, const char *format
, ...)
5700 va_start(ap
, format
);
5701 ok
= js_ReportErrorVA(cx
, JSREPORT_WARNING
, format
, ap
);
5706 JS_PUBLIC_API(JSBool
)
5707 JS_ReportErrorFlagsAndNumber(JSContext
*cx
, uintN flags
,
5708 JSErrorCallback errorCallback
, void *userRef
,
5709 const uintN errorNumber
, ...)
5714 va_start(ap
, errorNumber
);
5715 ok
= js_ReportErrorNumberVA(cx
, flags
, errorCallback
, userRef
,
5716 errorNumber
, JS_TRUE
, ap
);
5721 JS_PUBLIC_API(JSBool
)
5722 JS_ReportErrorFlagsAndNumberUC(JSContext
*cx
, uintN flags
,
5723 JSErrorCallback errorCallback
, void *userRef
,
5724 const uintN errorNumber
, ...)
5729 va_start(ap
, errorNumber
);
5730 ok
= js_ReportErrorNumberVA(cx
, flags
, errorCallback
, userRef
,
5731 errorNumber
, JS_FALSE
, ap
);
5737 JS_ReportOutOfMemory(JSContext
*cx
)
5739 js_ReportOutOfMemory(cx
);
5743 JS_ReportAllocationOverflow(JSContext
*cx
)
5745 js_ReportAllocationOverflow(cx
);
5748 JS_PUBLIC_API(JSErrorReporter
)
5749 JS_SetErrorReporter(JSContext
*cx
, JSErrorReporter er
)
5751 JSErrorReporter older
;
5753 older
= cx
->errorReporter
;
5754 cx
->errorReporter
= er
;
5758 /************************************************************************/
5763 JS_PUBLIC_API(JSObject
*)
5764 JS_NewDateObject(JSContext
*cx
, int year
, int mon
, int mday
, int hour
, int min
, int sec
)
5767 return js_NewDateObject(cx
, year
, mon
, mday
, hour
, min
, sec
);
5770 JS_PUBLIC_API(JSObject
*)
5771 JS_NewDateObjectMsec(JSContext
*cx
, jsdouble msec
)
5774 return js_NewDateObjectMsec(cx
, msec
);
5777 JS_PUBLIC_API(JSBool
)
5778 JS_ObjectIsDate(JSContext
*cx
, JSObject
*obj
)
5781 return obj
->isDate();
5784 /************************************************************************/
5787 * Regular Expressions.
5789 JS_PUBLIC_API(JSObject
*)
5790 JS_NewRegExpObject(JSContext
*cx
, JSObject
*obj
, char *bytes
, size_t length
, uintN flags
)
5793 jschar
*chars
= js_InflateString(cx
, bytes
, &length
);
5796 RegExpStatics
*res
= RegExpStatics::extractFrom(obj
);
5797 JSObject
*reobj
= RegExp::createObject(cx
, res
, chars
, length
, flags
);
5802 JS_PUBLIC_API(JSObject
*)
5803 JS_NewUCRegExpObject(JSContext
*cx
, JSObject
*obj
, jschar
*chars
, size_t length
, uintN flags
)
5806 RegExpStatics
*res
= RegExpStatics::extractFrom(obj
);
5807 return RegExp::createObject(cx
, res
, chars
, length
, flags
);
5811 JS_SetRegExpInput(JSContext
*cx
, JSObject
*obj
, JSString
*input
, JSBool multiline
)
5814 assertSameCompartment(cx
, input
);
5816 RegExpStatics::extractFrom(obj
)->reset(input
, !!multiline
);
5820 JS_ClearRegExpStatics(JSContext
*cx
, JSObject
*obj
)
5825 RegExpStatics::extractFrom(obj
)->clear();
5828 JS_PUBLIC_API(JSBool
)
5829 JS_ExecuteRegExp(JSContext
*cx
, JSObject
*obj
, JSObject
*reobj
, jschar
*chars
, size_t length
,
5830 size_t *indexp
, JSBool test
, jsval
*rval
)
5834 RegExp
*re
= RegExp::extractFrom(reobj
);
5838 JSString
*str
= js_NewStringCopyN(cx
, chars
, length
);
5842 return re
->execute(cx
, RegExpStatics::extractFrom(obj
), str
, indexp
, test
, Valueify(rval
));
5845 JS_PUBLIC_API(JSObject
*)
5846 JS_NewRegExpObjectNoStatics(JSContext
*cx
, char *bytes
, size_t length
, uintN flags
)
5849 jschar
*chars
= js_InflateString(cx
, bytes
, &length
);
5852 JSObject
*obj
= RegExp::createObjectNoStatics(cx
, chars
, length
, flags
);
5857 JS_PUBLIC_API(JSObject
*)
5858 JS_NewUCRegExpObjectNoStatics(JSContext
*cx
, jschar
*chars
, size_t length
, uintN flags
)
5861 return RegExp::createObjectNoStatics(cx
, chars
, length
, flags
);
5864 JS_PUBLIC_API(JSBool
)
5865 JS_ExecuteRegExpNoStatics(JSContext
*cx
, JSObject
*obj
, jschar
*chars
, size_t length
,
5866 size_t *indexp
, JSBool test
, jsval
*rval
)
5870 RegExp
*re
= RegExp::extractFrom(obj
);
5874 JSString
*str
= js_NewStringCopyN(cx
, chars
, length
);
5878 return re
->executeNoStatics(cx
, str
, indexp
, test
, Valueify(rval
));
5881 /************************************************************************/
5884 JS_SetLocaleCallbacks(JSContext
*cx
, JSLocaleCallbacks
*callbacks
)
5886 cx
->localeCallbacks
= callbacks
;
5889 JS_PUBLIC_API(JSLocaleCallbacks
*)
5890 JS_GetLocaleCallbacks(JSContext
*cx
)
5892 return cx
->localeCallbacks
;
5895 /************************************************************************/
5897 JS_PUBLIC_API(JSBool
)
5898 JS_IsExceptionPending(JSContext
*cx
)
5900 return (JSBool
) cx
->isExceptionPending();
5903 JS_PUBLIC_API(JSBool
)
5904 JS_GetPendingException(JSContext
*cx
, jsval
*vp
)
5907 if (!cx
->isExceptionPending())
5909 Valueify(*vp
) = cx
->getPendingException();
5910 assertSameCompartment(cx
, *vp
);
5915 JS_SetPendingException(JSContext
*cx
, jsval v
)
5918 assertSameCompartment(cx
, v
);
5919 cx
->setPendingException(Valueify(v
));
5923 JS_ClearPendingException(JSContext
*cx
)
5925 cx
->clearPendingException();
5928 JS_PUBLIC_API(JSBool
)
5929 JS_ReportPendingException(JSContext
*cx
)
5937 * Set cx->generatingError to suppress the standard error-to-exception
5938 * conversion done by all {js,JS}_Report* functions except for OOM. The
5939 * cx->generatingError flag was added to suppress recursive divergence
5940 * under js_ErrorToException, but it serves for our purposes here too.
5942 save
= cx
->generatingError
;
5943 cx
->generatingError
= JS_TRUE
;
5944 ok
= js_ReportUncaughtException(cx
);
5945 cx
->generatingError
= save
;
5949 struct JSExceptionState
{
5954 JS_PUBLIC_API(JSExceptionState
*)
5955 JS_SaveExceptionState(JSContext
*cx
)
5957 JSExceptionState
*state
;
5960 state
= (JSExceptionState
*) cx
->malloc(sizeof(JSExceptionState
));
5962 state
->throwing
= JS_GetPendingException(cx
, &state
->exception
);
5963 if (state
->throwing
&& JSVAL_IS_GCTHING(state
->exception
))
5964 js_AddRoot(cx
, Valueify(&state
->exception
), "JSExceptionState.exception");
5970 JS_RestoreExceptionState(JSContext
*cx
, JSExceptionState
*state
)
5974 if (state
->throwing
)
5975 JS_SetPendingException(cx
, state
->exception
);
5977 JS_ClearPendingException(cx
);
5978 JS_DropExceptionState(cx
, state
);
5983 JS_DropExceptionState(JSContext
*cx
, JSExceptionState
*state
)
5987 if (state
->throwing
&& JSVAL_IS_GCTHING(state
->exception
)) {
5988 assertSameCompartment(cx
, state
->exception
);
5989 JS_RemoveValueRoot(cx
, &state
->exception
);
5995 JS_PUBLIC_API(JSErrorReport
*)
5996 JS_ErrorFromException(JSContext
*cx
, jsval v
)
5999 assertSameCompartment(cx
, v
);
6000 return js_ErrorFromException(cx
, v
);
6003 JS_PUBLIC_API(JSBool
)
6004 JS_ThrowReportedError(JSContext
*cx
, const char *message
,
6005 JSErrorReport
*reportp
)
6007 return JS_IsRunning(cx
) &&
6008 js_ErrorToException(cx
, message
, reportp
, NULL
, NULL
);
6011 JS_PUBLIC_API(JSBool
)
6012 JS_ThrowStopIteration(JSContext
*cx
)
6014 return js_ThrowStopIteration(cx
);
6018 * Get the owning thread id of a context. Returns 0 if the context is not
6019 * owned by any thread.
6021 JS_PUBLIC_API(jsword
)
6022 JS_GetContextThread(JSContext
*cx
)
6024 #ifdef JS_THREADSAFE
6025 return reinterpret_cast<jsword
>(JS_THREAD_ID(cx
));
6032 * Set the current thread as the owning thread of a context. Returns the
6033 * old owning thread id, or -1 if the operation failed.
6035 JS_PUBLIC_API(jsword
)
6036 JS_SetContextThread(JSContext
*cx
)
6038 #ifdef JS_THREADSAFE
6039 JS_ASSERT(!cx
->outstandingRequests
);
6041 JS_ASSERT(CURRENT_THREAD_IS_ME(cx
->thread
));
6042 return reinterpret_cast<jsword
>(cx
->thread
->id
);
6045 if (!js_InitContextThread(cx
)) {
6046 js_ReportOutOfMemory(cx
);
6050 /* Here the GC lock is still held after js_InitContextThread took it. */
6051 JS_UNLOCK_GC(cx
->runtime
);
6056 JS_PUBLIC_API(jsword
)
6057 JS_ClearContextThread(JSContext
*cx
)
6059 #ifdef JS_THREADSAFE
6061 * cx must have exited all requests it entered and, if cx is associated
6062 * with a thread, this must be called only from that thread. If not, this
6063 * is a harmless no-op.
6065 JS_ASSERT(cx
->outstandingRequests
== 0);
6066 JSThread
*t
= cx
->thread
;
6069 JS_ASSERT(CURRENT_THREAD_IS_ME(t
));
6072 * We must not race with a GC that accesses cx->thread for all threads,
6075 JSRuntime
*rt
= cx
->runtime
;
6076 AutoLockGC
lock(rt
);
6078 js_ClearContextThread(cx
);
6079 JS_ASSERT_IF(JS_CLIST_IS_EMPTY(&t
->contextList
), !t
->data
.requestDepth
);
6082 * We can access t->id as long as the GC lock is held and we cannot race
6083 * with the GC that may delete t.
6085 return reinterpret_cast<jsword
>(t
->id
);
6091 #ifdef MOZ_TRACE_JSCALLS
6093 JS_SetFunctionCallback(JSContext
*cx
, JSFunctionCallback fcb
)
6095 cx
->functionCallback
= fcb
;
6098 JS_PUBLIC_API(JSFunctionCallback
)
6099 JS_GetFunctionCallback(JSContext
*cx
)
6101 return cx
->functionCallback
;
6107 JS_SetGCZeal(JSContext
*cx
, uint8 zeal
)
6109 cx
->runtime
->gcZeal
= zeal
;
6113 /************************************************************************/
6115 #if !defined(STATIC_EXPORTABLE_JS_API) && !defined(STATIC_JS_API) && defined(XP_WIN) && !defined (WINCE)
6120 * Initialization routine for the JS DLL.
6122 BOOL WINAPI
DllMain (HINSTANCE hDLL
, DWORD dwReason
, LPVOID lpReserved
)