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 ***** */
50 #include "jsarena.h" /* Added by JSIFY */
51 #include "jsutil.h" /* Added by JSIFY */
59 #include "jsbuiltins.h"
61 #include "jsversion.h"
85 #include "jsstaticcheck.h"
87 #include "jswrapper.h"
88 #include "jstypedarray.h"
90 #include "jsatominlines.h"
91 #include "jscntxtinlines.h"
92 #include "jsinterpinlines.h"
93 #include "jsobjinlines.h"
94 #include "jsscopeinlines.h"
95 #include "jscntxtinlines.h"
96 #include "jsregexpinlines.h"
97 #include "assembler/wtf/Platform.h"
100 #include "assembler/jit/ExecutableAllocator.h"
101 #include "methodjit/Logging.h"
104 #if JS_HAS_XML_SUPPORT
112 JSContext
* const cx
;
113 JSVersion oldVersion
;
114 bool oldVersionWasOverride
;
118 explicit AutoVersionAPI(JSContext
*cx
, JSVersion newVersion
)
119 : cx(cx
), oldVersion(cx
->findVersion()), oldVersionWasOverride(cx
->isVersionOverridden()),
120 oldOptions(cx
->options
) {
121 JS_ASSERT(!VersionExtractFlags(newVersion
) ||
122 VersionExtractFlags(newVersion
) == VersionFlags::HAS_XML
);
123 cx
->options
= VersionHasXML(newVersion
)
124 ? (cx
->options
| JSOPTION_XML
)
125 : (cx
->options
& ~JSOPTION_XML
);
126 cx
->maybeOverrideVersion(newVersion
);
127 SyncOptionsToVersion(cx
);
131 cx
->options
= oldOptions
;
132 if (oldVersionWasOverride
) {
133 JS_ALWAYS_TRUE(cx
->maybeOverrideVersion(oldVersion
));
135 cx
->clearVersionOverride();
136 cx
->setDefaultVersion(oldVersion
);
138 JS_ASSERT(cx
->findVersion() == oldVersion
);
142 #ifdef HAVE_VA_LIST_AS_ARRAY
143 #define JS_ADDRESSOF_VA_LIST(ap) ((va_list *)(ap))
145 #define JS_ADDRESSOF_VA_LIST(ap) (&(ap))
148 #ifdef JS_USE_JSVAL_JSID_STRUCT_TYPES
149 JS_PUBLIC_DATA(jsid
) JS_DEFAULT_XML_NAMESPACE_ID
= { size_t(JSID_TYPE_DEFAULT_XML_NAMESPACE
) };
150 JS_PUBLIC_DATA(jsid
) JSID_VOID
= { size_t(JSID_TYPE_VOID
) };
151 JS_PUBLIC_DATA(jsid
) JSID_EMPTY
= { size_t(JSID_TYPE_OBJECT
) };
154 #ifdef JS_USE_JSVAL_JSID_STRUCT_TYPES
155 JS_PUBLIC_DATA(jsval
) JSVAL_NULL
= { BUILD_JSVAL(JSVAL_TAG_NULL
, 0) };
156 JS_PUBLIC_DATA(jsval
) JSVAL_ZERO
= { BUILD_JSVAL(JSVAL_TAG_INT32
, 0) };
157 JS_PUBLIC_DATA(jsval
) JSVAL_ONE
= { BUILD_JSVAL(JSVAL_TAG_INT32
, 1) };
158 JS_PUBLIC_DATA(jsval
) JSVAL_FALSE
= { BUILD_JSVAL(JSVAL_TAG_BOOLEAN
, JS_FALSE
) };
159 JS_PUBLIC_DATA(jsval
) JSVAL_TRUE
= { BUILD_JSVAL(JSVAL_TAG_BOOLEAN
, JS_TRUE
) };
160 JS_PUBLIC_DATA(jsval
) JSVAL_VOID
= { BUILD_JSVAL(JSVAL_TAG_UNDEFINED
, 0) };
163 /* Make sure that jschar is two bytes unsigned integer */
164 JS_STATIC_ASSERT((jschar
)-1 > 0);
165 JS_STATIC_ASSERT(sizeof(jschar
) == 2);
174 JS_GetNaNValue(JSContext
*cx
)
176 return Jsvalify(cx
->runtime
->NaNValue
);
180 JS_GetNegativeInfinityValue(JSContext
*cx
)
182 return Jsvalify(cx
->runtime
->negativeInfinityValue
);
186 JS_GetPositiveInfinityValue(JSContext
*cx
)
188 return Jsvalify(cx
->runtime
->positiveInfinityValue
);
192 JS_GetEmptyStringValue(JSContext
*cx
)
194 return STRING_TO_JSVAL(cx
->runtime
->emptyString
);
198 TryArgumentFormatter(JSContext
*cx
, const char **formatp
, JSBool fromJS
, jsval
**vpp
, va_list *app
)
201 JSArgumentFormatMap
*map
;
204 for (map
= cx
->argumentFormatMap
; map
; map
= map
->next
) {
205 if (!strncmp(format
, map
->format
, map
->length
)) {
206 *formatp
= format
+ map
->length
;
207 return map
->formatter(cx
, format
, fromJS
, vpp
, app
);
210 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_BAD_CHAR
, format
);
214 JS_PUBLIC_API(JSBool
)
215 JS_ConvertArguments(JSContext
*cx
, uintN argc
, jsval
*argv
, const char *format
, ...)
220 va_start(ap
, format
);
221 ok
= JS_ConvertArgumentsVA(cx
, argc
, argv
, format
, ap
);
226 JS_PUBLIC_API(JSBool
)
227 JS_ConvertArgumentsVA(JSContext
*cx
, uintN argc
, jsval
*argv
, const char *format
, va_list ap
)
238 assertSameCompartment(cx
, JSValueArray(argv
- 2, argc
+ 2));
241 while ((c
= *format
++) != '\0') {
248 if (sp
== argv
+ argc
) {
250 fun
= js_ValueToFunction(cx
, Valueify(&argv
[-2]), 0);
253 JS_snprintf(numBuf
, sizeof numBuf
, "%u", argc
);
254 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
,
255 JSMSG_MORE_ARGS_NEEDED
,
256 JS_GetFunctionName(fun
), numBuf
,
257 (argc
== 1) ? "" : "s");
265 *va_arg(ap
, JSBool
*) = js_ValueToBoolean(Valueify(*sp
));
268 if (!JS_ValueToUint16(cx
, *sp
, va_arg(ap
, uint16
*)))
272 if (!JS_ValueToECMAInt32(cx
, *sp
, va_arg(ap
, int32
*)))
276 if (!JS_ValueToECMAUint32(cx
, *sp
, va_arg(ap
, uint32
*)))
280 if (!JS_ValueToInt32(cx
, *sp
, va_arg(ap
, int32
*)))
284 if (!JS_ValueToNumber(cx
, *sp
, va_arg(ap
, jsdouble
*)))
288 if (!JS_ValueToNumber(cx
, *sp
, &d
))
290 *va_arg(ap
, jsdouble
*) = js_DoubleToInteger(d
);
295 str
= js_ValueToString(cx
, Valueify(*sp
));
298 *sp
= STRING_TO_JSVAL(str
);
300 const char *bytes
= js_GetStringBytes(cx
, str
);
303 *va_arg(ap
, const char **) = bytes
;
304 } else if (c
== 'W') {
305 const jschar
*chars
= js_GetStringChars(cx
, str
);
308 *va_arg(ap
, const jschar
**) = chars
;
310 *va_arg(ap
, JSString
**) = str
;
314 if (!js_ValueToObjectOrNull(cx
, Valueify(*sp
), &obj
))
316 *sp
= OBJECT_TO_JSVAL(obj
);
317 *va_arg(ap
, JSObject
**) = obj
;
320 obj
= js_ValueToFunctionObject(cx
, Valueify(sp
), 0);
323 *sp
= OBJECT_TO_JSVAL(obj
);
324 *va_arg(ap
, JSFunction
**) = GET_FUNCTION_PRIVATE(cx
, obj
);
327 *va_arg(ap
, jsval
*) = *sp
;
333 if (!TryArgumentFormatter(cx
, &format
, JS_TRUE
, &sp
,
334 JS_ADDRESSOF_VA_LIST(ap
))) {
337 /* NB: the formatter already updated sp, so we continue here. */
345 JS_PUBLIC_API(JSBool
)
346 JS_AddArgumentFormatter(JSContext
*cx
, const char *format
, JSArgumentFormatter formatter
)
349 JSArgumentFormatMap
**mpp
, *map
;
351 length
= strlen(format
);
352 mpp
= &cx
->argumentFormatMap
;
353 while ((map
= *mpp
) != NULL
) {
354 /* Insert before any shorter string to match before prefixes. */
355 if (map
->length
< length
)
357 if (map
->length
== length
&& !strcmp(map
->format
, format
))
361 map
= (JSArgumentFormatMap
*) cx
->malloc(sizeof *map
);
364 map
->format
= format
;
365 map
->length
= length
;
369 map
->formatter
= formatter
;
374 JS_RemoveArgumentFormatter(JSContext
*cx
, const char *format
)
377 JSArgumentFormatMap
**mpp
, *map
;
379 length
= strlen(format
);
380 mpp
= &cx
->argumentFormatMap
;
381 while ((map
= *mpp
) != NULL
) {
382 if (map
->length
== length
&& !strcmp(map
->format
, format
)) {
391 JS_PUBLIC_API(JSBool
)
392 JS_ConvertValue(JSContext
*cx
, jsval v
, JSType type
, jsval
*vp
)
400 assertSameCompartment(cx
, v
);
407 ok
= js_ValueToObjectOrNull(cx
, Valueify(v
), &obj
);
409 *vp
= OBJECT_TO_JSVAL(obj
);
411 case JSTYPE_FUNCTION
:
413 obj
= js_ValueToFunctionObject(cx
, Valueify(vp
), JSV2F_SEARCH_STACK
);
417 str
= js_ValueToString(cx
, Valueify(v
));
420 *vp
= STRING_TO_JSVAL(str
);
423 ok
= JS_ValueToNumber(cx
, v
, &d
);
425 *vp
= DOUBLE_TO_JSVAL(d
);
428 *vp
= BOOLEAN_TO_JSVAL(js_ValueToBoolean(Valueify(v
)));
432 JS_snprintf(numBuf
, sizeof numBuf
, "%d", (int)type
);
433 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_BAD_TYPE
, numBuf
);
441 JS_PUBLIC_API(JSBool
)
442 JS_ValueToObject(JSContext
*cx
, jsval v
, JSObject
**objp
)
445 assertSameCompartment(cx
, v
);
446 return js_ValueToObjectOrNull(cx
, Valueify(v
), objp
);
449 JS_PUBLIC_API(JSFunction
*)
450 JS_ValueToFunction(JSContext
*cx
, jsval v
)
453 assertSameCompartment(cx
, v
);
454 return js_ValueToFunction(cx
, Valueify(&v
), JSV2F_SEARCH_STACK
);
457 JS_PUBLIC_API(JSFunction
*)
458 JS_ValueToConstructor(JSContext
*cx
, jsval v
)
461 assertSameCompartment(cx
, v
);
462 return js_ValueToFunction(cx
, Valueify(&v
), JSV2F_SEARCH_STACK
);
465 JS_PUBLIC_API(JSString
*)
466 JS_ValueToString(JSContext
*cx
, jsval v
)
469 assertSameCompartment(cx
, v
);
470 return js_ValueToString(cx
, Valueify(v
));
473 JS_PUBLIC_API(JSString
*)
474 JS_ValueToSource(JSContext
*cx
, jsval v
)
477 assertSameCompartment(cx
, v
);
478 return js_ValueToSource(cx
, Valueify(v
));
481 JS_PUBLIC_API(JSBool
)
482 JS_ValueToNumber(JSContext
*cx
, jsval v
, jsdouble
*dp
)
485 assertSameCompartment(cx
, v
);
487 AutoValueRooter
tvr(cx
, Valueify(v
));
488 return ValueToNumber(cx
, tvr
.value(), dp
);
491 JS_PUBLIC_API(JSBool
)
492 JS_DoubleIsInt32(jsdouble d
, jsint
*ip
)
494 return JSDOUBLE_IS_INT32(d
, (int32_t *)ip
);
497 JS_PUBLIC_API(JSBool
)
498 JS_ValueToECMAInt32(JSContext
*cx
, jsval v
, int32
*ip
)
501 assertSameCompartment(cx
, v
);
503 AutoValueRooter
tvr(cx
, Valueify(v
));
504 return ValueToECMAInt32(cx
, tvr
.value(), (int32_t *)ip
);
507 JS_PUBLIC_API(JSBool
)
508 JS_ValueToECMAUint32(JSContext
*cx
, jsval v
, uint32
*ip
)
511 assertSameCompartment(cx
, v
);
513 AutoValueRooter
tvr(cx
, Valueify(v
));
514 return ValueToECMAUint32(cx
, tvr
.value(), (uint32_t *)ip
);
517 JS_PUBLIC_API(JSBool
)
518 JS_ValueToInt32(JSContext
*cx
, jsval v
, int32
*ip
)
521 assertSameCompartment(cx
, v
);
523 AutoValueRooter
tvr(cx
, Valueify(v
));
524 return ValueToInt32(cx
, tvr
.value(), (int32_t *)ip
);
527 JS_PUBLIC_API(JSBool
)
528 JS_ValueToUint16(JSContext
*cx
, jsval v
, uint16
*ip
)
531 assertSameCompartment(cx
, v
);
533 AutoValueRooter
tvr(cx
, Valueify(v
));
534 return ValueToUint16(cx
, tvr
.value(), (uint16_t *)ip
);
537 JS_PUBLIC_API(JSBool
)
538 JS_ValueToBoolean(JSContext
*cx
, jsval v
, JSBool
*bp
)
541 assertSameCompartment(cx
, v
);
542 *bp
= js_ValueToBoolean(Valueify(v
));
546 JS_PUBLIC_API(JSType
)
547 JS_TypeOfValue(JSContext
*cx
, jsval v
)
550 assertSameCompartment(cx
, v
);
551 return TypeOfValue(cx
, Valueify(v
));
554 JS_PUBLIC_API(const char *)
555 JS_GetTypeName(JSContext
*cx
, JSType type
)
557 if ((uintN
)type
>= (uintN
)JSTYPE_LIMIT
)
559 return JS_TYPE_STR(type
);
562 JS_PUBLIC_API(JSBool
)
563 JS_StrictlyEqual(JSContext
*cx
, jsval v1
, jsval v2
)
565 assertSameCompartment(cx
, v1
, v2
);
566 return StrictlyEqual(cx
, Valueify(v1
), Valueify(v2
));
569 JS_PUBLIC_API(JSBool
)
570 JS_SameValue(JSContext
*cx
, jsval v1
, jsval v2
)
572 assertSameCompartment(cx
, v1
, v2
);
573 return SameValue(Valueify(v1
), Valueify(v2
), cx
);
576 /************************************************************************/
579 * Has a new runtime ever been created? This flag is used to detect unsafe
580 * changes to js_CStringsAreUTF8 after a runtime has been created, and to
581 * ensure that "first checks" on runtime creation are run only once.
584 static JSBool js_NewRuntimeWasCalled
= JS_FALSE
;
587 JSRuntime::JSRuntime()
588 : gcChunkAllocator(&defaultGCChunkAllocator
)
590 /* Initialize infallibly first, so we can goto bad and JS_DestroyRuntime. */
591 JS_INIT_CLIST(&contextList
);
592 JS_INIT_CLIST(&trapList
);
593 JS_INIT_CLIST(&watchPointList
);
597 JSRuntime::init(uint32 maxbytes
)
599 #ifdef JS_METHODJIT_SPEW
604 functionMeterFilename
= getenv("JS_FUNCTION_STATFILE");
605 if (functionMeterFilename
) {
606 if (!methodReadBarrierCountMap
.init())
608 if (!unjoinedFunctionCountMap
.init())
611 propTreeStatFilename
= getenv("JS_PROPTREE_STATFILE");
612 propTreeDumpFilename
= getenv("JS_PROPTREE_DUMPFILE");
613 if (meterEmptyShapes()) {
614 if (!emptyShapes
.init())
619 if (!(defaultCompartment
= new JSCompartment(this)) ||
620 !defaultCompartment
->init() ||
621 !compartments
.append(defaultCompartment
)) {
625 if (!js_InitGC(this, maxbytes
) || !js_InitAtomState(this))
629 regExpAllocator
= new JSC::ExecutableAllocator();
630 if (!regExpAllocator
)
634 deflatedStringCache
= new js::DeflatedStringCache();
635 if (!deflatedStringCache
|| !deflatedStringCache
->init())
638 wrapObjectCallback
= js::TransparentObjectWrapper
;
641 /* this is asymmetric with JS_ShutDown: */
642 if (!js_SetupLocks(8, 16))
644 rtLock
= JS_NEW_LOCK();
647 stateChange
= JS_NEW_CONDVAR(gcLock
);
650 titleSharingDone
= JS_NEW_CONDVAR(gcLock
);
651 if (!titleSharingDone
)
653 titleSharingTodo
= NO_TITLE_SHARING_TODO
;
654 debuggerLock
= JS_NEW_LOCK();
658 return propertyTree
.init() && js_InitThreads(this);
661 JSRuntime::~JSRuntime()
664 /* Don't hurt everyone in leaky ol' Mozilla with a fatal JS_ASSERT! */
665 if (!JS_CLIST_IS_EMPTY(&contextList
)) {
666 JSContext
*cx
, *iter
= NULL
;
668 while ((cx
= js_ContextIterator(this, JS_TRUE
, &iter
)) != NULL
) {
670 "JS API usage error: found live context at %p\n",
675 "JS API usage error: %u context%s left in runtime upon JS_DestroyRuntime.\n",
676 cxcount
, (cxcount
== 1) ? "" : "s");
680 js_FinishThreads(this);
681 js_FreeRuntimeScriptState(this);
682 js_FinishAtomState(this);
685 * Finish the deflated string cache after the last GC and after
686 * calling js_FinishAtomState, which finalizes strings.
688 delete deflatedStringCache
;
690 delete regExpAllocator
;
695 JS_DESTROY_LOCK(gcLock
);
697 JS_DESTROY_CONDVAR(gcDone
);
699 JS_DESTROY_CONDVAR(requestDone
);
701 JS_DESTROY_LOCK(rtLock
);
703 JS_DESTROY_CONDVAR(stateChange
);
704 if (titleSharingDone
)
705 JS_DESTROY_CONDVAR(titleSharingDone
);
707 JS_DESTROY_LOCK(debuggerLock
);
709 propertyTree
.finish();
710 /* Delete all remaining Compartments. Ideally only the defaultCompartment should be left. */
711 for (JSCompartment
**c
= compartments
.begin(); c
!= compartments
.end(); ++c
)
713 compartments
.clear();
716 JS_PUBLIC_API(JSRuntime
*)
717 JS_NewRuntime(uint32 maxbytes
)
720 if (!js_NewRuntimeWasCalled
) {
722 * This code asserts that the numbers associated with the error names
723 * in jsmsg.def are monotonically increasing. It uses values for the
724 * error names enumerated in jscntxt.c. It's not a compile-time check
725 * but it's better than nothing.
728 #define MSG_DEF(name, number, count, exception, format) \
729 JS_ASSERT(name == errorNumber++);
733 #define MSG_DEF(name, number, count, exception, format) \
735 uintN numfmtspecs = 0; \
737 for (fmt = format; *fmt != '\0'; fmt++) { \
738 if (*fmt == '{' && isdigit(fmt[1])) \
741 JS_ASSERT(count == numfmtspecs); \
746 js_NewRuntimeWasCalled
= JS_TRUE
;
750 void *mem
= js_calloc(sizeof(JSRuntime
));
754 JSRuntime
*rt
= new (mem
) JSRuntime();
755 if (!rt
->init(maxbytes
)) {
756 JS_DestroyRuntime(rt
);
764 JS_CommenceRuntimeShutDown(JSRuntime
*rt
)
766 rt
->gcFlushCodeCaches
= true;
770 JS_DestroyRuntime(JSRuntime
*rt
)
778 namespace reprmeter
{
779 extern void js_DumpReprMeter();
791 extern void js_DumpOpMeters();
796 reprmeter::js_DumpReprMeter();
805 JS_PUBLIC_API(void *)
806 JS_GetRuntimePrivate(JSRuntime
*rt
)
812 JS_SetRuntimePrivate(JSRuntime
*rt
, void *data
)
819 StartRequest(JSContext
*cx
)
821 JSThread
*t
= cx
->thread
;
822 JS_ASSERT(CURRENT_THREAD_IS_ME(t
));
824 if (t
->data
.requestDepth
) {
825 t
->data
.requestDepth
++;
827 JSRuntime
*rt
= cx
->runtime
;
830 /* Wait until the GC is finished. */
831 if (rt
->gcThread
!= cx
->thread
) {
833 JS_AWAIT_GC_DONE(rt
);
836 /* Indicate that a request is running. */
838 t
->data
.requestDepth
= 1;
841 * Adjust rt->interruptCounter to reflect any interrupts added while the
842 * thread was suspended.
844 if (t
->data
.interruptFlags
)
845 JS_ATOMIC_INCREMENT(&rt
->interruptCounter
);
847 if (rt
->requestCount
== 1 && rt
->activityCallback
)
848 rt
->activityCallback(rt
->activityCallbackArg
, true);
853 StopRequest(JSContext
*cx
)
855 JSThread
*t
= cx
->thread
;
856 JS_ASSERT(CURRENT_THREAD_IS_ME(t
));
857 JS_ASSERT(t
->data
.requestDepth
!= 0);
858 if (t
->data
.requestDepth
!= 1) {
859 t
->data
.requestDepth
--;
861 LeaveTrace(cx
); /* for GC safety */
863 t
->data
.conservativeGC
.updateForRequestEnd(t
->suspendCount
);
865 /* Lock before clearing to interlock with ClaimScope, in jslock.c. */
866 JSRuntime
*rt
= cx
->runtime
;
869 t
->data
.requestDepth
= 0;
872 * Adjust rt->interruptCounter to reflect any interrupts added while the
873 * thread still had active requests.
875 if (t
->data
.interruptFlags
)
876 JS_ATOMIC_DECREMENT(&rt
->interruptCounter
);
878 js_ShareWaitingTitles(cx
);
880 /* Give the GC a chance to run if this was the last request running. */
881 JS_ASSERT(rt
->requestCount
> 0);
883 if (rt
->requestCount
== 0) {
884 JS_NOTIFY_REQUEST_DONE(rt
);
885 if (rt
->activityCallback
)
886 rt
->activityCallback(rt
->activityCallbackArg
, false);
890 #endif /* JS_THREADSAFE */
893 JS_BeginRequest(JSContext
*cx
)
896 cx
->outstandingRequests
++;
902 JS_EndRequest(JSContext
*cx
)
905 JS_ASSERT(cx
->outstandingRequests
!= 0);
906 cx
->outstandingRequests
--;
911 /* Yield to pending GC operations, regardless of request depth */
913 JS_YieldRequest(JSContext
*cx
)
917 JS_ResumeRequest(cx
, JS_SuspendRequest(cx
));
921 JS_PUBLIC_API(jsrefcount
)
922 JS_SuspendRequest(JSContext
*cx
)
925 JSThread
*t
= cx
->thread
;
926 JS_ASSERT(CURRENT_THREAD_IS_ME(t
));
928 jsrefcount saveDepth
= t
->data
.requestDepth
;
933 t
->data
.requestDepth
= 1;
942 JS_ResumeRequest(JSContext
*cx
, jsrefcount saveDepth
)
945 JSThread
*t
= cx
->thread
;
946 JS_ASSERT(CURRENT_THREAD_IS_ME(t
));
949 JS_ASSERT(saveDepth
>= 1);
950 JS_ASSERT(!t
->data
.requestDepth
);
951 JS_ASSERT(t
->suspendCount
);
953 t
->data
.requestDepth
= saveDepth
;
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());
1035 CheckOptionVersionSync(JSContext
*cx
)
1038 uint32 options
= cx
->options
;
1039 JSVersion version
= cx
->findVersion();
1040 JS_ASSERT(OptionsHasXML(options
) == VersionHasXML(version
));
1041 JS_ASSERT(OptionsHasAnonFunFix(options
) == VersionHasAnonFunFix(version
));
1045 JS_PUBLIC_API(JSVersion
)
1046 JS_SetVersion(JSContext
*cx
, JSVersion newVersion
)
1048 JS_ASSERT(VersionIsKnown(newVersion
));
1049 JS_ASSERT(!VersionHasFlags(newVersion
));
1050 JSVersion newVersionNumber
= newVersion
;
1052 JSVersion oldVersion
= cx
->findVersion();
1053 JSVersion oldVersionNumber
= VersionNumber(oldVersion
);
1054 if (oldVersionNumber
== newVersionNumber
)
1055 return oldVersionNumber
; /* No override actually occurs! */
1057 /* We no longer support 1.4 or below. */
1058 if (newVersionNumber
!= JSVERSION_DEFAULT
&& newVersionNumber
<= JSVERSION_1_4
)
1059 return oldVersionNumber
;
1061 VersionCloneFlags(oldVersion
, &newVersion
);
1062 cx
->maybeOverrideVersion(newVersion
);
1063 CheckOptionVersionSync(cx
);
1064 return oldVersionNumber
;
1067 static struct v2smap
{
1071 {JSVERSION_1_0
, "1.0"},
1072 {JSVERSION_1_1
, "1.1"},
1073 {JSVERSION_1_2
, "1.2"},
1074 {JSVERSION_1_3
, "1.3"},
1075 {JSVERSION_1_4
, "1.4"},
1076 {JSVERSION_ECMA_3
, "ECMAv3"},
1077 {JSVERSION_1_5
, "1.5"},
1078 {JSVERSION_1_6
, "1.6"},
1079 {JSVERSION_1_7
, "1.7"},
1080 {JSVERSION_1_8
, "1.8"},
1081 {JSVERSION_ECMA_5
, "ECMAv5"},
1082 {JSVERSION_DEFAULT
, js_default_str
},
1083 {JSVERSION_UNKNOWN
, NULL
}, /* must be last, NULL is sentinel */
1086 JS_PUBLIC_API(const char *)
1087 JS_VersionToString(JSVersion version
)
1091 for (i
= 0; v2smap
[i
].string
; i
++)
1092 if (v2smap
[i
].version
== version
)
1093 return v2smap
[i
].string
;
1097 JS_PUBLIC_API(JSVersion
)
1098 JS_StringToVersion(const char *string
)
1102 for (i
= 0; v2smap
[i
].string
; i
++)
1103 if (strcmp(v2smap
[i
].string
, string
) == 0)
1104 return v2smap
[i
].version
;
1105 return JSVERSION_UNKNOWN
;
1108 JS_PUBLIC_API(uint32
)
1109 JS_GetOptions(JSContext
*cx
)
1112 * Can't check option/version synchronization here.
1113 * We may have been synchronized with a script version that was formerly on
1114 * the stack, but has now been popped.
1119 JS_PUBLIC_API(uint32
)
1120 JS_SetOptions(JSContext
*cx
, uint32 options
)
1122 AutoLockGC
lock(cx
->runtime
);
1123 uint32 oldopts
= cx
->options
;
1124 cx
->options
= options
;
1125 SyncOptionsToVersion(cx
);
1126 cx
->updateJITEnabled();
1127 CheckOptionVersionSync(cx
);
1131 JS_PUBLIC_API(uint32
)
1132 JS_ToggleOptions(JSContext
*cx
, uint32 options
)
1134 AutoLockGC
lock(cx
->runtime
);
1135 CheckOptionVersionSync(cx
);
1136 uint32 oldopts
= cx
->options
;
1137 cx
->options
^= options
;
1138 (void) SyncOptionsToVersion(cx
);
1139 cx
->updateJITEnabled();
1140 CheckOptionVersionSync(cx
);
1144 JS_PUBLIC_API(const char *)
1145 JS_GetImplementationVersion(void)
1147 return "JavaScript-C 1.8.0 pre-release 1 2007-10-03";
1150 JS_PUBLIC_API(JSCompartmentCallback
)
1151 JS_SetCompartmentCallback(JSRuntime
*rt
, JSCompartmentCallback callback
)
1153 JSCompartmentCallback old
= rt
->compartmentCallback
;
1154 rt
->compartmentCallback
= callback
;
1158 JS_PUBLIC_API(JSWrapObjectCallback
)
1159 JS_SetWrapObjectCallback(JSContext
*cx
, JSWrapObjectCallback callback
)
1161 JSRuntime
*rt
= cx
->runtime
;
1162 JSWrapObjectCallback old
= rt
->wrapObjectCallback
;
1163 rt
->wrapObjectCallback
= callback
;
1167 JS_PUBLIC_API(JSCrossCompartmentCall
*)
1168 JS_EnterCrossCompartmentCall(JSContext
*cx
, JSObject
*target
)
1173 AutoCompartment
*call
= new AutoCompartment(cx
, target
);
1176 if (!call
->enter()) {
1180 return reinterpret_cast<JSCrossCompartmentCall
*>(call
);
1184 JS_LeaveCrossCompartmentCall(JSCrossCompartmentCall
*call
)
1186 AutoCompartment
*realcall
= reinterpret_cast<AutoCompartment
*>(call
);
1187 CHECK_REQUEST(realcall
->context
);
1193 JSAutoCrossCompartmentCall::enter(JSContext
*cx
, JSObject
*target
)
1196 if (cx
->compartment
== target
->getCompartment(cx
))
1198 call
= JS_EnterCrossCompartmentCall(cx
, target
);
1199 return call
!= NULL
;
1202 JS_FRIEND_API(JSCompartment
*)
1203 js_SwitchToCompartment(JSContext
*cx
, JSCompartment
*compartment
)
1205 JSCompartment
*c
= cx
->compartment
;
1206 cx
->compartment
= compartment
;
1210 JS_FRIEND_API(JSCompartment
*)
1211 js_SwitchToObjectCompartment(JSContext
*cx
, JSObject
*obj
)
1213 JSCompartment
*c
= cx
->compartment
;
1214 cx
->compartment
= obj
->getCompartment(cx
);
1218 JS_PUBLIC_API(void *)
1219 JS_SetCompartmentPrivate(JSContext
*cx
, JSCompartment
*compartment
, void *data
)
1222 void *old
= compartment
->data
;
1223 compartment
->data
= data
;
1227 JS_PUBLIC_API(void *)
1228 JS_GetCompartmentPrivate(JSContext
*cx
, JSCompartment
*compartment
)
1231 return compartment
->data
;
1234 JS_PUBLIC_API(JSBool
)
1235 JS_WrapObject(JSContext
*cx
, JSObject
**objp
)
1238 return cx
->compartment
->wrap(cx
, objp
);
1241 JS_PUBLIC_API(JSBool
)
1242 JS_WrapValue(JSContext
*cx
, jsval
*vp
)
1245 return cx
->compartment
->wrap(cx
, Valueify(vp
));
1248 JS_PUBLIC_API(JSObject
*)
1249 JS_GetGlobalObject(JSContext
*cx
)
1251 return cx
->globalObject
;
1255 JS_SetGlobalObject(JSContext
*cx
, JSObject
*obj
)
1259 cx
->globalObject
= obj
;
1261 cx
->compartment
= obj
? obj
->getCompartment(cx
) : cx
->runtime
->defaultCompartment
;
1264 class AutoResolvingEntry
{
1266 AutoResolvingEntry() : entry(NULL
) {}
1269 * Returns false on error. But N.B. if obj[id] was already being resolved,
1270 * this is a no-op, and we silently treat that as success.
1272 bool start(JSContext
*cx
, JSObject
*obj
, jsid id
, uint32 flag
) {
1278 bool ok
= !!js_StartResolving(cx
, &key
, flag
, &entry
);
1279 JS_ASSERT_IF(!ok
, !entry
);
1283 ~AutoResolvingEntry() {
1285 js_StopResolving(cx
, &key
, flag
, NULL
, 0);
1292 JSResolvingEntry
*entry
;
1296 js_InitFunctionAndObjectClasses(JSContext
*cx
, JSObject
*obj
)
1298 JSObject
*fun_proto
, *obj_proto
;
1300 /* If cx has no global object, use obj so prototypes can be found. */
1301 if (!cx
->globalObject
)
1302 JS_SetGlobalObject(cx
, obj
);
1304 /* Record Function and Object in cx->resolvingTable. */
1305 AutoResolvingEntry e1
, e2
;
1306 JSAtom
**classAtoms
= cx
->runtime
->atomState
.classAtoms
;
1307 if (!e1
.start(cx
, obj
, ATOM_TO_JSID(classAtoms
[JSProto_Function
]), JSRESFLAG_LOOKUP
) ||
1308 !e2
.start(cx
, obj
, ATOM_TO_JSID(classAtoms
[JSProto_Object
]), JSRESFLAG_LOOKUP
)) {
1312 /* Initialize the function class first so constructors can be made. */
1313 if (!js_GetClassPrototype(cx
, obj
, JSProto_Function
, &fun_proto
))
1316 fun_proto
= js_InitFunctionClass(cx
, obj
);
1322 ctor
= JS_GetConstructor(cx
, fun_proto
);
1325 obj
->defineProperty(cx
, ATOM_TO_JSID(CLASS_ATOM(cx
, Function
)),
1326 ObjectValue(*ctor
), 0, 0, 0);
1329 /* Initialize the object class next so Object.prototype works. */
1330 if (!js_GetClassPrototype(cx
, obj
, JSProto_Object
, &obj_proto
))
1333 obj_proto
= js_InitObjectClass(cx
, obj
);
1337 /* Function.prototype and the global object delegate to Object.prototype. */
1338 fun_proto
->setProto(obj_proto
);
1339 if (!obj
->getProto())
1340 obj
->setProto(obj_proto
);
1345 JS_PUBLIC_API(JSBool
)
1346 JS_InitStandardClasses(JSContext
*cx
, JSObject
*obj
)
1351 * JS_SetGlobalObject might or might not change cx's compartment, so call
1352 * it before assertSameCompartment. (The API contract is that *after* this,
1353 * cx and obj must be in the same compartment.)
1355 if (!cx
->globalObject
)
1356 JS_SetGlobalObject(cx
, obj
);
1357 assertSameCompartment(cx
, obj
);
1359 /* Define a top-level property 'undefined' with the undefined value. */
1360 JSAtom
*atom
= cx
->runtime
->atomState
.typeAtoms
[JSTYPE_VOID
];
1361 if (!obj
->defineProperty(cx
, ATOM_TO_JSID(atom
), UndefinedValue(),
1362 PropertyStub
, PropertyStub
,
1363 JSPROP_PERMANENT
| JSPROP_READONLY
)) {
1367 /* Function and Object require cooperative bootstrapping magic. */
1368 if (!js_InitFunctionAndObjectClasses(cx
, obj
))
1371 /* Initialize the rest of the standard objects and functions. */
1372 return js_InitArrayClass(cx
, obj
) &&
1373 js_InitBooleanClass(cx
, obj
) &&
1374 js_InitExceptionClasses(cx
, obj
) &&
1375 js_InitMathClass(cx
, obj
) &&
1376 js_InitNumberClass(cx
, obj
) &&
1377 js_InitJSONClass(cx
, obj
) &&
1378 js_InitRegExpClass(cx
, obj
) &&
1379 js_InitStringClass(cx
, obj
) &&
1380 js_InitTypedArrayClasses(cx
, obj
) &&
1381 #if JS_HAS_XML_SUPPORT
1382 js_InitXMLClasses(cx
, obj
) &&
1384 #if JS_HAS_GENERATORS
1385 js_InitIteratorClasses(cx
, obj
) &&
1387 js_InitDateClass(cx
, obj
) &&
1388 js_InitProxyClass(cx
, obj
);
1391 #define CLASP(name) (&js_##name##Class)
1392 #define TYPED_ARRAY_CLASP(type) (&TypedArray::fastClasses[TypedArray::type])
1393 #define EAGER_ATOM(name) ATOM_OFFSET(name), NULL
1394 #define EAGER_CLASS_ATOM(name) CLASS_ATOM_OFFSET(name), NULL
1395 #define EAGER_ATOM_AND_CLASP(name) EAGER_CLASS_ATOM(name), CLASP(name)
1396 #define LAZY_ATOM(name) ATOM_OFFSET(lazy.name), js_##name##_str
1398 typedef struct JSStdName
{
1400 size_t atomOffset
; /* offset of atom pointer in JSAtomState */
1401 const char *name
; /* null if atom is pre-pinned, else name */
1406 StdNameToAtom(JSContext
*cx
, JSStdName
*stdn
)
1412 offset
= stdn
->atomOffset
;
1413 atom
= OFFSET_TO_ATOM(cx
->runtime
, offset
);
1417 atom
= js_Atomize(cx
, name
, strlen(name
), ATOM_PINNED
);
1418 OFFSET_TO_ATOM(cx
->runtime
, offset
) = atom
;
1425 * Table of class initializers and their atom offsets in rt->atomState.
1426 * If you add a "standard" class, remember to update this table.
1428 static JSStdName standard_class_atoms
[] = {
1429 {js_InitFunctionAndObjectClasses
, EAGER_ATOM_AND_CLASP(Function
)},
1430 {js_InitFunctionAndObjectClasses
, EAGER_ATOM_AND_CLASP(Object
)},
1431 {js_InitArrayClass
, EAGER_ATOM_AND_CLASP(Array
)},
1432 {js_InitBooleanClass
, EAGER_ATOM_AND_CLASP(Boolean
)},
1433 {js_InitDateClass
, EAGER_ATOM_AND_CLASP(Date
)},
1434 {js_InitMathClass
, EAGER_ATOM_AND_CLASP(Math
)},
1435 {js_InitNumberClass
, EAGER_ATOM_AND_CLASP(Number
)},
1436 {js_InitStringClass
, EAGER_ATOM_AND_CLASP(String
)},
1437 {js_InitExceptionClasses
, EAGER_ATOM_AND_CLASP(Error
)},
1438 {js_InitRegExpClass
, EAGER_ATOM_AND_CLASP(RegExp
)},
1439 #if JS_HAS_XML_SUPPORT
1440 {js_InitXMLClass
, EAGER_ATOM_AND_CLASP(XML
)},
1441 {js_InitNamespaceClass
, EAGER_ATOM_AND_CLASP(Namespace
)},
1442 {js_InitQNameClass
, EAGER_ATOM_AND_CLASP(QName
)},
1444 #if JS_HAS_GENERATORS
1445 {js_InitIteratorClasses
, EAGER_ATOM_AND_CLASP(StopIteration
)},
1447 {js_InitJSONClass
, EAGER_ATOM_AND_CLASP(JSON
)},
1448 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(ArrayBuffer
), &js::ArrayBuffer::jsclass
},
1449 {NULL
, 0, NULL
, NULL
}
1453 * Table of top-level function and constant names and their init functions.
1454 * If you add a "standard" global function or property, remember to update
1457 static JSStdName standard_class_names
[] = {
1458 {js_InitObjectClass
, EAGER_ATOM(eval
), CLASP(Object
)},
1460 /* Global properties and functions defined by the Number class. */
1461 {js_InitNumberClass
, LAZY_ATOM(NaN
), CLASP(Number
)},
1462 {js_InitNumberClass
, LAZY_ATOM(Infinity
), CLASP(Number
)},
1463 {js_InitNumberClass
, LAZY_ATOM(isNaN
), CLASP(Number
)},
1464 {js_InitNumberClass
, LAZY_ATOM(isFinite
), CLASP(Number
)},
1465 {js_InitNumberClass
, LAZY_ATOM(parseFloat
), CLASP(Number
)},
1466 {js_InitNumberClass
, LAZY_ATOM(parseInt
), CLASP(Number
)},
1468 /* String global functions. */
1469 {js_InitStringClass
, LAZY_ATOM(escape
), CLASP(String
)},
1470 {js_InitStringClass
, LAZY_ATOM(unescape
), CLASP(String
)},
1471 {js_InitStringClass
, LAZY_ATOM(decodeURI
), CLASP(String
)},
1472 {js_InitStringClass
, LAZY_ATOM(encodeURI
), CLASP(String
)},
1473 {js_InitStringClass
, LAZY_ATOM(decodeURIComponent
), CLASP(String
)},
1474 {js_InitStringClass
, LAZY_ATOM(encodeURIComponent
), CLASP(String
)},
1476 {js_InitStringClass
, LAZY_ATOM(uneval
), CLASP(String
)},
1479 /* Exception constructors. */
1480 {js_InitExceptionClasses
, EAGER_CLASS_ATOM(Error
), CLASP(Error
)},
1481 {js_InitExceptionClasses
, EAGER_CLASS_ATOM(InternalError
), CLASP(Error
)},
1482 {js_InitExceptionClasses
, EAGER_CLASS_ATOM(EvalError
), CLASP(Error
)},
1483 {js_InitExceptionClasses
, EAGER_CLASS_ATOM(RangeError
), CLASP(Error
)},
1484 {js_InitExceptionClasses
, EAGER_CLASS_ATOM(ReferenceError
), CLASP(Error
)},
1485 {js_InitExceptionClasses
, EAGER_CLASS_ATOM(SyntaxError
), CLASP(Error
)},
1486 {js_InitExceptionClasses
, EAGER_CLASS_ATOM(TypeError
), CLASP(Error
)},
1487 {js_InitExceptionClasses
, EAGER_CLASS_ATOM(URIError
), CLASP(Error
)},
1489 #if JS_HAS_XML_SUPPORT
1490 {js_InitAnyNameClass
, EAGER_ATOM_AND_CLASP(AnyName
)},
1491 {js_InitAttributeNameClass
, EAGER_ATOM_AND_CLASP(AttributeName
)},
1492 {js_InitXMLClass
, LAZY_ATOM(XMLList
), CLASP(XML
)},
1493 {js_InitXMLClass
, LAZY_ATOM(isXMLName
), CLASP(XML
)},
1496 #if JS_HAS_GENERATORS
1497 {js_InitIteratorClasses
, EAGER_ATOM_AND_CLASP(Iterator
)},
1498 {js_InitIteratorClasses
, EAGER_ATOM_AND_CLASP(Generator
)},
1502 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(ArrayBuffer
), &js::ArrayBuffer::jsclass
},
1503 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(Int8Array
), TYPED_ARRAY_CLASP(TYPE_INT8
)},
1504 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(Uint8Array
), TYPED_ARRAY_CLASP(TYPE_UINT8
)},
1505 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(Int16Array
), TYPED_ARRAY_CLASP(TYPE_INT16
)},
1506 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(Uint16Array
), TYPED_ARRAY_CLASP(TYPE_UINT16
)},
1507 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(Int32Array
), TYPED_ARRAY_CLASP(TYPE_INT32
)},
1508 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(Uint32Array
), TYPED_ARRAY_CLASP(TYPE_UINT32
)},
1509 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(Float32Array
), TYPED_ARRAY_CLASP(TYPE_FLOAT32
)},
1510 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(Float64Array
), TYPED_ARRAY_CLASP(TYPE_FLOAT64
)},
1511 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(Uint8ClampedArray
),
1512 TYPED_ARRAY_CLASP(TYPE_UINT8_CLAMPED
)},
1514 {js_InitProxyClass
, EAGER_ATOM_AND_CLASP(Proxy
)},
1516 {NULL
, 0, NULL
, NULL
}
1519 static JSStdName object_prototype_names
[] = {
1520 /* Object.prototype properties (global delegates to Object.prototype). */
1521 {js_InitObjectClass
, EAGER_ATOM(proto
), CLASP(Object
)},
1523 {js_InitObjectClass
, EAGER_ATOM(toSource
), CLASP(Object
)},
1525 {js_InitObjectClass
, EAGER_ATOM(toString
), CLASP(Object
)},
1526 {js_InitObjectClass
, EAGER_ATOM(toLocaleString
), CLASP(Object
)},
1527 {js_InitObjectClass
, EAGER_ATOM(valueOf
), CLASP(Object
)},
1528 #if JS_HAS_OBJ_WATCHPOINT
1529 {js_InitObjectClass
, LAZY_ATOM(watch
), CLASP(Object
)},
1530 {js_InitObjectClass
, LAZY_ATOM(unwatch
), CLASP(Object
)},
1532 {js_InitObjectClass
, LAZY_ATOM(hasOwnProperty
), CLASP(Object
)},
1533 {js_InitObjectClass
, LAZY_ATOM(isPrototypeOf
), CLASP(Object
)},
1534 {js_InitObjectClass
, LAZY_ATOM(propertyIsEnumerable
), CLASP(Object
)},
1535 #if OLD_GETTER_SETTER_METHODS
1536 {js_InitObjectClass
, LAZY_ATOM(defineGetter
), CLASP(Object
)},
1537 {js_InitObjectClass
, LAZY_ATOM(defineSetter
), CLASP(Object
)},
1538 {js_InitObjectClass
, LAZY_ATOM(lookupGetter
), CLASP(Object
)},
1539 {js_InitObjectClass
, LAZY_ATOM(lookupSetter
), CLASP(Object
)},
1542 {NULL
, 0, NULL
, NULL
}
1545 JS_PUBLIC_API(JSBool
)
1546 JS_ResolveStandardClass(JSContext
*cx
, JSObject
*obj
, jsid id
, JSBool
*resolved
)
1555 assertSameCompartment(cx
, obj
, id
);
1556 *resolved
= JS_FALSE
;
1559 JS_ASSERT(rt
->state
!= JSRTS_DOWN
);
1560 if (rt
->state
== JSRTS_LANDING
|| !JSID_IS_ATOM(id
))
1563 idstr
= JSID_TO_STRING(id
);
1565 /* Check whether we're resolving 'undefined', and define it if so. */
1566 atom
= rt
->atomState
.typeAtoms
[JSTYPE_VOID
];
1567 if (idstr
== ATOM_TO_STRING(atom
)) {
1568 *resolved
= JS_TRUE
;
1569 return obj
->defineProperty(cx
, ATOM_TO_JSID(atom
), UndefinedValue(),
1570 PropertyStub
, PropertyStub
,
1571 JSPROP_PERMANENT
| JSPROP_READONLY
);
1574 /* Try for class constructors/prototypes named by well-known atoms. */
1576 for (i
= 0; standard_class_atoms
[i
].init
; i
++) {
1577 JS_ASSERT(standard_class_atoms
[i
].clasp
);
1578 atom
= OFFSET_TO_ATOM(rt
, standard_class_atoms
[i
].atomOffset
);
1579 if (idstr
== ATOM_TO_STRING(atom
)) {
1580 stdnm
= &standard_class_atoms
[i
];
1586 /* Try less frequently used top-level functions and constants. */
1587 for (i
= 0; standard_class_names
[i
].init
; i
++) {
1588 JS_ASSERT(standard_class_names
[i
].clasp
);
1589 atom
= StdNameToAtom(cx
, &standard_class_names
[i
]);
1592 if (idstr
== ATOM_TO_STRING(atom
)) {
1593 stdnm
= &standard_class_names
[i
];
1598 if (!stdnm
&& !obj
->getProto()) {
1600 * Try even less frequently used names delegated from the global
1601 * object to Object.prototype, but only if the Object class hasn't
1602 * yet been initialized.
1604 for (i
= 0; object_prototype_names
[i
].init
; i
++) {
1605 JS_ASSERT(object_prototype_names
[i
].clasp
);
1606 atom
= StdNameToAtom(cx
, &object_prototype_names
[i
]);
1609 if (idstr
== ATOM_TO_STRING(atom
)) {
1610 stdnm
= &object_prototype_names
[i
];
1619 * If this standard class is anonymous, then we don't want to resolve
1622 JS_ASSERT(obj
->getClass()->flags
& JSCLASS_IS_GLOBAL
);
1623 if (stdnm
->clasp
->flags
& JSCLASS_IS_ANONYMOUS
)
1626 JSProtoKey key
= JSCLASS_CACHED_PROTO_KEY(stdnm
->clasp
);
1627 if (obj
->getReservedSlot(key
).isObject())
1630 if (!stdnm
->init(cx
, obj
))
1632 *resolved
= JS_TRUE
;
1638 AlreadyHasOwnProperty(JSContext
*cx
, JSObject
*obj
, JSAtom
*atom
)
1640 JS_LOCK_OBJ(cx
, obj
);
1641 bool found
= obj
->nativeContains(ATOM_TO_JSID(atom
));
1642 JS_UNLOCK_OBJ(cx
, obj
);
1646 JS_PUBLIC_API(JSBool
)
1647 JS_EnumerateStandardClasses(JSContext
*cx
, JSObject
*obj
)
1654 assertSameCompartment(cx
, obj
);
1657 /* Check whether we need to bind 'undefined' and define it if so. */
1658 atom
= rt
->atomState
.typeAtoms
[JSTYPE_VOID
];
1659 if (!AlreadyHasOwnProperty(cx
, obj
, atom
) &&
1660 !obj
->defineProperty(cx
, ATOM_TO_JSID(atom
), UndefinedValue(),
1661 PropertyStub
, PropertyStub
,
1662 JSPROP_PERMANENT
| JSPROP_READONLY
)) {
1666 /* Initialize any classes that have not been resolved yet. */
1667 for (i
= 0; standard_class_atoms
[i
].init
; i
++) {
1668 atom
= OFFSET_TO_ATOM(rt
, standard_class_atoms
[i
].atomOffset
);
1669 if (!AlreadyHasOwnProperty(cx
, obj
, atom
) &&
1670 !standard_class_atoms
[i
].init(cx
, obj
)) {
1681 NewIdArray(JSContext
*cx
, jsint length
)
1686 cx
->calloc(offsetof(JSIdArray
, vector
) + length
* sizeof(jsval
));
1688 ida
->length
= length
;
1695 * Unlike realloc(3), this function frees ida on failure.
1698 SetIdArrayLength(JSContext
*cx
, JSIdArray
*ida
, jsint length
)
1702 rida
= (JSIdArray
*)
1704 offsetof(JSIdArray
, vector
) + length
* sizeof(jsval
));
1706 JS_DestroyIdArray(cx
, ida
);
1708 rida
->length
= length
;
1714 AddAtomToArray(JSContext
*cx
, JSAtom
*atom
, JSIdArray
*ida
, jsint
*ip
)
1719 length
= ida
->length
;
1721 ida
= SetIdArrayLength(cx
, ida
, JS_MAX(length
* 2, 8));
1724 JS_ASSERT(i
< ida
->length
);
1726 ida
->vector
[i
] = ATOM_TO_JSID(atom
);
1732 EnumerateIfResolved(JSContext
*cx
, JSObject
*obj
, JSAtom
*atom
, JSIdArray
*ida
,
1733 jsint
*ip
, JSBool
*foundp
)
1735 *foundp
= AlreadyHasOwnProperty(cx
, obj
, atom
);
1737 ida
= AddAtomToArray(cx
, atom
, ida
, ip
);
1741 JS_PUBLIC_API(JSIdArray
*)
1742 JS_EnumerateResolvedStandardClasses(JSContext
*cx
, JSObject
*obj
, JSIdArray
*ida
)
1751 assertSameCompartment(cx
, obj
, ida
);
1756 ida
= NewIdArray(cx
, 8);
1762 /* Check whether 'undefined' has been resolved and enumerate it if so. */
1763 atom
= rt
->atomState
.typeAtoms
[JSTYPE_VOID
];
1764 ida
= EnumerateIfResolved(cx
, obj
, atom
, ida
, &i
, &found
);
1768 /* Enumerate only classes that *have* been resolved. */
1769 for (j
= 0; standard_class_atoms
[j
].init
; j
++) {
1770 atom
= OFFSET_TO_ATOM(rt
, standard_class_atoms
[j
].atomOffset
);
1771 ida
= EnumerateIfResolved(cx
, obj
, atom
, ida
, &i
, &found
);
1776 init
= standard_class_atoms
[j
].init
;
1778 for (k
= 0; standard_class_names
[k
].init
; k
++) {
1779 if (standard_class_names
[k
].init
== init
) {
1780 atom
= StdNameToAtom(cx
, &standard_class_names
[k
]);
1781 ida
= AddAtomToArray(cx
, atom
, ida
, &i
);
1787 if (init
== js_InitObjectClass
) {
1788 for (k
= 0; object_prototype_names
[k
].init
; k
++) {
1789 atom
= StdNameToAtom(cx
, &object_prototype_names
[k
]);
1790 ida
= AddAtomToArray(cx
, atom
, ida
, &i
);
1798 /* Trim to exact length. */
1799 return SetIdArrayLength(cx
, ida
, i
);
1804 #undef EAGER_CLASS_ATOM
1805 #undef EAGER_ATOM_CLASP
1808 JS_PUBLIC_API(JSBool
)
1809 JS_GetClassObject(JSContext
*cx
, JSObject
*obj
, JSProtoKey key
, JSObject
**objp
)
1812 assertSameCompartment(cx
, obj
);
1813 return js_GetClassObject(cx
, obj
, key
, objp
);
1816 JS_PUBLIC_API(JSObject
*)
1817 JS_GetScopeChain(JSContext
*cx
)
1822 fp
= js_GetTopStackFrame(cx
);
1825 * There is no code active on this context. In place of an actual
1826 * scope chain, use the context's global object, which is set in
1827 * js_InitFunctionAndObjectClasses, and which represents the default
1828 * scope chain for the embedding. See also js_FindClassObject.
1830 * For embeddings that use the inner and outer object hooks, the inner
1831 * object represents the ultimate global object, with the outer object
1832 * acting as a stand-in.
1834 JSObject
*obj
= cx
->globalObject
;
1836 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_INACTIVE
);
1840 OBJ_TO_INNER_OBJECT(cx
, obj
);
1843 return js_GetScopeChain(cx
, fp
);
1846 JS_PUBLIC_API(JSObject
*)
1847 JS_GetGlobalForObject(JSContext
*cx
, JSObject
*obj
)
1849 assertSameCompartment(cx
, obj
);
1850 return obj
->getGlobal();
1853 JS_PUBLIC_API(JSObject
*)
1854 JS_GetGlobalForScopeChain(JSContext
*cx
)
1857 * This is essentially JS_GetScopeChain(cx)->getGlobal(), but without
1858 * falling off trace.
1860 * This use of cx->fp, possibly on trace, is deliberate:
1861 * cx->fp->scopeChain->getGlobal() returns the same object whether we're on
1862 * trace or not, since we do not trace calls across global objects.
1864 VOUCH_DOES_NOT_REQUIRE_STACK();
1867 return cx
->fp()->scopeChain().getGlobal();
1869 JSObject
*scope
= cx
->globalObject
;
1871 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_INACTIVE
);
1874 OBJ_TO_INNER_OBJECT(cx
, scope
);
1878 JS_PUBLIC_API(jsval
)
1879 JS_ComputeThis(JSContext
*cx
, jsval
*vp
)
1881 assertSameCompartment(cx
, JSValueArray(vp
, 2));
1882 if (!ComputeThisFromVp(cx
, Valueify(vp
)))
1887 JS_PUBLIC_API(void *)
1888 JS_malloc(JSContext
*cx
, size_t nbytes
)
1890 return cx
->malloc(nbytes
);
1893 JS_PUBLIC_API(void *)
1894 JS_realloc(JSContext
*cx
, void *p
, size_t nbytes
)
1896 return cx
->realloc(p
, nbytes
);
1900 JS_free(JSContext
*cx
, void *p
)
1906 JS_updateMallocCounter(JSContext
*cx
, size_t nbytes
)
1908 return cx
->runtime
->updateMallocCounter(nbytes
);
1911 JS_PUBLIC_API(char *)
1912 JS_strdup(JSContext
*cx
, const char *s
)
1921 return (char *)memcpy(p
, s
, n
);
1924 JS_PUBLIC_API(JSBool
)
1925 JS_NewNumberValue(JSContext
*cx
, jsdouble d
, jsval
*rval
)
1927 d
= JS_CANONICALIZE_NAN(d
);
1928 Valueify(rval
)->setNumber(d
);
1934 JS_PUBLIC_API(JSBool
)
1935 JS_AddValueRoot(JSContext
*cx
, jsval
*vp
)
1938 return js_AddRoot(cx
, Valueify(vp
), NULL
);
1941 JS_PUBLIC_API(JSBool
)
1942 JS_AddStringRoot(JSContext
*cx
, JSString
**rp
)
1945 return js_AddGCThingRoot(cx
, (void **)rp
, NULL
);
1948 JS_PUBLIC_API(JSBool
)
1949 JS_AddObjectRoot(JSContext
*cx
, JSObject
**rp
)
1952 return js_AddGCThingRoot(cx
, (void **)rp
, NULL
);
1955 JS_PUBLIC_API(JSBool
)
1956 JS_AddGCThingRoot(JSContext
*cx
, void **rp
)
1959 return js_AddGCThingRoot(cx
, (void **)rp
, NULL
);
1962 JS_PUBLIC_API(JSBool
)
1963 JS_AddNamedValueRoot(JSContext
*cx
, jsval
*vp
, const char *name
)
1966 return js_AddRoot(cx
, Valueify(vp
), name
);
1969 JS_PUBLIC_API(JSBool
)
1970 JS_AddNamedStringRoot(JSContext
*cx
, JSString
**rp
, const char *name
)
1973 return js_AddGCThingRoot(cx
, (void **)rp
, name
);
1976 JS_PUBLIC_API(JSBool
)
1977 JS_AddNamedObjectRoot(JSContext
*cx
, JSObject
**rp
, const char *name
)
1980 return js_AddGCThingRoot(cx
, (void **)rp
, name
);
1983 JS_PUBLIC_API(JSBool
)
1984 JS_AddNamedGCThingRoot(JSContext
*cx
, void **rp
, const char *name
)
1987 return js_AddGCThingRoot(cx
, (void **)rp
, name
);
1990 JS_PUBLIC_API(JSBool
)
1991 JS_RemoveValueRoot(JSContext
*cx
, jsval
*vp
)
1994 return js_RemoveRoot(cx
->runtime
, (void *)vp
);
1997 JS_PUBLIC_API(JSBool
)
1998 JS_RemoveStringRoot(JSContext
*cx
, JSString
**rp
)
2001 return js_RemoveRoot(cx
->runtime
, (void *)rp
);
2004 JS_PUBLIC_API(JSBool
)
2005 JS_RemoveObjectRoot(JSContext
*cx
, JSObject
**rp
)
2008 return js_RemoveRoot(cx
->runtime
, (void *)rp
);
2011 JS_PUBLIC_API(JSBool
)
2012 JS_RemoveGCThingRoot(JSContext
*cx
, void **rp
)
2015 return js_RemoveRoot(cx
->runtime
, (void *)rp
);
2021 JS_DumpNamedRoots(JSRuntime
*rt
,
2022 void (*dump
)(const char *name
, void *rp
, JSGCRootType type
, void *data
),
2025 js_DumpNamedRoots(rt
, dump
, data
);
2030 JS_PUBLIC_API(uint32
)
2031 JS_MapGCRoots(JSRuntime
*rt
, JSGCRootMapFun map
, void *data
)
2033 return js_MapGCRoots(rt
, map
, data
);
2036 JS_PUBLIC_API(JSBool
)
2037 JS_LockGCThing(JSContext
*cx
, void *thing
)
2042 ok
= js_LockGCThingRT(cx
->runtime
, thing
);
2044 JS_ReportOutOfMemory(cx
);
2048 JS_PUBLIC_API(JSBool
)
2049 JS_LockGCThingRT(JSRuntime
*rt
, void *thing
)
2051 return js_LockGCThingRT(rt
, thing
);
2054 JS_PUBLIC_API(JSBool
)
2055 JS_UnlockGCThing(JSContext
*cx
, void *thing
)
2058 js_UnlockGCThingRT(cx
->runtime
, thing
);
2062 JS_PUBLIC_API(JSBool
)
2063 JS_UnlockGCThingRT(JSRuntime
*rt
, void *thing
)
2065 js_UnlockGCThingRT(rt
, thing
);
2070 JS_SetExtraGCRoots(JSRuntime
*rt
, JSTraceDataOp traceOp
, void *data
)
2072 rt
->gcExtraRootsTraceOp
= traceOp
;
2073 rt
->gcExtraRootsData
= data
;
2077 JS_TraceRuntime(JSTracer
*trc
)
2083 JS_CallTracer(JSTracer
*trc
, void *thing
, uint32 kind
)
2086 Mark(trc
, thing
, kind
);
2091 #ifdef HAVE_XPCONNECT
2092 #include "dump_xpc.h"
2096 JS_PrintTraceThingInfo(char *buf
, size_t bufsize
, JSTracer
*trc
, void *thing
, uint32 kind
,
2106 case JSTRACE_OBJECT
:
2108 JSObject
*obj
= (JSObject
*)thing
;
2109 Class
*clasp
= obj
->getClass();
2112 #ifdef HAVE_XPCONNECT
2113 if (clasp
->flags
& JSCLASS_PRIVATE_IS_NSISUPPORTS
) {
2114 void *privateThing
= obj
->getPrivate();
2116 const char *xpcClassName
= GetXPCObjectClassName(privateThing
);
2118 name
= xpcClassName
;
2125 case JSTRACE_STRING
:
2126 name
= ((JSString
*)thing
)->isDependent()
2131 #if JS_HAS_XML_SUPPORT
2143 if (n
> bufsize
- 1)
2145 memcpy(buf
, name
, n
+ 1);
2149 if (details
&& bufsize
> 2) {
2154 case JSTRACE_OBJECT
:
2156 JSObject
*obj
= (JSObject
*)thing
;
2157 Class
*clasp
= obj
->getClass();
2158 if (clasp
== &js_FunctionClass
) {
2159 JSFunction
*fun
= GET_FUNCTION_PRIVATE(trc
->context
, obj
);
2161 JS_snprintf(buf
, bufsize
, "<newborn>");
2162 } else if (FUN_OBJECT(fun
) != obj
) {
2163 JS_snprintf(buf
, bufsize
, "%p", fun
);
2166 js_PutEscapedString(buf
, bufsize
, ATOM_TO_STRING(fun
->atom
), 0);
2168 } else if (clasp
->flags
& JSCLASS_HAS_PRIVATE
) {
2169 JS_snprintf(buf
, bufsize
, "%p", obj
->getPrivate());
2171 JS_snprintf(buf
, bufsize
, "<no private>");
2176 case JSTRACE_STRING
:
2177 js_PutEscapedString(buf
, bufsize
, (JSString
*)thing
, 0);
2180 #if JS_HAS_XML_SUPPORT
2183 extern const char *js_xml_class_str
[];
2184 JSXML
*xml
= (JSXML
*)thing
;
2186 JS_snprintf(buf
, bufsize
, "%s", js_xml_class_str
[xml
->xml_class
]);
2195 buf
[bufsize
- 1] = '\0';
2198 typedef struct JSHeapDumpNode JSHeapDumpNode
;
2200 struct JSHeapDumpNode
{
2203 JSHeapDumpNode
*next
; /* next sibling */
2204 JSHeapDumpNode
*parent
; /* node with the thing that refer to thing
2206 char edgeName
[1]; /* name of the edge from parent->thing
2210 typedef struct JSDumpingTracer
{
2212 JSDHashTable visited
;
2216 void *thingToIgnore
;
2217 JSHeapDumpNode
*parentNode
;
2218 JSHeapDumpNode
**lastNodep
;
2223 DumpNotify(JSTracer
*trc
, void *thing
, uint32 kind
)
2225 JSDumpingTracer
*dtrc
;
2227 JSDHashEntryStub
*entry
;
2228 JSHeapDumpNode
*node
;
2229 const char *edgeName
;
2230 size_t edgeNameSize
;
2232 JS_ASSERT(trc
->callback
== DumpNotify
);
2233 dtrc
= (JSDumpingTracer
*)trc
;
2235 if (!dtrc
->ok
|| thing
== dtrc
->thingToIgnore
)
2241 * Check if we have already seen thing unless it is thingToFind to include
2242 * it to the graph each time we reach it and print all live things that
2243 * refer to thingToFind.
2245 * This does not print all possible paths leading to thingToFind since
2246 * when a thing A refers directly or indirectly to thingToFind and A is
2247 * present several times in the graph, we will print only the first path
2248 * leading to A and thingToFind, other ways to reach A will be ignored.
2250 if (dtrc
->thingToFind
!= thing
) {
2252 * The startThing check allows to avoid putting startThing into the
2253 * hash table before tracing startThing in JS_DumpHeap.
2255 if (thing
== dtrc
->startThing
)
2257 entry
= (JSDHashEntryStub
*)
2258 JS_DHashTableOperate(&dtrc
->visited
, thing
, JS_DHASH_ADD
);
2260 JS_ReportOutOfMemory(cx
);
2261 dtrc
->ok
= JS_FALSE
;
2269 if (dtrc
->base
.debugPrinter
) {
2270 dtrc
->base
.debugPrinter(trc
, dtrc
->buffer
, sizeof(dtrc
->buffer
));
2271 edgeName
= dtrc
->buffer
;
2272 } else if (dtrc
->base
.debugPrintIndex
!= (size_t)-1) {
2273 JS_snprintf(dtrc
->buffer
, sizeof(dtrc
->buffer
), "%s[%lu]",
2274 (const char *)dtrc
->base
.debugPrintArg
,
2275 dtrc
->base
.debugPrintIndex
);
2276 edgeName
= dtrc
->buffer
;
2278 edgeName
= (const char*)dtrc
->base
.debugPrintArg
;
2281 edgeNameSize
= strlen(edgeName
) + 1;
2282 node
= (JSHeapDumpNode
*)
2283 cx
->malloc(offsetof(JSHeapDumpNode
, edgeName
) + edgeNameSize
);
2285 dtrc
->ok
= JS_FALSE
;
2289 node
->thing
= thing
;
2292 node
->parent
= dtrc
->parentNode
;
2293 memcpy(node
->edgeName
, edgeName
, edgeNameSize
);
2295 JS_ASSERT(!*dtrc
->lastNodep
);
2296 *dtrc
->lastNodep
= node
;
2297 dtrc
->lastNodep
= &node
->next
;
2300 /* Dump node and the chain that leads to thing it contains. */
2302 DumpNode(JSDumpingTracer
*dtrc
, FILE* fp
, JSHeapDumpNode
*node
)
2304 JSHeapDumpNode
*prev
, *following
;
2307 enum { MAX_PARENTS_TO_PRINT
= 10 };
2309 JS_PrintTraceThingInfo(dtrc
->buffer
, sizeof dtrc
->buffer
,
2310 &dtrc
->base
, node
->thing
, node
->kind
, JS_TRUE
);
2311 if (fprintf(fp
, "%p %-22s via ", node
->thing
, dtrc
->buffer
) < 0)
2315 * We need to print the parent chain in the reverse order. To do it in
2316 * O(N) time where N is the chain length we first reverse the chain while
2317 * searching for the top and then print each node while restoring the
2320 chainLimit
= MAX_PARENTS_TO_PRINT
;
2323 following
= node
->parent
;
2324 node
->parent
= prev
;
2329 if (chainLimit
== 0) {
2330 if (fputs("...", fp
) < 0)
2341 /* Loop must continue even when !ok to restore the parent chain. */
2344 /* Print edge from some runtime root or startThing. */
2345 if (fputs(node
->edgeName
, fp
) < 0)
2348 JS_PrintTraceThingInfo(dtrc
->buffer
, sizeof dtrc
->buffer
,
2349 &dtrc
->base
, prev
->thing
, prev
->kind
,
2351 if (fprintf(fp
, "(%p %s).%s",
2352 prev
->thing
, dtrc
->buffer
, node
->edgeName
) < 0) {
2357 following
= node
->parent
;
2358 node
->parent
= prev
;
2363 return ok
&& putc('\n', fp
) >= 0;
2366 JS_PUBLIC_API(JSBool
)
2367 JS_DumpHeap(JSContext
*cx
, FILE *fp
, void* startThing
, uint32 startKind
,
2368 void *thingToFind
, size_t maxDepth
, void *thingToIgnore
)
2370 JSDumpingTracer dtrc
;
2371 JSHeapDumpNode
*node
, *children
, *next
, *parent
;
2373 JSBool thingToFindWasTraced
;
2378 JS_TRACER_INIT(&dtrc
.base
, cx
, DumpNotify
);
2379 if (!JS_DHashTableInit(&dtrc
.visited
, JS_DHashGetStubOps(),
2380 NULL
, sizeof(JSDHashEntryStub
),
2381 JS_DHASH_DEFAULT_CAPACITY(100))) {
2382 JS_ReportOutOfMemory(cx
);
2386 dtrc
.startThing
= startThing
;
2387 dtrc
.thingToFind
= thingToFind
;
2388 dtrc
.thingToIgnore
= thingToIgnore
;
2389 dtrc
.parentNode
= NULL
;
2391 dtrc
.lastNodep
= &node
;
2393 JS_ASSERT(startKind
== 0);
2394 TraceRuntime(&dtrc
.base
);
2396 JS_TraceChildren(&dtrc
.base
, startThing
, startKind
);
2403 thingToFindWasTraced
= thingToFind
&& thingToFind
== startThing
;
2406 * Loop must continue even when !dtrc.ok to free all nodes allocated
2410 if (thingToFind
== NULL
|| thingToFind
== node
->thing
)
2411 dtrc
.ok
= DumpNode(&dtrc
, fp
, node
);
2413 /* Descend into children. */
2416 (thingToFind
!= node
->thing
|| !thingToFindWasTraced
)) {
2417 dtrc
.parentNode
= node
;
2419 dtrc
.lastNodep
= &children
;
2420 JS_TraceChildren(&dtrc
.base
, node
->thing
, node
->kind
);
2421 if (thingToFind
== node
->thing
)
2422 thingToFindWasTraced
= JS_TRUE
;
2423 if (children
!= NULL
) {
2431 /* Move to next or parents next and free the node. */
2434 parent
= node
->parent
;
2441 JS_ASSERT(depth
> 1);
2448 JS_ASSERT(depth
== 1);
2449 JS_DHashTableFinish(&dtrc
.visited
);
2456 JS_MarkGCThing(JSContext
*cx
, jsval v
, const char *name
, void *arg
)
2460 trc
= (JSTracer
*)arg
;
2462 trc
= cx
->runtime
->gcMarkingTracer
;
2464 JS_ASSERT(trc
== cx
->runtime
->gcMarkingTracer
);
2466 #ifdef JS_THREADSAFE
2467 JS_ASSERT(cx
->runtime
->gcThread
== trc
->context
->thread
);
2469 MarkValue(trc
, Valueify(v
), name
? name
: "unknown");
2472 extern JS_PUBLIC_API(JSBool
)
2473 JS_IsGCMarkingTracer(JSTracer
*trc
)
2475 return IS_GC_MARKING_TRACER(trc
);
2479 JS_GC(JSContext
*cx
)
2483 /* Don't nuke active arenas if executing or compiling. */
2484 if (cx
->tempPool
.current
== &cx
->tempPool
.first
)
2485 JS_FinishArenaPool(&cx
->tempPool
);
2486 js_GC(cx
, GC_NORMAL
);
2490 JS_MaybeGC(JSContext
*cx
)
2493 uint32 bytes
, lastBytes
;
2498 if (rt
->gcZeal
> 0) {
2504 bytes
= rt
->gcBytes
;
2505 lastBytes
= rt
->gcLastBytes
;
2508 * We run the GC if we used all available free GC cells and had to
2509 * allocate extra 1/3 of GC arenas since the last run of GC, or if
2510 * we have malloc'd more bytes through JS_malloc than we were told
2511 * to allocate by JS_NewRuntime.
2514 * bytes > 4/3 lastBytes
2515 * condition is the following. Bug 312238 changed bytes and lastBytes
2516 * to mean the total amount of memory that the GC uses now and right
2517 * after the last GC.
2519 * Before the bug the variables meant the size of allocated GC things
2520 * now and right after the last GC. That size did not include the
2521 * memory taken by free GC cells and the condition was
2522 * bytes > 3/2 lastBytes.
2523 * That is, we run the GC if we have half again as many bytes of
2524 * GC-things as the last time we GC'd. To be compatible we need to
2525 * express that condition through the new meaning of bytes and
2528 * We write the original condition as
2529 * B*(1-F) > 3/2 Bl*(1-Fl)
2530 * where B is the total memory size allocated by GC and F is the free
2531 * cell density currently and Sl and Fl are the size and the density
2532 * right after GC. The density by definition is memory taken by free
2533 * cells divided by total amount of memory. In other words, B and Bl
2534 * are bytes and lastBytes with the new meaning and B*(1-F) and
2535 * Bl*(1-Fl) are bytes and lastBytes with the original meaning.
2537 * Our task is to exclude F and Fl from the last statement. According
2538 * to the stats from bug 331966 comment 23, Fl is about 10-25% for a
2539 * typical run of the browser. It means that the original condition
2540 * implied that we did not run GC unless we exhausted the pool of
2541 * free cells. Indeed if we still have free cells, then B == Bl since
2542 * we did not yet allocated any new arenas and the condition means
2543 * 1 - F > 3/2 (1-Fl) or 3/2Fl > 1/2 + F
2544 * That implies 3/2 Fl > 1/2 or Fl > 1/3. That cannot be fulfilled
2545 * for the state described by the stats. So we can write the original
2547 * F == 0 && B > 3/2 Bl(1-Fl)
2548 * Again using the stats we see that Fl is about 11% when the browser
2549 * starts up and when we are far from hitting rt->gcMaxBytes. With
2551 * F == 0 && B > 3/2 Bl(1-0.11)
2552 * or approximately F == 0 && B > 4/3 Bl.
2554 if ((bytes
> 8192 && bytes
> lastBytes
+ lastBytes
/ 3) ||
2555 rt
->isGCMallocLimitReached()) {
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 js_IsAboutToBeFinalized(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 JS_ASSERT(key
== JSGC_TRIGGER_FACTOR
);
2600 JS_ASSERT(value
>= 100);
2601 rt
->setGCTriggerFactor(value
);
2606 JS_PUBLIC_API(uint32
)
2607 JS_GetGCParameter(JSRuntime
*rt
, JSGCParamKey key
)
2610 case JSGC_MAX_BYTES
:
2611 return rt
->gcMaxBytes
;
2612 case JSGC_MAX_MALLOC_BYTES
:
2613 return rt
->gcMaxMallocBytes
;
2614 case JSGC_STACKPOOL_LIFESPAN
:
2615 return rt
->gcEmptyArenaPoolLifespan
;
2616 case JSGC_TRIGGER_FACTOR
:
2617 return rt
->gcTriggerFactor
;
2621 JS_ASSERT(key
== JSGC_NUMBER
);
2622 return rt
->gcNumber
;
2627 JS_SetGCParameterForThread(JSContext
*cx
, JSGCParamKey key
, uint32 value
)
2629 JS_ASSERT(key
== JSGC_MAX_CODE_CACHE_BYTES
);
2631 SetMaxCodeCacheBytes(cx
, value
);
2635 JS_PUBLIC_API(uint32
)
2636 JS_GetGCParameterForThread(JSContext
*cx
, JSGCParamKey key
)
2638 JS_ASSERT(key
== JSGC_MAX_CODE_CACHE_BYTES
);
2640 return JS_THREAD_DATA(cx
)->traceMonitor
.maxCodeCacheBytes
;
2647 JS_FlushCaches(JSContext
*cx
)
2655 JS_AddExternalStringFinalizer(JSStringFinalizeOp finalizer
)
2657 return js_ChangeExternalStringFinalizer(NULL
, finalizer
);
2661 JS_RemoveExternalStringFinalizer(JSStringFinalizeOp finalizer
)
2663 return js_ChangeExternalStringFinalizer(finalizer
, NULL
);
2666 JS_PUBLIC_API(JSString
*)
2667 JS_NewExternalString(JSContext
*cx
, jschar
*chars
, size_t length
, intN type
)
2670 JS_ASSERT(uintN(type
) < JS_EXTERNAL_STRING_LIMIT
);
2672 JSString
*str
= js_NewGCExternalString(cx
, uintN(type
));
2675 str
->initFlat(chars
, length
);
2676 cx
->runtime
->updateMallocCounter((length
+ 1) * sizeof(jschar
));
2681 JS_GetExternalStringGCType(JSRuntime
*rt
, JSString
*str
)
2684 * No need to test this in js_GetExternalStringGCType, which asserts its
2685 * inverse instead of wasting cycles on testing a condition we can ensure
2686 * by auditing in-VM calls to the js_... helper.
2688 if (JSString::isStatic(str
))
2691 return js_GetExternalStringGCType(str
);
2695 JS_SetThreadStackLimit(JSContext
*cx
, jsuword limitAddr
)
2697 #if JS_STACK_GROWTH_DIRECTION > 0
2699 limitAddr
= jsuword(-1);
2701 cx
->stackLimit
= limitAddr
;
2705 JS_SetNativeStackQuota(JSContext
*cx
, size_t stackSize
)
2707 #ifdef JS_THREADSAFE
2708 JS_ASSERT(cx
->thread
);
2711 #if JS_STACK_GROWTH_DIRECTION > 0
2712 if (stackSize
== 0) {
2713 cx
->stackLimit
= jsuword(-1);
2715 jsuword stackBase
= reinterpret_cast<jsuword
>(JS_THREAD_DATA(cx
)->nativeStackBase
);
2716 JS_ASSERT(stackBase
<= size_t(-1) - stackSize
);
2717 cx
->stackLimit
= stackBase
+ stackSize
- 1;
2720 if (stackSize
== 0) {
2723 jsuword stackBase
= reinterpret_cast<jsuword
>(JS_THREAD_DATA(cx
)->nativeStackBase
);
2724 JS_ASSERT(stackBase
>= stackSize
);
2725 cx
->stackLimit
= stackBase
- (stackSize
- 1);
2731 JS_SetScriptStackQuota(JSContext
*cx
, size_t quota
)
2733 cx
->scriptStackQuota
= quota
;
2736 /************************************************************************/
2739 JS_DestroyIdArray(JSContext
*cx
, JSIdArray
*ida
)
2744 JS_PUBLIC_API(JSBool
)
2745 JS_ValueToId(JSContext
*cx
, jsval v
, jsid
*idp
)
2748 assertSameCompartment(cx
, v
);
2749 return ValueToId(cx
, Valueify(v
), idp
);
2752 JS_PUBLIC_API(JSBool
)
2753 JS_IdToValue(JSContext
*cx
, jsid id
, jsval
*vp
)
2756 *vp
= IdToJsval(id
);
2757 assertSameCompartment(cx
, *vp
);
2761 JS_PUBLIC_API(JSBool
)
2762 JS_PropertyStub(JSContext
*cx
, JSObject
*obj
, jsid id
, jsval
*vp
)
2767 JS_PUBLIC_API(JSBool
)
2768 JS_EnumerateStub(JSContext
*cx
, JSObject
*obj
)
2773 JS_PUBLIC_API(JSBool
)
2774 JS_ResolveStub(JSContext
*cx
, JSObject
*obj
, jsid id
)
2779 JS_PUBLIC_API(JSBool
)
2780 JS_ConvertStub(JSContext
*cx
, JSObject
*obj
, JSType type
, jsval
*vp
)
2782 JS_ASSERT(type
!= JSTYPE_OBJECT
&& type
!= JSTYPE_FUNCTION
);
2783 return js_TryValueOf(cx
, obj
, type
, Valueify(vp
));
2787 JS_FinalizeStub(JSContext
*cx
, JSObject
*obj
)
2790 JS_PUBLIC_API(JSObject
*)
2791 JS_InitClass(JSContext
*cx
, JSObject
*obj
, JSObject
*parent_proto
,
2792 JSClass
*clasp
, JSNative constructor
, uintN nargs
,
2793 JSPropertySpec
*ps
, JSFunctionSpec
*fs
,
2794 JSPropertySpec
*static_ps
, JSFunctionSpec
*static_fs
)
2797 assertSameCompartment(cx
, obj
, parent_proto
);
2798 return js_InitClass(cx
, obj
, parent_proto
, Valueify(clasp
),
2799 Valueify(constructor
), nargs
,
2800 ps
, fs
, static_ps
, static_fs
);
2803 #ifdef JS_THREADSAFE
2804 JS_PUBLIC_API(JSClass
*)
2805 JS_GetClass(JSContext
*cx
, JSObject
*obj
)
2807 return Jsvalify(obj
->getClass());
2810 JS_PUBLIC_API(JSClass
*)
2811 JS_GetClass(JSObject
*obj
)
2813 return Jsvalify(obj
->getClass());
2817 JS_PUBLIC_API(JSBool
)
2818 JS_InstanceOf(JSContext
*cx
, JSObject
*obj
, JSClass
*clasp
, jsval
*argv
)
2821 assertSameCompartment(cx
, obj
);
2822 return InstanceOf(cx
, obj
, Valueify(clasp
), Valueify(argv
));
2825 JS_PUBLIC_API(JSBool
)
2826 JS_HasInstance(JSContext
*cx
, JSObject
*obj
, jsval v
, JSBool
*bp
)
2828 assertSameCompartment(cx
, obj
, v
);
2829 return HasInstance(cx
, obj
, Valueify(&v
), bp
);
2832 JS_PUBLIC_API(void *)
2833 JS_GetPrivate(JSContext
*cx
, JSObject
*obj
)
2835 assertSameCompartment(cx
, obj
);
2836 return obj
->getPrivate();
2839 JS_PUBLIC_API(JSBool
)
2840 JS_SetPrivate(JSContext
*cx
, JSObject
*obj
, void *data
)
2842 assertSameCompartment(cx
, obj
);
2843 obj
->setPrivate(data
);
2847 JS_PUBLIC_API(void *)
2848 JS_GetInstancePrivate(JSContext
*cx
, JSObject
*obj
, JSClass
*clasp
, jsval
*argv
)
2850 if (!InstanceOf(cx
, obj
, Valueify(clasp
), Valueify(argv
)))
2852 return obj
->getPrivate();
2855 JS_PUBLIC_API(JSObject
*)
2856 JS_GetPrototype(JSContext
*cx
, JSObject
*obj
)
2861 assertSameCompartment(cx
, obj
);
2862 proto
= obj
->getProto();
2864 /* Beware ref to dead object (we may be called from obj's finalizer). */
2865 return proto
&& proto
->map
? proto
: NULL
;
2868 JS_PUBLIC_API(JSBool
)
2869 JS_SetPrototype(JSContext
*cx
, JSObject
*obj
, JSObject
*proto
)
2872 assertSameCompartment(cx
, obj
, proto
);
2873 return SetProto(cx
, obj
, proto
, JS_FALSE
);
2876 JS_PUBLIC_API(JSObject
*)
2877 JS_GetParent(JSContext
*cx
, JSObject
*obj
)
2879 assertSameCompartment(cx
, obj
);
2880 JSObject
*parent
= obj
->getParent();
2882 /* Beware ref to dead object (we may be called from obj's finalizer). */
2883 return parent
&& parent
->map
? parent
: NULL
;
2886 JS_PUBLIC_API(JSBool
)
2887 JS_SetParent(JSContext
*cx
, JSObject
*obj
, JSObject
*parent
)
2890 JS_ASSERT(parent
|| !obj
->getParent());
2891 assertSameCompartment(cx
, obj
, parent
);
2892 obj
->setParent(parent
);
2896 JS_PUBLIC_API(JSObject
*)
2897 JS_GetConstructor(JSContext
*cx
, JSObject
*proto
)
2902 assertSameCompartment(cx
, proto
);
2904 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
);
2906 if (!proto
->getProperty(cx
, ATOM_TO_JSID(cx
->runtime
->atomState
.constructorAtom
), &cval
))
2910 if (!IsFunctionObject(cval
, &funobj
)) {
2911 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_NO_CONSTRUCTOR
,
2912 proto
->getClass()->name
);
2915 return &cval
.toObject();
2918 JS_PUBLIC_API(JSBool
)
2919 JS_GetObjectId(JSContext
*cx
, JSObject
*obj
, jsid
*idp
)
2921 assertSameCompartment(cx
, obj
);
2922 *idp
= OBJECT_TO_JSID(obj
);
2926 JS_PUBLIC_API(JSObject
*)
2927 JS_NewGlobalObject(JSContext
*cx
, JSClass
*clasp
)
2930 JS_ASSERT(clasp
->flags
& JSCLASS_IS_GLOBAL
);
2931 JSObject
*obj
= NewNonFunction
<WithProto::Given
>(cx
, Valueify(clasp
), NULL
, NULL
);
2933 !js_SetReservedSlot(cx
, obj
, JSRESERVED_GLOBAL_COMPARTMENT
,
2934 PrivateValue(cx
->compartment
))) {
2938 /* FIXME: comment. */
2939 JSObject
*res
= regexp_statics_construct(cx
);
2941 !js_SetReservedSlot(cx
, obj
, JSRESERVED_GLOBAL_REGEXP_STATICS
,
2942 ObjectValue(*res
))) {
2949 JS_PUBLIC_API(JSObject
*)
2950 JS_NewCompartmentAndGlobalObject(JSContext
*cx
, JSClass
*clasp
, JSPrincipals
*principals
)
2953 JSCompartment
*compartment
= NewCompartment(cx
, principals
);
2957 JSCompartment
*saved
= cx
->compartment
;
2958 cx
->compartment
= compartment
;
2959 JSObject
*obj
= JS_NewGlobalObject(cx
, clasp
);
2960 cx
->compartment
= saved
;
2965 JS_PUBLIC_API(JSObject
*)
2966 JS_NewObject(JSContext
*cx
, JSClass
*jsclasp
, JSObject
*proto
, JSObject
*parent
)
2969 assertSameCompartment(cx
, proto
, parent
);
2971 Class
*clasp
= Valueify(jsclasp
);
2973 clasp
= &js_ObjectClass
; /* default class is Object */
2975 JS_ASSERT(clasp
!= &js_FunctionClass
);
2976 JS_ASSERT(!(clasp
->flags
& JSCLASS_IS_GLOBAL
));
2978 JSObject
*obj
= NewNonFunction
<WithProto::Class
>(cx
, clasp
, proto
, parent
);
2980 JS_ASSERT_IF(obj
, obj
->getParent());
2984 JS_PUBLIC_API(JSObject
*)
2985 JS_NewObjectWithGivenProto(JSContext
*cx
, JSClass
*jsclasp
, JSObject
*proto
, JSObject
*parent
)
2988 assertSameCompartment(cx
, proto
, parent
);
2990 Class
*clasp
= Valueify(jsclasp
);
2992 clasp
= &js_ObjectClass
; /* default class is Object */
2994 JS_ASSERT(clasp
!= &js_FunctionClass
);
2995 JS_ASSERT(!(clasp
->flags
& JSCLASS_IS_GLOBAL
));
2997 return NewNonFunction
<WithProto::Given
>(cx
, clasp
, proto
, parent
);
3000 JS_PUBLIC_API(JSObject
*)
3001 JS_NewObjectForConstructor(JSContext
*cx
, const jsval
*vp
)
3004 assertSameCompartment(cx
, *vp
);
3006 return js_NewInstance(cx
, JSVAL_TO_OBJECT(*vp
));
3009 JS_PUBLIC_API(JSBool
)
3010 JS_IsExtensible(JSObject
*obj
)
3012 return obj
->isExtensible();
3015 JS_PUBLIC_API(JSBool
)
3016 JS_FreezeObject(JSContext
*cx
, JSObject
*obj
)
3019 assertSameCompartment(cx
, obj
);
3021 return obj
->freeze(cx
);
3024 JS_PUBLIC_API(JSBool
)
3025 JS_DeepFreezeObject(JSContext
*cx
, JSObject
*obj
)
3028 assertSameCompartment(cx
, obj
);
3030 /* Assume that non-extensible objects are already deep-frozen, to avoid divergence. */
3031 if (obj
->isExtensible())
3034 if (!obj
->freeze(cx
))
3037 /* Walk slots in obj and if any value is a non-null object, seal it. */
3038 for (uint32 i
= 0, n
= obj
->slotSpan(); i
< n
; ++i
) {
3039 const Value
&v
= obj
->getSlot(i
);
3040 if (i
== JSSLOT_PRIVATE
&& (obj
->getClass()->flags
& JSCLASS_HAS_PRIVATE
))
3042 if (v
.isPrimitive())
3044 if (!JS_DeepFreezeObject(cx
, &v
.toObject()))
3051 JS_PUBLIC_API(JSObject
*)
3052 JS_ConstructObject(JSContext
*cx
, JSClass
*jsclasp
, JSObject
*proto
, JSObject
*parent
)
3055 assertSameCompartment(cx
, proto
, parent
);
3056 Class
*clasp
= Valueify(jsclasp
);
3058 clasp
= &js_ObjectClass
; /* default class is Object */
3059 return js_ConstructObject(cx
, clasp
, proto
, parent
, 0, NULL
);
3062 JS_PUBLIC_API(JSObject
*)
3063 JS_ConstructObjectWithArguments(JSContext
*cx
, JSClass
*jsclasp
, JSObject
*proto
,
3064 JSObject
*parent
, uintN argc
, jsval
*argv
)
3067 assertSameCompartment(cx
, proto
, parent
, JSValueArray(argv
, argc
));
3068 Class
*clasp
= Valueify(jsclasp
);
3070 clasp
= &js_ObjectClass
; /* default class is Object */
3071 return js_ConstructObject(cx
, clasp
, proto
, parent
, argc
, Valueify(argv
));
3075 LookupPropertyById(JSContext
*cx
, JSObject
*obj
, jsid id
, uintN flags
,
3076 JSObject
**objp
, JSProperty
**propp
)
3079 assertSameCompartment(cx
, obj
, id
);
3081 JSAutoResolveFlags
rf(cx
, flags
);
3082 id
= js_CheckForStringIndex(id
);
3083 return obj
->lookupProperty(cx
, id
, objp
, propp
);
3086 #define AUTO_NAMELEN(s,n) (((n) == (size_t)-1) ? js_strlen(s) : (n))
3089 LookupResult(JSContext
*cx
, JSObject
*obj
, JSObject
*obj2
, jsid id
,
3090 JSProperty
*prop
, Value
*vp
)
3093 /* XXX bad API: no way to tell "not defined" from "void value" */
3098 if (obj2
->isNative()) {
3099 Shape
*shape
= (Shape
*) prop
;
3101 if (shape
->isMethod()) {
3102 AutoShapeRooter
root(cx
, shape
);
3103 JS_UNLOCK_OBJ(cx
, obj2
);
3104 vp
->setObject(shape
->methodObject());
3105 return obj2
->methodReadBarrier(cx
, *shape
, vp
);
3108 /* Peek at the native property's slot value, without doing a Get. */
3109 if (obj2
->containsSlot(shape
->slot
))
3110 *vp
= obj2
->lockedGetSlot(shape
->slot
);
3112 vp
->setBoolean(true);
3113 JS_UNLOCK_OBJ(cx
, obj2
);
3114 } else if (obj2
->isDenseArray()) {
3115 return js_GetDenseArrayElementValue(cx
, obj2
, id
, vp
);
3117 /* XXX bad API: no way to return "defined but value unknown" */
3118 vp
->setBoolean(true);
3123 JS_PUBLIC_API(JSBool
)
3124 JS_LookupPropertyById(JSContext
*cx
, JSObject
*obj
, jsid id
, jsval
*vp
)
3128 return LookupPropertyById(cx
, obj
, id
, JSRESOLVE_QUALIFIED
, &obj2
, &prop
) &&
3129 LookupResult(cx
, obj
, obj2
, id
, prop
, Valueify(vp
));
3132 JS_PUBLIC_API(JSBool
)
3133 JS_LookupElement(JSContext
*cx
, JSObject
*obj
, jsint index
, jsval
*vp
)
3135 return JS_LookupPropertyById(cx
, obj
, INT_TO_JSID(index
), vp
);
3138 JS_PUBLIC_API(JSBool
)
3139 JS_LookupProperty(JSContext
*cx
, JSObject
*obj
, const char *name
, jsval
*vp
)
3141 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3142 return atom
&& JS_LookupPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), vp
);
3145 JS_PUBLIC_API(JSBool
)
3146 JS_LookupUCProperty(JSContext
*cx
, JSObject
*obj
, const jschar
*name
, size_t namelen
, jsval
*vp
)
3148 JSAtom
*atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
3149 return atom
&& JS_LookupPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), vp
);
3152 JS_PUBLIC_API(JSBool
)
3153 JS_LookupPropertyWithFlagsById(JSContext
*cx
, JSObject
*obj
, jsid id
, uintN flags
,
3154 JSObject
**objp
, jsval
*vp
)
3160 assertSameCompartment(cx
, obj
, id
);
3161 ok
= obj
->isNative()
3162 ? js_LookupPropertyWithFlags(cx
, obj
, id
, flags
, objp
, &prop
) >= 0
3163 : obj
->lookupProperty(cx
, id
, objp
, &prop
);
3164 return ok
&& LookupResult(cx
, obj
, *objp
, id
, prop
, Valueify(vp
));
3167 JS_PUBLIC_API(JSBool
)
3168 JS_LookupPropertyWithFlags(JSContext
*cx
, JSObject
*obj
, const char *name
, uintN flags
, jsval
*vp
)
3171 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3172 return atom
&& JS_LookupPropertyWithFlagsById(cx
, obj
, ATOM_TO_JSID(atom
), flags
, &obj2
, vp
);
3176 HasPropertyResult(JSContext
*cx
, JSObject
*obj2
, JSProperty
*prop
, JSBool
*foundp
)
3178 *foundp
= (prop
!= NULL
);
3180 obj2
->dropProperty(cx
, prop
);
3184 JS_PUBLIC_API(JSBool
)
3185 JS_HasPropertyById(JSContext
*cx
, JSObject
*obj
, jsid id
, JSBool
*foundp
)
3189 return LookupPropertyById(cx
, obj
, id
, JSRESOLVE_QUALIFIED
| JSRESOLVE_DETECTING
,
3191 HasPropertyResult(cx
, obj2
, prop
, foundp
);
3194 JS_PUBLIC_API(JSBool
)
3195 JS_HasElement(JSContext
*cx
, JSObject
*obj
, jsint index
, JSBool
*foundp
)
3197 return JS_HasPropertyById(cx
, obj
, INT_TO_JSID(index
), foundp
);
3200 JS_PUBLIC_API(JSBool
)
3201 JS_HasProperty(JSContext
*cx
, JSObject
*obj
, const char *name
, JSBool
*foundp
)
3203 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3204 return atom
&& JS_HasPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), foundp
);
3207 JS_PUBLIC_API(JSBool
)
3208 JS_HasUCProperty(JSContext
*cx
, JSObject
*obj
, const jschar
*name
, size_t namelen
, JSBool
*foundp
)
3210 JSAtom
*atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
3211 return atom
&& JS_HasPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), foundp
);
3214 JS_PUBLIC_API(JSBool
)
3215 JS_AlreadyHasOwnPropertyById(JSContext
*cx
, JSObject
*obj
, jsid id
, JSBool
*foundp
)
3218 assertSameCompartment(cx
, obj
, id
);
3220 if (!obj
->isNative()) {
3224 if (!LookupPropertyById(cx
, obj
, id
, JSRESOLVE_QUALIFIED
| JSRESOLVE_DETECTING
,
3228 *foundp
= (obj
== obj2
);
3230 obj2
->dropProperty(cx
, prop
);
3234 JS_LOCK_OBJ(cx
, obj
);
3235 *foundp
= obj
->nativeContains(id
);
3236 JS_UNLOCK_OBJ(cx
, obj
);
3240 JS_PUBLIC_API(JSBool
)
3241 JS_AlreadyHasOwnElement(JSContext
*cx
, JSObject
*obj
, jsint index
, JSBool
*foundp
)
3243 return JS_AlreadyHasOwnPropertyById(cx
, obj
, INT_TO_JSID(index
), foundp
);
3246 JS_PUBLIC_API(JSBool
)
3247 JS_AlreadyHasOwnProperty(JSContext
*cx
, JSObject
*obj
, const char *name
, JSBool
*foundp
)
3249 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3250 return atom
&& JS_AlreadyHasOwnPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), foundp
);
3253 JS_PUBLIC_API(JSBool
)
3254 JS_AlreadyHasOwnUCProperty(JSContext
*cx
, JSObject
*obj
, const jschar
*name
, size_t namelen
,
3257 JSAtom
*atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
3258 return atom
&& JS_AlreadyHasOwnPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), foundp
);
3262 DefinePropertyById(JSContext
*cx
, JSObject
*obj
, jsid id
, const Value
&value
,
3263 PropertyOp getter
, PropertyOp setter
, uintN attrs
,
3264 uintN flags
, intN tinyid
)
3267 assertSameCompartment(cx
, obj
, id
, value
,
3268 (attrs
& JSPROP_GETTER
)
3269 ? JS_FUNC_TO_DATA_PTR(JSObject
*, getter
)
3271 (attrs
& JSPROP_SETTER
)
3272 ? JS_FUNC_TO_DATA_PTR(JSObject
*, setter
)
3275 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
| JSRESOLVE_DECLARING
);
3276 if (flags
!= 0 && obj
->isNative()) {
3277 return !!js_DefineNativeProperty(cx
, obj
, id
, value
, getter
, setter
,
3278 attrs
, flags
, tinyid
, NULL
);
3280 return obj
->defineProperty(cx
, id
, value
, getter
, setter
, attrs
);
3283 JS_PUBLIC_API(JSBool
)
3284 JS_DefinePropertyById(JSContext
*cx
, JSObject
*obj
, jsid id
, jsval value
,
3285 JSPropertyOp getter
, JSPropertyOp setter
, uintN attrs
)
3287 return DefinePropertyById(cx
, obj
, id
, Valueify(value
), Valueify(getter
),
3288 Valueify(setter
), attrs
, 0, 0);
3291 JS_PUBLIC_API(JSBool
)
3292 JS_DefineElement(JSContext
*cx
, JSObject
*obj
, jsint index
, jsval value
,
3293 JSPropertyOp getter
, JSPropertyOp setter
, uintN attrs
)
3295 return DefinePropertyById(cx
, obj
, INT_TO_JSID(index
), Valueify(value
),
3296 Valueify(getter
), Valueify(setter
), attrs
, 0, 0);
3300 DefineProperty(JSContext
*cx
, JSObject
*obj
, const char *name
, const Value
&value
,
3301 PropertyOp getter
, PropertyOp setter
, uintN attrs
,
3302 uintN flags
, intN tinyid
)
3307 if (attrs
& JSPROP_INDEX
) {
3308 id
= INT_TO_JSID(intptr_t(name
));
3310 attrs
&= ~JSPROP_INDEX
;
3312 atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3315 id
= ATOM_TO_JSID(atom
);
3317 return DefinePropertyById(cx
, obj
, id
, value
, getter
, setter
, attrs
, flags
, tinyid
);
3320 JS_PUBLIC_API(JSBool
)
3321 JS_DefineProperty(JSContext
*cx
, JSObject
*obj
, const char *name
, jsval value
,
3322 JSPropertyOp getter
, JSPropertyOp setter
, uintN attrs
)
3324 return DefineProperty(cx
, obj
, name
, Valueify(value
), Valueify(getter
),
3325 Valueify(setter
), attrs
, 0, 0);
3328 JS_PUBLIC_API(JSBool
)
3329 JS_DefinePropertyWithTinyId(JSContext
*cx
, JSObject
*obj
, const char *name
, int8 tinyid
,
3330 jsval value
, JSPropertyOp getter
, JSPropertyOp setter
, uintN attrs
)
3332 return DefineProperty(cx
, obj
, name
, Valueify(value
), Valueify(getter
),
3333 Valueify(setter
), attrs
, Shape::HAS_SHORTID
, tinyid
);
3337 DefineUCProperty(JSContext
*cx
, JSObject
*obj
, const jschar
*name
, size_t namelen
,
3338 const Value
&value
, PropertyOp getter
, PropertyOp setter
, uintN attrs
,
3339 uintN flags
, intN tinyid
)
3341 JSAtom
*atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
3342 return atom
&& DefinePropertyById(cx
, obj
, ATOM_TO_JSID(atom
), value
, getter
, setter
, attrs
,
3346 JS_PUBLIC_API(JSBool
)
3347 JS_DefineUCProperty(JSContext
*cx
, JSObject
*obj
, const jschar
*name
, size_t namelen
,
3348 jsval value
, JSPropertyOp getter
, JSPropertyOp setter
, uintN attrs
)
3350 return DefineUCProperty(cx
, obj
, name
, namelen
, Valueify(value
),
3351 Valueify(getter
), Valueify(setter
), attrs
, 0, 0);
3354 JS_PUBLIC_API(JSBool
)
3355 JS_DefineUCPropertyWithTinyId(JSContext
*cx
, JSObject
*obj
, const jschar
*name
, size_t namelen
,
3356 int8 tinyid
, jsval value
, JSPropertyOp getter
, JSPropertyOp setter
,
3359 return DefineUCProperty(cx
, obj
, name
, namelen
, Valueify(value
), Valueify(getter
),
3360 Valueify(setter
), attrs
, Shape::HAS_SHORTID
, tinyid
);
3363 JS_PUBLIC_API(JSBool
)
3364 JS_DefineOwnProperty(JSContext
*cx
, JSObject
*obj
, jsid id
, jsval descriptor
, JSBool
*bp
)
3367 assertSameCompartment(cx
, obj
, id
, descriptor
);
3368 return js_DefineOwnProperty(cx
, obj
, id
, Valueify(descriptor
), bp
);
3371 JS_PUBLIC_API(JSObject
*)
3372 JS_DefineObject(JSContext
*cx
, JSObject
*obj
, const char *name
, JSClass
*jsclasp
,
3373 JSObject
*proto
, uintN attrs
)
3376 assertSameCompartment(cx
, obj
, proto
);
3378 Class
*clasp
= Valueify(jsclasp
);
3380 clasp
= &js_ObjectClass
; /* default class is Object */
3382 JSObject
*nobj
= NewObject
<WithProto::Class
>(cx
, clasp
, proto
, obj
);
3386 if (!DefineProperty(cx
, obj
, name
, ObjectValue(*nobj
), NULL
, NULL
, attrs
, 0, 0))
3392 JS_PUBLIC_API(JSBool
)
3393 JS_DefineConstDoubles(JSContext
*cx
, JSObject
*obj
, JSConstDoubleSpec
*cds
)
3399 for (ok
= JS_TRUE
; cds
->name
; cds
++) {
3400 Value value
= DoubleValue(cds
->dval
);
3403 attrs
= JSPROP_READONLY
| JSPROP_PERMANENT
;
3404 ok
= DefineProperty(cx
, obj
, cds
->name
, value
, NULL
, NULL
, attrs
, 0, 0);
3411 JS_PUBLIC_API(JSBool
)
3412 JS_DefineProperties(JSContext
*cx
, JSObject
*obj
, JSPropertySpec
*ps
)
3416 for (ok
= true; ps
->name
; ps
++) {
3417 ok
= DefineProperty(cx
, obj
, ps
->name
, UndefinedValue(),
3418 Valueify(ps
->getter
), Valueify(ps
->setter
),
3419 ps
->flags
, Shape::HAS_SHORTID
, ps
->tinyid
);
3426 JS_PUBLIC_API(JSBool
)
3427 JS_AliasProperty(JSContext
*cx
, JSObject
*obj
, const char *name
, const char *alias
)
3435 assertSameCompartment(cx
, obj
);
3437 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3440 if (!LookupPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), JSRESOLVE_QUALIFIED
, &obj2
, &prop
))
3443 js_ReportIsNotDefined(cx
, name
);
3446 if (obj2
!= obj
|| !obj
->isNative()) {
3447 obj2
->dropProperty(cx
, prop
);
3448 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_CANT_ALIAS
,
3449 alias
, name
, obj2
->getClass()->name
);
3452 atom
= js_Atomize(cx
, alias
, strlen(alias
), 0);
3456 shape
= (Shape
*)prop
;
3457 ok
= (js_AddNativeProperty(cx
, obj
, ATOM_TO_JSID(atom
),
3458 shape
->getter(), shape
->setter(), shape
->slot
,
3459 shape
->attributes(), shape
->getFlags() | Shape::ALIAS
,
3463 JS_UNLOCK_OBJ(cx
, obj
);
3467 JS_PUBLIC_API(JSBool
)
3468 JS_AliasElement(JSContext
*cx
, JSObject
*obj
, const char *name
, jsint alias
)
3476 assertSameCompartment(cx
, obj
);
3478 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3481 if (!LookupPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), JSRESOLVE_QUALIFIED
, &obj2
, &prop
))
3484 js_ReportIsNotDefined(cx
, name
);
3487 if (obj2
!= obj
|| !obj
->isNative()) {
3489 obj2
->dropProperty(cx
, prop
);
3490 JS_snprintf(numBuf
, sizeof numBuf
, "%ld", (long)alias
);
3491 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_CANT_ALIAS
,
3492 numBuf
, name
, obj2
->getClass()->name
);
3495 shape
= (Shape
*)prop
;
3496 ok
= (js_AddNativeProperty(cx
, obj
, INT_TO_JSID(alias
),
3497 shape
->getter(), shape
->setter(), shape
->slot
,
3498 shape
->attributes(), shape
->getFlags() | Shape::ALIAS
,
3501 JS_UNLOCK_OBJ(cx
, obj
);
3506 GetPropertyDescriptorById(JSContext
*cx
, JSObject
*obj
, jsid id
, uintN flags
,
3507 JSBool own
, PropertyDescriptor
*desc
)
3512 if (!LookupPropertyById(cx
, obj
, id
, flags
, &obj2
, &prop
))
3515 if (!prop
|| (own
&& obj
!= obj2
)) {
3518 desc
->getter
= NULL
;
3519 desc
->setter
= NULL
;
3520 desc
->value
.setUndefined();
3522 obj2
->dropProperty(cx
, prop
);
3527 if (obj2
->isNative()) {
3528 Shape
*shape
= (Shape
*) prop
;
3529 desc
->attrs
= shape
->attributes();
3531 if (shape
->isMethod()) {
3532 desc
->getter
= desc
->setter
= PropertyStub
;
3533 desc
->value
.setObject(shape
->methodObject());
3535 desc
->getter
= shape
->getter();
3536 desc
->setter
= shape
->setter();
3537 if (obj2
->containsSlot(shape
->slot
))
3538 desc
->value
= obj2
->lockedGetSlot(shape
->slot
);
3540 desc
->value
.setUndefined();
3542 JS_UNLOCK_OBJ(cx
, obj2
);
3544 if (obj2
->isProxy()) {
3545 JSAutoResolveFlags
rf(cx
, flags
);
3547 ? JSProxy::getOwnPropertyDescriptor(cx
, obj2
, id
, desc
)
3548 : JSProxy::getPropertyDescriptor(cx
, obj2
, id
, 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
) {
3641 obj2
->dropProperty(cx
, prop
);
3644 JSBool ok
= obj
->isNative()
3645 ? js_SetNativeAttributes(cx
, obj
, (Shape
*) prop
, attrs
)
3646 : obj
->setAttributes(cx
, id
, &attrs
);
3652 JS_PUBLIC_API(JSBool
)
3653 JS_SetPropertyAttributes(JSContext
*cx
, JSObject
*obj
, const char *name
,
3654 uintN attrs
, JSBool
*foundp
)
3656 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3657 return atom
&& SetPropertyAttributesById(cx
, obj
, ATOM_TO_JSID(atom
), attrs
, foundp
);
3660 JS_PUBLIC_API(JSBool
)
3661 JS_SetUCPropertyAttributes(JSContext
*cx
, JSObject
*obj
, const jschar
*name
, size_t namelen
,
3662 uintN attrs
, JSBool
*foundp
)
3664 JSAtom
*atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
3665 return atom
&& SetPropertyAttributesById(cx
, obj
, ATOM_TO_JSID(atom
), attrs
, foundp
);
3668 JS_PUBLIC_API(JSBool
)
3669 JS_GetPropertyById(JSContext
*cx
, JSObject
*obj
, jsid id
, jsval
*vp
)
3672 assertSameCompartment(cx
, obj
, id
);
3673 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
);
3674 return obj
->getProperty(cx
, id
, Valueify(vp
));
3677 JS_PUBLIC_API(JSBool
)
3678 JS_GetElement(JSContext
*cx
, JSObject
*obj
, jsint index
, jsval
*vp
)
3680 return JS_GetPropertyById(cx
, obj
, INT_TO_JSID(index
), vp
);
3683 JS_PUBLIC_API(JSBool
)
3684 JS_GetProperty(JSContext
*cx
, JSObject
*obj
, const char *name
, jsval
*vp
)
3686 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3687 return atom
&& JS_GetPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), vp
);
3690 JS_PUBLIC_API(JSBool
)
3691 JS_GetUCProperty(JSContext
*cx
, JSObject
*obj
, const jschar
*name
, size_t namelen
, jsval
*vp
)
3693 JSAtom
*atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
3694 return atom
&& JS_GetPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), vp
);
3697 JS_PUBLIC_API(JSBool
)
3698 JS_GetMethodById(JSContext
*cx
, JSObject
*obj
, jsid id
, JSObject
**objp
, jsval
*vp
)
3701 assertSameCompartment(cx
, obj
, id
);
3702 if (!js_GetMethod(cx
, obj
, id
, JSGET_METHOD_BARRIER
, Valueify(vp
)))
3709 JS_PUBLIC_API(JSBool
)
3710 JS_GetMethod(JSContext
*cx
, JSObject
*obj
, const char *name
, JSObject
**objp
, jsval
*vp
)
3712 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3713 return atom
&& JS_GetMethodById(cx
, obj
, ATOM_TO_JSID(atom
), objp
, vp
);
3716 JS_PUBLIC_API(JSBool
)
3717 JS_SetPropertyById(JSContext
*cx
, JSObject
*obj
, jsid id
, jsval
*vp
)
3720 assertSameCompartment(cx
, obj
, id
);
3721 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
| JSRESOLVE_ASSIGNING
);
3722 return obj
->setProperty(cx
, id
, Valueify(vp
), false);
3725 JS_PUBLIC_API(JSBool
)
3726 JS_SetElement(JSContext
*cx
, JSObject
*obj
, jsint index
, jsval
*vp
)
3728 return JS_SetPropertyById(cx
, obj
, INT_TO_JSID(index
), vp
);
3731 JS_PUBLIC_API(JSBool
)
3732 JS_SetProperty(JSContext
*cx
, JSObject
*obj
, const char *name
, jsval
*vp
)
3734 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3735 return atom
&& JS_SetPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), vp
);
3738 JS_PUBLIC_API(JSBool
)
3739 JS_SetUCProperty(JSContext
*cx
, JSObject
*obj
, const jschar
*name
, size_t namelen
, jsval
*vp
)
3741 JSAtom
*atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
3742 return atom
&& JS_SetPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), vp
);
3745 JS_PUBLIC_API(JSBool
)
3746 JS_DeletePropertyById2(JSContext
*cx
, JSObject
*obj
, jsid id
, jsval
*rval
)
3749 assertSameCompartment(cx
, obj
, id
);
3750 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
);
3751 return obj
->deleteProperty(cx
, id
, Valueify(rval
), false);
3754 JS_PUBLIC_API(JSBool
)
3755 JS_DeleteElement2(JSContext
*cx
, JSObject
*obj
, jsint index
, jsval
*rval
)
3757 return JS_DeletePropertyById2(cx
, obj
, INT_TO_JSID(index
), rval
);
3760 JS_PUBLIC_API(JSBool
)
3761 JS_DeleteProperty2(JSContext
*cx
, JSObject
*obj
, const char *name
, jsval
*rval
)
3763 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3764 return atom
&& JS_DeletePropertyById2(cx
, obj
, ATOM_TO_JSID(atom
), rval
);
3767 JS_PUBLIC_API(JSBool
)
3768 JS_DeleteUCProperty2(JSContext
*cx
, JSObject
*obj
, const jschar
*name
, size_t namelen
, jsval
*rval
)
3770 JSAtom
*atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
3771 return atom
&& JS_DeletePropertyById2(cx
, obj
, ATOM_TO_JSID(atom
), rval
);
3774 JS_PUBLIC_API(JSBool
)
3775 JS_DeletePropertyById(JSContext
*cx
, JSObject
*obj
, jsid id
)
3778 return JS_DeletePropertyById2(cx
, obj
, id
, &junk
);
3781 JS_PUBLIC_API(JSBool
)
3782 JS_DeleteElement(JSContext
*cx
, JSObject
*obj
, jsint index
)
3785 return JS_DeleteElement2(cx
, obj
, index
, &junk
);
3788 JS_PUBLIC_API(JSBool
)
3789 JS_DeleteProperty(JSContext
*cx
, JSObject
*obj
, const char *name
)
3792 return JS_DeleteProperty2(cx
, obj
, name
, &junk
);
3796 JS_ClearScope(JSContext
*cx
, JSObject
*obj
)
3799 assertSameCompartment(cx
, obj
);
3801 JSFinalizeOp clearOp
= obj
->getOps()->clear
;
3805 if (obj
->isNative())
3806 js_ClearNative(cx
, obj
);
3808 /* Clear cached class objects on the global object. */
3809 if (obj
->getClass()->flags
& JSCLASS_IS_GLOBAL
) {
3812 for (key
= JSProto_Null
; key
< JSProto_LIMIT
* 3; key
++)
3813 JS_SetReservedSlot(cx
, obj
, key
, JSVAL_VOID
);
3819 JS_PUBLIC_API(JSIdArray
*)
3820 JS_Enumerate(JSContext
*cx
, JSObject
*obj
)
3823 assertSameCompartment(cx
, obj
);
3825 AutoIdVector
props(cx
);
3827 if (!GetPropertyNames(cx
, obj
, JSITER_OWNONLY
, &props
) || !VectorToIdArray(cx
, props
, &ida
))
3829 for (size_t n
= 0; n
< size_t(ida
->length
); ++n
)
3830 JS_ASSERT(js_CheckForStringIndex(ida
->vector
[n
]) == ida
->vector
[n
]);
3835 * XXX reverse iterator for properties, unreverse and meld with jsinterp.c's
3836 * prop_iterator_class somehow...
3837 * + preserve the obj->enumerate API while optimizing the native object case
3838 * + native case here uses a Shape *, but that iterates in reverse!
3839 * + so we make non-native match, by reverse-iterating after JS_Enumerating
3841 const uint32 JSSLOT_ITER_INDEX
= JSSLOT_PRIVATE
+ 1;
3842 JS_STATIC_ASSERT(JSSLOT_ITER_INDEX
< JS_INITIAL_NSLOTS
);
3845 prop_iter_finalize(JSContext
*cx
, JSObject
*obj
)
3847 void *pdata
= obj
->getPrivate();
3851 if (obj
->fslots
[JSSLOT_ITER_INDEX
].toInt32() >= 0) {
3852 /* Non-native case: destroy the ida enumerated when obj was created. */
3853 JSIdArray
*ida
= (JSIdArray
*) pdata
;
3854 JS_DestroyIdArray(cx
, ida
);
3859 prop_iter_trace(JSTracer
*trc
, JSObject
*obj
)
3861 void *pdata
= obj
->getPrivate();
3865 if (obj
->fslots
[JSSLOT_ITER_INDEX
].toInt32() < 0) {
3866 /* Native case: just mark the next property to visit. */
3867 ((Shape
*) pdata
)->trace(trc
);
3869 /* Non-native case: mark each id in the JSIdArray private. */
3870 JSIdArray
*ida
= (JSIdArray
*) pdata
;
3871 MarkIdRange(trc
, ida
->length
, ida
->vector
, "prop iter");
3875 static Class prop_iter_class
= {
3877 JSCLASS_HAS_PRIVATE
| JSCLASS_HAS_RESERVED_SLOTS(1) |
3878 JSCLASS_MARK_IS_TRACE
,
3879 PropertyStub
, /* addProperty */
3880 PropertyStub
, /* delProperty */
3881 PropertyStub
, /* getProperty */
3882 PropertyStub
, /* setProperty */
3887 NULL
, /* reserved0 */
3888 NULL
, /* checkAccess */
3890 NULL
, /* construct */
3891 NULL
, /* xdrObject */
3892 NULL
, /* hasInstance */
3893 JS_CLASS_TRACE(prop_iter_trace
)
3896 JS_PUBLIC_API(JSObject
*)
3897 JS_NewPropertyIterator(JSContext
*cx
, JSObject
*obj
)
3905 assertSameCompartment(cx
, obj
);
3906 iterobj
= NewNonFunction
<WithProto::Class
>(cx
, &prop_iter_class
, NULL
, obj
);
3910 if (obj
->isNative()) {
3911 /* Native case: start with the last property in obj. */
3912 pdata
= obj
->lastProperty();
3916 * Non-native case: enumerate a JSIdArray and keep it via private.
3918 * Note: we have to make sure that we root obj around the call to
3919 * JS_Enumerate to protect against multiple allocations under it.
3921 AutoObjectRooter
tvr(cx
, iterobj
);
3922 ida
= JS_Enumerate(cx
, obj
);
3926 index
= ida
->length
;
3929 /* iterobj cannot escape to other threads here. */
3930 iterobj
->setPrivate(const_cast<void *>(pdata
));
3931 iterobj
->fslots
[JSSLOT_ITER_INDEX
].setInt32(index
);
3935 JS_PUBLIC_API(JSBool
)
3936 JS_NextProperty(JSContext
*cx
, JSObject
*iterobj
, jsid
*idp
)
3944 assertSameCompartment(cx
, iterobj
);
3945 i
= iterobj
->fslots
[JSSLOT_ITER_INDEX
].toInt32();
3947 /* Native case: private data is a property tree node pointer. */
3948 obj
= iterobj
->getParent();
3949 JS_ASSERT(obj
->isNative());
3950 shape
= (Shape
*) iterobj
->getPrivate();
3953 * If the next property mapped by obj in the property tree ancestor
3954 * line is not enumerable, or it's an alias, skip it and keep on trying
3955 * to find an enumerable property that is still in obj.
3957 while (shape
->previous() && (!shape
->enumerable() || shape
->isAlias()))
3958 shape
= shape
->previous();
3960 if (!shape
->previous()) {
3961 JS_ASSERT(JSID_IS_EMPTY(shape
->id
));
3964 iterobj
->setPrivate(const_cast<Shape
*>(shape
->previous()));
3968 /* Non-native case: use the ida enumerated when iterobj was created. */
3969 ida
= (JSIdArray
*) iterobj
->getPrivate();
3970 JS_ASSERT(i
<= ida
->length
);
3974 *idp
= ida
->vector
[--i
];
3975 iterobj
->setSlot(JSSLOT_ITER_INDEX
, Int32Value(i
));
3981 JS_PUBLIC_API(JSBool
)
3982 JS_GetReservedSlot(JSContext
*cx
, JSObject
*obj
, uint32 index
, jsval
*vp
)
3985 assertSameCompartment(cx
, obj
);
3986 return js_GetReservedSlot(cx
, obj
, index
, Valueify(vp
));
3989 JS_PUBLIC_API(JSBool
)
3990 JS_SetReservedSlot(JSContext
*cx
, JSObject
*obj
, uint32 index
, jsval v
)
3993 assertSameCompartment(cx
, obj
, v
);
3994 return js_SetReservedSlot(cx
, obj
, index
, Valueify(v
));
3997 JS_PUBLIC_API(JSObject
*)
3998 JS_NewArrayObject(JSContext
*cx
, jsint length
, jsval
*vector
)
4001 /* NB: jsuint cast does ToUint32. */
4002 assertSameCompartment(cx
, JSValueArray(vector
, vector
? (jsuint
)length
: 0));
4003 return js_NewArrayObject(cx
, (jsuint
)length
, Valueify(vector
));
4006 JS_PUBLIC_API(JSBool
)
4007 JS_IsArrayObject(JSContext
*cx
, JSObject
*obj
)
4009 assertSameCompartment(cx
, obj
);
4010 return obj
->wrappedObject(cx
)->isArray();
4013 JS_PUBLIC_API(JSBool
)
4014 JS_GetArrayLength(JSContext
*cx
, JSObject
*obj
, jsuint
*lengthp
)
4017 assertSameCompartment(cx
, obj
);
4018 return js_GetLengthProperty(cx
, obj
, lengthp
);
4021 JS_PUBLIC_API(JSBool
)
4022 JS_SetArrayLength(JSContext
*cx
, JSObject
*obj
, jsuint length
)
4025 assertSameCompartment(cx
, obj
);
4026 return js_SetLengthProperty(cx
, obj
, length
);
4029 JS_PUBLIC_API(JSBool
)
4030 JS_HasArrayLength(JSContext
*cx
, JSObject
*obj
, jsuint
*lengthp
)
4033 assertSameCompartment(cx
, obj
);
4034 return js_HasLengthProperty(cx
, obj
, lengthp
);
4037 JS_PUBLIC_API(JSBool
)
4038 JS_CheckAccess(JSContext
*cx
, JSObject
*obj
, jsid id
, JSAccessMode mode
,
4039 jsval
*vp
, uintN
*attrsp
)
4042 assertSameCompartment(cx
, obj
, id
);
4043 return CheckAccess(cx
, obj
, id
, mode
, Valueify(vp
), attrsp
);
4046 #ifdef JS_THREADSAFE
4047 JS_PUBLIC_API(jsrefcount
)
4048 JS_HoldPrincipals(JSContext
*cx
, JSPrincipals
*principals
)
4050 return JS_ATOMIC_INCREMENT(&principals
->refcount
);
4053 JS_PUBLIC_API(jsrefcount
)
4054 JS_DropPrincipals(JSContext
*cx
, JSPrincipals
*principals
)
4056 jsrefcount rc
= JS_ATOMIC_DECREMENT(&principals
->refcount
);
4058 principals
->destroy(cx
, principals
);
4063 JS_PUBLIC_API(JSSecurityCallbacks
*)
4064 JS_SetRuntimeSecurityCallbacks(JSRuntime
*rt
, JSSecurityCallbacks
*callbacks
)
4066 JSSecurityCallbacks
*oldcallbacks
;
4068 oldcallbacks
= rt
->securityCallbacks
;
4069 rt
->securityCallbacks
= callbacks
;
4070 return oldcallbacks
;
4073 JS_PUBLIC_API(JSSecurityCallbacks
*)
4074 JS_GetRuntimeSecurityCallbacks(JSRuntime
*rt
)
4076 return rt
->securityCallbacks
;
4079 JS_PUBLIC_API(JSSecurityCallbacks
*)
4080 JS_SetContextSecurityCallbacks(JSContext
*cx
, JSSecurityCallbacks
*callbacks
)
4082 JSSecurityCallbacks
*oldcallbacks
;
4084 oldcallbacks
= cx
->securityCallbacks
;
4085 cx
->securityCallbacks
= callbacks
;
4086 return oldcallbacks
;
4089 JS_PUBLIC_API(JSSecurityCallbacks
*)
4090 JS_GetSecurityCallbacks(JSContext
*cx
)
4092 return cx
->securityCallbacks
4093 ? cx
->securityCallbacks
4094 : cx
->runtime
->securityCallbacks
;
4097 JS_PUBLIC_API(JSFunction
*)
4098 JS_NewFunction(JSContext
*cx
, JSNative native
, uintN nargs
, uintN flags
,
4099 JSObject
*parent
, const char *name
)
4104 assertSameCompartment(cx
, parent
);
4109 atom
= js_Atomize(cx
, name
, strlen(name
), 0);
4113 return js_NewFunction(cx
, NULL
, Valueify(native
), nargs
, flags
, parent
, atom
);
4116 JS_PUBLIC_API(JSObject
*)
4117 JS_CloneFunctionObject(JSContext
*cx
, JSObject
*funobj
, JSObject
*parent
)
4120 assertSameCompartment(cx
, parent
); // XXX no funobj for now
4123 parent
= js_GetScopeChain(cx
, cx
->fp());
4125 parent
= cx
->globalObject
;
4129 if (funobj
->getClass() != &js_FunctionClass
) {
4131 * We cannot clone this object, so fail (we used to return funobj, bad
4132 * idea, but we changed incompatibly to teach any abusers a lesson!).
4134 Value v
= ObjectValue(*funobj
);
4135 js_ReportIsNotFunction(cx
, &v
, 0);
4139 JSFunction
*fun
= GET_FUNCTION_PRIVATE(cx
, funobj
);
4140 if (!FUN_FLAT_CLOSURE(fun
))
4141 return CloneFunctionObject(cx
, fun
, parent
);
4144 * A flat closure carries its own environment, so why clone it? In case
4145 * someone wants to mutate its fixed slots or add ad-hoc properties. API
4146 * compatibility suggests we not return funobj and let callers mutate the
4147 * returned object at will.
4149 * But it's worse than that: API compatibility according to the test for
4150 * bug 300079 requires we get "upvars" from parent and its ancestors! So
4151 * we do that (grudgingly!). The scope chain ancestors are searched as if
4152 * they were activations, respecting the skip field in each upvar's cookie
4153 * but looking up the property by name instead of frame slot.
4155 JSObject
*clone
= js_AllocFlatClosure(cx
, fun
, parent
);
4159 JSUpvarArray
*uva
= fun
->u
.i
.script
->upvars();
4160 uint32 i
= uva
->length
;
4163 for (Shape::Range
r(fun
->lastUpvar()); i
-- != 0; r
.popFront()) {
4164 JSObject
*obj
= parent
;
4165 int skip
= uva
->vector
[i
].level();
4166 while (--skip
> 0) {
4168 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
,
4169 JSMSG_BAD_CLONE_FUNOBJ_SCOPE
);
4172 obj
= obj
->getParent();
4175 if (!obj
->getProperty(cx
, r
.front().id
, clone
->getFlatClosureUpvars() + i
))
4182 JS_PUBLIC_API(JSObject
*)
4183 JS_GetFunctionObject(JSFunction
*fun
)
4185 return FUN_OBJECT(fun
);
4188 JS_PUBLIC_API(const char *)
4189 JS_GetFunctionName(JSFunction
*fun
)
4192 ? JS_GetStringBytes(ATOM_TO_STRING(fun
->atom
))
4196 JS_PUBLIC_API(JSString
*)
4197 JS_GetFunctionId(JSFunction
*fun
)
4199 return fun
->atom
? ATOM_TO_STRING(fun
->atom
) : NULL
;
4202 JS_PUBLIC_API(uintN
)
4203 JS_GetFunctionFlags(JSFunction
*fun
)
4208 JS_PUBLIC_API(uint16
)
4209 JS_GetFunctionArity(JSFunction
*fun
)
4214 JS_PUBLIC_API(JSBool
)
4215 JS_ObjectIsFunction(JSContext
*cx
, JSObject
*obj
)
4217 return obj
->getClass() == &js_FunctionClass
;
4221 js_generic_native_method_dispatcher(JSContext
*cx
, uintN argc
, Value
*vp
)
4227 fs
= (JSFunctionSpec
*) vp
->toObject().getReservedSlot(0).toPrivate();
4228 JS_ASSERT((fs
->flags
& JSFUN_GENERIC_NATIVE
) != 0);
4231 js_ReportMissingArg(cx
, *vp
, 0);
4235 if (vp
[2].isPrimitive()) {
4237 * Make sure that this is an object or null, as required by the generic
4240 if (!js_ValueToObjectOrNull(cx
, vp
[2], &tmp
))
4242 vp
[2].setObjectOrNull(tmp
);
4246 * Copy all actual (argc) arguments down over our |this| parameter, vp[1],
4247 * which is almost always the class constructor object, e.g. Array. Then
4248 * call the corresponding prototype native method with our first argument
4251 memmove(vp
+ 1, vp
+ 2, argc
* sizeof(jsval
));
4254 * Follow Function.prototype.apply and .call by using the global object as
4255 * the 'this' param if no args.
4257 if (!ComputeThisFromArgv(cx
, vp
+ 2))
4260 /* Clear the last parameter in case too few arguments were passed. */
4261 vp
[2 + --argc
].setUndefined();
4265 (fs
->flags
& JSFUN_TRCINFO
)
4266 ? JS_FUNC_TO_DATA_PTR(JSNativeTraceInfo
*, fs
->call
)->native
4270 return native(cx
, argc
, vp
);
4273 JS_PUBLIC_API(JSBool
)
4274 JS_DefineFunctions(JSContext
*cx
, JSObject
*obj
, JSFunctionSpec
*fs
)
4281 assertSameCompartment(cx
, obj
);
4283 for (; fs
->name
; fs
++) {
4287 * Define a generic arity N+1 static method for the arity N prototype
4288 * method if flags contains JSFUN_GENERIC_NATIVE.
4290 if (flags
& JSFUN_GENERIC_NATIVE
) {
4292 ctor
= JS_GetConstructor(cx
, obj
);
4297 flags
&= ~JSFUN_GENERIC_NATIVE
;
4298 fun
= JS_DefineFunction(cx
, ctor
, fs
->name
,
4299 Jsvalify(js_generic_native_method_dispatcher
),
4301 flags
& ~JSFUN_TRCINFO
);
4306 * As jsapi.h notes, fs must point to storage that lives as long
4307 * as fun->object lives.
4309 Value priv
= PrivateValue(fs
);
4310 if (!js_SetReservedSlot(cx
, FUN_OBJECT(fun
), 0, priv
))
4314 fun
= JS_DefineFunction(cx
, obj
, fs
->name
, fs
->call
, fs
->nargs
, flags
);
4321 JS_PUBLIC_API(JSFunction
*)
4322 JS_DefineFunction(JSContext
*cx
, JSObject
*obj
, const char *name
, JSNative call
,
4323 uintN nargs
, uintN attrs
)
4326 assertSameCompartment(cx
, obj
);
4327 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
4328 return atom
? js_DefineFunction(cx
, obj
, atom
, Valueify(call
), nargs
, attrs
) : NULL
;
4331 JS_PUBLIC_API(JSFunction
*)
4332 JS_DefineUCFunction(JSContext
*cx
, JSObject
*obj
,
4333 const jschar
*name
, size_t namelen
, JSNative call
,
4334 uintN nargs
, uintN attrs
)
4337 assertSameCompartment(cx
, obj
);
4338 JSAtom
*atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
4339 return atom
? js_DefineFunction(cx
, obj
, atom
, Valueify(call
), nargs
, attrs
) : NULL
;
4343 LAST_FRAME_EXCEPTION_CHECK(JSContext
*cx
, bool result
)
4345 if (!result
&& !(cx
->options
& JSOPTION_DONT_REPORT_UNCAUGHT
))
4346 js_ReportUncaughtException(cx
);
4350 LAST_FRAME_CHECKS(JSContext
*cx
, bool result
)
4352 if (!JS_IsRunning(cx
)) {
4353 LAST_FRAME_EXCEPTION_CHECK(cx
, result
);
4357 inline static uint32
4358 JS_OPTIONS_TO_TCFLAGS(JSContext
*cx
)
4360 return ((cx
->options
& JSOPTION_COMPILE_N_GO
) ? TCF_COMPILE_N_GO
: 0) |
4361 ((cx
->options
& JSOPTION_NO_SCRIPT_RVAL
) ? TCF_NO_SCRIPT_RVAL
: 0);
4364 extern JS_PUBLIC_API(JSScript
*)
4365 JS_CompileUCScriptForPrincipalsVersion(JSContext
*cx
, JSObject
*obj
,
4366 JSPrincipals
*principals
,
4367 const jschar
*chars
, size_t length
,
4368 const char *filename
, uintN lineno
,
4371 AutoVersionAPI
avi(cx
, version
);
4372 return JS_CompileUCScriptForPrincipals(cx
, obj
, principals
, chars
, length
, filename
, lineno
);
4375 JS_PUBLIC_API(JSScript
*)
4376 JS_CompileUCScriptForPrincipals(JSContext
*cx
, JSObject
*obj
, JSPrincipals
*principals
,
4377 const jschar
*chars
, size_t length
,
4378 const char *filename
, uintN lineno
)
4381 assertSameCompartment(cx
, obj
, principals
);
4383 uint32 tcflags
= JS_OPTIONS_TO_TCFLAGS(cx
) | TCF_NEED_MUTABLE_SCRIPT
;
4384 JSScript
*script
= Compiler::compileScript(cx
, obj
, NULL
, principals
, tcflags
,
4385 chars
, length
, NULL
, filename
, lineno
);
4386 if (script
&& !js_NewScriptObject(cx
, script
)) {
4387 js_DestroyScript(cx
, script
);
4390 LAST_FRAME_CHECKS(cx
, script
);
4394 JS_PUBLIC_API(JSScript
*)
4395 JS_CompileUCScript(JSContext
*cx
, JSObject
*obj
, const jschar
*chars
, size_t length
,
4396 const char *filename
, uintN lineno
)
4398 return JS_CompileUCScriptForPrincipals(cx
, obj
, NULL
, chars
, length
, filename
, lineno
);
4401 JS_PUBLIC_API(JSScript
*)
4402 JS_CompileScriptForPrincipals(JSContext
*cx
, JSObject
*obj
,
4403 JSPrincipals
*principals
,
4404 const char *bytes
, size_t length
,
4405 const char *filename
, uintN lineno
)
4409 jschar
*chars
= js_InflateString(cx
, bytes
, &length
);
4412 JSScript
*script
= JS_CompileUCScriptForPrincipals(cx
, obj
, principals
, chars
, length
, filename
, lineno
);
4417 JS_PUBLIC_API(JSScript
*)
4418 JS_CompileScript(JSContext
*cx
, JSObject
*obj
, const char *bytes
, size_t length
,
4419 const char *filename
, uintN lineno
)
4421 return JS_CompileScriptForPrincipals(cx
, obj
, NULL
, bytes
, length
, filename
, lineno
);
4424 JS_PUBLIC_API(JSBool
)
4425 JS_BufferIsCompilableUnit(JSContext
*cx
, JSObject
*obj
, const char *bytes
, size_t length
)
4429 JSExceptionState
*exnState
;
4430 JSErrorReporter older
;
4433 assertSameCompartment(cx
, obj
);
4434 chars
= js_InflateString(cx
, bytes
, &length
);
4439 * Return true on any out-of-memory error, so our caller doesn't try to
4440 * collect more buffered source.
4443 exnState
= JS_SaveExceptionState(cx
);
4446 if (parser
.init(chars
, length
, NULL
, NULL
, 1)) {
4447 older
= JS_SetErrorReporter(cx
, NULL
);
4448 if (!parser
.parse(obj
) &&
4449 parser
.tokenStream
.isUnexpectedEOF()) {
4451 * We ran into an error. If it was because we ran out of
4452 * source, we return false so our caller knows to try to
4453 * collect more buffered source.
4457 JS_SetErrorReporter(cx
, older
);
4461 JS_RestoreExceptionState(cx
, exnState
);
4465 JS_PUBLIC_API(JSScript
*)
4466 JS_CompileFile(JSContext
*cx
, JSObject
*obj
, const char *filename
)
4473 assertSameCompartment(cx
, obj
);
4474 if (!filename
|| strcmp(filename
, "-") == 0) {
4477 fp
= fopen(filename
, "r");
4479 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_CANT_OPEN
,
4480 filename
, "No such file or directory");
4485 tcflags
= JS_OPTIONS_TO_TCFLAGS(cx
) | TCF_NEED_MUTABLE_SCRIPT
;
4486 script
= Compiler::compileScript(cx
, obj
, NULL
, NULL
, tcflags
,
4487 NULL
, 0, fp
, filename
, 1);
4490 if (script
&& !js_NewScriptObject(cx
, script
)) {
4491 js_DestroyScript(cx
, script
);
4494 LAST_FRAME_CHECKS(cx
, script
);
4498 JS_PUBLIC_API(JSScript
*)
4499 JS_CompileFileHandleForPrincipals(JSContext
*cx
, JSObject
*obj
, const char *filename
, FILE *file
,
4500 JSPrincipals
*principals
)
4506 assertSameCompartment(cx
, obj
, principals
);
4507 tcflags
= JS_OPTIONS_TO_TCFLAGS(cx
) | TCF_NEED_MUTABLE_SCRIPT
;
4508 script
= Compiler::compileScript(cx
, obj
, NULL
, principals
, tcflags
,
4509 NULL
, 0, file
, filename
, 1);
4510 if (script
&& !js_NewScriptObject(cx
, script
)) {
4511 js_DestroyScript(cx
, script
);
4514 LAST_FRAME_CHECKS(cx
, script
);
4518 JS_PUBLIC_API(JSScript
*)
4519 JS_CompileFileHandle(JSContext
*cx
, JSObject
*obj
, const char *filename
, FILE *file
)
4521 return JS_CompileFileHandleForPrincipals(cx
, obj
, filename
, file
, NULL
);
4524 JS_PUBLIC_API(JSObject
*)
4525 JS_NewScriptObject(JSContext
*cx
, JSScript
*script
)
4528 assertSameCompartment(cx
, script
);
4530 return NewNonFunction
<WithProto::Class
>(cx
, &js_ScriptClass
, NULL
, NULL
);
4533 * This function should only ever be applied to JSScripts that had
4534 * script objects allocated for them when they were created, as
4535 * described in the comment for JSScript::u.object.
4537 JS_ASSERT(script
->u
.object
);
4538 return script
->u
.object
;
4541 JS_PUBLIC_API(JSObject
*)
4542 JS_GetScriptObject(JSScript
*script
)
4545 * This function should only ever be applied to JSScripts that had
4546 * script objects allocated for them when they were created, as
4547 * described in the comment for JSScript::u.object.
4549 JS_ASSERT(script
->u
.object
);
4550 return script
->u
.object
;
4554 JS_DestroyScript(JSContext
*cx
, JSScript
*script
)
4559 * Originally, JSScript lifetimes were managed explicitly, and this function
4560 * was used to free a JSScript. Now, this function does nothing, and the
4561 * garbage collector manages JSScripts; you must root the JSScript's script
4562 * object (obtained via JS_GetScriptObject) to keep it alive.
4564 * However, since the script objects have taken over this responsibility, it
4565 * follows that every script passed here must have a script object.
4567 JS_ASSERT(script
->u
.object
);
4570 JS_PUBLIC_API(JSFunction
*)
4571 JS_CompileUCFunctionForPrincipalsVersion(JSContext
*cx
, JSObject
*obj
,
4572 JSPrincipals
*principals
, const char *name
,
4573 uintN nargs
, const char **argnames
,
4574 const jschar
*chars
, size_t length
,
4575 const char *filename
, uintN lineno
,
4578 AutoVersionAPI
avi(cx
, version
);
4579 return JS_CompileUCFunctionForPrincipals(cx
, obj
, principals
, name
, nargs
, argnames
, chars
,
4580 length
, filename
, lineno
);
4583 JS_PUBLIC_API(JSFunction
*)
4584 JS_CompileUCFunctionForPrincipals(JSContext
*cx
, JSObject
*obj
,
4585 JSPrincipals
*principals
, const char *name
,
4586 uintN nargs
, const char **argnames
,
4587 const jschar
*chars
, size_t length
,
4588 const char *filename
, uintN lineno
)
4591 JSAtom
*funAtom
, *argAtom
;
4595 assertSameCompartment(cx
, obj
, principals
);
4599 funAtom
= js_Atomize(cx
, name
, strlen(name
), 0);
4605 fun
= js_NewFunction(cx
, NULL
, NULL
, 0, JSFUN_INTERPRETED
, obj
, funAtom
);
4610 AutoObjectRooter
tvr(cx
, FUN_OBJECT(fun
));
4611 MUST_FLOW_THROUGH("out");
4613 for (i
= 0; i
< nargs
; i
++) {
4614 argAtom
= js_Atomize(cx
, argnames
[i
], strlen(argnames
[i
]), 0);
4619 if (!fun
->addLocal(cx
, argAtom
, JSLOCAL_ARG
)) {
4625 if (!Compiler::compileFunctionBody(cx
, fun
, principals
,
4626 chars
, length
, filename
, lineno
)) {
4631 if (obj
&& funAtom
&&
4632 !obj
->defineProperty(cx
, ATOM_TO_JSID(funAtom
), ObjectValue(*fun
),
4633 NULL
, NULL
, JSPROP_ENUMERATE
)) {
4637 #ifdef JS_SCOPE_DEPTH_METER
4639 JSObject
*pobj
= obj
;
4642 while ((pobj
= pobj
->getParent()) != NULL
)
4644 JS_BASIC_STATS_ACCUM(&cx
->runtime
->hostenvScopeDepthStats
, depth
);
4650 LAST_FRAME_CHECKS(cx
, fun
);
4654 JS_PUBLIC_API(JSFunction
*)
4655 JS_CompileUCFunction(JSContext
*cx
, JSObject
*obj
, const char *name
,
4656 uintN nargs
, const char **argnames
,
4657 const jschar
*chars
, size_t length
,
4658 const char *filename
, uintN lineno
)
4660 return JS_CompileUCFunctionForPrincipals(cx
, obj
, NULL
, name
, nargs
, argnames
,
4661 chars
, length
, filename
, lineno
);
4664 JS_PUBLIC_API(JSFunction
*)
4665 JS_CompileFunctionForPrincipals(JSContext
*cx
, JSObject
*obj
,
4666 JSPrincipals
*principals
, const char *name
,
4667 uintN nargs
, const char **argnames
,
4668 const char *bytes
, size_t length
,
4669 const char *filename
, uintN lineno
)
4671 jschar
*chars
= js_InflateString(cx
, bytes
, &length
);
4674 JSFunction
*fun
= JS_CompileUCFunctionForPrincipals(cx
, obj
, principals
, name
,
4675 nargs
, argnames
, chars
, length
,
4681 JS_PUBLIC_API(JSFunction
*)
4682 JS_CompileFunction(JSContext
*cx
, JSObject
*obj
, const char *name
,
4683 uintN nargs
, const char **argnames
,
4684 const char *bytes
, size_t length
,
4685 const char *filename
, uintN lineno
)
4687 return JS_CompileFunctionForPrincipals(cx
, obj
, NULL
, name
, nargs
, argnames
, bytes
, length
,
4691 JS_PUBLIC_API(JSString
*)
4692 JS_DecompileScript(JSContext
*cx
, JSScript
*script
, const char *name
, uintN indent
)
4698 assertSameCompartment(cx
, script
);
4699 jp
= js_NewPrinter(cx
, name
, NULL
,
4700 indent
& ~JS_DONT_PRETTY_PRINT
,
4701 !(indent
& JS_DONT_PRETTY_PRINT
),
4705 if (js_DecompileScript(jp
, script
))
4706 str
= js_GetPrinterOutput(jp
);
4709 js_DestroyPrinter(jp
);
4713 JS_PUBLIC_API(JSString
*)
4714 JS_DecompileFunction(JSContext
*cx
, JSFunction
*fun
, uintN indent
)
4717 assertSameCompartment(cx
, fun
);
4718 return js_DecompileToString(cx
, "JS_DecompileFunction", fun
,
4719 indent
& ~JS_DONT_PRETTY_PRINT
,
4720 !(indent
& JS_DONT_PRETTY_PRINT
),
4721 false, false, js_DecompileFunction
);
4724 JS_PUBLIC_API(JSString
*)
4725 JS_DecompileFunctionBody(JSContext
*cx
, JSFunction
*fun
, uintN indent
)
4728 assertSameCompartment(cx
, fun
);
4729 return js_DecompileToString(cx
, "JS_DecompileFunctionBody", fun
,
4730 indent
& ~JS_DONT_PRETTY_PRINT
,
4731 !(indent
& JS_DONT_PRETTY_PRINT
),
4732 false, false, js_DecompileFunctionBody
);
4735 JS_PUBLIC_API(JSBool
)
4736 JS_ExecuteScript(JSContext
*cx
, JSObject
*obj
, JSScript
*script
, jsval
*rval
)
4741 assertSameCompartment(cx
, obj
, script
);
4742 /* This should receive only scripts handed out via the JSAPI. */
4743 JS_ASSERT(script
== JSScript::emptyScript() || script
->u
.object
);
4744 ok
= Execute(cx
, obj
, script
, NULL
, 0, Valueify(rval
));
4745 LAST_FRAME_CHECKS(cx
, ok
);
4749 JS_PUBLIC_API(JSBool
)
4750 JS_EvaluateUCScriptForPrincipalsVersion(JSContext
*cx
, JSObject
*obj
,
4751 JSPrincipals
*principals
,
4752 const jschar
*chars
, uintN length
,
4753 const char *filename
, uintN lineno
,
4754 jsval
*rval
, JSVersion version
)
4756 AutoVersionAPI
avi(cx
, version
);
4757 return JS_EvaluateUCScriptForPrincipals(cx
, obj
, principals
, chars
, length
, filename
, lineno
,
4761 JS_PUBLIC_API(JSBool
)
4762 JS_EvaluateUCScriptForPrincipals(JSContext
*cx
, JSObject
*obj
,
4763 JSPrincipals
*principals
,
4764 const jschar
*chars
, uintN length
,
4765 const char *filename
, uintN lineno
,
4772 script
= Compiler::compileScript(cx
, obj
, NULL
, principals
,
4774 ? TCF_COMPILE_N_GO
| TCF_NO_SCRIPT_RVAL
4776 chars
, length
, NULL
, filename
, lineno
);
4778 LAST_FRAME_CHECKS(cx
, script
);
4781 ok
= Execute(cx
, obj
, script
, NULL
, 0, Valueify(rval
));
4782 LAST_FRAME_CHECKS(cx
, ok
);
4783 js_DestroyScript(cx
, script
);
4787 JS_PUBLIC_API(JSBool
)
4788 JS_EvaluateUCScript(JSContext
*cx
, JSObject
*obj
, const jschar
*chars
, uintN length
,
4789 const char *filename
, uintN lineno
, jsval
*rval
)
4791 return JS_EvaluateUCScriptForPrincipals(cx
, obj
, NULL
, chars
, length
, filename
, lineno
, rval
);
4794 /* Ancient uintN nbytes is part of API/ABI, so use size_t length local. */
4795 JS_PUBLIC_API(JSBool
)
4796 JS_EvaluateScriptForPrincipals(JSContext
*cx
, JSObject
*obj
, JSPrincipals
*principals
,
4797 const char *bytes
, uintN nbytes
,
4798 const char *filename
, uintN lineno
, jsval
*rval
)
4800 size_t length
= nbytes
;
4801 jschar
*chars
= js_InflateString(cx
, bytes
, &length
);
4804 JSBool ok
= JS_EvaluateUCScriptForPrincipals(cx
, obj
, principals
, chars
, length
,
4805 filename
, lineno
, rval
);
4810 JS_PUBLIC_API(JSBool
)
4811 JS_EvaluateScript(JSContext
*cx
, JSObject
*obj
, const char *bytes
, uintN nbytes
,
4812 const char *filename
, uintN lineno
, jsval
*rval
)
4814 return JS_EvaluateScriptForPrincipals(cx
, obj
, NULL
, bytes
, nbytes
, filename
, lineno
, rval
);
4817 JS_PUBLIC_API(JSBool
)
4818 JS_CallFunction(JSContext
*cx
, JSObject
*obj
, JSFunction
*fun
, uintN argc
, jsval
*argv
,
4824 assertSameCompartment(cx
, obj
, fun
, JSValueArray(argv
, argc
));
4825 ok
= ExternalInvoke(cx
, obj
, ObjectValue(*fun
), argc
, Valueify(argv
), Valueify(rval
));
4826 LAST_FRAME_CHECKS(cx
, ok
);
4830 JS_PUBLIC_API(JSBool
)
4831 JS_CallFunctionName(JSContext
*cx
, JSObject
*obj
, const char *name
, uintN argc
, jsval
*argv
,
4835 assertSameCompartment(cx
, obj
, JSValueArray(argv
, argc
));
4837 AutoValueRooter
tvr(cx
);
4838 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
4840 js_GetMethod(cx
, obj
, ATOM_TO_JSID(atom
), JSGET_NO_METHOD_BARRIER
, tvr
.addr()) &&
4841 ExternalInvoke(cx
, obj
, tvr
.value(), argc
, Valueify(argv
), Valueify(rval
));
4842 LAST_FRAME_CHECKS(cx
, ok
);
4846 JS_PUBLIC_API(JSBool
)
4847 JS_CallFunctionValue(JSContext
*cx
, JSObject
*obj
, jsval fval
, uintN argc
, jsval
*argv
,
4853 assertSameCompartment(cx
, obj
, fval
, JSValueArray(argv
, argc
));
4854 ok
= ExternalInvoke(cx
, obj
, Valueify(fval
), argc
, Valueify(argv
), Valueify(rval
));
4855 LAST_FRAME_CHECKS(cx
, ok
);
4859 JS_PUBLIC_API(JSObject
*)
4860 JS_New(JSContext
*cx
, JSObject
*ctor
, uintN argc
, jsval
*argv
)
4863 assertSameCompartment(cx
, ctor
, JSValueArray(argv
, argc
));
4865 // This is not a simple variation of JS_CallFunctionValue because JSOP_NEW
4866 // is not a simple variation of JSOP_CALL. We have to determine what class
4867 // of object to create, create it, and clamp the return value to an object,
4868 // among other details. js_InvokeConstructor does the hard work.
4869 InvokeArgsGuard args
;
4870 if (!cx
->stack().pushInvokeArgs(cx
, argc
, &args
))
4873 args
.callee().setObject(*ctor
);
4874 args
.thisv().setNull();
4875 memcpy(args
.argv(), argv
, argc
* sizeof(jsval
));
4877 bool ok
= InvokeConstructor(cx
, args
);
4878 JSObject
*obj
= (ok
&& args
.rval().isObject())
4879 ? &args
.rval().toObject()
4882 LAST_FRAME_CHECKS(cx
, ok
);
4886 JS_PUBLIC_API(JSOperationCallback
)
4887 JS_SetOperationCallback(JSContext
*cx
, JSOperationCallback callback
)
4889 #ifdef JS_THREADSAFE
4890 JS_ASSERT(CURRENT_THREAD_IS_ME(cx
->thread
));
4892 JSOperationCallback old
= cx
->operationCallback
;
4893 cx
->operationCallback
= callback
;
4897 JS_PUBLIC_API(JSOperationCallback
)
4898 JS_GetOperationCallback(JSContext
*cx
)
4900 return cx
->operationCallback
;
4904 JS_TriggerOperationCallback(JSContext
*cx
)
4906 #ifdef JS_THREADSAFE
4907 AutoLockGC
lock(cx
->runtime
);
4909 TriggerOperationCallback(cx
);
4913 JS_TriggerAllOperationCallbacks(JSRuntime
*rt
)
4915 #ifdef JS_THREADSAFE
4916 AutoLockGC
lock(rt
);
4918 TriggerAllOperationCallbacks(rt
);
4921 JS_PUBLIC_API(JSBool
)
4922 JS_IsRunning(JSContext
*cx
)
4925 * The use of cx->fp below is safe. Rationale: Here we don't care if the
4926 * interpreter state is stale. We just want to know if there *is* any
4927 * interpreter state.
4929 VOUCH_DOES_NOT_REQUIRE_STACK();
4932 JS_ASSERT_IF(JS_TRACE_MONITOR(cx
).tracecx
== cx
, cx
->hasfp());
4934 JSStackFrame
*fp
= cx
->maybefp();
4935 while (fp
&& fp
->isDummyFrame())
4940 JS_PUBLIC_API(JSStackFrame
*)
4941 JS_SaveFrameChain(JSContext
*cx
)
4944 JSStackFrame
*fp
= js_GetTopStackFrame(cx
);
4947 cx
->saveActiveSegment();
4952 JS_RestoreFrameChain(JSContext
*cx
, JSStackFrame
*fp
)
4955 JS_ASSERT_NOT_ON_TRACE(cx
);
4956 JS_ASSERT(!cx
->hasfp());
4959 cx
->restoreSegment();
4962 /************************************************************************/
4964 JS_PUBLIC_API(JSString
*)
4965 JS_NewString(JSContext
*cx
, char *bytes
, size_t nbytes
)
4967 size_t length
= nbytes
;
4973 /* Make a UTF-16 vector from the 8-bit char codes in bytes. */
4974 chars
= js_InflateString(cx
, bytes
, &length
);
4978 /* Free chars (but not bytes, which caller frees on error) if we fail. */
4979 str
= js_NewString(cx
, chars
, length
);
4985 /* Hand off bytes to the deflated string cache, if possible. */
4986 if (!cx
->runtime
->deflatedStringCache
->setBytes(cx
, str
, bytes
))
4991 JS_PUBLIC_API(JSString
*)
4992 JS_NewStringCopyN(JSContext
*cx
, const char *s
, size_t n
)
4998 js
= js_InflateString(cx
, s
, &n
);
5001 str
= js_NewString(cx
, js
, n
);
5007 JS_PUBLIC_API(JSString
*)
5008 JS_NewStringCopyZ(JSContext
*cx
, const char *s
)
5016 return cx
->runtime
->emptyString
;
5018 js
= js_InflateString(cx
, s
, &n
);
5021 str
= js_NewString(cx
, js
, n
);
5027 JS_PUBLIC_API(JSBool
)
5028 JS_StringHasBeenInterned(JSString
*str
)
5030 return str
->isAtomized();
5033 JS_PUBLIC_API(JSString
*)
5034 JS_InternString(JSContext
*cx
, const char *s
)
5039 atom
= js_Atomize(cx
, s
, strlen(s
), ATOM_INTERNED
);
5042 return ATOM_TO_STRING(atom
);
5045 JS_PUBLIC_API(JSString
*)
5046 JS_NewUCString(JSContext
*cx
, jschar
*chars
, size_t length
)
5049 return js_NewString(cx
, chars
, length
);
5052 JS_PUBLIC_API(JSString
*)
5053 JS_NewUCStringCopyN(JSContext
*cx
, const jschar
*s
, size_t n
)
5056 return js_NewStringCopyN(cx
, s
, n
);
5059 JS_PUBLIC_API(JSString
*)
5060 JS_NewUCStringCopyZ(JSContext
*cx
, const jschar
*s
)
5064 return cx
->runtime
->emptyString
;
5065 return js_NewStringCopyZ(cx
, s
);
5068 JS_PUBLIC_API(JSString
*)
5069 JS_InternUCStringN(JSContext
*cx
, const jschar
*s
, size_t length
)
5074 atom
= js_AtomizeChars(cx
, s
, length
, ATOM_INTERNED
);
5077 return ATOM_TO_STRING(atom
);
5080 JS_PUBLIC_API(JSString
*)
5081 JS_InternUCString(JSContext
*cx
, const jschar
*s
)
5083 return JS_InternUCStringN(cx
, s
, js_strlen(s
));
5086 JS_PUBLIC_API(char *)
5087 JS_GetStringBytes(JSString
*str
)
5091 bytes
= js_GetStringBytes(NULL
, str
);
5092 return (char *)(bytes
? bytes
: "");
5095 JS_PUBLIC_API(jschar
*)
5096 JS_GetStringChars(JSString
*str
)
5101 str
->ensureNotRope();
5104 * API botch (again, shades of JS_GetStringBytes): we have no cx to report
5105 * out-of-memory when undepending strings, so we replace JSString::undepend
5106 * with explicit malloc call and ignore its errors.
5108 * If we fail to convert a dependent string into an independent one, our
5109 * caller will not be guaranteed a \u0000 terminator as a backstop. This
5110 * may break some clients who already misbehave on embedded NULs.
5112 * The gain of dependent strings, which cure quadratic and cubic growth
5113 * rate bugs in string concatenation, is worth this slight loss in API
5116 if (str
->isDependent()) {
5117 n
= str
->dependentLength();
5118 size
= (n
+ 1) * sizeof(jschar
);
5119 s
= (jschar
*) js_malloc(size
);
5121 memcpy(s
, str
->dependentChars(), n
* sizeof *s
);
5123 str
->initFlat(s
, n
);
5125 s
= str
->dependentChars();
5128 str
->flatClearMutable();
5129 s
= str
->flatChars();
5134 JS_PUBLIC_API(size_t)
5135 JS_GetStringLength(JSString
*str
)
5137 return str
->length();
5140 JS_PUBLIC_API(const char *)
5141 JS_GetStringBytesZ(JSContext
*cx
, JSString
*str
)
5143 assertSameCompartment(cx
, str
);
5144 return js_GetStringBytes(cx
, str
);
5147 JS_PUBLIC_API(const jschar
*)
5148 JS_GetStringCharsZ(JSContext
*cx
, JSString
*str
)
5150 assertSameCompartment(cx
, str
);
5151 return str
->undepend(cx
);
5155 JS_CompareStrings(JSString
*str1
, JSString
*str2
)
5157 return js_CompareStrings(str1
, str2
);
5160 JS_PUBLIC_API(JSString
*)
5161 JS_NewGrowableString(JSContext
*cx
, jschar
*chars
, size_t length
)
5164 return js_NewString(cx
, chars
, length
);
5167 JS_PUBLIC_API(JSString
*)
5168 JS_NewDependentString(JSContext
*cx
, JSString
*str
, size_t start
, size_t length
)
5171 return js_NewDependentString(cx
, str
, start
, length
);
5174 JS_PUBLIC_API(JSString
*)
5175 JS_ConcatStrings(JSContext
*cx
, JSString
*left
, JSString
*right
)
5178 return js_ConcatStrings(cx
, left
, right
);
5181 JS_PUBLIC_API(const jschar
*)
5182 JS_UndependString(JSContext
*cx
, JSString
*str
)
5185 return str
->undepend(cx
);
5188 JS_PUBLIC_API(JSBool
)
5189 JS_MakeStringImmutable(JSContext
*cx
, JSString
*str
)
5192 return js_MakeStringImmutable(cx
, str
);
5195 JS_PUBLIC_API(JSBool
)
5196 JS_EncodeCharacters(JSContext
*cx
, const jschar
*src
, size_t srclen
, char *dst
, size_t *dstlenp
)
5201 n
= js_GetDeflatedStringLength(cx
, src
, srclen
);
5202 if (n
== (size_t)-1) {
5210 return js_DeflateStringToBuffer(cx
, src
, srclen
, dst
, dstlenp
);
5213 JS_PUBLIC_API(JSBool
)
5214 JS_DecodeBytes(JSContext
*cx
, const char *src
, size_t srclen
, jschar
*dst
, size_t *dstlenp
)
5216 return js_InflateStringToBuffer(cx
, src
, srclen
, dst
, dstlenp
);
5219 JS_PUBLIC_API(char *)
5220 JS_EncodeString(JSContext
*cx
, JSString
*str
)
5222 return js_DeflateString(cx
, str
->chars(), str
->length());
5225 JS_PUBLIC_API(JSBool
)
5226 JS_Stringify(JSContext
*cx
, jsval
*vp
, JSObject
*replacer
, jsval space
,
5227 JSONWriteCallback callback
, void *data
)
5230 assertSameCompartment(cx
, replacer
, space
);
5231 JSCharBuffer
cb(cx
);
5232 if (!js_Stringify(cx
, Valueify(vp
), replacer
, Valueify(space
), cb
))
5234 return callback(cb
.begin(), cb
.length(), data
);
5237 JS_PUBLIC_API(JSBool
)
5238 JS_TryJSON(JSContext
*cx
, jsval
*vp
)
5241 assertSameCompartment(cx
, *vp
);
5242 return js_TryJSON(cx
, Valueify(vp
));
5245 JS_PUBLIC_API(JSONParser
*)
5246 JS_BeginJSONParse(JSContext
*cx
, jsval
*vp
)
5249 return js_BeginJSONParse(cx
, Valueify(vp
));
5252 JS_PUBLIC_API(JSBool
)
5253 JS_ConsumeJSONText(JSContext
*cx
, JSONParser
*jp
, const jschar
*data
, uint32 len
)
5256 return js_ConsumeJSONText(cx
, jp
, data
, len
);
5259 JS_PUBLIC_API(JSBool
)
5260 JS_FinishJSONParse(JSContext
*cx
, JSONParser
*jp
, jsval reviver
)
5263 assertSameCompartment(cx
, reviver
);
5264 return js_FinishJSONParse(cx
, jp
, Valueify(reviver
));
5268 * The following determines whether C Strings are to be treated as UTF-8
5269 * or ISO-8859-1. For correct operation, it must be set prior to the
5270 * first call to JS_NewRuntime.
5272 #ifndef JS_C_STRINGS_ARE_UTF8
5273 JSBool js_CStringsAreUTF8
= JS_FALSE
;
5276 JS_PUBLIC_API(JSBool
)
5277 JS_CStringsAreUTF8()
5279 return js_CStringsAreUTF8
;
5283 JS_SetCStringsAreUTF8()
5285 JS_ASSERT(!js_NewRuntimeWasCalled
);
5287 #ifndef JS_C_STRINGS_ARE_UTF8
5288 js_CStringsAreUTF8
= JS_TRUE
;
5292 /************************************************************************/
5295 JS_ReportError(JSContext
*cx
, const char *format
, ...)
5299 va_start(ap
, format
);
5300 js_ReportErrorVA(cx
, JSREPORT_ERROR
, format
, ap
);
5305 JS_ReportErrorNumber(JSContext
*cx
, JSErrorCallback errorCallback
,
5306 void *userRef
, const uintN errorNumber
, ...)
5310 va_start(ap
, errorNumber
);
5311 js_ReportErrorNumberVA(cx
, JSREPORT_ERROR
, errorCallback
, userRef
,
5312 errorNumber
, JS_TRUE
, ap
);
5317 JS_ReportErrorNumberUC(JSContext
*cx
, JSErrorCallback errorCallback
,
5318 void *userRef
, const uintN errorNumber
, ...)
5322 va_start(ap
, errorNumber
);
5323 js_ReportErrorNumberVA(cx
, JSREPORT_ERROR
, errorCallback
, userRef
,
5324 errorNumber
, JS_FALSE
, ap
);
5328 JS_PUBLIC_API(JSBool
)
5329 JS_ReportWarning(JSContext
*cx
, const char *format
, ...)
5334 va_start(ap
, format
);
5335 ok
= js_ReportErrorVA(cx
, JSREPORT_WARNING
, format
, ap
);
5340 JS_PUBLIC_API(JSBool
)
5341 JS_ReportErrorFlagsAndNumber(JSContext
*cx
, uintN flags
,
5342 JSErrorCallback errorCallback
, void *userRef
,
5343 const uintN errorNumber
, ...)
5348 va_start(ap
, errorNumber
);
5349 ok
= js_ReportErrorNumberVA(cx
, flags
, errorCallback
, userRef
,
5350 errorNumber
, JS_TRUE
, ap
);
5355 JS_PUBLIC_API(JSBool
)
5356 JS_ReportErrorFlagsAndNumberUC(JSContext
*cx
, uintN flags
,
5357 JSErrorCallback errorCallback
, void *userRef
,
5358 const uintN errorNumber
, ...)
5363 va_start(ap
, errorNumber
);
5364 ok
= js_ReportErrorNumberVA(cx
, flags
, errorCallback
, userRef
,
5365 errorNumber
, JS_FALSE
, ap
);
5371 JS_ReportOutOfMemory(JSContext
*cx
)
5373 js_ReportOutOfMemory(cx
);
5377 JS_ReportAllocationOverflow(JSContext
*cx
)
5379 js_ReportAllocationOverflow(cx
);
5382 JS_PUBLIC_API(JSErrorReporter
)
5383 JS_SetErrorReporter(JSContext
*cx
, JSErrorReporter er
)
5385 JSErrorReporter older
;
5387 older
= cx
->errorReporter
;
5388 cx
->errorReporter
= er
;
5392 /************************************************************************/
5395 * Regular Expressions.
5397 JS_PUBLIC_API(JSObject
*)
5398 JS_NewRegExpObject(JSContext
*cx
, JSObject
*obj
, char *bytes
, size_t length
, uintN flags
)
5401 jschar
*chars
= js_InflateString(cx
, bytes
, &length
);
5404 RegExpStatics
*res
= RegExpStatics::extractFrom(obj
);
5405 JSObject
*reobj
= RegExp::createObject(cx
, res
, chars
, length
, flags
);
5410 JS_PUBLIC_API(JSObject
*)
5411 JS_NewUCRegExpObject(JSContext
*cx
, JSObject
*obj
, jschar
*chars
, size_t length
, uintN flags
)
5414 RegExpStatics
*res
= RegExpStatics::extractFrom(obj
);
5415 return RegExp::createObject(cx
, res
, chars
, length
, flags
);
5419 JS_SetRegExpInput(JSContext
*cx
, JSObject
*obj
, JSString
*input
, JSBool multiline
)
5422 assertSameCompartment(cx
, input
);
5424 RegExpStatics::extractFrom(obj
)->reset(input
, !!multiline
);
5428 JS_ClearRegExpStatics(JSContext
*cx
, JSObject
*obj
)
5433 RegExpStatics::extractFrom(obj
)->clear();
5436 JS_PUBLIC_API(JSBool
)
5437 JS_ExecuteRegExp(JSContext
*cx
, JSObject
*obj
, JSObject
*reobj
, jschar
*chars
, size_t length
,
5438 size_t *indexp
, JSBool test
, jsval
*rval
)
5442 RegExp
*re
= RegExp::extractFrom(reobj
);
5446 JSString
*str
= js_NewStringCopyN(cx
, chars
, length
);
5450 return re
->execute(cx
, RegExpStatics::extractFrom(obj
), str
, indexp
, test
, Valueify(rval
));
5453 JS_PUBLIC_API(JSObject
*)
5454 JS_NewRegExpObjectNoStatics(JSContext
*cx
, char *bytes
, size_t length
, uintN flags
)
5457 jschar
*chars
= js_InflateString(cx
, bytes
, &length
);
5460 JSObject
*obj
= RegExp::createObjectNoStatics(cx
, chars
, length
, flags
);
5465 JS_PUBLIC_API(JSObject
*)
5466 JS_NewUCRegExpObjectNoStatics(JSContext
*cx
, jschar
*chars
, size_t length
, uintN flags
)
5469 return RegExp::createObjectNoStatics(cx
, chars
, length
, flags
);
5472 JS_PUBLIC_API(JSBool
)
5473 JS_ExecuteRegExpNoStatics(JSContext
*cx
, JSObject
*obj
, jschar
*chars
, size_t length
,
5474 size_t *indexp
, JSBool test
, jsval
*rval
)
5478 RegExp
*re
= RegExp::extractFrom(obj
);
5482 JSString
*str
= js_NewStringCopyN(cx
, chars
, length
);
5486 return re
->executeNoStatics(cx
, str
, indexp
, test
, Valueify(rval
));
5489 /************************************************************************/
5492 JS_SetLocaleCallbacks(JSContext
*cx
, JSLocaleCallbacks
*callbacks
)
5494 cx
->localeCallbacks
= callbacks
;
5497 JS_PUBLIC_API(JSLocaleCallbacks
*)
5498 JS_GetLocaleCallbacks(JSContext
*cx
)
5500 return cx
->localeCallbacks
;
5503 /************************************************************************/
5505 JS_PUBLIC_API(JSBool
)
5506 JS_IsExceptionPending(JSContext
*cx
)
5508 return (JSBool
) cx
->throwing
;
5511 JS_PUBLIC_API(JSBool
)
5512 JS_GetPendingException(JSContext
*cx
, jsval
*vp
)
5517 Valueify(*vp
) = cx
->exception
;
5522 JS_SetPendingException(JSContext
*cx
, jsval v
)
5525 assertSameCompartment(cx
, v
);
5526 SetPendingException(cx
, Valueify(v
));
5530 JS_ClearPendingException(JSContext
*cx
)
5532 cx
->throwing
= JS_FALSE
;
5533 cx
->exception
.setUndefined();
5536 JS_PUBLIC_API(JSBool
)
5537 JS_ReportPendingException(JSContext
*cx
)
5545 * Set cx->generatingError to suppress the standard error-to-exception
5546 * conversion done by all {js,JS}_Report* functions except for OOM. The
5547 * cx->generatingError flag was added to suppress recursive divergence
5548 * under js_ErrorToException, but it serves for our purposes here too.
5550 save
= cx
->generatingError
;
5551 cx
->generatingError
= JS_TRUE
;
5552 ok
= js_ReportUncaughtException(cx
);
5553 cx
->generatingError
= save
;
5557 struct JSExceptionState
{
5562 JS_PUBLIC_API(JSExceptionState
*)
5563 JS_SaveExceptionState(JSContext
*cx
)
5565 JSExceptionState
*state
;
5568 state
= (JSExceptionState
*) cx
->malloc(sizeof(JSExceptionState
));
5570 state
->throwing
= JS_GetPendingException(cx
, &state
->exception
);
5571 if (state
->throwing
&& JSVAL_IS_GCTHING(state
->exception
))
5572 js_AddRoot(cx
, Valueify(&state
->exception
), "JSExceptionState.exception");
5578 JS_RestoreExceptionState(JSContext
*cx
, JSExceptionState
*state
)
5582 if (state
->throwing
)
5583 JS_SetPendingException(cx
, state
->exception
);
5585 JS_ClearPendingException(cx
);
5586 JS_DropExceptionState(cx
, state
);
5591 JS_DropExceptionState(JSContext
*cx
, JSExceptionState
*state
)
5595 if (state
->throwing
&& JSVAL_IS_GCTHING(state
->exception
)) {
5596 assertSameCompartment(cx
, state
->exception
);
5597 JS_RemoveValueRoot(cx
, &state
->exception
);
5603 JS_PUBLIC_API(JSErrorReport
*)
5604 JS_ErrorFromException(JSContext
*cx
, jsval v
)
5607 assertSameCompartment(cx
, v
);
5608 return js_ErrorFromException(cx
, v
);
5611 JS_PUBLIC_API(JSBool
)
5612 JS_ThrowReportedError(JSContext
*cx
, const char *message
,
5613 JSErrorReport
*reportp
)
5615 return JS_IsRunning(cx
) &&
5616 js_ErrorToException(cx
, message
, reportp
, NULL
, NULL
);
5619 JS_PUBLIC_API(JSBool
)
5620 JS_ThrowStopIteration(JSContext
*cx
)
5622 return js_ThrowStopIteration(cx
);
5626 * Get the owning thread id of a context. Returns 0 if the context is not
5627 * owned by any thread.
5629 JS_PUBLIC_API(jsword
)
5630 JS_GetContextThread(JSContext
*cx
)
5632 #ifdef JS_THREADSAFE
5633 return reinterpret_cast<jsword
>(JS_THREAD_ID(cx
));
5640 * Set the current thread as the owning thread of a context. Returns the
5641 * old owning thread id, or -1 if the operation failed.
5643 JS_PUBLIC_API(jsword
)
5644 JS_SetContextThread(JSContext
*cx
)
5646 #ifdef JS_THREADSAFE
5647 JS_ASSERT(!cx
->outstandingRequests
);
5649 JS_ASSERT(CURRENT_THREAD_IS_ME(cx
->thread
));
5650 return reinterpret_cast<jsword
>(cx
->thread
->id
);
5653 if (!js_InitContextThread(cx
)) {
5654 js_ReportOutOfMemory(cx
);
5658 /* Here the GC lock is still held after js_InitContextThread took it. */
5659 JS_UNLOCK_GC(cx
->runtime
);
5664 JS_PUBLIC_API(jsword
)
5665 JS_ClearContextThread(JSContext
*cx
)
5667 #ifdef JS_THREADSAFE
5669 * cx must have exited all requests it entered and, if cx is associated
5670 * with a thread, this must be called only from that thread. If not, this
5671 * is a harmless no-op.
5673 JS_ASSERT(cx
->outstandingRequests
== 0);
5674 JSThread
*t
= cx
->thread
;
5677 JS_ASSERT(CURRENT_THREAD_IS_ME(t
));
5680 * We must not race with a GC that accesses cx->thread for all threads,
5683 JSRuntime
*rt
= cx
->runtime
;
5684 AutoLockGC
lock(rt
);
5686 js_ClearContextThread(cx
);
5687 JS_ASSERT_IF(JS_CLIST_IS_EMPTY(&t
->contextList
), !t
->data
.requestDepth
);
5690 * We can access t->id as long as the GC lock is held and we cannot race
5691 * with the GC that may delete t.
5693 return reinterpret_cast<jsword
>(t
->id
);
5699 #ifdef MOZ_TRACE_JSCALLS
5701 JS_SetFunctionCallback(JSContext
*cx
, JSFunctionCallback fcb
)
5703 cx
->functionCallback
= fcb
;
5706 JS_PUBLIC_API(JSFunctionCallback
)
5707 JS_GetFunctionCallback(JSContext
*cx
)
5709 return cx
->functionCallback
;
5715 JS_SetGCZeal(JSContext
*cx
, uint8 zeal
)
5717 cx
->runtime
->gcZeal
= zeal
;
5721 /************************************************************************/
5723 #if !defined(STATIC_EXPORTABLE_JS_API) && !defined(STATIC_JS_API) && defined(XP_WIN) && !defined (WINCE)
5728 * Initialization routine for the JS DLL.
5730 BOOL WINAPI
DllMain (HINSTANCE hDLL
, DWORD dwReason
, LPVOID lpReserved
)