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_PropertyStub
,
120 JS_EnumerateStub
, JS_ResolveStub
,
121 JS_ConvertStub
, NULL
,
122 JSCLASS_NO_OPTIONAL_MEMBERS
127 JSContext
* const cx
;
128 JSVersion oldVersion
;
129 bool oldVersionWasOverride
;
133 explicit AutoVersionAPI(JSContext
*cx
, JSVersion newVersion
)
134 : cx(cx
), oldVersion(cx
->findVersion()), oldVersionWasOverride(cx
->isVersionOverridden()),
135 oldOptions(cx
->options
) {
137 * Note: ANONFUNFIX in newVersion is ignored for backwards
138 * compatibility, must be set via JS_SetOptions. (Because of this, we
139 * inherit the current ANONFUNFIX setting from the options.
141 cx
->options
= VersionHasXML(newVersion
)
142 ? (cx
->options
| JSOPTION_XML
)
143 : (cx
->options
& ~JSOPTION_XML
);
145 VersionSetAnonFunFix(&newVersion
, OptionsHasAnonFunFix(cx
->options
));
146 cx
->maybeOverrideVersion(newVersion
);
147 cx
->checkOptionVersionSync();
151 cx
->options
= oldOptions
;
152 if (oldVersionWasOverride
) {
153 JS_ALWAYS_TRUE(cx
->maybeOverrideVersion(oldVersion
));
155 cx
->clearVersionOverride();
156 cx
->setDefaultVersion(oldVersion
);
158 JS_ASSERT(cx
->findVersion() == oldVersion
);
162 #ifdef HAVE_VA_LIST_AS_ARRAY
163 #define JS_ADDRESSOF_VA_LIST(ap) ((va_list *)(ap))
165 #define JS_ADDRESSOF_VA_LIST(ap) (&(ap))
168 #ifdef JS_USE_JSVAL_JSID_STRUCT_TYPES
169 JS_PUBLIC_DATA(jsid
) JS_DEFAULT_XML_NAMESPACE_ID
= { size_t(JSID_TYPE_DEFAULT_XML_NAMESPACE
) };
170 JS_PUBLIC_DATA(jsid
) JSID_VOID
= { size_t(JSID_TYPE_VOID
) };
171 JS_PUBLIC_DATA(jsid
) JSID_EMPTY
= { size_t(JSID_TYPE_OBJECT
) };
174 #ifdef JS_USE_JSVAL_JSID_STRUCT_TYPES
175 JS_PUBLIC_DATA(jsval
) JSVAL_NULL
= { BUILD_JSVAL(JSVAL_TAG_NULL
, 0) };
176 JS_PUBLIC_DATA(jsval
) JSVAL_ZERO
= { BUILD_JSVAL(JSVAL_TAG_INT32
, 0) };
177 JS_PUBLIC_DATA(jsval
) JSVAL_ONE
= { BUILD_JSVAL(JSVAL_TAG_INT32
, 1) };
178 JS_PUBLIC_DATA(jsval
) JSVAL_FALSE
= { BUILD_JSVAL(JSVAL_TAG_BOOLEAN
, JS_FALSE
) };
179 JS_PUBLIC_DATA(jsval
) JSVAL_TRUE
= { BUILD_JSVAL(JSVAL_TAG_BOOLEAN
, JS_TRUE
) };
180 JS_PUBLIC_DATA(jsval
) JSVAL_VOID
= { BUILD_JSVAL(JSVAL_TAG_UNDEFINED
, 0) };
183 /* Make sure that jschar is two bytes unsigned integer */
184 JS_STATIC_ASSERT((jschar
)-1 > 0);
185 JS_STATIC_ASSERT(sizeof(jschar
) == 2);
194 JS_GetNaNValue(JSContext
*cx
)
196 return Jsvalify(cx
->runtime
->NaNValue
);
200 JS_GetNegativeInfinityValue(JSContext
*cx
)
202 return Jsvalify(cx
->runtime
->negativeInfinityValue
);
206 JS_GetPositiveInfinityValue(JSContext
*cx
)
208 return Jsvalify(cx
->runtime
->positiveInfinityValue
);
212 JS_GetEmptyStringValue(JSContext
*cx
)
214 return STRING_TO_JSVAL(cx
->runtime
->emptyString
);
217 JS_PUBLIC_API(JSString
*)
218 JS_GetEmptyString(JSRuntime
*rt
)
220 JS_ASSERT(rt
->state
== JSRTS_UP
);
221 return rt
->emptyString
;
225 TryArgumentFormatter(JSContext
*cx
, const char **formatp
, JSBool fromJS
, jsval
**vpp
, va_list *app
)
228 JSArgumentFormatMap
*map
;
231 for (map
= cx
->argumentFormatMap
; map
; map
= map
->next
) {
232 if (!strncmp(format
, map
->format
, map
->length
)) {
233 *formatp
= format
+ map
->length
;
234 return map
->formatter(cx
, format
, fromJS
, vpp
, app
);
237 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_BAD_CHAR
, format
);
241 JS_PUBLIC_API(JSBool
)
242 JS_ConvertArguments(JSContext
*cx
, uintN argc
, jsval
*argv
, const char *format
, ...)
247 va_start(ap
, format
);
248 ok
= JS_ConvertArgumentsVA(cx
, argc
, argv
, format
, ap
);
253 JS_PUBLIC_API(JSBool
)
254 JS_ConvertArgumentsVA(JSContext
*cx
, uintN argc
, jsval
*argv
, const char *format
, va_list ap
)
265 assertSameCompartment(cx
, JSValueArray(argv
- 2, argc
+ 2));
268 while ((c
= *format
++) != '\0') {
275 if (sp
== argv
+ argc
) {
277 fun
= js_ValueToFunction(cx
, Valueify(&argv
[-2]), 0);
280 JS_snprintf(numBuf
, sizeof numBuf
, "%u", argc
);
281 JSAutoByteString funNameBytes
;
282 if (const char *name
= GetFunctionNameBytes(cx
, fun
, &funNameBytes
)) {
283 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_MORE_ARGS_NEEDED
,
284 name
, numBuf
, (argc
== 1) ? "" : "s");
293 *va_arg(ap
, JSBool
*) = js_ValueToBoolean(Valueify(*sp
));
296 if (!JS_ValueToUint16(cx
, *sp
, va_arg(ap
, uint16
*)))
300 if (!JS_ValueToECMAInt32(cx
, *sp
, va_arg(ap
, int32
*)))
304 if (!JS_ValueToECMAUint32(cx
, *sp
, va_arg(ap
, uint32
*)))
308 if (!JS_ValueToInt32(cx
, *sp
, va_arg(ap
, int32
*)))
312 if (!JS_ValueToNumber(cx
, *sp
, va_arg(ap
, jsdouble
*)))
316 if (!JS_ValueToNumber(cx
, *sp
, &d
))
318 *va_arg(ap
, jsdouble
*) = js_DoubleToInteger(d
);
322 str
= js_ValueToString(cx
, Valueify(*sp
));
325 *sp
= STRING_TO_JSVAL(str
);
327 const jschar
*chars
= js_GetStringChars(cx
, str
);
330 *va_arg(ap
, const jschar
**) = chars
;
332 *va_arg(ap
, JSString
**) = str
;
336 if (!js_ValueToObjectOrNull(cx
, Valueify(*sp
), &obj
))
338 *sp
= OBJECT_TO_JSVAL(obj
);
339 *va_arg(ap
, JSObject
**) = obj
;
342 obj
= js_ValueToFunctionObject(cx
, Valueify(sp
), 0);
345 *sp
= OBJECT_TO_JSVAL(obj
);
346 *va_arg(ap
, JSFunction
**) = GET_FUNCTION_PRIVATE(cx
, obj
);
349 *va_arg(ap
, jsval
*) = *sp
;
355 if (!TryArgumentFormatter(cx
, &format
, JS_TRUE
, &sp
,
356 JS_ADDRESSOF_VA_LIST(ap
))) {
359 /* NB: the formatter already updated sp, so we continue here. */
367 JS_PUBLIC_API(JSBool
)
368 JS_AddArgumentFormatter(JSContext
*cx
, const char *format
, JSArgumentFormatter formatter
)
371 JSArgumentFormatMap
**mpp
, *map
;
373 length
= strlen(format
);
374 mpp
= &cx
->argumentFormatMap
;
375 while ((map
= *mpp
) != NULL
) {
376 /* Insert before any shorter string to match before prefixes. */
377 if (map
->length
< length
)
379 if (map
->length
== length
&& !strcmp(map
->format
, format
))
383 map
= (JSArgumentFormatMap
*) cx
->malloc(sizeof *map
);
386 map
->format
= format
;
387 map
->length
= length
;
391 map
->formatter
= formatter
;
396 JS_RemoveArgumentFormatter(JSContext
*cx
, const char *format
)
399 JSArgumentFormatMap
**mpp
, *map
;
401 length
= strlen(format
);
402 mpp
= &cx
->argumentFormatMap
;
403 while ((map
= *mpp
) != NULL
) {
404 if (map
->length
== length
&& !strcmp(map
->format
, format
)) {
413 JS_PUBLIC_API(JSBool
)
414 JS_ConvertValue(JSContext
*cx
, jsval v
, JSType type
, jsval
*vp
)
422 assertSameCompartment(cx
, v
);
429 ok
= js_ValueToObjectOrNull(cx
, Valueify(v
), &obj
);
431 *vp
= OBJECT_TO_JSVAL(obj
);
433 case JSTYPE_FUNCTION
:
435 obj
= js_ValueToFunctionObject(cx
, Valueify(vp
), JSV2F_SEARCH_STACK
);
439 str
= js_ValueToString(cx
, Valueify(v
));
442 *vp
= STRING_TO_JSVAL(str
);
445 ok
= JS_ValueToNumber(cx
, v
, &d
);
447 *vp
= DOUBLE_TO_JSVAL(d
);
450 *vp
= BOOLEAN_TO_JSVAL(js_ValueToBoolean(Valueify(v
)));
454 JS_snprintf(numBuf
, sizeof numBuf
, "%d", (int)type
);
455 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_BAD_TYPE
, numBuf
);
463 JS_PUBLIC_API(JSBool
)
464 JS_ValueToObject(JSContext
*cx
, jsval v
, JSObject
**objp
)
467 assertSameCompartment(cx
, v
);
468 return js_ValueToObjectOrNull(cx
, Valueify(v
), objp
);
471 JS_PUBLIC_API(JSFunction
*)
472 JS_ValueToFunction(JSContext
*cx
, jsval v
)
475 assertSameCompartment(cx
, v
);
476 return js_ValueToFunction(cx
, Valueify(&v
), JSV2F_SEARCH_STACK
);
479 JS_PUBLIC_API(JSFunction
*)
480 JS_ValueToConstructor(JSContext
*cx
, jsval v
)
483 assertSameCompartment(cx
, v
);
484 return js_ValueToFunction(cx
, Valueify(&v
), JSV2F_SEARCH_STACK
);
487 JS_PUBLIC_API(JSString
*)
488 JS_ValueToString(JSContext
*cx
, jsval v
)
491 assertSameCompartment(cx
, v
);
492 return js_ValueToString(cx
, Valueify(v
));
495 JS_PUBLIC_API(JSString
*)
496 JS_ValueToSource(JSContext
*cx
, jsval v
)
499 assertSameCompartment(cx
, v
);
500 return js_ValueToSource(cx
, Valueify(v
));
503 JS_PUBLIC_API(JSBool
)
504 JS_ValueToNumber(JSContext
*cx
, jsval v
, jsdouble
*dp
)
507 assertSameCompartment(cx
, v
);
509 AutoValueRooter
tvr(cx
, Valueify(v
));
510 return ValueToNumber(cx
, tvr
.value(), dp
);
513 JS_PUBLIC_API(JSBool
)
514 JS_DoubleIsInt32(jsdouble d
, jsint
*ip
)
516 return JSDOUBLE_IS_INT32(d
, (int32_t *)ip
);
519 JS_PUBLIC_API(JSBool
)
520 JS_ValueToECMAInt32(JSContext
*cx
, jsval v
, int32
*ip
)
523 assertSameCompartment(cx
, v
);
525 AutoValueRooter
tvr(cx
, Valueify(v
));
526 return ValueToECMAInt32(cx
, tvr
.value(), (int32_t *)ip
);
529 JS_PUBLIC_API(JSBool
)
530 JS_ValueToECMAUint32(JSContext
*cx
, jsval v
, uint32
*ip
)
533 assertSameCompartment(cx
, v
);
535 AutoValueRooter
tvr(cx
, Valueify(v
));
536 return ValueToECMAUint32(cx
, tvr
.value(), (uint32_t *)ip
);
539 JS_PUBLIC_API(JSBool
)
540 JS_ValueToInt32(JSContext
*cx
, jsval v
, int32
*ip
)
543 assertSameCompartment(cx
, v
);
545 AutoValueRooter
tvr(cx
, Valueify(v
));
546 return ValueToInt32(cx
, tvr
.value(), (int32_t *)ip
);
549 JS_PUBLIC_API(JSBool
)
550 JS_ValueToUint16(JSContext
*cx
, jsval v
, uint16
*ip
)
553 assertSameCompartment(cx
, v
);
555 AutoValueRooter
tvr(cx
, Valueify(v
));
556 return ValueToUint16(cx
, tvr
.value(), (uint16_t *)ip
);
559 JS_PUBLIC_API(JSBool
)
560 JS_ValueToBoolean(JSContext
*cx
, jsval v
, JSBool
*bp
)
563 assertSameCompartment(cx
, v
);
564 *bp
= js_ValueToBoolean(Valueify(v
));
568 JS_PUBLIC_API(JSType
)
569 JS_TypeOfValue(JSContext
*cx
, jsval v
)
572 assertSameCompartment(cx
, v
);
573 return TypeOfValue(cx
, Valueify(v
));
576 JS_PUBLIC_API(const char *)
577 JS_GetTypeName(JSContext
*cx
, JSType type
)
579 if ((uintN
)type
>= (uintN
)JSTYPE_LIMIT
)
581 return JS_TYPE_STR(type
);
584 JS_PUBLIC_API(JSBool
)
585 JS_StrictlyEqual(JSContext
*cx
, jsval v1
, jsval v2
, JSBool
*equal
)
587 assertSameCompartment(cx
, v1
, v2
);
588 return StrictlyEqual(cx
, Valueify(v1
), Valueify(v2
), equal
);
591 JS_PUBLIC_API(JSBool
)
592 JS_SameValue(JSContext
*cx
, jsval v1
, jsval v2
, JSBool
*same
)
594 assertSameCompartment(cx
, v1
, v2
);
595 return SameValue(cx
, Valueify(v1
), Valueify(v2
), same
);
598 /************************************************************************/
601 * Has a new runtime ever been created? This flag is used to detect unsafe
602 * changes to js_CStringsAreUTF8 after a runtime has been created, and to
603 * ensure that "first checks" on runtime creation are run only once.
606 static JSBool js_NewRuntimeWasCalled
= JS_FALSE
;
609 JSRuntime::JSRuntime()
610 : gcChunkAllocator(&defaultGCChunkAllocator
)
612 /* Initialize infallibly first, so we can goto bad and JS_DestroyRuntime. */
613 JS_INIT_CLIST(&contextList
);
614 JS_INIT_CLIST(&trapList
);
615 JS_INIT_CLIST(&watchPointList
);
619 JSRuntime::init(uint32 maxbytes
)
621 #ifdef JS_METHODJIT_SPEW
626 functionMeterFilename
= getenv("JS_FUNCTION_STATFILE");
627 if (functionMeterFilename
) {
628 if (!methodReadBarrierCountMap
.init())
630 if (!unjoinedFunctionCountMap
.init())
633 propTreeStatFilename
= getenv("JS_PROPTREE_STATFILE");
634 propTreeDumpFilename
= getenv("JS_PROPTREE_DUMPFILE");
635 if (meterEmptyShapes()) {
636 if (!emptyShapes
.init())
641 if (!(defaultCompartment
= new JSCompartment(this)) ||
642 !defaultCompartment
->init() ||
643 !compartments
.append(defaultCompartment
)) {
647 if (!js_InitGC(this, maxbytes
) || !js_InitAtomState(this))
650 wrapObjectCallback
= js::TransparentObjectWrapper
;
653 /* this is asymmetric with JS_ShutDown: */
654 if (!js_SetupLocks(8, 16))
656 rtLock
= JS_NEW_LOCK();
659 stateChange
= JS_NEW_CONDVAR(gcLock
);
662 debuggerLock
= JS_NEW_LOCK();
667 debugMode
= JS_FALSE
;
669 return propertyTree
.init() && js_InitThreads(this);
672 JSRuntime::~JSRuntime()
675 /* Don't hurt everyone in leaky ol' Mozilla with a fatal JS_ASSERT! */
676 if (!JS_CLIST_IS_EMPTY(&contextList
)) {
677 JSContext
*cx
, *iter
= NULL
;
679 while ((cx
= js_ContextIterator(this, JS_TRUE
, &iter
)) != NULL
) {
681 "JS API usage error: found live context at %p\n",
686 "JS API usage error: %u context%s left in runtime upon JS_DestroyRuntime.\n",
687 cxcount
, (cxcount
== 1) ? "" : "s");
691 js_FinishThreads(this);
692 js_FreeRuntimeScriptState(this);
693 js_FinishAtomState(this);
698 JS_DESTROY_LOCK(gcLock
);
700 JS_DESTROY_CONDVAR(gcDone
);
702 JS_DESTROY_CONDVAR(requestDone
);
704 JS_DESTROY_LOCK(rtLock
);
706 JS_DESTROY_CONDVAR(stateChange
);
708 JS_DESTROY_LOCK(debuggerLock
);
710 propertyTree
.finish();
713 JS_PUBLIC_API(JSRuntime
*)
714 JS_NewRuntime(uint32 maxbytes
)
717 if (!js_NewRuntimeWasCalled
) {
719 * This code asserts that the numbers associated with the error names
720 * in jsmsg.def are monotonically increasing. It uses values for the
721 * error names enumerated in jscntxt.c. It's not a compile-time check
722 * but it's better than nothing.
725 #define MSG_DEF(name, number, count, exception, format) \
726 JS_ASSERT(name == errorNumber++);
730 #define MSG_DEF(name, number, count, exception, format) \
732 uintN numfmtspecs = 0; \
734 for (fmt = format; *fmt != '\0'; fmt++) { \
735 if (*fmt == '{' && isdigit(fmt[1])) \
738 JS_ASSERT(count == numfmtspecs); \
743 js_NewRuntimeWasCalled
= JS_TRUE
;
747 void *mem
= js_calloc(sizeof(JSRuntime
));
751 JSRuntime
*rt
= new (mem
) JSRuntime();
752 if (!rt
->init(maxbytes
)) {
753 JS_DestroyRuntime(rt
);
761 JS_DestroyRuntime(JSRuntime
*rt
)
769 namespace reprmeter
{
770 extern void js_DumpReprMeter();
782 extern void js_DumpOpMeters();
787 reprmeter::js_DumpReprMeter();
796 JS_PUBLIC_API(void *)
797 JS_GetRuntimePrivate(JSRuntime
*rt
)
803 JS_SetRuntimePrivate(JSRuntime
*rt
, void *data
)
810 StartRequest(JSContext
*cx
)
812 JSThread
*t
= cx
->thread
;
813 JS_ASSERT(CURRENT_THREAD_IS_ME(t
));
815 if (t
->data
.requestDepth
) {
816 t
->data
.requestDepth
++;
818 JSRuntime
*rt
= cx
->runtime
;
821 /* Wait until the GC is finished. */
822 if (rt
->gcThread
!= cx
->thread
) {
824 JS_AWAIT_GC_DONE(rt
);
827 /* Indicate that a request is running. */
829 t
->data
.requestDepth
= 1;
832 * Adjust rt->interruptCounter to reflect any interrupts added while the
833 * thread was suspended.
835 if (t
->data
.interruptFlags
)
836 JS_ATOMIC_INCREMENT(&rt
->interruptCounter
);
838 if (rt
->requestCount
== 1 && rt
->activityCallback
)
839 rt
->activityCallback(rt
->activityCallbackArg
, true);
844 StopRequest(JSContext
*cx
)
846 JSThread
*t
= cx
->thread
;
847 JS_ASSERT(CURRENT_THREAD_IS_ME(t
));
848 JS_ASSERT(t
->data
.requestDepth
!= 0);
849 if (t
->data
.requestDepth
!= 1) {
850 t
->data
.requestDepth
--;
852 LeaveTrace(cx
); /* for GC safety */
854 t
->data
.conservativeGC
.updateForRequestEnd(t
->suspendCount
);
856 /* Lock before clearing to interlock with ClaimScope, in jslock.c. */
857 JSRuntime
*rt
= cx
->runtime
;
860 t
->data
.requestDepth
= 0;
863 * Adjust rt->interruptCounter to reflect any interrupts added while the
864 * thread still had active requests.
866 if (t
->data
.interruptFlags
)
867 JS_ATOMIC_DECREMENT(&rt
->interruptCounter
);
869 /* Give the GC a chance to run if this was the last request running. */
870 JS_ASSERT(rt
->requestCount
> 0);
872 if (rt
->requestCount
== 0) {
873 JS_NOTIFY_REQUEST_DONE(rt
);
874 if (rt
->activityCallback
)
875 rt
->activityCallback(rt
->activityCallbackArg
, false);
879 #endif /* JS_THREADSAFE */
882 JS_BeginRequest(JSContext
*cx
)
885 cx
->outstandingRequests
++;
891 JS_EndRequest(JSContext
*cx
)
894 JS_ASSERT(cx
->outstandingRequests
!= 0);
895 cx
->outstandingRequests
--;
900 /* Yield to pending GC operations, regardless of request depth */
902 JS_YieldRequest(JSContext
*cx
)
906 JS_ResumeRequest(cx
, JS_SuspendRequest(cx
));
910 JS_PUBLIC_API(jsrefcount
)
911 JS_SuspendRequest(JSContext
*cx
)
914 JSThread
*t
= cx
->thread
;
915 JS_ASSERT(CURRENT_THREAD_IS_ME(t
));
917 jsrefcount saveDepth
= t
->data
.requestDepth
;
922 t
->data
.requestDepth
= 1;
931 JS_ResumeRequest(JSContext
*cx
, jsrefcount saveDepth
)
934 JSThread
*t
= cx
->thread
;
935 JS_ASSERT(CURRENT_THREAD_IS_ME(t
));
938 JS_ASSERT(saveDepth
>= 1);
939 JS_ASSERT(!t
->data
.requestDepth
);
940 JS_ASSERT(t
->suspendCount
);
942 t
->data
.requestDepth
= saveDepth
;
947 JS_PUBLIC_API(JSBool
)
948 JS_IsInRequest(JSContext
*cx
)
951 JS_ASSERT(CURRENT_THREAD_IS_ME(cx
->thread
));
952 return JS_THREAD_DATA(cx
)->requestDepth
!= 0;
959 JS_Lock(JSRuntime
*rt
)
965 JS_Unlock(JSRuntime
*rt
)
967 JS_UNLOCK_RUNTIME(rt
);
970 JS_PUBLIC_API(JSContextCallback
)
971 JS_SetContextCallback(JSRuntime
*rt
, JSContextCallback cxCallback
)
973 JSContextCallback old
;
975 old
= rt
->cxCallback
;
976 rt
->cxCallback
= cxCallback
;
980 JS_PUBLIC_API(JSContext
*)
981 JS_NewContext(JSRuntime
*rt
, size_t stackChunkSize
)
983 return js_NewContext(rt
, stackChunkSize
);
987 JS_DestroyContext(JSContext
*cx
)
989 js_DestroyContext(cx
, JSDCM_FORCE_GC
);
993 JS_DestroyContextNoGC(JSContext
*cx
)
995 js_DestroyContext(cx
, JSDCM_NO_GC
);
999 JS_DestroyContextMaybeGC(JSContext
*cx
)
1001 js_DestroyContext(cx
, JSDCM_MAYBE_GC
);
1004 JS_PUBLIC_API(void *)
1005 JS_GetContextPrivate(JSContext
*cx
)
1011 JS_SetContextPrivate(JSContext
*cx
, void *data
)
1016 JS_PUBLIC_API(JSRuntime
*)
1017 JS_GetRuntime(JSContext
*cx
)
1022 JS_PUBLIC_API(JSContext
*)
1023 JS_ContextIterator(JSRuntime
*rt
, JSContext
**iterp
)
1025 return js_ContextIterator(rt
, JS_TRUE
, iterp
);
1028 JS_PUBLIC_API(JSVersion
)
1029 JS_GetVersion(JSContext
*cx
)
1031 return VersionNumber(cx
->findVersion());
1034 JS_PUBLIC_API(JSVersion
)
1035 JS_SetVersion(JSContext
*cx
, JSVersion newVersion
)
1037 JS_ASSERT(VersionIsKnown(newVersion
));
1038 JS_ASSERT(!VersionHasFlags(newVersion
));
1039 JSVersion newVersionNumber
= newVersion
;
1041 JSVersion oldVersion
= cx
->findVersion();
1042 JSVersion oldVersionNumber
= VersionNumber(oldVersion
);
1043 if (oldVersionNumber
== newVersionNumber
)
1044 return oldVersionNumber
; /* No override actually occurs! */
1046 /* We no longer support 1.4 or below. */
1047 if (newVersionNumber
!= JSVERSION_DEFAULT
&& newVersionNumber
<= JSVERSION_1_4
)
1048 return oldVersionNumber
;
1050 cx
->optionFlagsToVersion(&newVersion
);
1051 cx
->maybeOverrideVersion(newVersion
);
1052 cx
->checkOptionVersionSync();
1053 return oldVersionNumber
;
1056 static struct v2smap
{
1060 {JSVERSION_1_0
, "1.0"},
1061 {JSVERSION_1_1
, "1.1"},
1062 {JSVERSION_1_2
, "1.2"},
1063 {JSVERSION_1_3
, "1.3"},
1064 {JSVERSION_1_4
, "1.4"},
1065 {JSVERSION_ECMA_3
, "ECMAv3"},
1066 {JSVERSION_1_5
, "1.5"},
1067 {JSVERSION_1_6
, "1.6"},
1068 {JSVERSION_1_7
, "1.7"},
1069 {JSVERSION_1_8
, "1.8"},
1070 {JSVERSION_ECMA_5
, "ECMAv5"},
1071 {JSVERSION_DEFAULT
, js_default_str
},
1072 {JSVERSION_UNKNOWN
, NULL
}, /* must be last, NULL is sentinel */
1075 JS_PUBLIC_API(const char *)
1076 JS_VersionToString(JSVersion version
)
1080 for (i
= 0; v2smap
[i
].string
; i
++)
1081 if (v2smap
[i
].version
== version
)
1082 return v2smap
[i
].string
;
1086 JS_PUBLIC_API(JSVersion
)
1087 JS_StringToVersion(const char *string
)
1091 for (i
= 0; v2smap
[i
].string
; i
++)
1092 if (strcmp(v2smap
[i
].string
, string
) == 0)
1093 return v2smap
[i
].version
;
1094 return JSVERSION_UNKNOWN
;
1097 JS_PUBLIC_API(uint32
)
1098 JS_GetOptions(JSContext
*cx
)
1101 * Can't check option/version synchronization here.
1102 * We may have been synchronized with a script version that was formerly on
1103 * the stack, but has now been popped.
1108 JS_PUBLIC_API(uint32
)
1109 JS_SetOptions(JSContext
*cx
, uint32 options
)
1111 AutoLockGC
lock(cx
->runtime
);
1112 uint32 oldopts
= cx
->options
;
1113 cx
->options
= options
;
1114 cx
->syncOptionsToVersion();
1115 cx
->updateJITEnabled();
1116 cx
->checkOptionVersionSync();
1120 JS_PUBLIC_API(uint32
)
1121 JS_ToggleOptions(JSContext
*cx
, uint32 options
)
1123 AutoLockGC
lock(cx
->runtime
);
1124 cx
->checkOptionVersionSync();
1125 uint32 oldopts
= cx
->options
;
1126 cx
->options
^= options
;
1127 cx
->syncOptionsToVersion();
1128 cx
->updateJITEnabled();
1129 cx
->checkOptionVersionSync();
1133 JS_PUBLIC_API(const char *)
1134 JS_GetImplementationVersion(void)
1136 return "JavaScript-C 1.8.0 pre-release 1 2007-10-03";
1139 JS_PUBLIC_API(JSCompartmentCallback
)
1140 JS_SetCompartmentCallback(JSRuntime
*rt
, JSCompartmentCallback callback
)
1142 JSCompartmentCallback old
= rt
->compartmentCallback
;
1143 rt
->compartmentCallback
= callback
;
1147 JS_PUBLIC_API(JSWrapObjectCallback
)
1148 JS_SetWrapObjectCallbacks(JSRuntime
*rt
,
1149 JSWrapObjectCallback callback
,
1150 JSPreWrapCallback precallback
)
1152 JSWrapObjectCallback old
= rt
->wrapObjectCallback
;
1153 rt
->wrapObjectCallback
= callback
;
1154 rt
->preWrapObjectCallback
= precallback
;
1158 JS_PUBLIC_API(JSCrossCompartmentCall
*)
1159 JS_EnterCrossCompartmentCall(JSContext
*cx
, JSObject
*target
)
1164 AutoCompartment
*call
= new AutoCompartment(cx
, target
);
1167 if (!call
->enter()) {
1171 return reinterpret_cast<JSCrossCompartmentCall
*>(call
);
1174 JS_PUBLIC_API(JSCrossCompartmentCall
*)
1175 JS_EnterCrossCompartmentCallScript(JSContext
*cx
, JSScript
*target
)
1180 JSObject
*scriptObject
= target
->u
.object
;
1181 if (!scriptObject
) {
1182 SwitchToCompartment
sc(cx
, target
->compartment
);
1183 scriptObject
= JS_NewGlobalObject(cx
, &dummy_class
);
1187 return JS_EnterCrossCompartmentCall(cx
, scriptObject
);
1191 JS_LeaveCrossCompartmentCall(JSCrossCompartmentCall
*call
)
1193 AutoCompartment
*realcall
= reinterpret_cast<AutoCompartment
*>(call
);
1194 CHECK_REQUEST(realcall
->context
);
1200 JSAutoEnterCompartment::enter(JSContext
*cx
, JSObject
*target
)
1203 if (cx
->compartment
== target
->getCompartment()) {
1204 call
= reinterpret_cast<JSCrossCompartmentCall
*>(1);
1207 call
= JS_EnterCrossCompartmentCall(cx
, target
);
1208 return call
!= NULL
;
1212 JSAutoEnterCompartment::enter(JSContext
*cx
, JSScript
*target
)
1215 if (cx
->compartment
== target
->compartment
) {
1216 call
= reinterpret_cast<JSCrossCompartmentCall
*>(1);
1219 call
= JS_EnterCrossCompartmentCallScript(cx
, target
);
1220 return call
!= NULL
;
1224 JSAutoEnterCompartment::enterAndIgnoreErrors(JSContext
*cx
, JSObject
*target
)
1226 (void) enter(cx
, target
);
1229 JS_PUBLIC_API(void *)
1230 JS_SetCompartmentPrivate(JSContext
*cx
, JSCompartment
*compartment
, void *data
)
1233 void *old
= compartment
->data
;
1234 compartment
->data
= data
;
1238 JS_PUBLIC_API(void *)
1239 JS_GetCompartmentPrivate(JSContext
*cx
, JSCompartment
*compartment
)
1242 return compartment
->data
;
1245 JS_PUBLIC_API(JSBool
)
1246 JS_WrapObject(JSContext
*cx
, JSObject
**objp
)
1249 return cx
->compartment
->wrap(cx
, objp
);
1252 JS_PUBLIC_API(JSBool
)
1253 JS_WrapValue(JSContext
*cx
, jsval
*vp
)
1256 return cx
->compartment
->wrap(cx
, Valueify(vp
));
1259 JS_PUBLIC_API(JSObject
*)
1260 JS_TransplantObject(JSContext
*cx
, JSObject
*origobj
, JSObject
*target
)
1262 // This function is called when an object moves between two different
1263 // compartments. In that case, we need to "move" the window from origobj's
1264 // compartment to target's compartment.
1265 JSCompartment
*destination
= target
->getCompartment();
1266 if (origobj
->getCompartment() == destination
) {
1267 // If the original object is in the same compartment as the
1268 // destination, then we know that we won't find wrapper in the
1269 // destination's cross compartment map and that the same object
1270 // will continue to work.
1271 if (!origobj
->swap(cx
, target
))
1277 WrapperMap
&map
= destination
->crossCompartmentWrappers
;
1278 Value origv
= ObjectValue(*origobj
);
1280 // There might already be a wrapper for the original object in the new
1282 if (WrapperMap::Ptr p
= map
.lookup(origv
)) {
1283 // If there is, make it the primary outer window proxy around the
1284 // inner (accomplished by swapping target's innards with the old,
1285 // possibly security wrapper, innards).
1286 obj
= &p
->value
.toObject();
1288 if (!obj
->swap(cx
, target
))
1291 // Otherwise, this is going to be our outer window proxy in the new
1296 // Now, iterate through other scopes looking for references to the old
1297 // outer window. They need to be updated to point at the new outer window.
1298 // They also might transition between different types of security wrappers
1299 // based on whether the new compartment is same origin with them.
1300 Value targetv
= ObjectValue(*obj
);
1301 WrapperVector
&vector
= cx
->runtime
->compartments
;
1302 AutoValueVector
toTransplant(cx
);
1303 toTransplant
.reserve(vector
.length());
1305 for (JSCompartment
**p
= vector
.begin(), **end
= vector
.end(); p
!= end
; ++p
) {
1306 WrapperMap
&pmap
= (*p
)->crossCompartmentWrappers
;
1307 if (WrapperMap::Ptr wp
= pmap
.lookup(origv
)) {
1308 // We found a wrapper. Remember and root it.
1309 toTransplant
.append(wp
->value
);
1313 for (Value
*begin
= toTransplant
.begin(), *end
= toTransplant
.end(); begin
!= end
; ++begin
) {
1314 JSObject
*wobj
= &begin
->toObject();
1315 JSCompartment
*wcompartment
= wobj
->compartment();
1316 WrapperMap
&pmap
= wcompartment
->crossCompartmentWrappers
;
1317 JS_ASSERT(pmap
.lookup(origv
));
1320 // First, we wrap it in the new compartment. This will return a
1322 AutoCompartment
ac(cx
, wobj
);
1323 JSObject
*tobj
= obj
;
1324 if (!ac
.enter() || !wcompartment
->wrap(cx
, &tobj
))
1327 // Now, because we need to maintain object identity, we do a brain
1328 // transplant on the old object. At the same time, we update the
1329 // entry in the compartment's wrapper map to point to the old
1331 JS_ASSERT(tobj
!= wobj
);
1332 if (!wobj
->swap(cx
, tobj
))
1334 pmap
.put(targetv
, ObjectValue(*wobj
));
1337 // Lastly, update the original object to point to the new one.
1339 AutoCompartment
ac(cx
, origobj
);
1340 JSObject
*tobj
= obj
;
1341 if (!ac
.enter() || !JS_WrapObject(cx
, &tobj
))
1343 if (!origobj
->swap(cx
, tobj
))
1345 origobj
->getCompartment()->crossCompartmentWrappers
.put(targetv
, origv
);
1351 JS_PUBLIC_API(JSObject
*)
1352 JS_GetGlobalObject(JSContext
*cx
)
1354 return cx
->globalObject
;
1358 JS_SetGlobalObject(JSContext
*cx
, JSObject
*obj
)
1362 cx
->globalObject
= obj
;
1364 cx
->resetCompartment();
1367 class AutoResolvingEntry
{
1369 AutoResolvingEntry() : entry(NULL
) {}
1372 * Returns false on error. But N.B. if obj[id] was already being resolved,
1373 * this is a no-op, and we silently treat that as success.
1375 bool start(JSContext
*cx
, JSObject
*obj
, jsid id
, uint32 flag
) {
1381 bool ok
= !!js_StartResolving(cx
, &key
, flag
, &entry
);
1382 JS_ASSERT_IF(!ok
, !entry
);
1386 ~AutoResolvingEntry() {
1388 js_StopResolving(cx
, &key
, flag
, NULL
, 0);
1395 JSResolvingEntry
*entry
;
1399 js_InitFunctionAndObjectClasses(JSContext
*cx
, JSObject
*obj
)
1401 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
1402 JSObject
*fun_proto
, *obj_proto
;
1404 /* If cx has no global object, use obj so prototypes can be found. */
1405 if (!cx
->globalObject
)
1406 JS_SetGlobalObject(cx
, obj
);
1408 /* Record Function and Object in cx->resolvingTable. */
1409 AutoResolvingEntry e1
, e2
;
1410 JSAtom
**classAtoms
= cx
->runtime
->atomState
.classAtoms
;
1411 if (!e1
.start(cx
, obj
, ATOM_TO_JSID(classAtoms
[JSProto_Function
]), JSRESFLAG_LOOKUP
) ||
1412 !e2
.start(cx
, obj
, ATOM_TO_JSID(classAtoms
[JSProto_Object
]), JSRESFLAG_LOOKUP
)) {
1416 /* Initialize the function class first so constructors can be made. */
1417 if (!js_GetClassPrototype(cx
, obj
, JSProto_Function
, &fun_proto
))
1420 fun_proto
= js_InitFunctionClass(cx
, obj
);
1426 ctor
= JS_GetConstructor(cx
, fun_proto
);
1429 obj
->defineProperty(cx
, ATOM_TO_JSID(CLASS_ATOM(cx
, Function
)),
1430 ObjectValue(*ctor
), 0, 0, 0);
1433 /* Initialize the object class next so Object.prototype works. */
1434 if (!js_GetClassPrototype(cx
, obj
, JSProto_Object
, &obj_proto
))
1437 obj_proto
= js_InitObjectClass(cx
, obj
);
1441 /* Function.prototype and the global object delegate to Object.prototype. */
1442 fun_proto
->setProto(obj_proto
);
1443 if (!obj
->getProto())
1444 obj
->setProto(obj_proto
);
1449 JS_PUBLIC_API(JSBool
)
1450 JS_InitStandardClasses(JSContext
*cx
, JSObject
*obj
)
1452 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
1456 * JS_SetGlobalObject might or might not change cx's compartment, so call
1457 * it before assertSameCompartment. (The API contract is that *after* this,
1458 * cx and obj must be in the same compartment.)
1460 if (!cx
->globalObject
)
1461 JS_SetGlobalObject(cx
, obj
);
1462 assertSameCompartment(cx
, obj
);
1464 /* Define a top-level property 'undefined' with the undefined value. */
1465 JSAtom
*atom
= cx
->runtime
->atomState
.typeAtoms
[JSTYPE_VOID
];
1466 if (!obj
->defineProperty(cx
, ATOM_TO_JSID(atom
), UndefinedValue(),
1467 PropertyStub
, PropertyStub
,
1468 JSPROP_PERMANENT
| JSPROP_READONLY
)) {
1472 /* Function and Object require cooperative bootstrapping magic. */
1473 if (!js_InitFunctionAndObjectClasses(cx
, obj
))
1476 /* Initialize the rest of the standard objects and functions. */
1477 return js_InitArrayClass(cx
, obj
) &&
1478 js_InitBooleanClass(cx
, obj
) &&
1479 js_InitExceptionClasses(cx
, obj
) &&
1480 js_InitMathClass(cx
, obj
) &&
1481 js_InitNumberClass(cx
, obj
) &&
1482 js_InitJSONClass(cx
, obj
) &&
1483 js_InitRegExpClass(cx
, obj
) &&
1484 js_InitStringClass(cx
, obj
) &&
1485 js_InitTypedArrayClasses(cx
, obj
) &&
1486 #if JS_HAS_XML_SUPPORT
1487 js_InitXMLClasses(cx
, obj
) &&
1489 #if JS_HAS_GENERATORS
1490 js_InitIteratorClasses(cx
, obj
) &&
1492 js_InitDateClass(cx
, obj
) &&
1493 js_InitProxyClass(cx
, obj
);
1496 #define CLASP(name) (&js_##name##Class)
1497 #define TYPED_ARRAY_CLASP(type) (&TypedArray::fastClasses[TypedArray::type])
1498 #define EAGER_ATOM(name) ATOM_OFFSET(name), NULL
1499 #define EAGER_CLASS_ATOM(name) CLASS_ATOM_OFFSET(name), NULL
1500 #define EAGER_ATOM_AND_CLASP(name) EAGER_CLASS_ATOM(name), CLASP(name)
1501 #define LAZY_ATOM(name) ATOM_OFFSET(lazy.name), js_##name##_str
1503 typedef struct JSStdName
{
1505 size_t atomOffset
; /* offset of atom pointer in JSAtomState */
1506 const char *name
; /* null if atom is pre-pinned, else name */
1511 StdNameToAtom(JSContext
*cx
, JSStdName
*stdn
)
1517 offset
= stdn
->atomOffset
;
1518 atom
= OFFSET_TO_ATOM(cx
->runtime
, offset
);
1522 atom
= js_Atomize(cx
, name
, strlen(name
), ATOM_PINNED
);
1523 OFFSET_TO_ATOM(cx
->runtime
, offset
) = atom
;
1530 * Table of class initializers and their atom offsets in rt->atomState.
1531 * If you add a "standard" class, remember to update this table.
1533 static JSStdName standard_class_atoms
[] = {
1534 {js_InitFunctionAndObjectClasses
, EAGER_ATOM_AND_CLASP(Function
)},
1535 {js_InitFunctionAndObjectClasses
, EAGER_ATOM_AND_CLASP(Object
)},
1536 {js_InitArrayClass
, EAGER_ATOM_AND_CLASP(Array
)},
1537 {js_InitBooleanClass
, EAGER_ATOM_AND_CLASP(Boolean
)},
1538 {js_InitDateClass
, EAGER_ATOM_AND_CLASP(Date
)},
1539 {js_InitMathClass
, EAGER_ATOM_AND_CLASP(Math
)},
1540 {js_InitNumberClass
, EAGER_ATOM_AND_CLASP(Number
)},
1541 {js_InitStringClass
, EAGER_ATOM_AND_CLASP(String
)},
1542 {js_InitExceptionClasses
, EAGER_ATOM_AND_CLASP(Error
)},
1543 {js_InitRegExpClass
, EAGER_ATOM_AND_CLASP(RegExp
)},
1544 #if JS_HAS_XML_SUPPORT
1545 {js_InitXMLClass
, EAGER_ATOM_AND_CLASP(XML
)},
1546 {js_InitNamespaceClass
, EAGER_ATOM_AND_CLASP(Namespace
)},
1547 {js_InitQNameClass
, EAGER_ATOM_AND_CLASP(QName
)},
1549 #if JS_HAS_GENERATORS
1550 {js_InitIteratorClasses
, EAGER_ATOM_AND_CLASP(StopIteration
)},
1552 {js_InitJSONClass
, EAGER_ATOM_AND_CLASP(JSON
)},
1553 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(ArrayBuffer
), &js::ArrayBuffer::jsclass
},
1554 {NULL
, 0, NULL
, NULL
}
1558 * Table of top-level function and constant names and their init functions.
1559 * If you add a "standard" global function or property, remember to update
1562 static JSStdName standard_class_names
[] = {
1563 {js_InitObjectClass
, EAGER_ATOM(eval
), CLASP(Object
)},
1565 /* Global properties and functions defined by the Number class. */
1566 {js_InitNumberClass
, EAGER_ATOM(NaN
), CLASP(Number
)},
1567 {js_InitNumberClass
, EAGER_ATOM(Infinity
), CLASP(Number
)},
1568 {js_InitNumberClass
, LAZY_ATOM(isNaN
), CLASP(Number
)},
1569 {js_InitNumberClass
, LAZY_ATOM(isFinite
), CLASP(Number
)},
1570 {js_InitNumberClass
, LAZY_ATOM(parseFloat
), CLASP(Number
)},
1571 {js_InitNumberClass
, LAZY_ATOM(parseInt
), CLASP(Number
)},
1573 /* String global functions. */
1574 {js_InitStringClass
, LAZY_ATOM(escape
), CLASP(String
)},
1575 {js_InitStringClass
, LAZY_ATOM(unescape
), CLASP(String
)},
1576 {js_InitStringClass
, LAZY_ATOM(decodeURI
), CLASP(String
)},
1577 {js_InitStringClass
, LAZY_ATOM(encodeURI
), CLASP(String
)},
1578 {js_InitStringClass
, LAZY_ATOM(decodeURIComponent
), CLASP(String
)},
1579 {js_InitStringClass
, LAZY_ATOM(encodeURIComponent
), CLASP(String
)},
1581 {js_InitStringClass
, LAZY_ATOM(uneval
), CLASP(String
)},
1584 /* Exception constructors. */
1585 {js_InitExceptionClasses
, EAGER_CLASS_ATOM(Error
), CLASP(Error
)},
1586 {js_InitExceptionClasses
, EAGER_CLASS_ATOM(InternalError
), CLASP(Error
)},
1587 {js_InitExceptionClasses
, EAGER_CLASS_ATOM(EvalError
), CLASP(Error
)},
1588 {js_InitExceptionClasses
, EAGER_CLASS_ATOM(RangeError
), CLASP(Error
)},
1589 {js_InitExceptionClasses
, EAGER_CLASS_ATOM(ReferenceError
), CLASP(Error
)},
1590 {js_InitExceptionClasses
, EAGER_CLASS_ATOM(SyntaxError
), CLASP(Error
)},
1591 {js_InitExceptionClasses
, EAGER_CLASS_ATOM(TypeError
), CLASP(Error
)},
1592 {js_InitExceptionClasses
, EAGER_CLASS_ATOM(URIError
), CLASP(Error
)},
1594 #if JS_HAS_XML_SUPPORT
1595 {js_InitXMLClass
, LAZY_ATOM(XMLList
), CLASP(XML
)},
1596 {js_InitXMLClass
, LAZY_ATOM(isXMLName
), CLASP(XML
)},
1599 #if JS_HAS_GENERATORS
1600 {js_InitIteratorClasses
, EAGER_ATOM_AND_CLASP(Iterator
)},
1601 {js_InitIteratorClasses
, EAGER_ATOM_AND_CLASP(Generator
)},
1605 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(ArrayBuffer
), &js::ArrayBuffer::jsclass
},
1606 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(Int8Array
), TYPED_ARRAY_CLASP(TYPE_INT8
)},
1607 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(Uint8Array
), TYPED_ARRAY_CLASP(TYPE_UINT8
)},
1608 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(Int16Array
), TYPED_ARRAY_CLASP(TYPE_INT16
)},
1609 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(Uint16Array
), TYPED_ARRAY_CLASP(TYPE_UINT16
)},
1610 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(Int32Array
), TYPED_ARRAY_CLASP(TYPE_INT32
)},
1611 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(Uint32Array
), TYPED_ARRAY_CLASP(TYPE_UINT32
)},
1612 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(Float32Array
), TYPED_ARRAY_CLASP(TYPE_FLOAT32
)},
1613 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(Float64Array
), TYPED_ARRAY_CLASP(TYPE_FLOAT64
)},
1614 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(Uint8ClampedArray
),
1615 TYPED_ARRAY_CLASP(TYPE_UINT8_CLAMPED
)},
1617 {js_InitProxyClass
, EAGER_ATOM_AND_CLASP(Proxy
)},
1619 {NULL
, 0, NULL
, NULL
}
1622 static JSStdName object_prototype_names
[] = {
1623 /* Object.prototype properties (global delegates to Object.prototype). */
1624 {js_InitObjectClass
, EAGER_ATOM(proto
), CLASP(Object
)},
1626 {js_InitObjectClass
, EAGER_ATOM(toSource
), CLASP(Object
)},
1628 {js_InitObjectClass
, EAGER_ATOM(toString
), CLASP(Object
)},
1629 {js_InitObjectClass
, EAGER_ATOM(toLocaleString
), CLASP(Object
)},
1630 {js_InitObjectClass
, EAGER_ATOM(valueOf
), CLASP(Object
)},
1631 #if JS_HAS_OBJ_WATCHPOINT
1632 {js_InitObjectClass
, LAZY_ATOM(watch
), CLASP(Object
)},
1633 {js_InitObjectClass
, LAZY_ATOM(unwatch
), CLASP(Object
)},
1635 {js_InitObjectClass
, LAZY_ATOM(hasOwnProperty
), CLASP(Object
)},
1636 {js_InitObjectClass
, LAZY_ATOM(isPrototypeOf
), CLASP(Object
)},
1637 {js_InitObjectClass
, LAZY_ATOM(propertyIsEnumerable
), CLASP(Object
)},
1638 #if OLD_GETTER_SETTER_METHODS
1639 {js_InitObjectClass
, LAZY_ATOM(defineGetter
), CLASP(Object
)},
1640 {js_InitObjectClass
, LAZY_ATOM(defineSetter
), CLASP(Object
)},
1641 {js_InitObjectClass
, LAZY_ATOM(lookupGetter
), CLASP(Object
)},
1642 {js_InitObjectClass
, LAZY_ATOM(lookupSetter
), CLASP(Object
)},
1645 {NULL
, 0, NULL
, NULL
}
1648 JS_PUBLIC_API(JSBool
)
1649 JS_ResolveStandardClass(JSContext
*cx
, JSObject
*obj
, jsid id
, JSBool
*resolved
)
1658 assertSameCompartment(cx
, obj
, id
);
1659 *resolved
= JS_FALSE
;
1662 JS_ASSERT(rt
->state
!= JSRTS_DOWN
);
1663 if (rt
->state
== JSRTS_LANDING
|| !JSID_IS_ATOM(id
))
1666 idstr
= JSID_TO_STRING(id
);
1668 /* Check whether we're resolving 'undefined', and define it if so. */
1669 atom
= rt
->atomState
.typeAtoms
[JSTYPE_VOID
];
1670 if (idstr
== ATOM_TO_STRING(atom
)) {
1671 *resolved
= JS_TRUE
;
1672 return obj
->defineProperty(cx
, ATOM_TO_JSID(atom
), UndefinedValue(),
1673 PropertyStub
, PropertyStub
,
1674 JSPROP_PERMANENT
| JSPROP_READONLY
);
1677 /* Try for class constructors/prototypes named by well-known atoms. */
1679 for (i
= 0; standard_class_atoms
[i
].init
; i
++) {
1680 JS_ASSERT(standard_class_atoms
[i
].clasp
);
1681 atom
= OFFSET_TO_ATOM(rt
, standard_class_atoms
[i
].atomOffset
);
1682 if (idstr
== ATOM_TO_STRING(atom
)) {
1683 stdnm
= &standard_class_atoms
[i
];
1689 /* Try less frequently used top-level functions and constants. */
1690 for (i
= 0; standard_class_names
[i
].init
; i
++) {
1691 JS_ASSERT(standard_class_names
[i
].clasp
);
1692 atom
= StdNameToAtom(cx
, &standard_class_names
[i
]);
1695 if (idstr
== ATOM_TO_STRING(atom
)) {
1696 stdnm
= &standard_class_names
[i
];
1701 if (!stdnm
&& !obj
->getProto()) {
1703 * Try even less frequently used names delegated from the global
1704 * object to Object.prototype, but only if the Object class hasn't
1705 * yet been initialized.
1707 for (i
= 0; object_prototype_names
[i
].init
; i
++) {
1708 JS_ASSERT(object_prototype_names
[i
].clasp
);
1709 atom
= StdNameToAtom(cx
, &object_prototype_names
[i
]);
1712 if (idstr
== ATOM_TO_STRING(atom
)) {
1713 stdnm
= &object_prototype_names
[i
];
1722 * If this standard class is anonymous, then we don't want to resolve
1725 JS_ASSERT(obj
->isGlobal());
1726 if (stdnm
->clasp
->flags
& JSCLASS_IS_ANONYMOUS
)
1729 JSProtoKey key
= JSCLASS_CACHED_PROTO_KEY(stdnm
->clasp
);
1730 if (obj
->getReservedSlot(key
).isObject())
1733 if (!stdnm
->init(cx
, obj
))
1735 *resolved
= JS_TRUE
;
1740 JS_PUBLIC_API(JSBool
)
1741 JS_EnumerateStandardClasses(JSContext
*cx
, JSObject
*obj
)
1748 assertSameCompartment(cx
, obj
);
1751 /* Check whether we need to bind 'undefined' and define it if so. */
1752 atom
= rt
->atomState
.typeAtoms
[JSTYPE_VOID
];
1753 if (!obj
->nativeContains(ATOM_TO_JSID(atom
)) &&
1754 !obj
->defineProperty(cx
, ATOM_TO_JSID(atom
), UndefinedValue(),
1755 PropertyStub
, PropertyStub
,
1756 JSPROP_PERMANENT
| JSPROP_READONLY
)) {
1760 /* Initialize any classes that have not been resolved yet. */
1761 for (i
= 0; standard_class_atoms
[i
].init
; i
++) {
1762 atom
= OFFSET_TO_ATOM(rt
, standard_class_atoms
[i
].atomOffset
);
1763 if (!obj
->nativeContains(ATOM_TO_JSID(atom
)) &&
1764 !standard_class_atoms
[i
].init(cx
, obj
)) {
1775 NewIdArray(JSContext
*cx
, jsint length
)
1780 cx
->calloc(offsetof(JSIdArray
, vector
) + length
* sizeof(jsval
));
1782 ida
->length
= length
;
1789 * Unlike realloc(3), this function frees ida on failure.
1792 SetIdArrayLength(JSContext
*cx
, JSIdArray
*ida
, jsint length
)
1796 rida
= (JSIdArray
*)
1798 offsetof(JSIdArray
, vector
) + length
* sizeof(jsval
));
1800 JS_DestroyIdArray(cx
, ida
);
1802 rida
->length
= length
;
1808 AddAtomToArray(JSContext
*cx
, JSAtom
*atom
, JSIdArray
*ida
, jsint
*ip
)
1813 length
= ida
->length
;
1815 ida
= SetIdArrayLength(cx
, ida
, JS_MAX(length
* 2, 8));
1818 JS_ASSERT(i
< ida
->length
);
1820 ida
->vector
[i
] = ATOM_TO_JSID(atom
);
1826 EnumerateIfResolved(JSContext
*cx
, JSObject
*obj
, JSAtom
*atom
, JSIdArray
*ida
,
1827 jsint
*ip
, JSBool
*foundp
)
1829 *foundp
= obj
->nativeContains(ATOM_TO_JSID(atom
));
1831 ida
= AddAtomToArray(cx
, atom
, ida
, ip
);
1835 JS_PUBLIC_API(JSIdArray
*)
1836 JS_EnumerateResolvedStandardClasses(JSContext
*cx
, JSObject
*obj
, JSIdArray
*ida
)
1845 assertSameCompartment(cx
, obj
, ida
);
1850 ida
= NewIdArray(cx
, 8);
1856 /* Check whether 'undefined' has been resolved and enumerate it if so. */
1857 atom
= rt
->atomState
.typeAtoms
[JSTYPE_VOID
];
1858 ida
= EnumerateIfResolved(cx
, obj
, atom
, ida
, &i
, &found
);
1862 /* Enumerate only classes that *have* been resolved. */
1863 for (j
= 0; standard_class_atoms
[j
].init
; j
++) {
1864 atom
= OFFSET_TO_ATOM(rt
, standard_class_atoms
[j
].atomOffset
);
1865 ida
= EnumerateIfResolved(cx
, obj
, atom
, ida
, &i
, &found
);
1870 init
= standard_class_atoms
[j
].init
;
1872 for (k
= 0; standard_class_names
[k
].init
; k
++) {
1873 if (standard_class_names
[k
].init
== init
) {
1874 atom
= StdNameToAtom(cx
, &standard_class_names
[k
]);
1875 ida
= AddAtomToArray(cx
, atom
, ida
, &i
);
1881 if (init
== js_InitObjectClass
) {
1882 for (k
= 0; object_prototype_names
[k
].init
; k
++) {
1883 atom
= StdNameToAtom(cx
, &object_prototype_names
[k
]);
1884 ida
= AddAtomToArray(cx
, atom
, ida
, &i
);
1892 /* Trim to exact length. */
1893 return SetIdArrayLength(cx
, ida
, i
);
1898 #undef EAGER_CLASS_ATOM
1899 #undef EAGER_ATOM_CLASP
1902 JS_PUBLIC_API(JSBool
)
1903 JS_GetClassObject(JSContext
*cx
, JSObject
*obj
, JSProtoKey key
, JSObject
**objp
)
1906 assertSameCompartment(cx
, obj
);
1907 return js_GetClassObject(cx
, obj
, key
, objp
);
1910 JS_PUBLIC_API(JSObject
*)
1911 JS_GetScopeChain(JSContext
*cx
)
1914 return GetScopeChain(cx
);
1917 JS_PUBLIC_API(JSObject
*)
1918 JS_GetGlobalForObject(JSContext
*cx
, JSObject
*obj
)
1920 assertSameCompartment(cx
, obj
);
1921 return obj
->getGlobal();
1924 JS_PUBLIC_API(JSObject
*)
1925 JS_GetGlobalForScopeChain(JSContext
*cx
)
1928 return GetGlobalForScopeChain(cx
);
1931 JS_PUBLIC_API(jsval
)
1932 JS_ComputeThis(JSContext
*cx
, jsval
*vp
)
1934 assertSameCompartment(cx
, JSValueArray(vp
, 2));
1935 if (!ComputeThisFromVp(cx
, Valueify(vp
)))
1940 JS_PUBLIC_API(void *)
1941 JS_malloc(JSContext
*cx
, size_t nbytes
)
1943 return cx
->malloc(nbytes
);
1946 JS_PUBLIC_API(void *)
1947 JS_realloc(JSContext
*cx
, void *p
, size_t nbytes
)
1949 return cx
->realloc(p
, nbytes
);
1953 JS_free(JSContext
*cx
, void *p
)
1959 JS_updateMallocCounter(JSContext
*cx
, size_t nbytes
)
1961 return cx
->runtime
->updateMallocCounter(nbytes
);
1964 JS_PUBLIC_API(char *)
1965 JS_strdup(JSContext
*cx
, const char *s
)
1974 return (char *)memcpy(p
, s
, n
);
1977 JS_PUBLIC_API(JSBool
)
1978 JS_NewNumberValue(JSContext
*cx
, jsdouble d
, jsval
*rval
)
1980 d
= JS_CANONICALIZE_NAN(d
);
1981 Valueify(rval
)->setNumber(d
);
1987 JS_PUBLIC_API(JSBool
)
1988 JS_AddValueRoot(JSContext
*cx
, jsval
*vp
)
1991 return js_AddRoot(cx
, Valueify(vp
), NULL
);
1994 JS_PUBLIC_API(JSBool
)
1995 JS_AddStringRoot(JSContext
*cx
, JSString
**rp
)
1998 return js_AddGCThingRoot(cx
, (void **)rp
, NULL
);
2001 JS_PUBLIC_API(JSBool
)
2002 JS_AddObjectRoot(JSContext
*cx
, JSObject
**rp
)
2005 return js_AddGCThingRoot(cx
, (void **)rp
, NULL
);
2008 JS_PUBLIC_API(JSBool
)
2009 JS_AddGCThingRoot(JSContext
*cx
, void **rp
)
2012 return js_AddGCThingRoot(cx
, (void **)rp
, NULL
);
2015 JS_PUBLIC_API(JSBool
)
2016 JS_AddNamedValueRoot(JSContext
*cx
, jsval
*vp
, const char *name
)
2019 return js_AddRoot(cx
, Valueify(vp
), name
);
2022 JS_PUBLIC_API(JSBool
)
2023 JS_AddNamedStringRoot(JSContext
*cx
, JSString
**rp
, const char *name
)
2026 return js_AddGCThingRoot(cx
, (void **)rp
, name
);
2029 JS_PUBLIC_API(JSBool
)
2030 JS_AddNamedObjectRoot(JSContext
*cx
, JSObject
**rp
, const char *name
)
2033 return js_AddGCThingRoot(cx
, (void **)rp
, name
);
2036 JS_PUBLIC_API(JSBool
)
2037 JS_AddNamedGCThingRoot(JSContext
*cx
, void **rp
, const char *name
)
2040 return js_AddGCThingRoot(cx
, (void **)rp
, name
);
2043 JS_PUBLIC_API(JSBool
)
2044 JS_RemoveValueRoot(JSContext
*cx
, jsval
*vp
)
2047 return js_RemoveRoot(cx
->runtime
, (void *)vp
);
2050 JS_PUBLIC_API(JSBool
)
2051 JS_RemoveStringRoot(JSContext
*cx
, JSString
**rp
)
2054 return js_RemoveRoot(cx
->runtime
, (void *)rp
);
2057 JS_PUBLIC_API(JSBool
)
2058 JS_RemoveObjectRoot(JSContext
*cx
, JSObject
**rp
)
2061 return js_RemoveRoot(cx
->runtime
, (void *)rp
);
2064 JS_PUBLIC_API(JSBool
)
2065 JS_RemoveGCThingRoot(JSContext
*cx
, void **rp
)
2068 return js_RemoveRoot(cx
->runtime
, (void *)rp
);
2074 JS_DumpNamedRoots(JSRuntime
*rt
,
2075 void (*dump
)(const char *name
, void *rp
, JSGCRootType type
, void *data
),
2078 js_DumpNamedRoots(rt
, dump
, data
);
2083 JS_PUBLIC_API(uint32
)
2084 JS_MapGCRoots(JSRuntime
*rt
, JSGCRootMapFun map
, void *data
)
2086 return js_MapGCRoots(rt
, map
, data
);
2089 JS_PUBLIC_API(JSBool
)
2090 JS_LockGCThing(JSContext
*cx
, void *thing
)
2095 ok
= js_LockGCThingRT(cx
->runtime
, thing
);
2097 JS_ReportOutOfMemory(cx
);
2101 JS_PUBLIC_API(JSBool
)
2102 JS_LockGCThingRT(JSRuntime
*rt
, void *thing
)
2104 return js_LockGCThingRT(rt
, thing
);
2107 JS_PUBLIC_API(JSBool
)
2108 JS_UnlockGCThing(JSContext
*cx
, void *thing
)
2111 js_UnlockGCThingRT(cx
->runtime
, thing
);
2115 JS_PUBLIC_API(JSBool
)
2116 JS_UnlockGCThingRT(JSRuntime
*rt
, void *thing
)
2118 js_UnlockGCThingRT(rt
, thing
);
2123 JS_SetExtraGCRoots(JSRuntime
*rt
, JSTraceDataOp traceOp
, void *data
)
2125 rt
->gcExtraRootsTraceOp
= traceOp
;
2126 rt
->gcExtraRootsData
= data
;
2130 JS_TraceRuntime(JSTracer
*trc
)
2136 JS_CallTracer(JSTracer
*trc
, void *thing
, uint32 kind
)
2139 MarkKind(trc
, thing
, kind
);
2144 #ifdef HAVE_XPCONNECT
2145 #include "dump_xpc.h"
2149 JS_PrintTraceThingInfo(char *buf
, size_t bufsize
, JSTracer
*trc
, void *thing
, uint32 kind
,
2159 case JSTRACE_OBJECT
:
2161 JSObject
*obj
= (JSObject
*)thing
;
2162 Class
*clasp
= obj
->getClass();
2165 #ifdef HAVE_XPCONNECT
2166 if (clasp
->flags
& JSCLASS_PRIVATE_IS_NSISUPPORTS
) {
2167 void *privateThing
= obj
->getPrivate();
2169 const char *xpcClassName
= GetXPCObjectClassName(privateThing
);
2171 name
= xpcClassName
;
2178 case JSTRACE_STRING
:
2179 name
= ((JSString
*)thing
)->isDependent()
2184 #if JS_HAS_XML_SUPPORT
2196 if (n
> bufsize
- 1)
2198 memcpy(buf
, name
, n
+ 1);
2202 if (details
&& bufsize
> 2) {
2207 case JSTRACE_OBJECT
:
2209 JSObject
*obj
= (JSObject
*)thing
;
2210 Class
*clasp
= obj
->getClass();
2211 if (clasp
== &js_FunctionClass
) {
2212 JSFunction
*fun
= GET_FUNCTION_PRIVATE(trc
->context
, obj
);
2214 JS_snprintf(buf
, bufsize
, "<newborn>");
2215 } else if (FUN_OBJECT(fun
) != obj
) {
2216 JS_snprintf(buf
, bufsize
, "%p", fun
);
2219 PutEscapedString(buf
, bufsize
, ATOM_TO_STRING(fun
->atom
), 0);
2221 } else if (clasp
->flags
& JSCLASS_HAS_PRIVATE
) {
2222 JS_snprintf(buf
, bufsize
, "%p", obj
->getPrivate());
2224 JS_snprintf(buf
, bufsize
, "<no private>");
2229 case JSTRACE_STRING
:
2231 JSString
*str
= (JSString
*)thing
;
2232 if (str
->isLinear())
2233 PutEscapedString(buf
, bufsize
, str
->assertIsLinear(), 0);
2235 JS_snprintf(buf
, bufsize
, "<rope: length %d>", (int)str
->length());
2239 #if JS_HAS_XML_SUPPORT
2242 extern const char *js_xml_class_str
[];
2243 JSXML
*xml
= (JSXML
*)thing
;
2245 JS_snprintf(buf
, bufsize
, "%s", js_xml_class_str
[xml
->xml_class
]);
2254 buf
[bufsize
- 1] = '\0';
2257 typedef struct JSHeapDumpNode JSHeapDumpNode
;
2259 struct JSHeapDumpNode
{
2262 JSHeapDumpNode
*next
; /* next sibling */
2263 JSHeapDumpNode
*parent
; /* node with the thing that refer to thing
2265 char edgeName
[1]; /* name of the edge from parent->thing
2269 typedef struct JSDumpingTracer
{
2271 JSDHashTable visited
;
2275 void *thingToIgnore
;
2276 JSHeapDumpNode
*parentNode
;
2277 JSHeapDumpNode
**lastNodep
;
2282 DumpNotify(JSTracer
*trc
, void *thing
, uint32 kind
)
2284 JSDumpingTracer
*dtrc
;
2286 JSDHashEntryStub
*entry
;
2287 JSHeapDumpNode
*node
;
2288 const char *edgeName
;
2289 size_t edgeNameSize
;
2291 JS_ASSERT(trc
->callback
== DumpNotify
);
2292 dtrc
= (JSDumpingTracer
*)trc
;
2294 if (!dtrc
->ok
|| thing
== dtrc
->thingToIgnore
)
2300 * Check if we have already seen thing unless it is thingToFind to include
2301 * it to the graph each time we reach it and print all live things that
2302 * refer to thingToFind.
2304 * This does not print all possible paths leading to thingToFind since
2305 * when a thing A refers directly or indirectly to thingToFind and A is
2306 * present several times in the graph, we will print only the first path
2307 * leading to A and thingToFind, other ways to reach A will be ignored.
2309 if (dtrc
->thingToFind
!= thing
) {
2311 * The startThing check allows to avoid putting startThing into the
2312 * hash table before tracing startThing in JS_DumpHeap.
2314 if (thing
== dtrc
->startThing
)
2316 entry
= (JSDHashEntryStub
*)
2317 JS_DHashTableOperate(&dtrc
->visited
, thing
, JS_DHASH_ADD
);
2319 JS_ReportOutOfMemory(cx
);
2320 dtrc
->ok
= JS_FALSE
;
2328 if (dtrc
->base
.debugPrinter
) {
2329 dtrc
->base
.debugPrinter(trc
, dtrc
->buffer
, sizeof(dtrc
->buffer
));
2330 edgeName
= dtrc
->buffer
;
2331 } else if (dtrc
->base
.debugPrintIndex
!= (size_t)-1) {
2332 JS_snprintf(dtrc
->buffer
, sizeof(dtrc
->buffer
), "%s[%lu]",
2333 (const char *)dtrc
->base
.debugPrintArg
,
2334 dtrc
->base
.debugPrintIndex
);
2335 edgeName
= dtrc
->buffer
;
2337 edgeName
= (const char*)dtrc
->base
.debugPrintArg
;
2340 edgeNameSize
= strlen(edgeName
) + 1;
2341 node
= (JSHeapDumpNode
*)
2342 cx
->malloc(offsetof(JSHeapDumpNode
, edgeName
) + edgeNameSize
);
2344 dtrc
->ok
= JS_FALSE
;
2348 node
->thing
= thing
;
2351 node
->parent
= dtrc
->parentNode
;
2352 memcpy(node
->edgeName
, edgeName
, edgeNameSize
);
2354 JS_ASSERT(!*dtrc
->lastNodep
);
2355 *dtrc
->lastNodep
= node
;
2356 dtrc
->lastNodep
= &node
->next
;
2359 /* Dump node and the chain that leads to thing it contains. */
2361 DumpNode(JSDumpingTracer
*dtrc
, FILE* fp
, JSHeapDumpNode
*node
)
2363 JSHeapDumpNode
*prev
, *following
;
2366 enum { MAX_PARENTS_TO_PRINT
= 10 };
2368 JS_PrintTraceThingInfo(dtrc
->buffer
, sizeof dtrc
->buffer
,
2369 &dtrc
->base
, node
->thing
, node
->kind
, JS_TRUE
);
2370 if (fprintf(fp
, "%p %-22s via ", node
->thing
, dtrc
->buffer
) < 0)
2374 * We need to print the parent chain in the reverse order. To do it in
2375 * O(N) time where N is the chain length we first reverse the chain while
2376 * searching for the top and then print each node while restoring the
2379 chainLimit
= MAX_PARENTS_TO_PRINT
;
2382 following
= node
->parent
;
2383 node
->parent
= prev
;
2388 if (chainLimit
== 0) {
2389 if (fputs("...", fp
) < 0)
2400 /* Loop must continue even when !ok to restore the parent chain. */
2403 /* Print edge from some runtime root or startThing. */
2404 if (fputs(node
->edgeName
, fp
) < 0)
2407 JS_PrintTraceThingInfo(dtrc
->buffer
, sizeof dtrc
->buffer
,
2408 &dtrc
->base
, prev
->thing
, prev
->kind
,
2410 if (fprintf(fp
, "(%p %s).%s",
2411 prev
->thing
, dtrc
->buffer
, node
->edgeName
) < 0) {
2416 following
= node
->parent
;
2417 node
->parent
= prev
;
2422 return ok
&& putc('\n', fp
) >= 0;
2425 JS_PUBLIC_API(JSBool
)
2426 JS_DumpHeap(JSContext
*cx
, FILE *fp
, void* startThing
, uint32 startKind
,
2427 void *thingToFind
, size_t maxDepth
, void *thingToIgnore
)
2429 JSDumpingTracer dtrc
;
2430 JSHeapDumpNode
*node
, *children
, *next
, *parent
;
2432 JSBool thingToFindWasTraced
;
2437 JS_TRACER_INIT(&dtrc
.base
, cx
, DumpNotify
);
2438 if (!JS_DHashTableInit(&dtrc
.visited
, JS_DHashGetStubOps(),
2439 NULL
, sizeof(JSDHashEntryStub
),
2440 JS_DHASH_DEFAULT_CAPACITY(100))) {
2441 JS_ReportOutOfMemory(cx
);
2445 dtrc
.startThing
= startThing
;
2446 dtrc
.thingToFind
= thingToFind
;
2447 dtrc
.thingToIgnore
= thingToIgnore
;
2448 dtrc
.parentNode
= NULL
;
2450 dtrc
.lastNodep
= &node
;
2452 JS_ASSERT(startKind
== 0);
2453 TraceRuntime(&dtrc
.base
);
2455 JS_TraceChildren(&dtrc
.base
, startThing
, startKind
);
2462 thingToFindWasTraced
= thingToFind
&& thingToFind
== startThing
;
2465 * Loop must continue even when !dtrc.ok to free all nodes allocated
2469 if (thingToFind
== NULL
|| thingToFind
== node
->thing
)
2470 dtrc
.ok
= DumpNode(&dtrc
, fp
, node
);
2472 /* Descend into children. */
2475 (thingToFind
!= node
->thing
|| !thingToFindWasTraced
)) {
2476 dtrc
.parentNode
= node
;
2478 dtrc
.lastNodep
= &children
;
2479 JS_TraceChildren(&dtrc
.base
, node
->thing
, node
->kind
);
2480 if (thingToFind
== node
->thing
)
2481 thingToFindWasTraced
= JS_TRUE
;
2482 if (children
!= NULL
) {
2490 /* Move to next or parents next and free the node. */
2493 parent
= node
->parent
;
2500 JS_ASSERT(depth
> 1);
2507 JS_ASSERT(depth
== 1);
2508 JS_DHashTableFinish(&dtrc
.visited
);
2515 JS_MarkGCThing(JSContext
*cx
, jsval v
, const char *name
, void *arg
)
2519 trc
= (JSTracer
*)arg
;
2521 trc
= cx
->runtime
->gcMarkingTracer
;
2523 JS_ASSERT(trc
== cx
->runtime
->gcMarkingTracer
);
2525 #ifdef JS_THREADSAFE
2526 JS_ASSERT(cx
->runtime
->gcThread
== trc
->context
->thread
);
2528 MarkValue(trc
, Valueify(v
), name
? name
: "unknown");
2531 extern JS_PUBLIC_API(JSBool
)
2532 JS_IsGCMarkingTracer(JSTracer
*trc
)
2534 return IS_GC_MARKING_TRACER(trc
);
2538 JS_GC(JSContext
*cx
)
2542 /* Don't nuke active arenas if executing or compiling. */
2543 if (cx
->tempPool
.current
== &cx
->tempPool
.first
)
2544 JS_FinishArenaPool(&cx
->tempPool
);
2545 js_GC(cx
, NULL
, GC_NORMAL
);
2549 JS_MaybeGC(JSContext
*cx
)
2553 /* Don't nuke active arenas if executing or compiling. */
2554 if (cx
->tempPool
.current
== &cx
->tempPool
.first
)
2555 JS_FinishArenaPool(&cx
->tempPool
);
2560 JS_PUBLIC_API(JSGCCallback
)
2561 JS_SetGCCallback(JSContext
*cx
, JSGCCallback cb
)
2564 return JS_SetGCCallbackRT(cx
->runtime
, cb
);
2567 JS_PUBLIC_API(JSGCCallback
)
2568 JS_SetGCCallbackRT(JSRuntime
*rt
, JSGCCallback cb
)
2572 oldcb
= rt
->gcCallback
;
2573 rt
->gcCallback
= cb
;
2577 JS_PUBLIC_API(JSBool
)
2578 JS_IsAboutToBeFinalized(JSContext
*cx
, void *thing
)
2581 JS_ASSERT(!cx
->runtime
->gcMarkingTracer
);
2582 return IsAboutToBeFinalized(cx
, thing
);
2586 JS_SetGCParameter(JSRuntime
*rt
, JSGCParamKey key
, uint32 value
)
2589 case JSGC_MAX_BYTES
:
2590 rt
->gcMaxBytes
= value
;
2592 case JSGC_MAX_MALLOC_BYTES
:
2593 rt
->setGCMaxMallocBytes(value
);
2595 case JSGC_STACKPOOL_LIFESPAN
:
2596 rt
->gcEmptyArenaPoolLifespan
= value
;
2599 rt
->gcMode
= JSGCMode(value
);
2600 JS_ASSERT(rt
->gcMode
== JSGC_MODE_GLOBAL
||
2601 rt
->gcMode
== JSGC_MODE_COMPARTMENT
);
2604 JS_ASSERT(key
== JSGC_TRIGGER_FACTOR
);
2605 JS_ASSERT(value
>= 100);
2606 rt
->setGCTriggerFactor(value
);
2611 JS_PUBLIC_API(uint32
)
2612 JS_GetGCParameter(JSRuntime
*rt
, JSGCParamKey key
)
2615 case JSGC_MAX_BYTES
:
2616 return rt
->gcMaxBytes
;
2617 case JSGC_MAX_MALLOC_BYTES
:
2618 return rt
->gcMaxMallocBytes
;
2619 case JSGC_STACKPOOL_LIFESPAN
:
2620 return rt
->gcEmptyArenaPoolLifespan
;
2621 case JSGC_TRIGGER_FACTOR
:
2622 return rt
->gcTriggerFactor
;
2626 return uint32(rt
->gcMode
);
2628 JS_ASSERT(key
== JSGC_NUMBER
);
2629 return rt
->gcNumber
;
2634 JS_SetGCParameterForThread(JSContext
*cx
, JSGCParamKey key
, uint32 value
)
2636 JS_ASSERT(key
== JSGC_MAX_CODE_CACHE_BYTES
);
2638 SetMaxCodeCacheBytes(cx
, value
);
2642 JS_PUBLIC_API(uint32
)
2643 JS_GetGCParameterForThread(JSContext
*cx
, JSGCParamKey key
)
2645 JS_ASSERT(key
== JSGC_MAX_CODE_CACHE_BYTES
);
2647 return JS_THREAD_DATA(cx
)->maxCodeCacheBytes
;
2654 JS_FlushCaches(JSContext
*cx
)
2662 JS_AddExternalStringFinalizer(JSStringFinalizeOp finalizer
)
2664 return JSExternalString::changeFinalizer(NULL
, finalizer
);
2668 JS_RemoveExternalStringFinalizer(JSStringFinalizeOp finalizer
)
2670 return JSExternalString::changeFinalizer(finalizer
, NULL
);
2673 JS_PUBLIC_API(JSString
*)
2674 JS_NewExternalString(JSContext
*cx
, jschar
*chars
, size_t length
, intN type
)
2677 JS_ASSERT(uintN(type
) < JSExternalString::TYPE_LIMIT
);
2679 JSExternalString
*str
= js_NewGCExternalString(cx
, uintN(type
));
2682 str
->initFlat(chars
, length
);
2683 str
->externalStringType
= type
;
2684 cx
->runtime
->updateMallocCounter((length
+ 1) * sizeof(jschar
));
2689 JS_GetExternalStringGCType(JSRuntime
*rt
, JSString
*str
)
2692 * No need to test this in js_GetExternalStringGCType, which asserts its
2693 * inverse instead of wasting cycles on testing a condition we can ensure
2694 * by auditing in-VM calls to the js_... helper.
2696 if (JSString::isStatic(str
))
2699 return js_GetExternalStringGCType(str
);
2703 JS_SetThreadStackLimit(JSContext
*cx
, jsuword limitAddr
)
2705 #if JS_STACK_GROWTH_DIRECTION > 0
2707 limitAddr
= jsuword(-1);
2709 cx
->stackLimit
= limitAddr
;
2713 JS_SetNativeStackQuota(JSContext
*cx
, size_t stackSize
)
2715 #ifdef JS_THREADSAFE
2716 JS_ASSERT(cx
->thread
);
2719 #if JS_STACK_GROWTH_DIRECTION > 0
2720 if (stackSize
== 0) {
2721 cx
->stackLimit
= jsuword(-1);
2723 jsuword stackBase
= reinterpret_cast<jsuword
>(JS_THREAD_DATA(cx
)->nativeStackBase
);
2724 JS_ASSERT(stackBase
<= size_t(-1) - stackSize
);
2725 cx
->stackLimit
= stackBase
+ stackSize
- 1;
2728 if (stackSize
== 0) {
2731 jsuword stackBase
= reinterpret_cast<jsuword
>(JS_THREAD_DATA(cx
)->nativeStackBase
);
2732 JS_ASSERT(stackBase
>= stackSize
);
2733 cx
->stackLimit
= stackBase
- (stackSize
- 1);
2739 JS_SetScriptStackQuota(JSContext
*cx
, size_t quota
)
2741 cx
->scriptStackQuota
= quota
;
2744 /************************************************************************/
2747 JS_DestroyIdArray(JSContext
*cx
, JSIdArray
*ida
)
2752 JS_PUBLIC_API(JSBool
)
2753 JS_ValueToId(JSContext
*cx
, jsval v
, jsid
*idp
)
2756 assertSameCompartment(cx
, v
);
2757 return ValueToId(cx
, Valueify(v
), idp
);
2760 JS_PUBLIC_API(JSBool
)
2761 JS_IdToValue(JSContext
*cx
, jsid id
, jsval
*vp
)
2764 *vp
= IdToJsval(id
);
2765 assertSameCompartment(cx
, *vp
);
2769 JS_PUBLIC_API(JSBool
)
2770 JS_PropertyStub(JSContext
*cx
, JSObject
*obj
, jsid id
, jsval
*vp
)
2775 JS_PUBLIC_API(JSBool
)
2776 JS_EnumerateStub(JSContext
*cx
, JSObject
*obj
)
2781 JS_PUBLIC_API(JSBool
)
2782 JS_ResolveStub(JSContext
*cx
, JSObject
*obj
, jsid id
)
2787 JS_PUBLIC_API(JSBool
)
2788 JS_ConvertStub(JSContext
*cx
, JSObject
*obj
, JSType type
, jsval
*vp
)
2790 JS_ASSERT(type
!= JSTYPE_OBJECT
&& type
!= JSTYPE_FUNCTION
);
2791 return js_TryValueOf(cx
, obj
, type
, Valueify(vp
));
2795 JS_FinalizeStub(JSContext
*cx
, JSObject
*obj
)
2798 JS_PUBLIC_API(JSObject
*)
2799 JS_InitClass(JSContext
*cx
, JSObject
*obj
, JSObject
*parent_proto
,
2800 JSClass
*clasp
, JSNative constructor
, uintN nargs
,
2801 JSPropertySpec
*ps
, JSFunctionSpec
*fs
,
2802 JSPropertySpec
*static_ps
, JSFunctionSpec
*static_fs
)
2805 assertSameCompartment(cx
, obj
, parent_proto
);
2806 return js_InitClass(cx
, obj
, parent_proto
, Valueify(clasp
),
2807 Valueify(constructor
), nargs
,
2808 ps
, fs
, static_ps
, static_fs
);
2811 #ifdef JS_THREADSAFE
2812 JS_PUBLIC_API(JSClass
*)
2813 JS_GetClass(JSContext
*cx
, JSObject
*obj
)
2815 return Jsvalify(obj
->getClass());
2818 JS_PUBLIC_API(JSClass
*)
2819 JS_GetClass(JSObject
*obj
)
2821 return Jsvalify(obj
->getClass());
2825 JS_PUBLIC_API(JSBool
)
2826 JS_InstanceOf(JSContext
*cx
, JSObject
*obj
, JSClass
*clasp
, jsval
*argv
)
2829 assertSameCompartment(cx
, obj
);
2830 return InstanceOf(cx
, obj
, Valueify(clasp
), Valueify(argv
));
2833 JS_PUBLIC_API(JSBool
)
2834 JS_HasInstance(JSContext
*cx
, JSObject
*obj
, jsval v
, JSBool
*bp
)
2836 assertSameCompartment(cx
, obj
, v
);
2837 return HasInstance(cx
, obj
, Valueify(&v
), bp
);
2840 JS_PUBLIC_API(void *)
2841 JS_GetPrivate(JSContext
*cx
, JSObject
*obj
)
2843 return obj
->getPrivate();
2846 JS_PUBLIC_API(JSBool
)
2847 JS_SetPrivate(JSContext
*cx
, JSObject
*obj
, void *data
)
2849 obj
->setPrivate(data
);
2853 JS_PUBLIC_API(void *)
2854 JS_GetInstancePrivate(JSContext
*cx
, JSObject
*obj
, JSClass
*clasp
, jsval
*argv
)
2856 if (!InstanceOf(cx
, obj
, Valueify(clasp
), Valueify(argv
)))
2858 return obj
->getPrivate();
2861 JS_PUBLIC_API(JSObject
*)
2862 JS_GetPrototype(JSContext
*cx
, JSObject
*obj
)
2867 assertSameCompartment(cx
, obj
);
2868 proto
= obj
->getProto();
2870 /* Beware ref to dead object (we may be called from obj's finalizer). */
2871 return proto
&& proto
->map
? proto
: NULL
;
2874 JS_PUBLIC_API(JSBool
)
2875 JS_SetPrototype(JSContext
*cx
, JSObject
*obj
, JSObject
*proto
)
2878 assertSameCompartment(cx
, obj
, proto
);
2879 return SetProto(cx
, obj
, proto
, JS_FALSE
);
2882 JS_PUBLIC_API(JSObject
*)
2883 JS_GetParent(JSContext
*cx
, JSObject
*obj
)
2885 assertSameCompartment(cx
, obj
);
2886 JSObject
*parent
= obj
->getParent();
2888 /* Beware ref to dead object (we may be called from obj's finalizer). */
2889 return parent
&& parent
->map
? parent
: NULL
;
2892 JS_PUBLIC_API(JSBool
)
2893 JS_SetParent(JSContext
*cx
, JSObject
*obj
, JSObject
*parent
)
2896 JS_ASSERT(parent
|| !obj
->getParent());
2897 assertSameCompartment(cx
, obj
, parent
);
2898 obj
->setParent(parent
);
2902 JS_PUBLIC_API(JSObject
*)
2903 JS_GetConstructor(JSContext
*cx
, JSObject
*proto
)
2908 assertSameCompartment(cx
, proto
);
2910 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
);
2912 if (!proto
->getProperty(cx
, ATOM_TO_JSID(cx
->runtime
->atomState
.constructorAtom
), &cval
))
2916 if (!IsFunctionObject(cval
, &funobj
)) {
2917 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_NO_CONSTRUCTOR
,
2918 proto
->getClass()->name
);
2921 return &cval
.toObject();
2924 JS_PUBLIC_API(JSBool
)
2925 JS_GetObjectId(JSContext
*cx
, JSObject
*obj
, jsid
*idp
)
2927 assertSameCompartment(cx
, obj
);
2928 *idp
= OBJECT_TO_JSID(obj
);
2932 JS_PUBLIC_API(JSObject
*)
2933 JS_NewGlobalObject(JSContext
*cx
, JSClass
*clasp
)
2935 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
2937 JS_ASSERT(clasp
->flags
& JSCLASS_IS_GLOBAL
);
2938 JSObject
*obj
= NewNonFunction
<WithProto::Given
>(cx
, Valueify(clasp
), NULL
, NULL
);
2942 obj
->syncSpecialEquality();
2944 /* Construct a regexp statics object for this global object. */
2945 JSObject
*res
= regexp_statics_construct(cx
, obj
);
2947 !js_SetReservedSlot(cx
, obj
, JSRESERVED_GLOBAL_REGEXP_STATICS
,
2948 ObjectValue(*res
))) {
2955 JS_PUBLIC_API(JSObject
*)
2956 JS_NewCompartmentAndGlobalObject(JSContext
*cx
, JSClass
*clasp
, JSPrincipals
*principals
)
2959 JSCompartment
*compartment
= NewCompartment(cx
, principals
);
2963 JSCompartment
*saved
= cx
->compartment
;
2964 cx
->compartment
= compartment
;
2965 JSObject
*obj
= JS_NewGlobalObject(cx
, clasp
);
2966 cx
->compartment
= saved
;
2971 JS_PUBLIC_API(JSObject
*)
2972 JS_NewObject(JSContext
*cx
, JSClass
*jsclasp
, JSObject
*proto
, JSObject
*parent
)
2974 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
2976 assertSameCompartment(cx
, proto
, parent
);
2978 Class
*clasp
= Valueify(jsclasp
);
2980 clasp
= &js_ObjectClass
; /* default class is Object */
2982 JS_ASSERT(clasp
!= &js_FunctionClass
);
2983 JS_ASSERT(!(clasp
->flags
& JSCLASS_IS_GLOBAL
));
2985 JSObject
*obj
= NewNonFunction
<WithProto::Class
>(cx
, clasp
, proto
, parent
);
2987 obj
->syncSpecialEquality();
2989 JS_ASSERT_IF(obj
, obj
->getParent());
2993 JS_PUBLIC_API(JSObject
*)
2994 JS_NewObjectWithGivenProto(JSContext
*cx
, JSClass
*jsclasp
, JSObject
*proto
, JSObject
*parent
)
2996 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
2998 assertSameCompartment(cx
, proto
, parent
);
3000 Class
*clasp
= Valueify(jsclasp
);
3002 clasp
= &js_ObjectClass
; /* default class is Object */
3004 JS_ASSERT(clasp
!= &js_FunctionClass
);
3005 JS_ASSERT(!(clasp
->flags
& JSCLASS_IS_GLOBAL
));
3007 JSObject
*obj
= NewNonFunction
<WithProto::Given
>(cx
, clasp
, proto
, parent
);
3009 obj
->syncSpecialEquality();
3013 JS_PUBLIC_API(JSObject
*)
3014 JS_NewObjectForConstructor(JSContext
*cx
, const jsval
*vp
)
3017 assertSameCompartment(cx
, *vp
);
3019 return js_CreateThis(cx
, JSVAL_TO_OBJECT(*vp
));
3022 JS_PUBLIC_API(JSBool
)
3023 JS_IsExtensible(JSObject
*obj
)
3025 return obj
->isExtensible();
3028 JS_PUBLIC_API(JSBool
)
3029 JS_FreezeObject(JSContext
*cx
, JSObject
*obj
)
3032 assertSameCompartment(cx
, obj
);
3034 return obj
->freeze(cx
);
3037 JS_PUBLIC_API(JSBool
)
3038 JS_DeepFreezeObject(JSContext
*cx
, JSObject
*obj
)
3041 assertSameCompartment(cx
, obj
);
3043 /* Assume that non-extensible objects are already deep-frozen, to avoid divergence. */
3044 if (!obj
->isExtensible())
3047 if (!obj
->freeze(cx
))
3050 /* Walk slots in obj and if any value is a non-null object, seal it. */
3051 for (uint32 i
= 0, n
= obj
->slotSpan(); i
< n
; ++i
) {
3052 const Value
&v
= obj
->getSlot(i
);
3053 if (v
.isPrimitive())
3055 if (!JS_DeepFreezeObject(cx
, &v
.toObject()))
3062 JS_PUBLIC_API(JSObject
*)
3063 JS_ConstructObject(JSContext
*cx
, JSClass
*jsclasp
, JSObject
*proto
, JSObject
*parent
)
3066 assertSameCompartment(cx
, proto
, parent
);
3067 Class
*clasp
= Valueify(jsclasp
);
3069 clasp
= &js_ObjectClass
; /* default class is Object */
3070 return js_ConstructObject(cx
, clasp
, proto
, parent
, 0, NULL
);
3073 JS_PUBLIC_API(JSObject
*)
3074 JS_ConstructObjectWithArguments(JSContext
*cx
, JSClass
*jsclasp
, JSObject
*proto
,
3075 JSObject
*parent
, uintN argc
, jsval
*argv
)
3078 assertSameCompartment(cx
, proto
, parent
, JSValueArray(argv
, argc
));
3079 Class
*clasp
= Valueify(jsclasp
);
3081 clasp
= &js_ObjectClass
; /* default class is Object */
3082 return js_ConstructObject(cx
, clasp
, proto
, parent
, argc
, Valueify(argv
));
3086 LookupPropertyById(JSContext
*cx
, JSObject
*obj
, jsid id
, uintN flags
,
3087 JSObject
**objp
, JSProperty
**propp
)
3090 assertSameCompartment(cx
, obj
, id
);
3092 JSAutoResolveFlags
rf(cx
, flags
);
3093 id
= js_CheckForStringIndex(id
);
3094 return obj
->lookupProperty(cx
, id
, objp
, propp
);
3097 #define AUTO_NAMELEN(s,n) (((n) == (size_t)-1) ? js_strlen(s) : (n))
3100 LookupResult(JSContext
*cx
, JSObject
*obj
, JSObject
*obj2
, jsid id
,
3101 JSProperty
*prop
, Value
*vp
)
3104 /* XXX bad API: no way to tell "not defined" from "void value" */
3109 if (obj2
->isNative()) {
3110 Shape
*shape
= (Shape
*) prop
;
3112 if (shape
->isMethod()) {
3113 AutoShapeRooter
root(cx
, shape
);
3114 vp
->setObject(shape
->methodObject());
3115 return obj2
->methodReadBarrier(cx
, *shape
, vp
);
3118 /* Peek at the native property's slot value, without doing a Get. */
3119 if (obj2
->containsSlot(shape
->slot
)) {
3120 *vp
= obj2
->nativeGetSlot(shape
->slot
);
3124 if (obj2
->isDenseArray())
3125 return js_GetDenseArrayElementValue(cx
, obj2
, id
, vp
);
3126 if (obj2
->isProxy()) {
3127 AutoPropertyDescriptorRooter
desc(cx
);
3128 if (!JSProxy::getPropertyDescriptor(cx
, obj2
, id
, false, &desc
))
3130 if (!(desc
.attrs
& JSPROP_SHARED
)) {
3137 /* XXX bad API: no way to return "defined but value unknown" */
3138 vp
->setBoolean(true);
3142 JS_PUBLIC_API(JSBool
)
3143 JS_LookupPropertyById(JSContext
*cx
, JSObject
*obj
, jsid id
, jsval
*vp
)
3147 return LookupPropertyById(cx
, obj
, id
, JSRESOLVE_QUALIFIED
, &obj2
, &prop
) &&
3148 LookupResult(cx
, obj
, obj2
, id
, prop
, Valueify(vp
));
3151 JS_PUBLIC_API(JSBool
)
3152 JS_LookupElement(JSContext
*cx
, JSObject
*obj
, jsint index
, jsval
*vp
)
3154 return JS_LookupPropertyById(cx
, obj
, INT_TO_JSID(index
), vp
);
3157 JS_PUBLIC_API(JSBool
)
3158 JS_LookupProperty(JSContext
*cx
, JSObject
*obj
, const char *name
, jsval
*vp
)
3160 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3161 return atom
&& JS_LookupPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), vp
);
3164 JS_PUBLIC_API(JSBool
)
3165 JS_LookupUCProperty(JSContext
*cx
, JSObject
*obj
, const jschar
*name
, size_t namelen
, jsval
*vp
)
3167 JSAtom
*atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
3168 return atom
&& JS_LookupPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), vp
);
3171 JS_PUBLIC_API(JSBool
)
3172 JS_LookupPropertyWithFlagsById(JSContext
*cx
, JSObject
*obj
, jsid id
, uintN flags
,
3173 JSObject
**objp
, jsval
*vp
)
3179 assertSameCompartment(cx
, obj
, id
);
3180 ok
= obj
->isNative()
3181 ? js_LookupPropertyWithFlags(cx
, obj
, id
, flags
, objp
, &prop
) >= 0
3182 : obj
->lookupProperty(cx
, id
, objp
, &prop
);
3183 return ok
&& LookupResult(cx
, obj
, *objp
, id
, prop
, Valueify(vp
));
3186 JS_PUBLIC_API(JSBool
)
3187 JS_LookupPropertyWithFlags(JSContext
*cx
, JSObject
*obj
, const char *name
, uintN flags
, jsval
*vp
)
3190 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3191 return atom
&& JS_LookupPropertyWithFlagsById(cx
, obj
, ATOM_TO_JSID(atom
), flags
, &obj2
, vp
);
3194 JS_PUBLIC_API(JSBool
)
3195 JS_HasPropertyById(JSContext
*cx
, JSObject
*obj
, jsid id
, JSBool
*foundp
)
3199 JSBool ok
= LookupPropertyById(cx
, obj
, id
, JSRESOLVE_QUALIFIED
| JSRESOLVE_DETECTING
,
3201 *foundp
= (prop
!= NULL
);
3205 JS_PUBLIC_API(JSBool
)
3206 JS_HasElement(JSContext
*cx
, JSObject
*obj
, jsint index
, JSBool
*foundp
)
3208 return JS_HasPropertyById(cx
, obj
, INT_TO_JSID(index
), foundp
);
3211 JS_PUBLIC_API(JSBool
)
3212 JS_HasProperty(JSContext
*cx
, JSObject
*obj
, const char *name
, JSBool
*foundp
)
3214 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3215 return atom
&& JS_HasPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), foundp
);
3218 JS_PUBLIC_API(JSBool
)
3219 JS_HasUCProperty(JSContext
*cx
, JSObject
*obj
, const jschar
*name
, size_t namelen
, JSBool
*foundp
)
3221 JSAtom
*atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
3222 return atom
&& JS_HasPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), foundp
);
3225 JS_PUBLIC_API(JSBool
)
3226 JS_AlreadyHasOwnPropertyById(JSContext
*cx
, JSObject
*obj
, jsid id
, JSBool
*foundp
)
3229 assertSameCompartment(cx
, obj
, id
);
3231 if (!obj
->isNative()) {
3235 if (!LookupPropertyById(cx
, obj
, id
, JSRESOLVE_QUALIFIED
| JSRESOLVE_DETECTING
,
3239 *foundp
= (obj
== obj2
);
3243 *foundp
= obj
->nativeContains(id
);
3247 JS_PUBLIC_API(JSBool
)
3248 JS_AlreadyHasOwnElement(JSContext
*cx
, JSObject
*obj
, jsint index
, JSBool
*foundp
)
3250 return JS_AlreadyHasOwnPropertyById(cx
, obj
, INT_TO_JSID(index
), foundp
);
3253 JS_PUBLIC_API(JSBool
)
3254 JS_AlreadyHasOwnProperty(JSContext
*cx
, JSObject
*obj
, const char *name
, JSBool
*foundp
)
3256 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3257 return atom
&& JS_AlreadyHasOwnPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), foundp
);
3260 JS_PUBLIC_API(JSBool
)
3261 JS_AlreadyHasOwnUCProperty(JSContext
*cx
, JSObject
*obj
, const jschar
*name
, size_t namelen
,
3264 JSAtom
*atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
3265 return atom
&& JS_AlreadyHasOwnPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), foundp
);
3269 DefinePropertyById(JSContext
*cx
, JSObject
*obj
, jsid id
, const Value
&value
,
3270 PropertyOp getter
, PropertyOp setter
, uintN attrs
,
3271 uintN flags
, intN tinyid
)
3274 assertSameCompartment(cx
, obj
, id
, value
,
3275 (attrs
& JSPROP_GETTER
)
3276 ? JS_FUNC_TO_DATA_PTR(JSObject
*, getter
)
3278 (attrs
& JSPROP_SETTER
)
3279 ? JS_FUNC_TO_DATA_PTR(JSObject
*, setter
)
3282 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
| JSRESOLVE_DECLARING
);
3283 if (flags
!= 0 && obj
->isNative()) {
3284 return !!js_DefineNativeProperty(cx
, obj
, id
, value
, getter
, setter
,
3285 attrs
, flags
, tinyid
, NULL
);
3287 return obj
->defineProperty(cx
, id
, value
, getter
, setter
, attrs
);
3290 JS_PUBLIC_API(JSBool
)
3291 JS_DefinePropertyById(JSContext
*cx
, JSObject
*obj
, jsid id
, jsval value
,
3292 JSPropertyOp getter
, JSPropertyOp setter
, uintN attrs
)
3294 return DefinePropertyById(cx
, obj
, id
, Valueify(value
), Valueify(getter
),
3295 Valueify(setter
), attrs
, 0, 0);
3298 JS_PUBLIC_API(JSBool
)
3299 JS_DefineElement(JSContext
*cx
, JSObject
*obj
, jsint index
, jsval value
,
3300 JSPropertyOp getter
, JSPropertyOp setter
, uintN attrs
)
3302 return DefinePropertyById(cx
, obj
, INT_TO_JSID(index
), Valueify(value
),
3303 Valueify(getter
), Valueify(setter
), attrs
, 0, 0);
3307 DefineProperty(JSContext
*cx
, JSObject
*obj
, const char *name
, const Value
&value
,
3308 PropertyOp getter
, PropertyOp setter
, uintN attrs
,
3309 uintN flags
, intN tinyid
)
3314 if (attrs
& JSPROP_INDEX
) {
3315 id
= INT_TO_JSID(intptr_t(name
));
3317 attrs
&= ~JSPROP_INDEX
;
3319 atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3322 id
= ATOM_TO_JSID(atom
);
3324 return DefinePropertyById(cx
, obj
, id
, value
, getter
, setter
, attrs
, flags
, tinyid
);
3327 JS_PUBLIC_API(JSBool
)
3328 JS_DefineProperty(JSContext
*cx
, JSObject
*obj
, const char *name
, jsval value
,
3329 JSPropertyOp getter
, JSPropertyOp setter
, uintN attrs
)
3331 return DefineProperty(cx
, obj
, name
, Valueify(value
), Valueify(getter
),
3332 Valueify(setter
), attrs
, 0, 0);
3335 JS_PUBLIC_API(JSBool
)
3336 JS_DefinePropertyWithTinyId(JSContext
*cx
, JSObject
*obj
, const char *name
, int8 tinyid
,
3337 jsval value
, JSPropertyOp getter
, JSPropertyOp setter
, uintN attrs
)
3339 return DefineProperty(cx
, obj
, name
, Valueify(value
), Valueify(getter
),
3340 Valueify(setter
), attrs
, Shape::HAS_SHORTID
, tinyid
);
3344 DefineUCProperty(JSContext
*cx
, JSObject
*obj
, const jschar
*name
, size_t namelen
,
3345 const Value
&value
, PropertyOp getter
, PropertyOp setter
, uintN attrs
,
3346 uintN flags
, intN tinyid
)
3348 JSAtom
*atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
3349 return atom
&& DefinePropertyById(cx
, obj
, ATOM_TO_JSID(atom
), value
, getter
, setter
, attrs
,
3353 JS_PUBLIC_API(JSBool
)
3354 JS_DefineUCProperty(JSContext
*cx
, JSObject
*obj
, const jschar
*name
, size_t namelen
,
3355 jsval value
, JSPropertyOp getter
, JSPropertyOp setter
, uintN attrs
)
3357 return DefineUCProperty(cx
, obj
, name
, namelen
, Valueify(value
),
3358 Valueify(getter
), Valueify(setter
), attrs
, 0, 0);
3361 JS_PUBLIC_API(JSBool
)
3362 JS_DefineUCPropertyWithTinyId(JSContext
*cx
, JSObject
*obj
, const jschar
*name
, size_t namelen
,
3363 int8 tinyid
, jsval value
, JSPropertyOp getter
, JSPropertyOp setter
,
3366 return DefineUCProperty(cx
, obj
, name
, namelen
, Valueify(value
), Valueify(getter
),
3367 Valueify(setter
), attrs
, Shape::HAS_SHORTID
, tinyid
);
3370 JS_PUBLIC_API(JSBool
)
3371 JS_DefineOwnProperty(JSContext
*cx
, JSObject
*obj
, jsid id
, jsval descriptor
, JSBool
*bp
)
3374 assertSameCompartment(cx
, obj
, id
, descriptor
);
3375 return js_DefineOwnProperty(cx
, obj
, id
, Valueify(descriptor
), bp
);
3378 JS_PUBLIC_API(JSObject
*)
3379 JS_DefineObject(JSContext
*cx
, JSObject
*obj
, const char *name
, JSClass
*jsclasp
,
3380 JSObject
*proto
, uintN attrs
)
3383 assertSameCompartment(cx
, obj
, proto
);
3385 Class
*clasp
= Valueify(jsclasp
);
3387 clasp
= &js_ObjectClass
; /* default class is Object */
3389 JSObject
*nobj
= NewObject
<WithProto::Class
>(cx
, clasp
, proto
, obj
);
3393 nobj
->syncSpecialEquality();
3395 if (!DefineProperty(cx
, obj
, name
, ObjectValue(*nobj
), NULL
, NULL
, attrs
, 0, 0))
3401 JS_PUBLIC_API(JSBool
)
3402 JS_DefineConstDoubles(JSContext
*cx
, JSObject
*obj
, JSConstDoubleSpec
*cds
)
3408 for (ok
= JS_TRUE
; cds
->name
; cds
++) {
3409 Value value
= DoubleValue(cds
->dval
);
3412 attrs
= JSPROP_READONLY
| JSPROP_PERMANENT
;
3413 ok
= DefineProperty(cx
, obj
, cds
->name
, value
, NULL
, NULL
, attrs
, 0, 0);
3420 JS_PUBLIC_API(JSBool
)
3421 JS_DefineProperties(JSContext
*cx
, JSObject
*obj
, JSPropertySpec
*ps
)
3425 for (ok
= true; ps
->name
; ps
++) {
3426 ok
= DefineProperty(cx
, obj
, ps
->name
, UndefinedValue(),
3427 Valueify(ps
->getter
), Valueify(ps
->setter
),
3428 ps
->flags
, Shape::HAS_SHORTID
, ps
->tinyid
);
3435 JS_PUBLIC_API(JSBool
)
3436 JS_AliasProperty(JSContext
*cx
, JSObject
*obj
, const char *name
, const char *alias
)
3444 assertSameCompartment(cx
, obj
);
3446 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3449 if (!LookupPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), JSRESOLVE_QUALIFIED
, &obj2
, &prop
))
3452 js_ReportIsNotDefined(cx
, name
);
3455 if (obj2
!= obj
|| !obj
->isNative()) {
3456 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_CANT_ALIAS
,
3457 alias
, name
, obj2
->getClass()->name
);
3460 atom
= js_Atomize(cx
, alias
, strlen(alias
), 0);
3464 shape
= (Shape
*)prop
;
3465 ok
= (js_AddNativeProperty(cx
, obj
, ATOM_TO_JSID(atom
),
3466 shape
->getter(), shape
->setter(), shape
->slot
,
3467 shape
->attributes(), shape
->getFlags() | Shape::ALIAS
,
3474 JS_PUBLIC_API(JSBool
)
3475 JS_AliasElement(JSContext
*cx
, JSObject
*obj
, const char *name
, jsint alias
)
3482 assertSameCompartment(cx
, obj
);
3484 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3487 if (!LookupPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), JSRESOLVE_QUALIFIED
, &obj2
, &prop
))
3490 js_ReportIsNotDefined(cx
, name
);
3493 if (obj2
!= obj
|| !obj
->isNative()) {
3495 JS_snprintf(numBuf
, sizeof numBuf
, "%ld", (long)alias
);
3496 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_CANT_ALIAS
,
3497 numBuf
, name
, obj2
->getClass()->name
);
3500 shape
= (Shape
*)prop
;
3501 return js_AddNativeProperty(cx
, obj
, INT_TO_JSID(alias
),
3502 shape
->getter(), shape
->setter(), shape
->slot
,
3503 shape
->attributes(), shape
->getFlags() | Shape::ALIAS
,
3509 GetPropertyDescriptorById(JSContext
*cx
, JSObject
*obj
, jsid id
, uintN flags
,
3510 JSBool own
, PropertyDescriptor
*desc
)
3515 if (!LookupPropertyById(cx
, obj
, id
, flags
, &obj2
, &prop
))
3518 if (!prop
|| (own
&& obj
!= obj2
)) {
3521 desc
->getter
= NULL
;
3522 desc
->setter
= NULL
;
3523 desc
->value
.setUndefined();
3528 if (obj2
->isNative()) {
3529 Shape
*shape
= (Shape
*) prop
;
3530 desc
->attrs
= shape
->attributes();
3532 if (shape
->isMethod()) {
3533 desc
->getter
= desc
->setter
= PropertyStub
;
3534 desc
->value
.setObject(shape
->methodObject());
3536 desc
->getter
= shape
->getter();
3537 desc
->setter
= shape
->setter();
3538 if (obj2
->containsSlot(shape
->slot
))
3539 desc
->value
= obj2
->nativeGetSlot(shape
->slot
);
3541 desc
->value
.setUndefined();
3544 if (obj2
->isProxy()) {
3545 JSAutoResolveFlags
rf(cx
, flags
);
3547 ? JSProxy::getOwnPropertyDescriptor(cx
, obj2
, id
, false, desc
)
3548 : JSProxy::getPropertyDescriptor(cx
, obj2
, id
, false, desc
);
3550 if (!obj2
->getAttributes(cx
, id
, &desc
->attrs
))
3552 desc
->getter
= NULL
;
3553 desc
->setter
= NULL
;
3554 desc
->value
.setUndefined();
3559 JS_PUBLIC_API(JSBool
)
3560 JS_GetPropertyDescriptorById(JSContext
*cx
, JSObject
*obj
, jsid id
, uintN flags
,
3561 JSPropertyDescriptor
*desc
)
3563 return GetPropertyDescriptorById(cx
, obj
, id
, flags
, JS_FALSE
, Valueify(desc
));
3566 JS_PUBLIC_API(JSBool
)
3567 JS_GetPropertyAttrsGetterAndSetterById(JSContext
*cx
, JSObject
*obj
, jsid id
,
3568 uintN
*attrsp
, JSBool
*foundp
,
3569 JSPropertyOp
*getterp
, JSPropertyOp
*setterp
)
3571 PropertyDescriptor desc
;
3572 if (!GetPropertyDescriptorById(cx
, obj
, id
, JSRESOLVE_QUALIFIED
, JS_FALSE
, &desc
))
3575 *attrsp
= desc
.attrs
;
3576 *foundp
= (desc
.obj
!= NULL
);
3578 *getterp
= Jsvalify(desc
.getter
);
3580 *setterp
= Jsvalify(desc
.setter
);
3584 JS_PUBLIC_API(JSBool
)
3585 JS_GetPropertyAttributes(JSContext
*cx
, JSObject
*obj
, const char *name
,
3586 uintN
*attrsp
, JSBool
*foundp
)
3588 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3589 return atom
&& JS_GetPropertyAttrsGetterAndSetterById(cx
, obj
, ATOM_TO_JSID(atom
),
3590 attrsp
, foundp
, NULL
, NULL
);
3593 JS_PUBLIC_API(JSBool
)
3594 JS_GetUCPropertyAttributes(JSContext
*cx
, JSObject
*obj
, const jschar
*name
, size_t namelen
,
3595 uintN
*attrsp
, JSBool
*foundp
)
3597 JSAtom
*atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
3598 return atom
&& JS_GetPropertyAttrsGetterAndSetterById(cx
, obj
, ATOM_TO_JSID(atom
),
3599 attrsp
, foundp
, NULL
, NULL
);
3602 JS_PUBLIC_API(JSBool
)
3603 JS_GetPropertyAttrsGetterAndSetter(JSContext
*cx
, JSObject
*obj
, const char *name
,
3604 uintN
*attrsp
, JSBool
*foundp
,
3605 JSPropertyOp
*getterp
, JSPropertyOp
*setterp
)
3607 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3608 return atom
&& JS_GetPropertyAttrsGetterAndSetterById(cx
, obj
, ATOM_TO_JSID(atom
),
3609 attrsp
, foundp
, getterp
, setterp
);
3612 JS_PUBLIC_API(JSBool
)
3613 JS_GetUCPropertyAttrsGetterAndSetter(JSContext
*cx
, JSObject
*obj
,
3614 const jschar
*name
, size_t namelen
,
3615 uintN
*attrsp
, JSBool
*foundp
,
3616 JSPropertyOp
*getterp
, JSPropertyOp
*setterp
)
3618 JSAtom
*atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
3619 return atom
&& JS_GetPropertyAttrsGetterAndSetterById(cx
, obj
, ATOM_TO_JSID(atom
),
3620 attrsp
, foundp
, getterp
, setterp
);
3623 JS_PUBLIC_API(JSBool
)
3624 JS_GetOwnPropertyDescriptor(JSContext
*cx
, JSObject
*obj
, jsid id
, jsval
*vp
)
3627 return js_GetOwnPropertyDescriptor(cx
, obj
, id
, Valueify(vp
));
3631 SetPropertyAttributesById(JSContext
*cx
, JSObject
*obj
, jsid id
, uintN attrs
, JSBool
*foundp
)
3636 if (!LookupPropertyById(cx
, obj
, id
, JSRESOLVE_QUALIFIED
, &obj2
, &prop
))
3638 if (!prop
|| obj
!= obj2
) {
3642 JSBool ok
= obj
->isNative()
3643 ? js_SetNativeAttributes(cx
, obj
, (Shape
*) prop
, attrs
)
3644 : obj
->setAttributes(cx
, id
, &attrs
);
3650 JS_PUBLIC_API(JSBool
)
3651 JS_SetPropertyAttributes(JSContext
*cx
, JSObject
*obj
, const char *name
,
3652 uintN attrs
, JSBool
*foundp
)
3654 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3655 return atom
&& SetPropertyAttributesById(cx
, obj
, ATOM_TO_JSID(atom
), attrs
, foundp
);
3658 JS_PUBLIC_API(JSBool
)
3659 JS_SetUCPropertyAttributes(JSContext
*cx
, JSObject
*obj
, const jschar
*name
, size_t namelen
,
3660 uintN attrs
, JSBool
*foundp
)
3662 JSAtom
*atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
3663 return atom
&& SetPropertyAttributesById(cx
, obj
, ATOM_TO_JSID(atom
), attrs
, foundp
);
3666 JS_PUBLIC_API(JSBool
)
3667 JS_GetPropertyById(JSContext
*cx
, JSObject
*obj
, jsid id
, jsval
*vp
)
3670 assertSameCompartment(cx
, obj
, id
);
3671 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
);
3672 return obj
->getProperty(cx
, id
, Valueify(vp
));
3675 JS_PUBLIC_API(JSBool
)
3676 JS_GetPropertyByIdDefault(JSContext
*cx
, JSObject
*obj
, jsid id
, jsval def
, jsval
*vp
)
3678 return GetPropertyDefault(cx
, obj
, id
, Valueify(def
), Valueify(vp
));
3681 JS_PUBLIC_API(JSBool
)
3682 JS_GetElement(JSContext
*cx
, JSObject
*obj
, jsint index
, jsval
*vp
)
3684 return JS_GetPropertyById(cx
, obj
, INT_TO_JSID(index
), vp
);
3687 JS_PUBLIC_API(JSBool
)
3688 JS_GetProperty(JSContext
*cx
, JSObject
*obj
, const char *name
, jsval
*vp
)
3690 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3691 return atom
&& JS_GetPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), vp
);
3694 JS_PUBLIC_API(JSBool
)
3695 JS_GetPropertyDefault(JSContext
*cx
, JSObject
*obj
, const char *name
, jsval def
, jsval
*vp
)
3697 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3698 return atom
&& JS_GetPropertyByIdDefault(cx
, obj
, ATOM_TO_JSID(atom
), def
, vp
);
3701 JS_PUBLIC_API(JSBool
)
3702 JS_GetUCProperty(JSContext
*cx
, JSObject
*obj
, const jschar
*name
, size_t namelen
, jsval
*vp
)
3704 JSAtom
*atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
3705 return atom
&& JS_GetPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), vp
);
3708 JS_PUBLIC_API(JSBool
)
3709 JS_GetMethodById(JSContext
*cx
, JSObject
*obj
, jsid id
, JSObject
**objp
, jsval
*vp
)
3712 assertSameCompartment(cx
, obj
, id
);
3713 if (!js_GetMethod(cx
, obj
, id
, JSGET_METHOD_BARRIER
, Valueify(vp
)))
3720 JS_PUBLIC_API(JSBool
)
3721 JS_GetMethod(JSContext
*cx
, JSObject
*obj
, const char *name
, JSObject
**objp
, jsval
*vp
)
3723 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3724 return atom
&& JS_GetMethodById(cx
, obj
, ATOM_TO_JSID(atom
), objp
, vp
);
3727 JS_PUBLIC_API(JSBool
)
3728 JS_SetPropertyById(JSContext
*cx
, JSObject
*obj
, jsid id
, jsval
*vp
)
3731 assertSameCompartment(cx
, obj
, id
);
3732 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
| JSRESOLVE_ASSIGNING
);
3733 return obj
->setProperty(cx
, id
, Valueify(vp
), false);
3736 JS_PUBLIC_API(JSBool
)
3737 JS_SetElement(JSContext
*cx
, JSObject
*obj
, jsint index
, jsval
*vp
)
3739 return JS_SetPropertyById(cx
, obj
, INT_TO_JSID(index
), vp
);
3742 JS_PUBLIC_API(JSBool
)
3743 JS_SetProperty(JSContext
*cx
, JSObject
*obj
, const char *name
, jsval
*vp
)
3745 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3746 return atom
&& JS_SetPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), vp
);
3749 JS_PUBLIC_API(JSBool
)
3750 JS_SetUCProperty(JSContext
*cx
, JSObject
*obj
, const jschar
*name
, size_t namelen
, jsval
*vp
)
3752 JSAtom
*atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
3753 return atom
&& JS_SetPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), vp
);
3756 JS_PUBLIC_API(JSBool
)
3757 JS_DeletePropertyById2(JSContext
*cx
, JSObject
*obj
, jsid id
, jsval
*rval
)
3760 assertSameCompartment(cx
, obj
, id
);
3761 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
);
3762 return obj
->deleteProperty(cx
, id
, Valueify(rval
), false);
3765 JS_PUBLIC_API(JSBool
)
3766 JS_DeleteElement2(JSContext
*cx
, JSObject
*obj
, jsint index
, jsval
*rval
)
3768 return JS_DeletePropertyById2(cx
, obj
, INT_TO_JSID(index
), rval
);
3771 JS_PUBLIC_API(JSBool
)
3772 JS_DeleteProperty2(JSContext
*cx
, JSObject
*obj
, const char *name
, jsval
*rval
)
3774 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3775 return atom
&& JS_DeletePropertyById2(cx
, obj
, ATOM_TO_JSID(atom
), rval
);
3778 JS_PUBLIC_API(JSBool
)
3779 JS_DeleteUCProperty2(JSContext
*cx
, JSObject
*obj
, const jschar
*name
, size_t namelen
, jsval
*rval
)
3781 JSAtom
*atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
3782 return atom
&& JS_DeletePropertyById2(cx
, obj
, ATOM_TO_JSID(atom
), rval
);
3785 JS_PUBLIC_API(JSBool
)
3786 JS_DeletePropertyById(JSContext
*cx
, JSObject
*obj
, jsid id
)
3789 return JS_DeletePropertyById2(cx
, obj
, id
, &junk
);
3792 JS_PUBLIC_API(JSBool
)
3793 JS_DeleteElement(JSContext
*cx
, JSObject
*obj
, jsint index
)
3796 return JS_DeleteElement2(cx
, obj
, index
, &junk
);
3799 JS_PUBLIC_API(JSBool
)
3800 JS_DeleteProperty(JSContext
*cx
, JSObject
*obj
, const char *name
)
3803 return JS_DeleteProperty2(cx
, obj
, name
, &junk
);
3807 JS_ClearScope(JSContext
*cx
, JSObject
*obj
)
3810 assertSameCompartment(cx
, obj
);
3812 JSFinalizeOp clearOp
= obj
->getOps()->clear
;
3816 if (obj
->isNative())
3817 js_ClearNative(cx
, obj
);
3819 /* Clear cached class objects on the global object. */
3820 if (obj
->isGlobal()) {
3821 for (int key
= JSProto_Null
; key
< JSProto_LIMIT
* 3; key
++)
3822 JS_SetReservedSlot(cx
, obj
, key
, JSVAL_VOID
);
3828 JS_PUBLIC_API(JSIdArray
*)
3829 JS_Enumerate(JSContext
*cx
, JSObject
*obj
)
3832 assertSameCompartment(cx
, obj
);
3834 AutoIdVector
props(cx
);
3836 if (!GetPropertyNames(cx
, obj
, JSITER_OWNONLY
, &props
) || !VectorToIdArray(cx
, props
, &ida
))
3838 for (size_t n
= 0; n
< size_t(ida
->length
); ++n
)
3839 JS_ASSERT(js_CheckForStringIndex(ida
->vector
[n
]) == ida
->vector
[n
]);
3844 * XXX reverse iterator for properties, unreverse and meld with jsinterp.c's
3845 * prop_iterator_class somehow...
3846 * + preserve the obj->enumerate API while optimizing the native object case
3847 * + native case here uses a Shape *, but that iterates in reverse!
3848 * + so we make non-native match, by reverse-iterating after JS_Enumerating
3850 const uint32 JSSLOT_ITER_INDEX
= 0;
3853 prop_iter_finalize(JSContext
*cx
, JSObject
*obj
)
3855 void *pdata
= obj
->getPrivate();
3859 if (obj
->getSlot(JSSLOT_ITER_INDEX
).toInt32() >= 0) {
3860 /* Non-native case: destroy the ida enumerated when obj was created. */
3861 JSIdArray
*ida
= (JSIdArray
*) pdata
;
3862 JS_DestroyIdArray(cx
, ida
);
3867 prop_iter_trace(JSTracer
*trc
, JSObject
*obj
)
3869 void *pdata
= obj
->getPrivate();
3873 if (obj
->getSlot(JSSLOT_ITER_INDEX
).toInt32() < 0) {
3874 /* Native case: just mark the next property to visit. */
3875 ((Shape
*) pdata
)->trace(trc
);
3877 /* Non-native case: mark each id in the JSIdArray private. */
3878 JSIdArray
*ida
= (JSIdArray
*) pdata
;
3879 MarkIdRange(trc
, ida
->length
, ida
->vector
, "prop iter");
3883 static Class prop_iter_class
= {
3885 JSCLASS_HAS_PRIVATE
| JSCLASS_HAS_RESERVED_SLOTS(1) |
3886 JSCLASS_MARK_IS_TRACE
,
3887 PropertyStub
, /* addProperty */
3888 PropertyStub
, /* delProperty */
3889 PropertyStub
, /* getProperty */
3890 PropertyStub
, /* setProperty */
3895 NULL
, /* reserved0 */
3896 NULL
, /* checkAccess */
3898 NULL
, /* construct */
3899 NULL
, /* xdrObject */
3900 NULL
, /* hasInstance */
3901 JS_CLASS_TRACE(prop_iter_trace
)
3904 JS_PUBLIC_API(JSObject
*)
3905 JS_NewPropertyIterator(JSContext
*cx
, JSObject
*obj
)
3913 assertSameCompartment(cx
, obj
);
3914 iterobj
= NewNonFunction
<WithProto::Class
>(cx
, &prop_iter_class
, NULL
, obj
);
3918 if (obj
->isNative()) {
3919 /* Native case: start with the last property in obj. */
3920 pdata
= obj
->lastProperty();
3924 * Non-native case: enumerate a JSIdArray and keep it via private.
3926 * Note: we have to make sure that we root obj around the call to
3927 * JS_Enumerate to protect against multiple allocations under it.
3929 AutoObjectRooter
tvr(cx
, iterobj
);
3930 ida
= JS_Enumerate(cx
, obj
);
3934 index
= ida
->length
;
3937 /* iterobj cannot escape to other threads here. */
3938 iterobj
->setPrivate(const_cast<void *>(pdata
));
3939 iterobj
->getSlotRef(JSSLOT_ITER_INDEX
).setInt32(index
);
3943 JS_PUBLIC_API(JSBool
)
3944 JS_NextProperty(JSContext
*cx
, JSObject
*iterobj
, jsid
*idp
)
3951 assertSameCompartment(cx
, iterobj
);
3952 i
= iterobj
->getSlot(JSSLOT_ITER_INDEX
).toInt32();
3954 /* Native case: private data is a property tree node pointer. */
3955 JS_ASSERT(iterobj
->getParent()->isNative());
3956 shape
= (Shape
*) iterobj
->getPrivate();
3958 while (shape
->previous() && (!shape
->enumerable() || shape
->isAlias()))
3959 shape
= shape
->previous();
3961 if (!shape
->previous()) {
3962 JS_ASSERT(JSID_IS_EMPTY(shape
->id
));
3965 iterobj
->setPrivate(const_cast<Shape
*>(shape
->previous()));
3969 /* Non-native case: use the ida enumerated when iterobj was created. */
3970 ida
= (JSIdArray
*) iterobj
->getPrivate();
3971 JS_ASSERT(i
<= ida
->length
);
3972 STATIC_ASSUME(i
<= ida
->length
);
3976 *idp
= ida
->vector
[--i
];
3977 iterobj
->setSlot(JSSLOT_ITER_INDEX
, Int32Value(i
));
3983 JS_PUBLIC_API(JSBool
)
3984 JS_GetReservedSlot(JSContext
*cx
, JSObject
*obj
, uint32 index
, jsval
*vp
)
3987 assertSameCompartment(cx
, obj
);
3988 return js_GetReservedSlot(cx
, obj
, index
, Valueify(vp
));
3991 JS_PUBLIC_API(JSBool
)
3992 JS_SetReservedSlot(JSContext
*cx
, JSObject
*obj
, uint32 index
, jsval v
)
3995 assertSameCompartment(cx
, obj
, v
);
3996 return js_SetReservedSlot(cx
, obj
, index
, Valueify(v
));
3999 JS_PUBLIC_API(JSObject
*)
4000 JS_NewArrayObject(JSContext
*cx
, jsint length
, jsval
*vector
)
4002 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
4004 /* NB: jsuint cast does ToUint32. */
4005 assertSameCompartment(cx
, JSValueArray(vector
, vector
? (jsuint
)length
: 0));
4006 return NewDenseCopiedArray(cx
, (jsuint
)length
, Valueify(vector
));
4009 JS_PUBLIC_API(JSBool
)
4010 JS_IsArrayObject(JSContext
*cx
, JSObject
*obj
)
4012 assertSameCompartment(cx
, obj
);
4013 return obj
->isArray() ||
4014 (obj
->isWrapper() && JSWrapper::wrappedObject(obj
)->isArray());
4017 JS_PUBLIC_API(JSBool
)
4018 JS_GetArrayLength(JSContext
*cx
, JSObject
*obj
, jsuint
*lengthp
)
4021 assertSameCompartment(cx
, obj
);
4022 return js_GetLengthProperty(cx
, obj
, lengthp
);
4025 JS_PUBLIC_API(JSBool
)
4026 JS_SetArrayLength(JSContext
*cx
, JSObject
*obj
, jsuint length
)
4029 assertSameCompartment(cx
, obj
);
4030 return js_SetLengthProperty(cx
, obj
, length
);
4033 JS_PUBLIC_API(JSBool
)
4034 JS_HasArrayLength(JSContext
*cx
, JSObject
*obj
, jsuint
*lengthp
)
4037 assertSameCompartment(cx
, obj
);
4038 return js_HasLengthProperty(cx
, obj
, lengthp
);
4041 JS_PUBLIC_API(JSBool
)
4042 JS_CheckAccess(JSContext
*cx
, JSObject
*obj
, jsid id
, JSAccessMode mode
,
4043 jsval
*vp
, uintN
*attrsp
)
4046 assertSameCompartment(cx
, obj
, id
);
4047 return CheckAccess(cx
, obj
, id
, mode
, Valueify(vp
), attrsp
);
4050 #ifdef JS_THREADSAFE
4051 JS_PUBLIC_API(jsrefcount
)
4052 JS_HoldPrincipals(JSContext
*cx
, JSPrincipals
*principals
)
4054 return JS_ATOMIC_INCREMENT(&principals
->refcount
);
4057 JS_PUBLIC_API(jsrefcount
)
4058 JS_DropPrincipals(JSContext
*cx
, JSPrincipals
*principals
)
4060 jsrefcount rc
= JS_ATOMIC_DECREMENT(&principals
->refcount
);
4062 principals
->destroy(cx
, principals
);
4067 JS_PUBLIC_API(JSSecurityCallbacks
*)
4068 JS_SetRuntimeSecurityCallbacks(JSRuntime
*rt
, JSSecurityCallbacks
*callbacks
)
4070 JSSecurityCallbacks
*oldcallbacks
;
4072 oldcallbacks
= rt
->securityCallbacks
;
4073 rt
->securityCallbacks
= callbacks
;
4074 return oldcallbacks
;
4077 JS_PUBLIC_API(JSSecurityCallbacks
*)
4078 JS_GetRuntimeSecurityCallbacks(JSRuntime
*rt
)
4080 return rt
->securityCallbacks
;
4083 JS_PUBLIC_API(JSSecurityCallbacks
*)
4084 JS_SetContextSecurityCallbacks(JSContext
*cx
, JSSecurityCallbacks
*callbacks
)
4086 JSSecurityCallbacks
*oldcallbacks
;
4088 oldcallbacks
= cx
->securityCallbacks
;
4089 cx
->securityCallbacks
= callbacks
;
4090 return oldcallbacks
;
4093 JS_PUBLIC_API(JSSecurityCallbacks
*)
4094 JS_GetSecurityCallbacks(JSContext
*cx
)
4096 return cx
->securityCallbacks
4097 ? cx
->securityCallbacks
4098 : cx
->runtime
->securityCallbacks
;
4101 JS_PUBLIC_API(JSFunction
*)
4102 JS_NewFunction(JSContext
*cx
, JSNative native
, uintN nargs
, uintN flags
,
4103 JSObject
*parent
, const char *name
)
4105 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
4109 assertSameCompartment(cx
, parent
);
4114 atom
= js_Atomize(cx
, name
, strlen(name
), 0);
4118 return js_NewFunction(cx
, NULL
, Valueify(native
), nargs
, flags
, parent
, atom
);
4121 JS_PUBLIC_API(JSFunction
*)
4122 JS_NewFunctionById(JSContext
*cx
, JSNative native
, uintN nargs
, uintN flags
, JSObject
*parent
,
4125 JS_ASSERT(JSID_IS_STRING(id
));
4126 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
4128 assertSameCompartment(cx
, parent
);
4130 return js_NewFunction(cx
, NULL
, Valueify(native
), nargs
, flags
, parent
, JSID_TO_ATOM(id
));
4133 JS_PUBLIC_API(JSObject
*)
4134 JS_CloneFunctionObject(JSContext
*cx
, JSObject
*funobj
, JSObject
*parent
)
4137 assertSameCompartment(cx
, parent
); // XXX no funobj for now
4140 parent
= GetScopeChain(cx
, cx
->fp());
4142 parent
= cx
->globalObject
;
4146 if (funobj
->getClass() != &js_FunctionClass
) {
4148 * We cannot clone this object, so fail (we used to return funobj, bad
4149 * idea, but we changed incompatibly to teach any abusers a lesson!).
4151 Value v
= ObjectValue(*funobj
);
4152 js_ReportIsNotFunction(cx
, &v
, 0);
4156 JSFunction
*fun
= GET_FUNCTION_PRIVATE(cx
, funobj
);
4157 if (!FUN_FLAT_CLOSURE(fun
))
4158 return CloneFunctionObject(cx
, fun
, parent
);
4161 * A flat closure carries its own environment, so why clone it? In case
4162 * someone wants to mutate its fixed slots or add ad-hoc properties. API
4163 * compatibility suggests we not return funobj and let callers mutate the
4164 * returned object at will.
4166 * But it's worse than that: API compatibility according to the test for
4167 * bug 300079 requires we get "upvars" from parent and its ancestors! So
4168 * we do that (grudgingly!). The scope chain ancestors are searched as if
4169 * they were activations, respecting the skip field in each upvar's cookie
4170 * but looking up the property by name instead of frame slot.
4172 JSObject
*clone
= js_AllocFlatClosure(cx
, fun
, parent
);
4176 JSUpvarArray
*uva
= fun
->u
.i
.script
->upvars();
4177 uint32 i
= uva
->length
;
4180 for (Shape::Range
r(fun
->script()->bindings
.lastUpvar()); i
-- != 0; r
.popFront()) {
4181 JSObject
*obj
= parent
;
4182 int skip
= uva
->vector
[i
].level();
4183 while (--skip
> 0) {
4185 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
,
4186 JSMSG_BAD_CLONE_FUNOBJ_SCOPE
);
4189 obj
= obj
->getParent();
4192 if (!obj
->getProperty(cx
, r
.front().id
, clone
->getFlatClosureUpvars() + i
))
4199 JS_PUBLIC_API(JSObject
*)
4200 JS_GetFunctionObject(JSFunction
*fun
)
4202 return FUN_OBJECT(fun
);
4205 JS_PUBLIC_API(JSString
*)
4206 JS_GetFunctionId(JSFunction
*fun
)
4208 return fun
->atom
? ATOM_TO_STRING(fun
->atom
) : NULL
;
4211 JS_PUBLIC_API(uintN
)
4212 JS_GetFunctionFlags(JSFunction
*fun
)
4217 JS_PUBLIC_API(uint16
)
4218 JS_GetFunctionArity(JSFunction
*fun
)
4223 JS_PUBLIC_API(JSBool
)
4224 JS_ObjectIsFunction(JSContext
*cx
, JSObject
*obj
)
4226 return obj
->getClass() == &js_FunctionClass
;
4229 JS_PUBLIC_API(JSBool
)
4230 JS_ObjectIsCallable(JSContext
*cx
, JSObject
*obj
)
4232 return obj
->isCallable();
4236 js_generic_native_method_dispatcher(JSContext
*cx
, uintN argc
, Value
*vp
)
4242 fs
= (JSFunctionSpec
*) vp
->toObject().getReservedSlot(0).toPrivate();
4243 JS_ASSERT((fs
->flags
& JSFUN_GENERIC_NATIVE
) != 0);
4246 js_ReportMissingArg(cx
, *vp
, 0);
4250 if (vp
[2].isPrimitive()) {
4252 * Make sure that this is an object or null, as required by the generic
4255 if (!js_ValueToObjectOrNull(cx
, vp
[2], &tmp
))
4257 vp
[2].setObjectOrNull(tmp
);
4261 * Copy all actual (argc) arguments down over our |this| parameter, vp[1],
4262 * which is almost always the class constructor object, e.g. Array. Then
4263 * call the corresponding prototype native method with our first argument
4266 memmove(vp
+ 1, vp
+ 2, argc
* sizeof(jsval
));
4269 * Follow Function.prototype.apply and .call by using the global object as
4270 * the 'this' param if no args.
4272 if (!ComputeThisFromArgv(cx
, vp
+ 2))
4275 /* Clear the last parameter in case too few arguments were passed. */
4276 vp
[2 + --argc
].setUndefined();
4280 (fs
->flags
& JSFUN_TRCINFO
)
4281 ? JS_FUNC_TO_DATA_PTR(JSNativeTraceInfo
*, fs
->call
)->native
4285 return native(cx
, argc
, vp
);
4288 JS_PUBLIC_API(JSBool
)
4289 JS_DefineFunctions(JSContext
*cx
, JSObject
*obj
, JSFunctionSpec
*fs
)
4291 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
4297 assertSameCompartment(cx
, obj
);
4299 for (; fs
->name
; fs
++) {
4303 * Define a generic arity N+1 static method for the arity N prototype
4304 * method if flags contains JSFUN_GENERIC_NATIVE.
4306 if (flags
& JSFUN_GENERIC_NATIVE
) {
4308 ctor
= JS_GetConstructor(cx
, obj
);
4313 flags
&= ~JSFUN_GENERIC_NATIVE
;
4314 fun
= JS_DefineFunction(cx
, ctor
, fs
->name
,
4315 Jsvalify(js_generic_native_method_dispatcher
),
4317 flags
& ~JSFUN_TRCINFO
);
4322 * As jsapi.h notes, fs must point to storage that lives as long
4323 * as fun->object lives.
4325 Value priv
= PrivateValue(fs
);
4326 if (!js_SetReservedSlot(cx
, FUN_OBJECT(fun
), 0, priv
))
4330 fun
= JS_DefineFunction(cx
, obj
, fs
->name
, fs
->call
, fs
->nargs
, flags
);
4337 JS_PUBLIC_API(JSFunction
*)
4338 JS_DefineFunction(JSContext
*cx
, JSObject
*obj
, const char *name
, JSNative call
,
4339 uintN nargs
, uintN attrs
)
4341 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
4343 assertSameCompartment(cx
, obj
);
4344 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
4347 return js_DefineFunction(cx
, obj
, ATOM_TO_JSID(atom
), Valueify(call
), nargs
, attrs
);
4350 JS_PUBLIC_API(JSFunction
*)
4351 JS_DefineUCFunction(JSContext
*cx
, JSObject
*obj
,
4352 const jschar
*name
, size_t namelen
, JSNative call
,
4353 uintN nargs
, uintN attrs
)
4355 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
4357 assertSameCompartment(cx
, obj
);
4358 JSAtom
*atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
4361 return js_DefineFunction(cx
, obj
, ATOM_TO_JSID(atom
), Valueify(call
), nargs
, attrs
);
4364 extern JS_PUBLIC_API(JSFunction
*)
4365 JS_DefineFunctionById(JSContext
*cx
, JSObject
*obj
, jsid id
, JSNative call
,
4366 uintN nargs
, uintN attrs
)
4368 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
4370 assertSameCompartment(cx
, obj
);
4371 return js_DefineFunction(cx
, obj
, id
, Valueify(call
), nargs
, attrs
);
4375 LAST_FRAME_EXCEPTION_CHECK(JSContext
*cx
, bool result
)
4377 if (!result
&& !(cx
->options
& JSOPTION_DONT_REPORT_UNCAUGHT
))
4378 js_ReportUncaughtException(cx
);
4382 LAST_FRAME_CHECKS(JSContext
*cx
, bool result
)
4384 if (!JS_IsRunning(cx
)) {
4385 LAST_FRAME_EXCEPTION_CHECK(cx
, result
);
4389 inline static uint32
4390 JS_OPTIONS_TO_TCFLAGS(JSContext
*cx
)
4392 return ((cx
->options
& JSOPTION_COMPILE_N_GO
) ? TCF_COMPILE_N_GO
: 0) |
4393 ((cx
->options
& JSOPTION_NO_SCRIPT_RVAL
) ? TCF_NO_SCRIPT_RVAL
: 0);
4396 extern JS_PUBLIC_API(JSScript
*)
4397 JS_CompileUCScriptForPrincipalsVersion(JSContext
*cx
, JSObject
*obj
,
4398 JSPrincipals
*principals
,
4399 const jschar
*chars
, size_t length
,
4400 const char *filename
, uintN lineno
,
4403 AutoVersionAPI
avi(cx
, version
);
4404 return JS_CompileUCScriptForPrincipals(cx
, obj
, principals
, chars
, length
, filename
, lineno
);
4407 JS_PUBLIC_API(JSScript
*)
4408 JS_CompileUCScriptForPrincipals(JSContext
*cx
, JSObject
*obj
, JSPrincipals
*principals
,
4409 const jschar
*chars
, size_t length
,
4410 const char *filename
, uintN lineno
)
4412 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
4414 assertSameCompartment(cx
, obj
, principals
);
4416 uint32 tcflags
= JS_OPTIONS_TO_TCFLAGS(cx
) | TCF_NEED_MUTABLE_SCRIPT
;
4417 JSScript
*script
= Compiler::compileScript(cx
, obj
, NULL
, principals
, tcflags
,
4418 chars
, length
, filename
, lineno
);
4419 if (script
&& !js_NewScriptObject(cx
, script
)) {
4420 js_DestroyScript(cx
, script
);
4423 LAST_FRAME_CHECKS(cx
, script
);
4427 JS_PUBLIC_API(JSScript
*)
4428 JS_CompileUCScript(JSContext
*cx
, JSObject
*obj
, const jschar
*chars
, size_t length
,
4429 const char *filename
, uintN lineno
)
4431 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
4432 return JS_CompileUCScriptForPrincipals(cx
, obj
, NULL
, chars
, length
, filename
, lineno
);
4435 JS_PUBLIC_API(JSScript
*)
4436 JS_CompileScriptForPrincipalsVersion(JSContext
*cx
, JSObject
*obj
,
4437 JSPrincipals
*principals
,
4438 const char *bytes
, size_t length
,
4439 const char *filename
, uintN lineno
,
4442 AutoVersionAPI
ava(cx
, version
);
4443 return JS_CompileScriptForPrincipals(cx
, obj
, principals
, bytes
, length
, filename
, lineno
);
4446 JS_PUBLIC_API(JSScript
*)
4447 JS_CompileScriptForPrincipals(JSContext
*cx
, JSObject
*obj
,
4448 JSPrincipals
*principals
,
4449 const char *bytes
, size_t length
,
4450 const char *filename
, uintN lineno
)
4452 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
4455 jschar
*chars
= js_InflateString(cx
, bytes
, &length
);
4458 JSScript
*script
= JS_CompileUCScriptForPrincipals(cx
, obj
, principals
, chars
, length
, filename
, lineno
);
4463 JS_PUBLIC_API(JSScript
*)
4464 JS_CompileScript(JSContext
*cx
, JSObject
*obj
, const char *bytes
, size_t length
,
4465 const char *filename
, uintN lineno
)
4467 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
4468 return JS_CompileScriptForPrincipals(cx
, obj
, NULL
, bytes
, length
, filename
, lineno
);
4471 JS_PUBLIC_API(JSBool
)
4472 JS_BufferIsCompilableUnit(JSContext
*cx
, JSObject
*obj
, const char *bytes
, size_t length
)
4476 JSExceptionState
*exnState
;
4477 JSErrorReporter older
;
4480 assertSameCompartment(cx
, obj
);
4481 chars
= js_InflateString(cx
, bytes
, &length
);
4486 * Return true on any out-of-memory error, so our caller doesn't try to
4487 * collect more buffered source.
4490 exnState
= JS_SaveExceptionState(cx
);
4493 if (parser
.init(chars
, length
, NULL
, 1)) {
4494 older
= JS_SetErrorReporter(cx
, NULL
);
4495 if (!parser
.parse(obj
) &&
4496 parser
.tokenStream
.isUnexpectedEOF()) {
4498 * We ran into an error. If it was because we ran out of
4499 * source, we return false so our caller knows to try to
4500 * collect more buffered source.
4504 JS_SetErrorReporter(cx
, older
);
4508 JS_RestoreExceptionState(cx
, exnState
);
4512 /* Use the fastest available getc. */
4513 #if defined(HAVE_GETC_UNLOCKED)
4514 # define fast_getc getc_unlocked
4515 #elif defined(HAVE__GETC_NOLOCK)
4516 # define fast_getc _getc_nolock
4518 # define fast_getc getc
4522 CompileFileHelper(JSContext
*cx
, JSObject
*obj
, JSPrincipals
*principals
, uint32 tcflags
,
4523 const char* filename
, FILE *fp
)
4526 int ok
= fstat(fileno(fp
), &st
);
4531 size_t len
= st
.st_size
;
4535 /* Read in the whole file, then compile it. */
4537 JS_ASSERT(len
== 0);
4538 len
= 8; /* start with a small buffer, expand as necessary */
4540 bool hitEOF
= false;
4543 jschar
* tmpbuf
= (jschar
*) cx
->realloc(buf
, len
* sizeof(jschar
));
4556 buf
[i
++] = (jschar
) (unsigned char) c
;
4560 buf
= (jschar
*) cx
->malloc(len
* sizeof(jschar
));
4565 while ((c
= fast_getc(fp
)) != EOF
)
4566 buf
[i
++] = (jschar
) (unsigned char) c
;
4569 JS_ASSERT(i
<= len
);
4571 script
= Compiler::compileScript(cx
, obj
, NULL
, principals
, tcflags
, buf
, len
, filename
, 1);
4576 JS_PUBLIC_API(JSScript
*)
4577 JS_CompileFile(JSContext
*cx
, JSObject
*obj
, const char *filename
)
4579 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
4585 assertSameCompartment(cx
, obj
);
4586 if (!filename
|| strcmp(filename
, "-") == 0) {
4589 fp
= fopen(filename
, "r");
4591 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_CANT_OPEN
,
4592 filename
, "No such file or directory");
4597 tcflags
= JS_OPTIONS_TO_TCFLAGS(cx
) | TCF_NEED_MUTABLE_SCRIPT
;
4598 script
= CompileFileHelper(cx
, obj
, NULL
, tcflags
, filename
, fp
);
4602 if (script
&& !js_NewScriptObject(cx
, script
)) {
4603 js_DestroyScript(cx
, script
);
4606 LAST_FRAME_CHECKS(cx
, script
);
4610 JS_PUBLIC_API(JSScript
*)
4611 JS_CompileFileHandleForPrincipals(JSContext
*cx
, JSObject
*obj
, const char *filename
, FILE *file
,
4612 JSPrincipals
*principals
)
4614 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
4619 assertSameCompartment(cx
, obj
, principals
);
4620 tcflags
= JS_OPTIONS_TO_TCFLAGS(cx
) | TCF_NEED_MUTABLE_SCRIPT
;
4621 script
= CompileFileHelper(cx
, obj
, principals
, tcflags
, filename
, file
);
4623 if (script
&& !js_NewScriptObject(cx
, script
)) {
4624 js_DestroyScript(cx
, script
);
4627 LAST_FRAME_CHECKS(cx
, script
);
4631 JS_PUBLIC_API(JSScript
*)
4632 JS_CompileFileHandleForPrincipalsVersion(JSContext
*cx
, JSObject
*obj
, const char *filename
,
4633 FILE *file
, JSPrincipals
*principals
, JSVersion version
)
4635 AutoVersionAPI
ava(cx
, version
);
4636 return JS_CompileFileHandleForPrincipals(cx
, obj
, filename
, file
, principals
);
4639 JS_PUBLIC_API(JSScript
*)
4640 JS_CompileFileHandle(JSContext
*cx
, JSObject
*obj
, const char *filename
, FILE *file
)
4642 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
4643 return JS_CompileFileHandleForPrincipals(cx
, obj
, filename
, file
, NULL
);
4646 JS_PUBLIC_API(JSObject
*)
4647 JS_NewScriptObject(JSContext
*cx
, JSScript
*script
)
4649 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
4651 assertSameCompartment(cx
, script
);
4653 return NewNonFunction
<WithProto::Class
>(cx
, &js_ScriptClass
, NULL
, NULL
);
4656 * This function should only ever be applied to JSScripts that had
4657 * script objects allocated for them when they were created, as
4658 * described in the comment for JSScript::u.object.
4660 JS_ASSERT(script
->u
.object
);
4661 return script
->u
.object
;
4664 JS_PUBLIC_API(JSObject
*)
4665 JS_GetScriptObject(JSScript
*script
)
4668 * This function should only ever be applied to JSScripts that had
4669 * script objects allocated for them when they were created, as
4670 * described in the comment for JSScript::u.object.
4672 JS_ASSERT(script
->u
.object
);
4673 return script
->u
.object
;
4677 JS_DestroyScript(JSContext
*cx
, JSScript
*script
)
4682 * Originally, JSScript lifetimes were managed explicitly, and this function
4683 * was used to free a JSScript. Now, this function does nothing, and the
4684 * garbage collector manages JSScripts; you must root the JSScript's script
4685 * object (obtained via JS_GetScriptObject) to keep it alive.
4687 * However, since the script objects have taken over this responsibility, it
4688 * follows that every script passed here must have a script object.
4690 JS_ASSERT(script
->u
.object
);
4693 JS_PUBLIC_API(JSFunction
*)
4694 JS_CompileUCFunctionForPrincipalsVersion(JSContext
*cx
, JSObject
*obj
,
4695 JSPrincipals
*principals
, const char *name
,
4696 uintN nargs
, const char **argnames
,
4697 const jschar
*chars
, size_t length
,
4698 const char *filename
, uintN lineno
,
4701 AutoVersionAPI
avi(cx
, version
);
4702 return JS_CompileUCFunctionForPrincipals(cx
, obj
, principals
, name
, nargs
, argnames
, chars
,
4703 length
, filename
, lineno
);
4706 JS_PUBLIC_API(JSFunction
*)
4707 JS_CompileUCFunctionForPrincipals(JSContext
*cx
, JSObject
*obj
,
4708 JSPrincipals
*principals
, const char *name
,
4709 uintN nargs
, const char **argnames
,
4710 const jschar
*chars
, size_t length
,
4711 const char *filename
, uintN lineno
)
4713 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
4715 JSAtom
*funAtom
, *argAtom
;
4719 assertSameCompartment(cx
, obj
, principals
);
4723 funAtom
= js_Atomize(cx
, name
, strlen(name
), 0);
4730 fun
= js_NewFunction(cx
, NULL
, NULL
, 0, JSFUN_INTERPRETED
, obj
, funAtom
);
4735 AutoObjectRooter
tvr(cx
, FUN_OBJECT(fun
));
4736 MUST_FLOW_THROUGH("out");
4738 Bindings
bindings(cx
);
4739 AutoBindingsRooter
root(cx
, bindings
);
4740 for (i
= 0; i
< nargs
; i
++) {
4741 argAtom
= js_Atomize(cx
, argnames
[i
], strlen(argnames
[i
]), 0);
4748 if (!bindings
.addArgument(cx
, argAtom
, &dummy
)) {
4754 if (!Compiler::compileFunctionBody(cx
, fun
, principals
, &bindings
,
4755 chars
, length
, filename
, lineno
)) {
4760 if (obj
&& funAtom
&&
4761 !obj
->defineProperty(cx
, ATOM_TO_JSID(funAtom
), ObjectValue(*fun
),
4762 NULL
, NULL
, JSPROP_ENUMERATE
)) {
4766 #ifdef JS_SCOPE_DEPTH_METER
4768 JSObject
*pobj
= obj
;
4771 while ((pobj
= pobj
->getParent()) != NULL
)
4773 JS_BASIC_STATS_ACCUM(&cx
->runtime
->hostenvScopeDepthStats
, depth
);
4779 LAST_FRAME_CHECKS(cx
, fun
);
4783 JS_PUBLIC_API(JSFunction
*)
4784 JS_CompileUCFunction(JSContext
*cx
, JSObject
*obj
, const char *name
,
4785 uintN nargs
, const char **argnames
,
4786 const jschar
*chars
, size_t length
,
4787 const char *filename
, uintN lineno
)
4789 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
4790 return JS_CompileUCFunctionForPrincipals(cx
, obj
, NULL
, name
, nargs
, argnames
,
4791 chars
, length
, filename
, lineno
);
4794 JS_PUBLIC_API(JSFunction
*)
4795 JS_CompileFunctionForPrincipals(JSContext
*cx
, JSObject
*obj
,
4796 JSPrincipals
*principals
, const char *name
,
4797 uintN nargs
, const char **argnames
,
4798 const char *bytes
, size_t length
,
4799 const char *filename
, uintN lineno
)
4801 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
4802 jschar
*chars
= js_InflateString(cx
, bytes
, &length
);
4805 JSFunction
*fun
= JS_CompileUCFunctionForPrincipals(cx
, obj
, principals
, name
,
4806 nargs
, argnames
, chars
, length
,
4812 JS_PUBLIC_API(JSFunction
*)
4813 JS_CompileFunction(JSContext
*cx
, JSObject
*obj
, const char *name
,
4814 uintN nargs
, const char **argnames
,
4815 const char *bytes
, size_t length
,
4816 const char *filename
, uintN lineno
)
4818 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
4819 return JS_CompileFunctionForPrincipals(cx
, obj
, NULL
, name
, nargs
, argnames
, bytes
, length
,
4823 JS_PUBLIC_API(JSString
*)
4824 JS_DecompileScript(JSContext
*cx
, JSScript
*script
, const char *name
, uintN indent
)
4826 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
4832 if (cx
->compartment
!= script
->compartment
)
4833 CompartmentChecker::fail(cx
->compartment
, script
->compartment
);
4835 jp
= js_NewPrinter(cx
, name
, NULL
,
4836 indent
& ~JS_DONT_PRETTY_PRINT
,
4837 !(indent
& JS_DONT_PRETTY_PRINT
),
4841 if (js_DecompileScript(jp
, script
))
4842 str
= js_GetPrinterOutput(jp
);
4845 js_DestroyPrinter(jp
);
4849 JS_PUBLIC_API(JSString
*)
4850 JS_DecompileFunction(JSContext
*cx
, JSFunction
*fun
, uintN indent
)
4852 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
4854 assertSameCompartment(cx
, fun
);
4855 return js_DecompileToString(cx
, "JS_DecompileFunction", fun
,
4856 indent
& ~JS_DONT_PRETTY_PRINT
,
4857 !(indent
& JS_DONT_PRETTY_PRINT
),
4858 false, false, js_DecompileFunction
);
4861 JS_PUBLIC_API(JSString
*)
4862 JS_DecompileFunctionBody(JSContext
*cx
, JSFunction
*fun
, uintN indent
)
4864 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
4866 assertSameCompartment(cx
, fun
);
4867 return js_DecompileToString(cx
, "JS_DecompileFunctionBody", fun
,
4868 indent
& ~JS_DONT_PRETTY_PRINT
,
4869 !(indent
& JS_DONT_PRETTY_PRINT
),
4870 false, false, js_DecompileFunctionBody
);
4873 JS_PUBLIC_API(JSBool
)
4874 JS_ExecuteScript(JSContext
*cx
, JSObject
*obj
, JSScript
*script
, jsval
*rval
)
4876 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
4880 assertSameCompartment(cx
, obj
, script
);
4881 /* This should receive only scripts handed out via the JSAPI. */
4882 JS_ASSERT(script
->u
.object
);
4883 ok
= Execute(cx
, obj
, script
, NULL
, 0, Valueify(rval
));
4884 LAST_FRAME_CHECKS(cx
, ok
);
4888 JS_PUBLIC_API(JSBool
)
4889 JS_ExecuteScriptVersion(JSContext
*cx
, JSObject
*obj
, JSScript
*script
, jsval
*rval
,
4892 AutoVersionAPI
ava(cx
, version
);
4893 return JS_ExecuteScript(cx
, obj
, script
, rval
);
4897 JS_PUBLIC_API(JSBool
)
4898 JS_EvaluateUCScriptForPrincipalsVersion(JSContext
*cx
, JSObject
*obj
,
4899 JSPrincipals
*principals
,
4900 const jschar
*chars
, uintN length
,
4901 const char *filename
, uintN lineno
,
4902 jsval
*rval
, JSVersion version
)
4904 AutoVersionAPI
avi(cx
, version
);
4905 return JS_EvaluateUCScriptForPrincipals(cx
, obj
, principals
, chars
, length
, filename
, lineno
,
4909 JS_PUBLIC_API(JSBool
)
4910 JS_EvaluateUCScriptForPrincipals(JSContext
*cx
, JSObject
*obj
,
4911 JSPrincipals
*principals
,
4912 const jschar
*chars
, uintN length
,
4913 const char *filename
, uintN lineno
,
4916 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
4921 script
= Compiler::compileScript(cx
, obj
, NULL
, principals
,
4923 ? TCF_COMPILE_N_GO
| TCF_NO_SCRIPT_RVAL
4925 chars
, length
, filename
, lineno
);
4927 LAST_FRAME_CHECKS(cx
, script
);
4930 ok
= Execute(cx
, obj
, script
, NULL
, 0, Valueify(rval
));
4931 LAST_FRAME_CHECKS(cx
, ok
);
4932 js_DestroyScript(cx
, script
);
4936 JS_PUBLIC_API(JSBool
)
4937 JS_EvaluateUCScript(JSContext
*cx
, JSObject
*obj
, const jschar
*chars
, uintN length
,
4938 const char *filename
, uintN lineno
, jsval
*rval
)
4940 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
4941 return JS_EvaluateUCScriptForPrincipals(cx
, obj
, NULL
, chars
, length
, filename
, lineno
, rval
);
4944 /* Ancient uintN nbytes is part of API/ABI, so use size_t length local. */
4945 JS_PUBLIC_API(JSBool
)
4946 JS_EvaluateScriptForPrincipals(JSContext
*cx
, JSObject
*obj
, JSPrincipals
*principals
,
4947 const char *bytes
, uintN nbytes
,
4948 const char *filename
, uintN lineno
, jsval
*rval
)
4950 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
4951 size_t length
= nbytes
;
4952 jschar
*chars
= js_InflateString(cx
, bytes
, &length
);
4955 JSBool ok
= JS_EvaluateUCScriptForPrincipals(cx
, obj
, principals
, chars
, length
,
4956 filename
, lineno
, rval
);
4961 JS_PUBLIC_API(JSBool
)
4962 JS_EvaluateScriptForPrincipalsVersion(JSContext
*cx
, JSObject
*obj
, JSPrincipals
*principals
,
4963 const char *bytes
, uintN nbytes
,
4964 const char *filename
, uintN lineno
, jsval
*rval
, JSVersion version
)
4966 AutoVersionAPI
avi(cx
, version
);
4967 return JS_EvaluateScriptForPrincipals(cx
, obj
, principals
, bytes
, nbytes
, filename
, lineno
,
4971 JS_PUBLIC_API(JSBool
)
4972 JS_EvaluateScript(JSContext
*cx
, JSObject
*obj
, const char *bytes
, uintN nbytes
,
4973 const char *filename
, uintN lineno
, jsval
*rval
)
4975 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
4976 return JS_EvaluateScriptForPrincipals(cx
, obj
, NULL
, bytes
, nbytes
, filename
, lineno
, rval
);
4979 JS_PUBLIC_API(JSBool
)
4980 JS_CallFunction(JSContext
*cx
, JSObject
*obj
, JSFunction
*fun
, uintN argc
, jsval
*argv
,
4983 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
4987 assertSameCompartment(cx
, obj
, fun
, JSValueArray(argv
, argc
));
4988 ok
= ExternalInvoke(cx
, obj
, ObjectValue(*fun
), argc
, Valueify(argv
), Valueify(rval
));
4989 LAST_FRAME_CHECKS(cx
, ok
);
4993 JS_PUBLIC_API(JSBool
)
4994 JS_CallFunctionName(JSContext
*cx
, JSObject
*obj
, const char *name
, uintN argc
, jsval
*argv
,
4997 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
4999 assertSameCompartment(cx
, obj
, JSValueArray(argv
, argc
));
5001 AutoValueRooter
tvr(cx
);
5002 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
5004 js_GetMethod(cx
, obj
, ATOM_TO_JSID(atom
), JSGET_NO_METHOD_BARRIER
, tvr
.addr()) &&
5005 ExternalInvoke(cx
, obj
, tvr
.value(), argc
, Valueify(argv
), Valueify(rval
));
5006 LAST_FRAME_CHECKS(cx
, ok
);
5010 JS_PUBLIC_API(JSBool
)
5011 JS_CallFunctionValue(JSContext
*cx
, JSObject
*obj
, jsval fval
, uintN argc
, jsval
*argv
,
5014 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->defaultCompartment
);
5018 assertSameCompartment(cx
, obj
, fval
, JSValueArray(argv
, argc
));
5019 ok
= ExternalInvoke(cx
, obj
, Valueify(fval
), argc
, Valueify(argv
), Valueify(rval
));
5020 LAST_FRAME_CHECKS(cx
, ok
);
5027 Call(JSContext
*cx
, jsval thisv
, jsval fval
, uintN argc
, jsval
*argv
, jsval
*rval
)
5032 assertSameCompartment(cx
, thisv
, fval
, JSValueArray(argv
, argc
));
5033 ok
= ExternalInvoke(cx
, Valueify(thisv
), Valueify(fval
), argc
, Valueify(argv
), Valueify(rval
));
5034 LAST_FRAME_CHECKS(cx
, ok
);
5040 JS_PUBLIC_API(JSObject
*)
5041 JS_New(JSContext
*cx
, JSObject
*ctor
, uintN argc
, jsval
*argv
)
5044 assertSameCompartment(cx
, ctor
, JSValueArray(argv
, argc
));
5046 // This is not a simple variation of JS_CallFunctionValue because JSOP_NEW
5047 // is not a simple variation of JSOP_CALL. We have to determine what class
5048 // of object to create, create it, and clamp the return value to an object,
5049 // among other details. js_InvokeConstructor does the hard work.
5050 InvokeArgsGuard args
;
5051 if (!cx
->stack().pushInvokeArgs(cx
, argc
, &args
))
5054 args
.callee().setObject(*ctor
);
5055 args
.thisv().setNull();
5056 memcpy(args
.argv(), argv
, argc
* sizeof(jsval
));
5058 bool ok
= InvokeConstructor(cx
, args
);
5060 JSObject
*obj
= NULL
;
5062 if (args
.rval().isObject()) {
5063 obj
= &args
.rval().toObject();
5066 * Although constructors may return primitives (via proxies), this
5067 * API is asking for an object, so we report an error.
5069 JSAutoByteString bytes
;
5070 if (js_ValueToPrintable(cx
, args
.rval(), &bytes
)) {
5071 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_BAD_NEW_RESULT
,
5077 LAST_FRAME_CHECKS(cx
, ok
);
5081 JS_PUBLIC_API(JSOperationCallback
)
5082 JS_SetOperationCallback(JSContext
*cx
, JSOperationCallback callback
)
5084 #ifdef JS_THREADSAFE
5085 JS_ASSERT(CURRENT_THREAD_IS_ME(cx
->thread
));
5087 JSOperationCallback old
= cx
->operationCallback
;
5088 cx
->operationCallback
= callback
;
5092 JS_PUBLIC_API(JSOperationCallback
)
5093 JS_GetOperationCallback(JSContext
*cx
)
5095 return cx
->operationCallback
;
5099 JS_TriggerOperationCallback(JSContext
*cx
)
5101 #ifdef JS_THREADSAFE
5102 AutoLockGC
lock(cx
->runtime
);
5104 TriggerOperationCallback(cx
);
5108 JS_TriggerAllOperationCallbacks(JSRuntime
*rt
)
5110 #ifdef JS_THREADSAFE
5111 AutoLockGC
lock(rt
);
5113 TriggerAllOperationCallbacks(rt
);
5116 JS_PUBLIC_API(JSBool
)
5117 JS_IsRunning(JSContext
*cx
)
5120 * The use of cx->fp below is safe. Rationale: Here we don't care if the
5121 * interpreter state is stale. We just want to know if there *is* any
5122 * interpreter state.
5124 VOUCH_DOES_NOT_REQUIRE_STACK();
5127 JS_ASSERT_IF(cx
->compartment
&&
5128 JS_TRACE_MONITOR(cx
).tracecx
== cx
, cx
->hasfp());
5130 JSStackFrame
*fp
= cx
->maybefp();
5131 while (fp
&& fp
->isDummyFrame())
5136 JS_PUBLIC_API(JSStackFrame
*)
5137 JS_SaveFrameChain(JSContext
*cx
)
5140 JSStackFrame
*fp
= js_GetTopStackFrame(cx
);
5143 cx
->saveActiveSegment();
5148 JS_RestoreFrameChain(JSContext
*cx
, JSStackFrame
*fp
)
5151 JS_ASSERT_NOT_ON_TRACE(cx
);
5152 JS_ASSERT(!cx
->hasfp());
5155 cx
->restoreSegment();
5156 cx
->resetCompartment();
5159 /************************************************************************/
5160 JS_PUBLIC_API(JSString
*)
5161 JS_NewStringCopyN(JSContext
*cx
, const char *s
, size_t n
)
5164 return js_NewStringCopyN(cx
, s
, n
);
5167 JS_PUBLIC_API(JSString
*)
5168 JS_NewStringCopyZ(JSContext
*cx
, const char *s
)
5176 return cx
->runtime
->emptyString
;
5178 js
= js_InflateString(cx
, s
, &n
);
5181 str
= js_NewString(cx
, js
, n
);
5187 JS_PUBLIC_API(JSBool
)
5188 JS_StringHasBeenInterned(JSString
*str
)
5190 return str
->isAtomized();
5193 JS_PUBLIC_API(JSString
*)
5194 JS_InternJSString(JSContext
*cx
, JSString
*str
)
5197 JSAtom
*atom
= js_AtomizeString(cx
, str
, 0);
5200 return ATOM_TO_STRING(atom
);
5203 JS_PUBLIC_API(JSString
*)
5204 JS_InternString(JSContext
*cx
, const char *s
)
5209 atom
= js_Atomize(cx
, s
, strlen(s
), ATOM_INTERNED
);
5212 return ATOM_TO_STRING(atom
);
5215 JS_PUBLIC_API(JSString
*)
5216 JS_NewUCString(JSContext
*cx
, jschar
*chars
, size_t length
)
5219 return js_NewString(cx
, chars
, length
);
5222 JS_PUBLIC_API(JSString
*)
5223 JS_NewUCStringCopyN(JSContext
*cx
, const jschar
*s
, size_t n
)
5226 return js_NewStringCopyN(cx
, s
, n
);
5229 JS_PUBLIC_API(JSString
*)
5230 JS_NewUCStringCopyZ(JSContext
*cx
, const jschar
*s
)
5234 return cx
->runtime
->emptyString
;
5235 return js_NewStringCopyZ(cx
, s
);
5238 JS_PUBLIC_API(JSString
*)
5239 JS_InternUCStringN(JSContext
*cx
, const jschar
*s
, size_t length
)
5244 atom
= js_AtomizeChars(cx
, s
, length
, ATOM_INTERNED
);
5247 return ATOM_TO_STRING(atom
);
5250 JS_PUBLIC_API(JSString
*)
5251 JS_InternUCString(JSContext
*cx
, const jschar
*s
)
5253 return JS_InternUCStringN(cx
, s
, js_strlen(s
));
5256 JS_PUBLIC_API(size_t)
5257 JS_GetStringLength(JSString
*str
)
5259 return str
->length();
5262 JS_PUBLIC_API(const jschar
*)
5263 JS_GetStringCharsZ(JSContext
*cx
, JSString
*str
)
5266 assertSameCompartment(cx
, str
);
5267 return str
->getCharsZ(cx
);
5270 JS_PUBLIC_API(const jschar
*)
5271 JS_GetStringCharsZAndLength(JSContext
*cx
, JSString
*str
, size_t *plength
)
5274 assertSameCompartment(cx
, str
);
5275 *plength
= str
->length();
5276 return str
->getCharsZ(cx
);
5279 JS_PUBLIC_API(const jschar
*)
5280 JS_GetStringCharsAndLength(JSContext
*cx
, JSString
*str
, size_t *plength
)
5283 assertSameCompartment(cx
, str
);
5284 *plength
= str
->length();
5285 return str
->getChars(cx
);
5288 JS_PUBLIC_API(const jschar
*)
5289 JS_GetInternedStringChars(JSString
*str
)
5291 JS_ASSERT(str
->isAtomized());
5292 return str
->flatChars();
5295 JS_PUBLIC_API(const jschar
*)
5296 JS_GetInternedStringCharsAndLength(JSString
*str
, size_t *plength
)
5298 JS_ASSERT(str
->isAtomized());
5299 *plength
= str
->flatLength();
5300 return str
->flatChars();
5303 extern JS_PUBLIC_API(JSFlatString
*)
5304 JS_FlattenString(JSContext
*cx
, JSString
*str
)
5307 assertSameCompartment(cx
, str
);
5308 return str
->getCharsZ(cx
) ? (JSFlatString
*)str
: NULL
;
5311 extern JS_PUBLIC_API(const jschar
*)
5312 JS_GetFlatStringChars(JSFlatString
*str
)
5314 return str
->chars();
5317 JS_PUBLIC_API(JSBool
)
5318 JS_CompareStrings(JSContext
*cx
, JSString
*str1
, JSString
*str2
, int32
*result
)
5320 return CompareStrings(cx
, str1
, str2
, result
);
5323 JS_PUBLIC_API(JSBool
)
5324 JS_StringEqualsAscii(JSContext
*cx
, JSString
*str
, const char *asciiBytes
, JSBool
*match
)
5326 JSLinearString
*linearStr
= str
->ensureLinear(cx
);
5329 *match
= StringEqualsAscii(linearStr
, asciiBytes
);
5333 JS_PUBLIC_API(JSBool
)
5334 JS_FlatStringEqualsAscii(JSFlatString
*str
, const char *asciiBytes
)
5336 return StringEqualsAscii(str
, asciiBytes
);
5339 JS_PUBLIC_API(size_t)
5340 JS_PutEscapedFlatString(char *buffer
, size_t size
, JSFlatString
*str
, char quote
)
5342 return PutEscapedString(buffer
, size
, str
, quote
);
5345 JS_PUBLIC_API(size_t)
5346 JS_PutEscapedString(JSContext
*cx
, char *buffer
, size_t size
, JSString
*str
, char quote
)
5348 JSLinearString
*linearStr
= str
->ensureLinear(cx
);
5351 return PutEscapedString(buffer
, size
, linearStr
, quote
);
5354 JS_PUBLIC_API(JSBool
)
5355 JS_FileEscapedString(FILE *fp
, JSString
*str
, char quote
)
5357 JSLinearString
*linearStr
= str
->ensureLinear(NULL
);
5358 return linearStr
&& FileEscapedString(fp
, linearStr
, quote
);
5361 JS_PUBLIC_API(JSString
*)
5362 JS_NewGrowableString(JSContext
*cx
, jschar
*chars
, size_t length
)
5365 return js_NewString(cx
, chars
, length
);
5368 JS_PUBLIC_API(JSString
*)
5369 JS_NewDependentString(JSContext
*cx
, JSString
*str
, size_t start
, size_t length
)
5372 return js_NewDependentString(cx
, str
, start
, length
);
5375 JS_PUBLIC_API(JSString
*)
5376 JS_ConcatStrings(JSContext
*cx
, JSString
*left
, JSString
*right
)
5379 return js_ConcatStrings(cx
, left
, right
);
5382 JS_PUBLIC_API(const jschar
*)
5383 JS_UndependString(JSContext
*cx
, JSString
*str
)
5386 return str
->getCharsZ(cx
);
5389 JS_PUBLIC_API(JSBool
)
5390 JS_MakeStringImmutable(JSContext
*cx
, JSString
*str
)
5393 return js_MakeStringImmutable(cx
, str
);
5396 JS_PUBLIC_API(JSBool
)
5397 JS_EncodeCharacters(JSContext
*cx
, const jschar
*src
, size_t srclen
, char *dst
, size_t *dstlenp
)
5401 n
= js_GetDeflatedStringLength(cx
, src
, srclen
);
5402 if (n
== (size_t)-1) {
5410 return js_DeflateStringToBuffer(cx
, src
, srclen
, dst
, dstlenp
);
5413 JS_PUBLIC_API(JSBool
)
5414 JS_DecodeBytes(JSContext
*cx
, const char *src
, size_t srclen
, jschar
*dst
, size_t *dstlenp
)
5416 return js_InflateStringToBuffer(cx
, src
, srclen
, dst
, dstlenp
);
5419 JS_PUBLIC_API(char *)
5420 JS_EncodeString(JSContext
*cx
, JSString
*str
)
5422 const jschar
*chars
= str
->getChars(cx
);
5425 return js_DeflateString(cx
, chars
, str
->length());
5428 JS_PUBLIC_API(size_t)
5429 JS_GetStringEncodingLength(JSContext
*cx
, JSString
*str
)
5431 const jschar
*chars
= str
->getChars(cx
);
5434 return js_GetDeflatedStringLength(cx
, chars
, str
->length());
5437 JS_PUBLIC_API(size_t)
5438 JS_EncodeStringToBuffer(JSString
*str
, char *buffer
, size_t length
)
5441 * FIXME bug 612141 - fix js_DeflateStringToBuffer interface so the result
5442 * would allow to distinguish between insufficient buffer and encoding
5445 size_t writtenLength
= length
;
5446 const jschar
*chars
= str
->getChars(NULL
);
5449 if (js_DeflateStringToBuffer(NULL
, chars
, str
->length(), buffer
, &writtenLength
)) {
5450 JS_ASSERT(writtenLength
<= length
);
5451 return writtenLength
;
5453 JS_ASSERT(writtenLength
<= length
);
5454 size_t necessaryLength
= js_GetDeflatedStringLength(NULL
, chars
, str
->length());
5455 if (necessaryLength
== size_t(-1))
5457 if (writtenLength
!= length
) {
5458 /* Make sure that the buffer contains only valid UTF-8 sequences. */
5459 JS_ASSERT(js_CStringsAreUTF8
);
5460 PodZero(buffer
+ writtenLength
, length
- writtenLength
);
5462 return necessaryLength
;
5465 JS_PUBLIC_API(JSBool
)
5466 JS_Stringify(JSContext
*cx
, jsval
*vp
, JSObject
*replacer
, jsval space
,
5467 JSONWriteCallback callback
, void *data
)
5470 assertSameCompartment(cx
, replacer
, space
);
5471 StringBuffer
sb(cx
);
5472 if (!js_Stringify(cx
, Valueify(vp
), replacer
, Valueify(space
), sb
))
5474 return callback(sb
.begin(), sb
.length(), data
);
5477 JS_PUBLIC_API(JSBool
)
5478 JS_TryJSON(JSContext
*cx
, jsval
*vp
)
5481 assertSameCompartment(cx
, *vp
);
5482 return js_TryJSON(cx
, Valueify(vp
));
5485 JS_PUBLIC_API(JSONParser
*)
5486 JS_BeginJSONParse(JSContext
*cx
, jsval
*vp
)
5489 return js_BeginJSONParse(cx
, Valueify(vp
));
5492 JS_PUBLIC_API(JSBool
)
5493 JS_ConsumeJSONText(JSContext
*cx
, JSONParser
*jp
, const jschar
*data
, uint32 len
)
5496 return js_ConsumeJSONText(cx
, jp
, data
, len
);
5499 JS_PUBLIC_API(JSBool
)
5500 JS_FinishJSONParse(JSContext
*cx
, JSONParser
*jp
, jsval reviver
)
5503 assertSameCompartment(cx
, reviver
);
5504 return js_FinishJSONParse(cx
, jp
, Valueify(reviver
));
5507 JS_PUBLIC_API(JSBool
)
5508 JS_ReadStructuredClone(JSContext
*cx
, const uint64
*buf
, size_t nbytes
,
5509 uint32 version
, jsval
*vp
,
5510 const JSStructuredCloneCallbacks
*optionalCallbacks
,
5513 if (version
> JS_STRUCTURED_CLONE_VERSION
) {
5514 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_BAD_CLONE_VERSION
);
5517 const JSStructuredCloneCallbacks
*callbacks
=
5520 cx
->runtime
->structuredCloneCallbacks
;
5521 return ReadStructuredClone(cx
, buf
, nbytes
, Valueify(vp
), callbacks
, closure
);
5524 JS_PUBLIC_API(JSBool
)
5525 JS_WriteStructuredClone(JSContext
*cx
, jsval v
, uint64
**bufp
, size_t *nbytesp
,
5526 const JSStructuredCloneCallbacks
*optionalCallbacks
,
5529 const JSStructuredCloneCallbacks
*callbacks
=
5532 cx
->runtime
->structuredCloneCallbacks
;
5533 return WriteStructuredClone(cx
, Valueify(v
), (uint64_t **) bufp
, nbytesp
,
5534 callbacks
, closure
);
5537 JS_PUBLIC_API(JSBool
)
5538 JS_StructuredClone(JSContext
*cx
, jsval v
, jsval
*vp
,
5539 ReadStructuredCloneOp optionalReadOp
,
5540 const JSStructuredCloneCallbacks
*optionalCallbacks
,
5543 const JSStructuredCloneCallbacks
*callbacks
=
5546 cx
->runtime
->structuredCloneCallbacks
;
5547 JSAutoStructuredCloneBuffer buf
;
5548 return buf
.write(cx
, v
, callbacks
, closure
) &&
5549 buf
.read(vp
, cx
, callbacks
, closure
);
5553 JS_SetStructuredCloneCallbacks(JSRuntime
*rt
, const JSStructuredCloneCallbacks
*callbacks
)
5555 rt
->structuredCloneCallbacks
= callbacks
;
5558 JS_PUBLIC_API(JSBool
)
5559 JS_ReadUint32Pair(JSStructuredCloneReader
*r
, uint32
*p1
, uint32
*p2
)
5561 return r
->input().readPair((uint32_t *) p1
, (uint32_t *) p2
);
5564 JS_PUBLIC_API(JSBool
)
5565 JS_ReadBytes(JSStructuredCloneReader
*r
, void *p
, size_t len
)
5567 return r
->input().readBytes(p
, len
);
5570 JS_PUBLIC_API(JSBool
)
5571 JS_WriteUint32Pair(JSStructuredCloneWriter
*w
, uint32 tag
, uint32 data
)
5573 return w
->output().writePair(tag
, data
);
5576 JS_PUBLIC_API(JSBool
)
5577 JS_WriteBytes(JSStructuredCloneWriter
*w
, const void *p
, size_t len
)
5579 return w
->output().writeBytes(p
, len
);
5583 * The following determines whether C Strings are to be treated as UTF-8
5584 * or ISO-8859-1. For correct operation, it must be set prior to the
5585 * first call to JS_NewRuntime.
5587 #ifndef JS_C_STRINGS_ARE_UTF8
5588 JSBool js_CStringsAreUTF8
= JS_FALSE
;
5591 JS_PUBLIC_API(JSBool
)
5592 JS_CStringsAreUTF8()
5594 return js_CStringsAreUTF8
;
5598 JS_SetCStringsAreUTF8()
5600 JS_ASSERT(!js_NewRuntimeWasCalled
);
5602 #ifndef JS_C_STRINGS_ARE_UTF8
5603 js_CStringsAreUTF8
= JS_TRUE
;
5607 /************************************************************************/
5610 JS_ReportError(JSContext
*cx
, const char *format
, ...)
5614 va_start(ap
, format
);
5615 js_ReportErrorVA(cx
, JSREPORT_ERROR
, format
, ap
);
5620 JS_ReportErrorNumber(JSContext
*cx
, JSErrorCallback errorCallback
,
5621 void *userRef
, const uintN errorNumber
, ...)
5625 va_start(ap
, errorNumber
);
5626 js_ReportErrorNumberVA(cx
, JSREPORT_ERROR
, errorCallback
, userRef
,
5627 errorNumber
, JS_TRUE
, ap
);
5632 JS_ReportErrorNumberUC(JSContext
*cx
, JSErrorCallback errorCallback
,
5633 void *userRef
, const uintN errorNumber
, ...)
5637 va_start(ap
, errorNumber
);
5638 js_ReportErrorNumberVA(cx
, JSREPORT_ERROR
, errorCallback
, userRef
,
5639 errorNumber
, JS_FALSE
, ap
);
5643 JS_PUBLIC_API(JSBool
)
5644 JS_ReportWarning(JSContext
*cx
, const char *format
, ...)
5649 va_start(ap
, format
);
5650 ok
= js_ReportErrorVA(cx
, JSREPORT_WARNING
, format
, ap
);
5655 JS_PUBLIC_API(JSBool
)
5656 JS_ReportErrorFlagsAndNumber(JSContext
*cx
, uintN flags
,
5657 JSErrorCallback errorCallback
, void *userRef
,
5658 const uintN errorNumber
, ...)
5663 va_start(ap
, errorNumber
);
5664 ok
= js_ReportErrorNumberVA(cx
, flags
, errorCallback
, userRef
,
5665 errorNumber
, JS_TRUE
, ap
);
5670 JS_PUBLIC_API(JSBool
)
5671 JS_ReportErrorFlagsAndNumberUC(JSContext
*cx
, uintN flags
,
5672 JSErrorCallback errorCallback
, void *userRef
,
5673 const uintN errorNumber
, ...)
5678 va_start(ap
, errorNumber
);
5679 ok
= js_ReportErrorNumberVA(cx
, flags
, errorCallback
, userRef
,
5680 errorNumber
, JS_FALSE
, ap
);
5686 JS_ReportOutOfMemory(JSContext
*cx
)
5688 js_ReportOutOfMemory(cx
);
5692 JS_ReportAllocationOverflow(JSContext
*cx
)
5694 js_ReportAllocationOverflow(cx
);
5697 JS_PUBLIC_API(JSErrorReporter
)
5698 JS_SetErrorReporter(JSContext
*cx
, JSErrorReporter er
)
5700 JSErrorReporter older
;
5702 older
= cx
->errorReporter
;
5703 cx
->errorReporter
= er
;
5707 /************************************************************************/
5710 * Regular Expressions.
5712 JS_PUBLIC_API(JSObject
*)
5713 JS_NewRegExpObject(JSContext
*cx
, JSObject
*obj
, char *bytes
, size_t length
, uintN flags
)
5716 jschar
*chars
= js_InflateString(cx
, bytes
, &length
);
5719 RegExpStatics
*res
= RegExpStatics::extractFrom(obj
);
5720 JSObject
*reobj
= RegExp::createObject(cx
, res
, chars
, length
, flags
);
5725 JS_PUBLIC_API(JSObject
*)
5726 JS_NewUCRegExpObject(JSContext
*cx
, JSObject
*obj
, jschar
*chars
, size_t length
, uintN flags
)
5729 RegExpStatics
*res
= RegExpStatics::extractFrom(obj
);
5730 return RegExp::createObject(cx
, res
, chars
, length
, flags
);
5734 JS_SetRegExpInput(JSContext
*cx
, JSObject
*obj
, JSString
*input
, JSBool multiline
)
5737 assertSameCompartment(cx
, input
);
5739 RegExpStatics::extractFrom(obj
)->reset(input
, !!multiline
);
5743 JS_ClearRegExpStatics(JSContext
*cx
, JSObject
*obj
)
5748 RegExpStatics::extractFrom(obj
)->clear();
5751 JS_PUBLIC_API(JSBool
)
5752 JS_ExecuteRegExp(JSContext
*cx
, JSObject
*obj
, JSObject
*reobj
, jschar
*chars
, size_t length
,
5753 size_t *indexp
, JSBool test
, jsval
*rval
)
5757 RegExp
*re
= RegExp::extractFrom(reobj
);
5761 JSString
*str
= js_NewStringCopyN(cx
, chars
, length
);
5765 return re
->execute(cx
, RegExpStatics::extractFrom(obj
), str
, indexp
, test
, Valueify(rval
));
5768 JS_PUBLIC_API(JSObject
*)
5769 JS_NewRegExpObjectNoStatics(JSContext
*cx
, char *bytes
, size_t length
, uintN flags
)
5772 jschar
*chars
= js_InflateString(cx
, bytes
, &length
);
5775 JSObject
*obj
= RegExp::createObjectNoStatics(cx
, chars
, length
, flags
);
5780 JS_PUBLIC_API(JSObject
*)
5781 JS_NewUCRegExpObjectNoStatics(JSContext
*cx
, jschar
*chars
, size_t length
, uintN flags
)
5784 return RegExp::createObjectNoStatics(cx
, chars
, length
, flags
);
5787 JS_PUBLIC_API(JSBool
)
5788 JS_ExecuteRegExpNoStatics(JSContext
*cx
, JSObject
*obj
, jschar
*chars
, size_t length
,
5789 size_t *indexp
, JSBool test
, jsval
*rval
)
5793 RegExp
*re
= RegExp::extractFrom(obj
);
5797 JSString
*str
= js_NewStringCopyN(cx
, chars
, length
);
5801 return re
->executeNoStatics(cx
, str
, indexp
, test
, Valueify(rval
));
5804 /************************************************************************/
5807 JS_SetLocaleCallbacks(JSContext
*cx
, JSLocaleCallbacks
*callbacks
)
5809 cx
->localeCallbacks
= callbacks
;
5812 JS_PUBLIC_API(JSLocaleCallbacks
*)
5813 JS_GetLocaleCallbacks(JSContext
*cx
)
5815 return cx
->localeCallbacks
;
5818 /************************************************************************/
5820 JS_PUBLIC_API(JSBool
)
5821 JS_IsExceptionPending(JSContext
*cx
)
5823 return (JSBool
) cx
->isExceptionPending();
5826 JS_PUBLIC_API(JSBool
)
5827 JS_GetPendingException(JSContext
*cx
, jsval
*vp
)
5830 if (!cx
->isExceptionPending())
5832 Valueify(*vp
) = cx
->getPendingException();
5833 assertSameCompartment(cx
, *vp
);
5838 JS_SetPendingException(JSContext
*cx
, jsval v
)
5841 assertSameCompartment(cx
, v
);
5842 cx
->setPendingException(Valueify(v
));
5846 JS_ClearPendingException(JSContext
*cx
)
5848 cx
->clearPendingException();
5851 JS_PUBLIC_API(JSBool
)
5852 JS_ReportPendingException(JSContext
*cx
)
5860 * Set cx->generatingError to suppress the standard error-to-exception
5861 * conversion done by all {js,JS}_Report* functions except for OOM. The
5862 * cx->generatingError flag was added to suppress recursive divergence
5863 * under js_ErrorToException, but it serves for our purposes here too.
5865 save
= cx
->generatingError
;
5866 cx
->generatingError
= JS_TRUE
;
5867 ok
= js_ReportUncaughtException(cx
);
5868 cx
->generatingError
= save
;
5872 struct JSExceptionState
{
5877 JS_PUBLIC_API(JSExceptionState
*)
5878 JS_SaveExceptionState(JSContext
*cx
)
5880 JSExceptionState
*state
;
5883 state
= (JSExceptionState
*) cx
->malloc(sizeof(JSExceptionState
));
5885 state
->throwing
= JS_GetPendingException(cx
, &state
->exception
);
5886 if (state
->throwing
&& JSVAL_IS_GCTHING(state
->exception
))
5887 js_AddRoot(cx
, Valueify(&state
->exception
), "JSExceptionState.exception");
5893 JS_RestoreExceptionState(JSContext
*cx
, JSExceptionState
*state
)
5897 if (state
->throwing
)
5898 JS_SetPendingException(cx
, state
->exception
);
5900 JS_ClearPendingException(cx
);
5901 JS_DropExceptionState(cx
, state
);
5906 JS_DropExceptionState(JSContext
*cx
, JSExceptionState
*state
)
5910 if (state
->throwing
&& JSVAL_IS_GCTHING(state
->exception
)) {
5911 assertSameCompartment(cx
, state
->exception
);
5912 JS_RemoveValueRoot(cx
, &state
->exception
);
5918 JS_PUBLIC_API(JSErrorReport
*)
5919 JS_ErrorFromException(JSContext
*cx
, jsval v
)
5922 assertSameCompartment(cx
, v
);
5923 return js_ErrorFromException(cx
, v
);
5926 JS_PUBLIC_API(JSBool
)
5927 JS_ThrowReportedError(JSContext
*cx
, const char *message
,
5928 JSErrorReport
*reportp
)
5930 return JS_IsRunning(cx
) &&
5931 js_ErrorToException(cx
, message
, reportp
, NULL
, NULL
);
5934 JS_PUBLIC_API(JSBool
)
5935 JS_ThrowStopIteration(JSContext
*cx
)
5937 return js_ThrowStopIteration(cx
);
5941 * Get the owning thread id of a context. Returns 0 if the context is not
5942 * owned by any thread.
5944 JS_PUBLIC_API(jsword
)
5945 JS_GetContextThread(JSContext
*cx
)
5947 #ifdef JS_THREADSAFE
5948 return reinterpret_cast<jsword
>(JS_THREAD_ID(cx
));
5955 * Set the current thread as the owning thread of a context. Returns the
5956 * old owning thread id, or -1 if the operation failed.
5958 JS_PUBLIC_API(jsword
)
5959 JS_SetContextThread(JSContext
*cx
)
5961 #ifdef JS_THREADSAFE
5962 JS_ASSERT(!cx
->outstandingRequests
);
5964 JS_ASSERT(CURRENT_THREAD_IS_ME(cx
->thread
));
5965 return reinterpret_cast<jsword
>(cx
->thread
->id
);
5968 if (!js_InitContextThread(cx
)) {
5969 js_ReportOutOfMemory(cx
);
5973 /* Here the GC lock is still held after js_InitContextThread took it. */
5974 JS_UNLOCK_GC(cx
->runtime
);
5979 JS_PUBLIC_API(jsword
)
5980 JS_ClearContextThread(JSContext
*cx
)
5982 #ifdef JS_THREADSAFE
5984 * cx must have exited all requests it entered and, if cx is associated
5985 * with a thread, this must be called only from that thread. If not, this
5986 * is a harmless no-op.
5988 JS_ASSERT(cx
->outstandingRequests
== 0);
5989 JSThread
*t
= cx
->thread
;
5992 JS_ASSERT(CURRENT_THREAD_IS_ME(t
));
5995 * We must not race with a GC that accesses cx->thread for all threads,
5998 JSRuntime
*rt
= cx
->runtime
;
5999 AutoLockGC
lock(rt
);
6001 js_ClearContextThread(cx
);
6002 JS_ASSERT_IF(JS_CLIST_IS_EMPTY(&t
->contextList
), !t
->data
.requestDepth
);
6005 * We can access t->id as long as the GC lock is held and we cannot race
6006 * with the GC that may delete t.
6008 return reinterpret_cast<jsword
>(t
->id
);
6014 #ifdef MOZ_TRACE_JSCALLS
6016 JS_SetFunctionCallback(JSContext
*cx
, JSFunctionCallback fcb
)
6018 cx
->functionCallback
= fcb
;
6021 JS_PUBLIC_API(JSFunctionCallback
)
6022 JS_GetFunctionCallback(JSContext
*cx
)
6024 return cx
->functionCallback
;
6030 JS_SetGCZeal(JSContext
*cx
, uint8 zeal
)
6032 cx
->runtime
->gcZeal
= zeal
;
6036 /************************************************************************/
6038 #if !defined(STATIC_EXPORTABLE_JS_API) && !defined(STATIC_JS_API) && defined(XP_WIN) && !defined (WINCE)
6043 * Initialization routine for the JS DLL.
6045 BOOL WINAPI
DllMain (HINSTANCE hDLL
, DWORD dwReason
, LPVOID lpReserved
)