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"
84 #include "jsstaticcheck.h"
86 #if !defined JS_THREADSAFE && defined JS_TRACER
90 #if JS_HAS_FILE_OBJECT
94 #if JS_HAS_XML_SUPPORT
98 #ifdef HAVE_VA_LIST_AS_ARRAY
99 #define JS_ADDRESSOF_VA_LIST(ap) ((va_list *)(ap))
101 #define JS_ADDRESSOF_VA_LIST(ap) (&(ap))
104 #if defined(JS_THREADSAFE)
105 #define CHECK_REQUEST(cx) \
106 JS_ASSERT((cx)->requestDepth || (cx)->thread == (cx)->runtime->gcThread)
108 #define CHECK_REQUEST(cx) ((void)0)
118 JS_GetNaNValue(JSContext
*cx
)
120 return DOUBLE_TO_JSVAL(cx
->runtime
->jsNaN
);
124 JS_GetNegativeInfinityValue(JSContext
*cx
)
126 return DOUBLE_TO_JSVAL(cx
->runtime
->jsNegativeInfinity
);
130 JS_GetPositiveInfinityValue(JSContext
*cx
)
132 return DOUBLE_TO_JSVAL(cx
->runtime
->jsPositiveInfinity
);
136 JS_GetEmptyStringValue(JSContext
*cx
)
138 return STRING_TO_JSVAL(cx
->runtime
->emptyString
);
142 TryArgumentFormatter(JSContext
*cx
, const char **formatp
, JSBool fromJS
,
143 jsval
**vpp
, va_list *app
)
146 JSArgumentFormatMap
*map
;
149 for (map
= cx
->argumentFormatMap
; map
; map
= map
->next
) {
150 if (!strncmp(format
, map
->format
, map
->length
)) {
151 *formatp
= format
+ map
->length
;
152 return map
->formatter(cx
, format
, fromJS
, vpp
, app
);
155 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_BAD_CHAR
, format
);
159 JS_PUBLIC_API(JSBool
)
160 JS_ConvertArguments(JSContext
*cx
, uintN argc
, jsval
*argv
, const char *format
,
166 va_start(ap
, format
);
167 ok
= JS_ConvertArgumentsVA(cx
, argc
, argv
, format
, ap
);
172 JS_PUBLIC_API(JSBool
)
173 JS_ConvertArgumentsVA(JSContext
*cx
, uintN argc
, jsval
*argv
,
174 const char *format
, va_list ap
)
187 while ((c
= *format
++) != '\0') {
194 if (sp
== argv
+ argc
) {
196 fun
= js_ValueToFunction(cx
, &argv
[-2], 0);
199 JS_snprintf(numBuf
, sizeof numBuf
, "%u", argc
);
200 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
,
201 JSMSG_MORE_ARGS_NEEDED
,
202 JS_GetFunctionName(fun
), numBuf
,
203 (argc
== 1) ? "" : "s");
211 *va_arg(ap
, JSBool
*) = js_ValueToBoolean(*sp
);
214 if (!JS_ValueToUint16(cx
, *sp
, va_arg(ap
, uint16
*)))
218 if (!JS_ValueToECMAInt32(cx
, *sp
, va_arg(ap
, int32
*)))
222 if (!JS_ValueToECMAUint32(cx
, *sp
, va_arg(ap
, uint32
*)))
226 if (!JS_ValueToInt32(cx
, *sp
, va_arg(ap
, int32
*)))
230 if (!JS_ValueToNumber(cx
, *sp
, va_arg(ap
, jsdouble
*)))
234 if (!JS_ValueToNumber(cx
, *sp
, &d
))
236 *va_arg(ap
, jsdouble
*) = js_DoubleToInteger(d
);
241 str
= js_ValueToString(cx
, *sp
);
244 *sp
= STRING_TO_JSVAL(str
);
246 const char *bytes
= js_GetStringBytes(cx
, str
);
249 *va_arg(ap
, const char **) = bytes
;
250 } else if (c
== 'W') {
251 const jschar
*chars
= js_GetStringChars(cx
, str
);
254 *va_arg(ap
, const jschar
**) = chars
;
256 *va_arg(ap
, JSString
**) = str
;
260 if (!js_ValueToObject(cx
, *sp
, &obj
))
262 *sp
= OBJECT_TO_JSVAL(obj
);
263 *va_arg(ap
, JSObject
**) = obj
;
266 obj
= js_ValueToFunctionObject(cx
, sp
, 0);
269 *sp
= OBJECT_TO_JSVAL(obj
);
270 *va_arg(ap
, JSFunction
**) = (JSFunction
*) JS_GetPrivate(cx
, obj
);
273 *va_arg(ap
, jsval
*) = *sp
;
279 if (!TryArgumentFormatter(cx
, &format
, JS_TRUE
, &sp
,
280 JS_ADDRESSOF_VA_LIST(ap
))) {
283 /* NB: the formatter already updated sp, so we continue here. */
291 JS_PUBLIC_API(jsval
*)
292 JS_PushArguments(JSContext
*cx
, void **markp
, const char *format
, ...)
297 va_start(ap
, format
);
298 argv
= JS_PushArgumentsVA(cx
, markp
, format
, ap
);
303 JS_PUBLIC_API(jsval
*)
304 JS_PushArgumentsVA(JSContext
*cx
, void **markp
, const char *format
, va_list ap
)
317 for (cp
= format
; (c
= *cp
) != '\0'; cp
++) {
319 * Count non-space non-star characters as individual jsval arguments.
320 * This may over-allocate stack, but we'll fix below.
322 if (isspace(c
) || c
== '*')
326 sp
= js_AllocStack(cx
, argc
, markp
);
330 while ((c
= *format
++) != '\0') {
331 if (isspace(c
) || c
== '*')
335 *sp
= BOOLEAN_TO_JSVAL((JSBool
) va_arg(ap
, int));
338 *sp
= INT_TO_JSVAL((uint16
) va_arg(ap
, unsigned int));
343 * Use JS_New{Double,Number}Value here and in the next two cases,
344 * not js_New{Double,Number}InRootedValue, as sp may point to an
347 if (!JS_NewNumberValue(cx
, (jsdouble
) va_arg(ap
, int32
), sp
))
351 if (!JS_NewNumberValue(cx
, (jsdouble
) va_arg(ap
, uint32
), sp
))
356 if (!JS_NewDoubleValue(cx
, va_arg(ap
, jsdouble
), sp
))
360 str
= JS_NewStringCopyZ(cx
, va_arg(ap
, char *));
363 *sp
= STRING_TO_JSVAL(str
);
366 str
= JS_NewUCStringCopyZ(cx
, va_arg(ap
, jschar
*));
369 *sp
= STRING_TO_JSVAL(str
);
372 str
= va_arg(ap
, JSString
*);
373 *sp
= STRING_TO_JSVAL(str
);
376 *sp
= OBJECT_TO_JSVAL(va_arg(ap
, JSObject
*));
379 fun
= va_arg(ap
, JSFunction
*);
380 *sp
= fun
? OBJECT_TO_JSVAL(FUN_OBJECT(fun
)) : JSVAL_NULL
;
383 *sp
= va_arg(ap
, jsval
);
387 if (!TryArgumentFormatter(cx
, &format
, JS_FALSE
, &sp
,
388 JS_ADDRESSOF_VA_LIST(ap
))) {
391 /* NB: the formatter already updated sp, so we continue here. */
398 * We may have overallocated stack due to a multi-character format code
399 * handled by a JSArgumentFormatter. Give back that stack space!
401 JS_ASSERT(sp
<= argv
+ argc
);
402 if (sp
< argv
+ argc
) {
403 /* Return slots not pushed to the current stack arena. */
404 cx
->stackPool
.current
->avail
= (jsuword
)sp
;
406 /* Reduce the count of slots the GC will scan in this stack segment. */
407 sh
= cx
->stackHeaders
;
408 JS_ASSERT(JS_STACK_SEGMENT(sh
) + sh
->nslots
== argv
+ argc
);
409 sh
->nslots
-= argc
- (sp
- argv
);
414 js_FreeStack(cx
, *markp
);
419 JS_PopArguments(JSContext
*cx
, void *mark
)
422 js_FreeStack(cx
, mark
);
425 JS_PUBLIC_API(JSBool
)
426 JS_AddArgumentFormatter(JSContext
*cx
, const char *format
,
427 JSArgumentFormatter formatter
)
430 JSArgumentFormatMap
**mpp
, *map
;
432 length
= strlen(format
);
433 mpp
= &cx
->argumentFormatMap
;
434 while ((map
= *mpp
) != NULL
) {
435 /* Insert before any shorter string to match before prefixes. */
436 if (map
->length
< length
)
438 if (map
->length
== length
&& !strcmp(map
->format
, format
))
442 map
= (JSArgumentFormatMap
*) JS_malloc(cx
, sizeof *map
);
445 map
->format
= format
;
446 map
->length
= length
;
450 map
->formatter
= formatter
;
455 JS_RemoveArgumentFormatter(JSContext
*cx
, const char *format
)
458 JSArgumentFormatMap
**mpp
, *map
;
460 length
= strlen(format
);
461 mpp
= &cx
->argumentFormatMap
;
462 while ((map
= *mpp
) != NULL
) {
463 if (map
->length
== length
&& !strcmp(map
->format
, format
)) {
472 JS_PUBLIC_API(JSBool
)
473 JS_ConvertValue(JSContext
*cx
, jsval v
, JSType type
, jsval
*vp
)
487 ok
= js_ValueToObject(cx
, v
, &obj
);
489 *vp
= OBJECT_TO_JSVAL(obj
);
491 case JSTYPE_FUNCTION
:
493 obj
= js_ValueToFunctionObject(cx
, vp
, JSV2F_SEARCH_STACK
);
497 str
= js_ValueToString(cx
, v
);
500 *vp
= STRING_TO_JSVAL(str
);
503 ok
= JS_ValueToNumber(cx
, v
, &d
);
505 dp
= js_NewWeaklyRootedDouble(cx
, d
);
508 *vp
= DOUBLE_TO_JSVAL(dp
);
512 *vp
= BOOLEAN_TO_JSVAL(js_ValueToBoolean(v
));
516 JS_snprintf(numBuf
, sizeof numBuf
, "%d", (int)type
);
517 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_BAD_TYPE
,
526 JS_PUBLIC_API(JSBool
)
527 JS_ValueToObject(JSContext
*cx
, jsval v
, JSObject
**objp
)
530 return js_ValueToObject(cx
, v
, objp
);
533 JS_PUBLIC_API(JSFunction
*)
534 JS_ValueToFunction(JSContext
*cx
, jsval v
)
537 return js_ValueToFunction(cx
, &v
, JSV2F_SEARCH_STACK
);
540 JS_PUBLIC_API(JSFunction
*)
541 JS_ValueToConstructor(JSContext
*cx
, jsval v
)
544 return js_ValueToFunction(cx
, &v
, JSV2F_SEARCH_STACK
);
547 JS_PUBLIC_API(JSString
*)
548 JS_ValueToString(JSContext
*cx
, jsval v
)
551 return js_ValueToString(cx
, v
);
554 JS_PUBLIC_API(JSString
*)
555 JS_ValueToSource(JSContext
*cx
, jsval v
)
558 return js_ValueToSource(cx
, v
);
561 JS_PUBLIC_API(JSBool
)
562 JS_ValueToNumber(JSContext
*cx
, jsval v
, jsdouble
*dp
)
564 JSTempValueRooter tvr
;
567 JS_PUSH_SINGLE_TEMP_ROOT(cx
, v
, &tvr
);
568 *dp
= js_ValueToNumber(cx
, &tvr
.u
.value
);
569 JS_POP_TEMP_ROOT(cx
, &tvr
);
570 return !JSVAL_IS_NULL(tvr
.u
.value
);
573 JS_PUBLIC_API(JSBool
)
574 JS_ValueToECMAInt32(JSContext
*cx
, jsval v
, int32
*ip
)
576 JSTempValueRooter tvr
;
579 JS_PUSH_SINGLE_TEMP_ROOT(cx
, v
, &tvr
);
580 *ip
= js_ValueToECMAInt32(cx
, &tvr
.u
.value
);
581 JS_POP_TEMP_ROOT(cx
, &tvr
);
582 return !JSVAL_IS_NULL(tvr
.u
.value
);
585 JS_PUBLIC_API(JSBool
)
586 JS_ValueToECMAUint32(JSContext
*cx
, jsval v
, uint32
*ip
)
588 JSTempValueRooter tvr
;
591 JS_PUSH_SINGLE_TEMP_ROOT(cx
, v
, &tvr
);
592 *ip
= js_ValueToECMAUint32(cx
, &tvr
.u
.value
);
593 JS_POP_TEMP_ROOT(cx
, &tvr
);
594 return !JSVAL_IS_NULL(tvr
.u
.value
);
597 JS_PUBLIC_API(JSBool
)
598 JS_ValueToInt32(JSContext
*cx
, jsval v
, int32
*ip
)
600 JSTempValueRooter tvr
;
603 JS_PUSH_SINGLE_TEMP_ROOT(cx
, v
, &tvr
);
604 *ip
= js_ValueToInt32(cx
, &tvr
.u
.value
);
605 JS_POP_TEMP_ROOT(cx
, &tvr
);
606 return !JSVAL_IS_NULL(tvr
.u
.value
);
609 JS_PUBLIC_API(JSBool
)
610 JS_ValueToUint16(JSContext
*cx
, jsval v
, uint16
*ip
)
612 JSTempValueRooter tvr
;
615 JS_PUSH_SINGLE_TEMP_ROOT(cx
, v
, &tvr
);
616 *ip
= js_ValueToUint16(cx
, &tvr
.u
.value
);
617 JS_POP_TEMP_ROOT(cx
, &tvr
);
618 return !JSVAL_IS_NULL(tvr
.u
.value
);
621 JS_PUBLIC_API(JSBool
)
622 JS_ValueToBoolean(JSContext
*cx
, jsval v
, JSBool
*bp
)
625 *bp
= js_ValueToBoolean(v
);
629 JS_PUBLIC_API(JSType
)
630 JS_TypeOfValue(JSContext
*cx
, jsval v
)
638 if (JSVAL_IS_OBJECT(v
)) {
639 type
= JSTYPE_OBJECT
; /* XXXbe JSTYPE_NULL for JS2 */
640 obj
= JSVAL_TO_OBJECT(v
);
644 wrapped
= js_GetWrappedObject(cx
, obj
);
649 #if JS_HAS_XML_SUPPORT
650 if (ops
== &js_XMLObjectOps
.base
) {
656 * ECMA 262, 11.4.3 says that any native object that implements
657 * [[Call]] should be of type "function". Note that RegExp and
658 * Script are both of type "function" for compatibility with
659 * older SpiderMonkeys.
661 clasp
= OBJ_GET_CLASS(cx
, obj
);
662 if ((ops
== &js_ObjectOps
)
664 ? clasp
== &js_ScriptClass
665 : clasp
== &js_FunctionClass
)
666 : ops
->call
!= NULL
) {
667 type
= JSTYPE_FUNCTION
;
670 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
);
672 if (!OBJ_GET_PROPERTY(cx
, obj
,
673 ATOM_TO_JSID(cx
->runtime
->atomState
676 JS_ClearPendingException(cx
);
677 } else if (VALUE_IS_FUNCTION(cx
, v
)) {
678 type
= JSTYPE_FUNCTION
;
684 } else if (JSVAL_IS_NUMBER(v
)) {
685 type
= JSTYPE_NUMBER
;
686 } else if (JSVAL_IS_STRING(v
)) {
687 type
= JSTYPE_STRING
;
688 } else if (JSVAL_IS_BOOLEAN(v
)) {
689 type
= JSTYPE_BOOLEAN
;
696 JS_PUBLIC_API(const char *)
697 JS_GetTypeName(JSContext
*cx
, JSType type
)
699 if ((uintN
)type
>= (uintN
)JSTYPE_LIMIT
)
701 return JS_TYPE_STR(type
);
704 /************************************************************************/
707 * Has a new runtime ever been created? This flag is used to detect unsafe
708 * changes to js_CStringsAreUTF8 after a runtime has been created, and to
709 * ensure that "first checks" on runtime creation are run only once.
712 static JSBool js_NewRuntimeWasCalled
= JS_FALSE
;
715 JS_PUBLIC_API(JSRuntime
*)
716 JS_NewRuntime(uint32 maxbytes
)
721 if (!js_NewRuntimeWasCalled
) {
723 * This code asserts that the numbers associated with the error names
724 * in jsmsg.def are monotonically increasing. It uses values for the
725 * error names enumerated in jscntxt.c. It's not a compile-time check
726 * but it's better than nothing.
729 #define MSG_DEF(name, number, count, exception, format) \
730 JS_ASSERT(name == errorNumber++);
734 #define MSG_DEF(name, number, count, exception, format) \
736 uintN numfmtspecs = 0; \
738 for (fmt = format; *fmt != '\0'; fmt++) { \
739 if (*fmt == '{' && isdigit(fmt[1])) \
742 JS_ASSERT(count == numfmtspecs); \
747 js_NewRuntimeWasCalled
= JS_TRUE
;
751 rt
= (JSRuntime
*) malloc(sizeof(JSRuntime
));
755 /* Initialize infallibly first, so we can goto bad and JS_DestroyRuntime. */
756 memset(rt
, 0, sizeof(JSRuntime
));
757 JS_INIT_CLIST(&rt
->contextList
);
758 JS_INIT_CLIST(&rt
->trapList
);
759 JS_INIT_CLIST(&rt
->watchPointList
);
763 if (!js_InitGC(rt
, maxbytes
))
765 if (!js_InitAtomState(rt
))
767 if (!js_InitDeflatedStringCache(rt
))
770 if (!js_InitThreadPrivateIndex(js_ThreadDestructorCB
))
772 rt
->gcLock
= JS_NEW_LOCK();
775 rt
->gcDone
= JS_NEW_CONDVAR(rt
->gcLock
);
778 rt
->requestDone
= JS_NEW_CONDVAR(rt
->gcLock
);
779 if (!rt
->requestDone
)
781 /* this is asymmetric with JS_ShutDown: */
782 if (!js_SetupLocks(8, 16))
784 rt
->rtLock
= JS_NEW_LOCK();
787 rt
->stateChange
= JS_NEW_CONDVAR(rt
->gcLock
);
788 if (!rt
->stateChange
)
790 rt
->titleSharingDone
= JS_NEW_CONDVAR(rt
->gcLock
);
791 if (!rt
->titleSharingDone
)
793 rt
->titleSharingTodo
= NO_TITLE_SHARING_TODO
;
794 rt
->debuggerLock
= JS_NEW_LOCK();
795 if (!rt
->debuggerLock
)
798 if (!js_InitPropertyTree(rt
))
801 #if !defined JS_THREADSAFE && defined JS_TRACER
802 js_InitJIT(&rt
->traceMonitor
);
808 JS_DestroyRuntime(rt
);
813 JS_DestroyRuntime(JSRuntime
*rt
)
816 /* Don't hurt everyone in leaky ol' Mozilla with a fatal JS_ASSERT! */
817 if (!JS_CLIST_IS_EMPTY(&rt
->contextList
)) {
818 JSContext
*cx
, *iter
= NULL
;
820 while ((cx
= js_ContextIterator(rt
, JS_TRUE
, &iter
)) != NULL
) {
822 "JS API usage error: found live context at %p\n",
827 "JS API usage error: %u context%s left in runtime upon JS_DestroyRuntime.\n",
828 cxcount
, (cxcount
== 1) ? "" : "s");
832 #if !defined JS_THREADSAFE && defined JS_TRACER
833 js_FinishJIT(&rt
->traceMonitor
);
836 js_FreeRuntimeScriptState(rt
);
837 js_FinishAtomState(rt
);
840 * Free unit string storage only after all strings have been finalized, so
841 * that js_FinalizeString can detect unit strings and avoid calling free
842 * on their chars storage.
844 js_FinishUnitStrings(rt
);
847 * Finish the deflated string cache after the last GC and after
848 * calling js_FinishAtomState, which finalizes strings.
850 js_FinishDeflatedStringCache(rt
);
854 JS_DESTROY_LOCK(rt
->gcLock
);
856 JS_DESTROY_CONDVAR(rt
->gcDone
);
858 JS_DESTROY_CONDVAR(rt
->requestDone
);
860 JS_DESTROY_LOCK(rt
->rtLock
);
862 JS_DESTROY_CONDVAR(rt
->stateChange
);
863 if (rt
->titleSharingDone
)
864 JS_DESTROY_CONDVAR(rt
->titleSharingDone
);
865 if (rt
->debuggerLock
)
866 JS_DESTROY_LOCK(rt
->debuggerLock
);
868 GSN_CACHE_CLEAR(&rt
->gsnCache
);
870 js_FinishPropertyTree(rt
);
878 extern void js_DumpOpMeters();
885 js_CleanupThreadPrivateData(); /* Fixes bug 464828. */
891 JS_PUBLIC_API(void *)
892 JS_GetRuntimePrivate(JSRuntime
*rt
)
898 JS_SetRuntimePrivate(JSRuntime
*rt
, void *data
)
904 JS_BeginRequest(JSContext
*cx
)
909 JS_ASSERT(cx
->thread
->id
== js_CurrentThreadId());
910 if (!cx
->requestDepth
) {
911 JS_ASSERT(cx
->gcLocalFreeLists
== &js_GCEmptyFreeListSet
);
913 /* Wait until the GC is finished. */
917 /* NB: we use cx->thread here, not js_GetCurrentThread(). */
918 if (rt
->gcThread
!= cx
->thread
) {
919 while (rt
->gcLevel
> 0)
920 JS_AWAIT_GC_DONE(rt
);
923 /* Indicate that a request is running. */
925 cx
->requestDepth
= 1;
926 cx
->outstandingRequests
++;
931 cx
->outstandingRequests
++;
936 JS_EndRequest(JSContext
*cx
)
940 JSTitle
*title
, **todop
;
944 JS_ASSERT(cx
->requestDepth
> 0);
945 JS_ASSERT(cx
->outstandingRequests
> 0);
946 if (cx
->requestDepth
== 1) {
947 /* Lock before clearing to interlock with ClaimScope, in jslock.c. */
950 cx
->requestDepth
= 0;
951 cx
->outstandingRequests
--;
953 /* See whether cx has any single-threaded titles to start sharing. */
954 todop
= &rt
->titleSharingTodo
;
956 while ((title
= *todop
) != NO_TITLE_SHARING_TODO
) {
957 if (title
->ownercx
!= cx
) {
958 todop
= &title
->u
.link
;
961 *todop
= title
->u
.link
;
962 title
->u
.link
= NULL
; /* null u.link for sanity ASAP */
965 * If js_DropObjectMap returns null, we held the last ref to scope.
966 * The waiting thread(s) must have been killed, after which the GC
967 * collected the object that held this scope. Unlikely, because it
968 * requires that the GC ran (e.g., from an operation callback)
969 * during this request, but possible.
971 if (js_DropObjectMap(cx
, TITLE_TO_MAP(title
), NULL
)) {
972 js_InitLock(&title
->lock
);
973 title
->u
.count
= 0; /* NULL may not pun as 0 */
974 js_FinishSharingTitle(cx
, title
); /* set ownercx = NULL */
979 JS_NOTIFY_ALL_CONDVAR(rt
->titleSharingDone
);
981 js_RevokeGCLocalFreeLists(cx
);
983 /* Give the GC a chance to run if this was the last request running. */
984 JS_ASSERT(rt
->requestCount
> 0);
986 if (rt
->requestCount
== 0)
987 JS_NOTIFY_REQUEST_DONE(rt
);
994 cx
->outstandingRequests
--;
998 /* Yield to pending GC operations, regardless of request depth */
1000 JS_YieldRequest(JSContext
*cx
)
1002 #ifdef JS_THREADSAFE
1003 JS_ASSERT(cx
->thread
);
1005 JS_ResumeRequest(cx
, JS_SuspendRequest(cx
));
1009 JS_PUBLIC_API(jsrefcount
)
1010 JS_SuspendRequest(JSContext
*cx
)
1012 #ifdef JS_THREADSAFE
1013 jsrefcount saveDepth
= cx
->requestDepth
;
1015 while (cx
->requestDepth
) {
1016 cx
->outstandingRequests
++; /* compensate for JS_EndRequest */
1026 JS_ResumeRequest(JSContext
*cx
, jsrefcount saveDepth
)
1028 #ifdef JS_THREADSAFE
1029 JS_ASSERT(!cx
->requestDepth
);
1030 while (--saveDepth
>= 0) {
1031 JS_BeginRequest(cx
);
1032 cx
->outstandingRequests
--; /* compensate for JS_BeginRequest */
1038 JS_Lock(JSRuntime
*rt
)
1040 JS_LOCK_RUNTIME(rt
);
1044 JS_Unlock(JSRuntime
*rt
)
1046 JS_UNLOCK_RUNTIME(rt
);
1049 JS_PUBLIC_API(JSContextCallback
)
1050 JS_SetContextCallback(JSRuntime
*rt
, JSContextCallback cxCallback
)
1052 JSContextCallback old
;
1054 old
= rt
->cxCallback
;
1055 rt
->cxCallback
= cxCallback
;
1059 JS_PUBLIC_API(JSContext
*)
1060 JS_NewContext(JSRuntime
*rt
, size_t stackChunkSize
)
1062 return js_NewContext(rt
, stackChunkSize
);
1066 JS_DestroyContext(JSContext
*cx
)
1068 js_DestroyContext(cx
, JSDCM_FORCE_GC
);
1072 JS_DestroyContextNoGC(JSContext
*cx
)
1074 js_DestroyContext(cx
, JSDCM_NO_GC
);
1078 JS_DestroyContextMaybeGC(JSContext
*cx
)
1080 js_DestroyContext(cx
, JSDCM_MAYBE_GC
);
1083 JS_PUBLIC_API(void *)
1084 JS_GetContextPrivate(JSContext
*cx
)
1090 JS_SetContextPrivate(JSContext
*cx
, void *data
)
1095 JS_PUBLIC_API(JSRuntime
*)
1096 JS_GetRuntime(JSContext
*cx
)
1101 JS_PUBLIC_API(JSContext
*)
1102 JS_ContextIterator(JSRuntime
*rt
, JSContext
**iterp
)
1104 return js_ContextIterator(rt
, JS_TRUE
, iterp
);
1107 JS_PUBLIC_API(JSVersion
)
1108 JS_GetVersion(JSContext
*cx
)
1110 return JSVERSION_NUMBER(cx
);
1113 JS_PUBLIC_API(JSVersion
)
1114 JS_SetVersion(JSContext
*cx
, JSVersion version
)
1116 JSVersion oldVersion
;
1118 JS_ASSERT(version
!= JSVERSION_UNKNOWN
);
1119 JS_ASSERT((version
& ~JSVERSION_MASK
) == 0);
1121 oldVersion
= JSVERSION_NUMBER(cx
);
1122 if (version
== oldVersion
)
1125 /* We no longer support 1.4 or below. */
1126 if (version
!= JSVERSION_DEFAULT
&& version
<= JSVERSION_1_4
)
1129 cx
->version
= (cx
->version
& ~JSVERSION_MASK
) | version
;
1130 js_OnVersionChange(cx
);
1134 static struct v2smap
{
1138 {JSVERSION_1_0
, "1.0"},
1139 {JSVERSION_1_1
, "1.1"},
1140 {JSVERSION_1_2
, "1.2"},
1141 {JSVERSION_1_3
, "1.3"},
1142 {JSVERSION_1_4
, "1.4"},
1143 {JSVERSION_ECMA_3
, "ECMAv3"},
1144 {JSVERSION_1_5
, "1.5"},
1145 {JSVERSION_1_6
, "1.6"},
1146 {JSVERSION_1_7
, "1.7"},
1147 {JSVERSION_1_8
, "1.8"},
1148 {JSVERSION_DEFAULT
, js_default_str
},
1149 {JSVERSION_UNKNOWN
, NULL
}, /* must be last, NULL is sentinel */
1152 JS_PUBLIC_API(const char *)
1153 JS_VersionToString(JSVersion version
)
1157 for (i
= 0; v2smap
[i
].string
; i
++)
1158 if (v2smap
[i
].version
== version
)
1159 return v2smap
[i
].string
;
1163 JS_PUBLIC_API(JSVersion
)
1164 JS_StringToVersion(const char *string
)
1168 for (i
= 0; v2smap
[i
].string
; i
++)
1169 if (strcmp(v2smap
[i
].string
, string
) == 0)
1170 return v2smap
[i
].version
;
1171 return JSVERSION_UNKNOWN
;
1174 JS_PUBLIC_API(uint32
)
1175 JS_GetOptions(JSContext
*cx
)
1180 #define SYNC_OPTIONS_TO_VERSION(cx) \
1182 if ((cx)->options & JSOPTION_XML) \
1183 (cx)->version |= JSVERSION_HAS_XML; \
1185 (cx)->version &= ~JSVERSION_HAS_XML; \
1188 JS_PUBLIC_API(uint32
)
1189 JS_SetOptions(JSContext
*cx
, uint32 options
)
1191 uint32 oldopts
= cx
->options
;
1192 cx
->options
= options
;
1193 SYNC_OPTIONS_TO_VERSION(cx
);
1197 JS_PUBLIC_API(uint32
)
1198 JS_ToggleOptions(JSContext
*cx
, uint32 options
)
1200 uint32 oldopts
= cx
->options
;
1201 cx
->options
^= options
;
1202 SYNC_OPTIONS_TO_VERSION(cx
);
1206 JS_PUBLIC_API(const char *)
1207 JS_GetImplementationVersion(void)
1209 return "JavaScript-C 1.8.0 pre-release 1 2007-10-03";
1213 JS_PUBLIC_API(JSObject
*)
1214 JS_GetGlobalObject(JSContext
*cx
)
1216 return cx
->globalObject
;
1220 JS_SetGlobalObject(JSContext
*cx
, JSObject
*obj
)
1222 cx
->globalObject
= obj
;
1224 #if JS_HAS_XML_SUPPORT
1225 cx
->xmlSettingFlags
= 0;
1232 js_InitFunctionAndObjectClasses(JSContext
*cx
, JSObject
*obj
)
1234 JSDHashTable
*table
;
1238 JSResolvingEntry
*entry
;
1239 JSObject
*fun_proto
, *obj_proto
;
1241 /* If cx has no global object, use obj so prototypes can be found. */
1242 if (!cx
->globalObject
)
1243 JS_SetGlobalObject(cx
, obj
);
1245 /* Record Function and Object in cx->resolvingTable, if we are resolving. */
1246 table
= cx
->resolvingTable
;
1247 resolving
= (table
&& table
->entryCount
);
1251 key
.id
= ATOM_TO_JSID(rt
->atomState
.classAtoms
[JSProto_Function
]);
1252 entry
= (JSResolvingEntry
*)
1253 JS_DHashTableOperate(table
, &key
, JS_DHASH_ADD
);
1254 if (entry
&& entry
->key
.obj
&& (entry
->flags
& JSRESFLAG_LOOKUP
)) {
1255 /* Already resolving Function, record Object too. */
1256 JS_ASSERT(entry
->key
.obj
== obj
);
1257 key
.id
= ATOM_TO_JSID(rt
->atomState
.classAtoms
[JSProto_Object
]);
1258 entry
= (JSResolvingEntry
*)
1259 JS_DHashTableOperate(table
, &key
, JS_DHASH_ADD
);
1262 JS_ReportOutOfMemory(cx
);
1265 JS_ASSERT(!entry
->key
.obj
&& entry
->flags
== 0);
1267 entry
->flags
= JSRESFLAG_LOOKUP
;
1269 key
.id
= ATOM_TO_JSID(rt
->atomState
.classAtoms
[JSProto_Object
]);
1270 if (!js_StartResolving(cx
, &key
, JSRESFLAG_LOOKUP
, &entry
))
1273 key
.id
= ATOM_TO_JSID(rt
->atomState
.classAtoms
[JSProto_Function
]);
1274 if (!js_StartResolving(cx
, &key
, JSRESFLAG_LOOKUP
, &entry
)) {
1275 key
.id
= ATOM_TO_JSID(rt
->atomState
.classAtoms
[JSProto_Object
]);
1276 JS_DHashTableOperate(table
, &key
, JS_DHASH_REMOVE
);
1280 table
= cx
->resolvingTable
;
1283 /* Initialize the function class first so constructors can be made. */
1284 if (!js_GetClassPrototype(cx
, obj
, INT_TO_JSID(JSProto_Function
),
1290 fun_proto
= js_InitFunctionClass(cx
, obj
);
1296 ctor
= JS_GetConstructor(cx
, fun_proto
);
1301 OBJ_DEFINE_PROPERTY(cx
, obj
, ATOM_TO_JSID(CLASS_ATOM(cx
, Function
)),
1302 OBJECT_TO_JSVAL(ctor
), 0, 0, 0, NULL
);
1305 /* Initialize the object class next so Object.prototype works. */
1306 if (!js_GetClassPrototype(cx
, obj
, INT_TO_JSID(JSProto_Object
),
1312 obj_proto
= js_InitObjectClass(cx
, obj
);
1318 /* Function.prototype and the global object delegate to Object.prototype. */
1319 OBJ_SET_PROTO(cx
, fun_proto
, obj_proto
);
1320 if (!OBJ_GET_PROTO(cx
, obj
))
1321 OBJ_SET_PROTO(cx
, obj
, obj_proto
);
1324 /* If resolving, remove the other entry (Object or Function) from table. */
1325 JS_DHashTableOperate(table
, &key
, JS_DHASH_REMOVE
);
1327 /* If not resolving, remove the first entry added above, for Object. */
1328 JS_ASSERT(key
.id
== \
1329 ATOM_TO_JSID(rt
->atomState
.classAtoms
[JSProto_Function
]));
1330 key
.id
= ATOM_TO_JSID(rt
->atomState
.classAtoms
[JSProto_Object
]);
1331 JS_DHashTableOperate(table
, &key
, JS_DHASH_REMOVE
);
1338 JS_PUBLIC_API(JSBool
)
1339 JS_InitStandardClasses(JSContext
*cx
, JSObject
*obj
)
1345 /* Define a top-level property 'undefined' with the undefined value. */
1346 atom
= cx
->runtime
->atomState
.typeAtoms
[JSTYPE_VOID
];
1347 if (!OBJ_DEFINE_PROPERTY(cx
, obj
, ATOM_TO_JSID(atom
), JSVAL_VOID
,
1348 NULL
, NULL
, JSPROP_PERMANENT
, NULL
)) {
1352 /* Function and Object require cooperative bootstrapping magic. */
1353 if (!js_InitFunctionAndObjectClasses(cx
, obj
))
1356 /* Initialize the rest of the standard objects and functions. */
1357 return js_InitArrayClass(cx
, obj
) &&
1358 js_InitBlockClass(cx
, obj
) &&
1359 js_InitBooleanClass(cx
, obj
) &&
1360 js_InitCallClass(cx
, obj
) &&
1361 js_InitExceptionClasses(cx
, obj
) &&
1362 js_InitMathClass(cx
, obj
) &&
1363 js_InitNumberClass(cx
, obj
) &&
1364 js_InitJSONClass(cx
, obj
) &&
1365 js_InitRegExpClass(cx
, obj
) &&
1366 js_InitStringClass(cx
, obj
) &&
1367 js_InitEval(cx
, obj
) &&
1368 #if JS_HAS_SCRIPT_OBJECT
1369 js_InitScriptClass(cx
, obj
) &&
1371 #if JS_HAS_XML_SUPPORT
1372 js_InitXMLClasses(cx
, obj
) &&
1374 #if JS_HAS_FILE_OBJECT
1375 js_InitFileClass(cx
, obj
) &&
1377 #if JS_HAS_GENERATORS
1378 js_InitIteratorClasses(cx
, obj
) &&
1380 js_InitDateClass(cx
, obj
);
1383 #define CLASP(name) (&js_##name##Class)
1384 #define EXT_CLASP(name) (&js_##name##Class.base)
1385 #define EAGER_ATOM(name) ATOM_OFFSET(name), NULL
1386 #define EAGER_CLASS_ATOM(name) CLASS_ATOM_OFFSET(name), NULL
1387 #define EAGER_ATOM_AND_CLASP(name) EAGER_CLASS_ATOM(name), CLASP(name)
1388 #define EAGER_ATOM_AND_EXT_CLASP(name) EAGER_CLASS_ATOM(name), EXT_CLASP(name)
1389 #define LAZY_ATOM(name) ATOM_OFFSET(lazy.name), js_##name##_str
1391 typedef struct JSStdName
{
1393 size_t atomOffset
; /* offset of atom pointer in JSAtomState */
1394 const char *name
; /* null if atom is pre-pinned, else name */
1399 StdNameToAtom(JSContext
*cx
, JSStdName
*stdn
)
1405 offset
= stdn
->atomOffset
;
1406 atom
= OFFSET_TO_ATOM(cx
->runtime
, offset
);
1410 atom
= js_Atomize(cx
, name
, strlen(name
), ATOM_PINNED
);
1411 OFFSET_TO_ATOM(cx
->runtime
, offset
) = atom
;
1418 * Table of class initializers and their atom offsets in rt->atomState.
1419 * If you add a "standard" class, remember to update this table.
1421 static JSStdName standard_class_atoms
[] = {
1422 {js_InitFunctionAndObjectClasses
, EAGER_ATOM_AND_CLASP(Function
)},
1423 {js_InitFunctionAndObjectClasses
, EAGER_ATOM_AND_CLASP(Object
)},
1424 {js_InitArrayClass
, EAGER_ATOM_AND_CLASP(Array
)},
1425 {js_InitBlockClass
, EAGER_ATOM_AND_CLASP(Block
)},
1426 {js_InitBooleanClass
, EAGER_ATOM_AND_CLASP(Boolean
)},
1427 {js_InitDateClass
, EAGER_ATOM_AND_CLASP(Date
)},
1428 {js_InitMathClass
, EAGER_ATOM_AND_CLASP(Math
)},
1429 {js_InitNumberClass
, EAGER_ATOM_AND_CLASP(Number
)},
1430 {js_InitStringClass
, EAGER_ATOM_AND_CLASP(String
)},
1431 {js_InitCallClass
, EAGER_ATOM_AND_CLASP(Call
)},
1432 {js_InitExceptionClasses
, EAGER_ATOM_AND_CLASP(Error
)},
1433 {js_InitRegExpClass
, EAGER_ATOM_AND_CLASP(RegExp
)},
1434 #if JS_HAS_SCRIPT_OBJECT
1435 {js_InitScriptClass
, EAGER_ATOM_AND_CLASP(Script
)},
1437 #if JS_HAS_XML_SUPPORT
1438 {js_InitXMLClass
, EAGER_ATOM_AND_CLASP(XML
)},
1439 {js_InitNamespaceClass
, EAGER_ATOM_AND_EXT_CLASP(Namespace
)},
1440 {js_InitQNameClass
, EAGER_ATOM_AND_EXT_CLASP(QName
)},
1442 #if JS_HAS_FILE_OBJECT
1443 {js_InitFileClass
, EAGER_ATOM_AND_CLASP(File
)},
1445 #if JS_HAS_GENERATORS
1446 {js_InitIteratorClasses
, EAGER_ATOM_AND_CLASP(StopIteration
)},
1448 {js_InitJSONClass
, EAGER_ATOM_AND_CLASP(JSON
)},
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 /* ECMA requires that eval be a direct property of the global object. */
1459 {js_InitEval
, EAGER_ATOM(eval
), NULL
},
1461 /* Global properties and functions defined by the Number class. */
1462 {js_InitNumberClass
, LAZY_ATOM(NaN
), NULL
},
1463 {js_InitNumberClass
, LAZY_ATOM(Infinity
), NULL
},
1464 {js_InitNumberClass
, LAZY_ATOM(isNaN
), NULL
},
1465 {js_InitNumberClass
, LAZY_ATOM(isFinite
), NULL
},
1466 {js_InitNumberClass
, LAZY_ATOM(parseFloat
), NULL
},
1467 {js_InitNumberClass
, LAZY_ATOM(parseInt
), NULL
},
1469 /* String global functions. */
1470 {js_InitStringClass
, LAZY_ATOM(escape
), NULL
},
1471 {js_InitStringClass
, LAZY_ATOM(unescape
), NULL
},
1472 {js_InitStringClass
, LAZY_ATOM(decodeURI
), NULL
},
1473 {js_InitStringClass
, LAZY_ATOM(encodeURI
), NULL
},
1474 {js_InitStringClass
, LAZY_ATOM(decodeURIComponent
), NULL
},
1475 {js_InitStringClass
, LAZY_ATOM(encodeURIComponent
), NULL
},
1477 {js_InitStringClass
, LAZY_ATOM(uneval
), NULL
},
1480 /* Exception constructors. */
1481 {js_InitExceptionClasses
, EAGER_CLASS_ATOM(Error
), CLASP(Error
)},
1482 {js_InitExceptionClasses
, EAGER_CLASS_ATOM(InternalError
), CLASP(Error
)},
1483 {js_InitExceptionClasses
, EAGER_CLASS_ATOM(EvalError
), CLASP(Error
)},
1484 {js_InitExceptionClasses
, EAGER_CLASS_ATOM(RangeError
), CLASP(Error
)},
1485 {js_InitExceptionClasses
, EAGER_CLASS_ATOM(ReferenceError
), CLASP(Error
)},
1486 {js_InitExceptionClasses
, EAGER_CLASS_ATOM(SyntaxError
), CLASP(Error
)},
1487 {js_InitExceptionClasses
, EAGER_CLASS_ATOM(TypeError
), CLASP(Error
)},
1488 {js_InitExceptionClasses
, EAGER_CLASS_ATOM(URIError
), CLASP(Error
)},
1490 #if JS_HAS_XML_SUPPORT
1491 {js_InitAnyNameClass
, EAGER_ATOM_AND_CLASP(AnyName
)},
1492 {js_InitAttributeNameClass
, EAGER_ATOM_AND_CLASP(AttributeName
)},
1493 {js_InitXMLClass
, LAZY_ATOM(XMLList
), &js_XMLClass
},
1494 {js_InitXMLClass
, LAZY_ATOM(isXMLName
), NULL
},
1497 #if JS_HAS_GENERATORS
1498 {js_InitIteratorClasses
, EAGER_ATOM_AND_CLASP(Iterator
)},
1499 {js_InitIteratorClasses
, EAGER_ATOM_AND_CLASP(Generator
)},
1502 {NULL
, 0, NULL
, NULL
}
1505 static JSStdName object_prototype_names
[] = {
1506 /* Object.prototype properties (global delegates to Object.prototype). */
1507 {js_InitObjectClass
, EAGER_ATOM(proto
), NULL
},
1508 {js_InitObjectClass
, EAGER_ATOM(parent
), NULL
},
1509 {js_InitObjectClass
, EAGER_ATOM(count
), NULL
},
1511 {js_InitObjectClass
, EAGER_ATOM(toSource
), NULL
},
1513 {js_InitObjectClass
, EAGER_ATOM(toString
), NULL
},
1514 {js_InitObjectClass
, EAGER_ATOM(toLocaleString
), NULL
},
1515 {js_InitObjectClass
, EAGER_ATOM(valueOf
), NULL
},
1516 #if JS_HAS_OBJ_WATCHPOINT
1517 {js_InitObjectClass
, LAZY_ATOM(watch
), NULL
},
1518 {js_InitObjectClass
, LAZY_ATOM(unwatch
), NULL
},
1520 {js_InitObjectClass
, LAZY_ATOM(hasOwnProperty
), NULL
},
1521 {js_InitObjectClass
, LAZY_ATOM(isPrototypeOf
), NULL
},
1522 {js_InitObjectClass
, LAZY_ATOM(propertyIsEnumerable
), NULL
},
1523 #if JS_HAS_GETTER_SETTER
1524 {js_InitObjectClass
, LAZY_ATOM(defineGetter
), NULL
},
1525 {js_InitObjectClass
, LAZY_ATOM(defineSetter
), NULL
},
1526 {js_InitObjectClass
, LAZY_ATOM(lookupGetter
), NULL
},
1527 {js_InitObjectClass
, LAZY_ATOM(lookupSetter
), NULL
},
1530 {NULL
, 0, NULL
, NULL
}
1533 JS_PUBLIC_API(JSBool
)
1534 JS_ResolveStandardClass(JSContext
*cx
, JSObject
*obj
, jsval id
,
1544 *resolved
= JS_FALSE
;
1547 JS_ASSERT(rt
->state
!= JSRTS_DOWN
);
1548 if (rt
->state
== JSRTS_LANDING
|| !JSVAL_IS_STRING(id
))
1551 idstr
= JSVAL_TO_STRING(id
);
1553 /* Check whether we're resolving 'undefined', and define it if so. */
1554 atom
= rt
->atomState
.typeAtoms
[JSTYPE_VOID
];
1555 if (idstr
== ATOM_TO_STRING(atom
)) {
1556 *resolved
= JS_TRUE
;
1557 return OBJ_DEFINE_PROPERTY(cx
, obj
, ATOM_TO_JSID(atom
), JSVAL_VOID
,
1558 NULL
, NULL
, JSPROP_PERMANENT
, NULL
);
1561 /* Try for class constructors/prototypes named by well-known atoms. */
1563 for (i
= 0; standard_class_atoms
[i
].init
; i
++) {
1564 atom
= OFFSET_TO_ATOM(rt
, standard_class_atoms
[i
].atomOffset
);
1565 if (idstr
== ATOM_TO_STRING(atom
)) {
1566 stdnm
= &standard_class_atoms
[i
];
1572 /* Try less frequently used top-level functions and constants. */
1573 for (i
= 0; standard_class_names
[i
].init
; i
++) {
1574 atom
= StdNameToAtom(cx
, &standard_class_names
[i
]);
1577 if (idstr
== ATOM_TO_STRING(atom
)) {
1578 stdnm
= &standard_class_names
[i
];
1583 if (!stdnm
&& !OBJ_GET_PROTO(cx
, obj
)) {
1585 * Try even less frequently used names delegated from the global
1586 * object to Object.prototype, but only if the Object class hasn't
1587 * yet been initialized.
1589 for (i
= 0; object_prototype_names
[i
].init
; i
++) {
1590 atom
= StdNameToAtom(cx
, &object_prototype_names
[i
]);
1593 if (idstr
== ATOM_TO_STRING(atom
)) {
1594 stdnm
= &standard_class_names
[i
];
1603 * If this standard class is anonymous and obj advertises itself as a
1604 * global object (in order to reserve slots for standard class object
1605 * pointers), then we don't want to resolve by name.
1607 * If inversely, either id does not name a class, or id does not name
1608 * an anonymous class, or the global does not reserve slots for class
1609 * objects, then we must call the init hook here.
1612 (stdnm
->clasp
->flags
& JSCLASS_IS_ANONYMOUS
) &&
1613 (OBJ_GET_CLASS(cx
, obj
)->flags
& JSCLASS_IS_GLOBAL
)) {
1617 if (!stdnm
->init(cx
, obj
))
1619 *resolved
= JS_TRUE
;
1625 AlreadyHasOwnProperty(JSContext
*cx
, JSObject
*obj
, JSAtom
*atom
)
1627 JSScopeProperty
*sprop
;
1630 JS_ASSERT(OBJ_IS_NATIVE(obj
));
1631 JS_LOCK_OBJ(cx
, obj
);
1632 scope
= OBJ_SCOPE(obj
);
1633 sprop
= SCOPE_GET_PROPERTY(scope
, ATOM_TO_JSID(atom
));
1634 JS_UNLOCK_SCOPE(cx
, scope
);
1635 return sprop
!= NULL
;
1638 JS_PUBLIC_API(JSBool
)
1639 JS_EnumerateStandardClasses(JSContext
*cx
, JSObject
*obj
)
1648 /* Check whether we need to bind 'undefined' and define it if so. */
1649 atom
= rt
->atomState
.typeAtoms
[JSTYPE_VOID
];
1650 if (!AlreadyHasOwnProperty(cx
, obj
, atom
) &&
1651 !OBJ_DEFINE_PROPERTY(cx
, obj
, ATOM_TO_JSID(atom
), JSVAL_VOID
,
1652 NULL
, NULL
, JSPROP_PERMANENT
, NULL
)) {
1656 /* Initialize any classes that have not been resolved yet. */
1657 for (i
= 0; standard_class_atoms
[i
].init
; i
++) {
1658 atom
= OFFSET_TO_ATOM(rt
, standard_class_atoms
[i
].atomOffset
);
1659 if (!AlreadyHasOwnProperty(cx
, obj
, atom
) &&
1660 !standard_class_atoms
[i
].init(cx
, obj
)) {
1669 NewIdArray(JSContext
*cx
, jsint length
)
1674 JS_malloc(cx
, offsetof(JSIdArray
, vector
) + length
* sizeof(jsval
));
1676 ida
->length
= length
;
1681 * Unlike realloc(3), this function frees ida on failure.
1684 SetIdArrayLength(JSContext
*cx
, JSIdArray
*ida
, jsint length
)
1688 rida
= (JSIdArray
*)
1690 offsetof(JSIdArray
, vector
) + length
* sizeof(jsval
));
1692 JS_DestroyIdArray(cx
, ida
);
1694 rida
->length
= length
;
1699 AddAtomToArray(JSContext
*cx
, JSAtom
*atom
, JSIdArray
*ida
, jsint
*ip
)
1704 length
= ida
->length
;
1706 ida
= SetIdArrayLength(cx
, ida
, JS_MAX(length
* 2, 8));
1709 JS_ASSERT(i
< ida
->length
);
1711 ida
->vector
[i
] = ATOM_TO_JSID(atom
);
1717 EnumerateIfResolved(JSContext
*cx
, JSObject
*obj
, JSAtom
*atom
, JSIdArray
*ida
,
1718 jsint
*ip
, JSBool
*foundp
)
1720 *foundp
= AlreadyHasOwnProperty(cx
, obj
, atom
);
1722 ida
= AddAtomToArray(cx
, atom
, ida
, ip
);
1726 JS_PUBLIC_API(JSIdArray
*)
1727 JS_EnumerateResolvedStandardClasses(JSContext
*cx
, JSObject
*obj
,
1741 ida
= NewIdArray(cx
, 8);
1747 /* Check whether 'undefined' has been resolved and enumerate it if so. */
1748 atom
= rt
->atomState
.typeAtoms
[JSTYPE_VOID
];
1749 ida
= EnumerateIfResolved(cx
, obj
, atom
, ida
, &i
, &found
);
1753 /* Enumerate only classes that *have* been resolved. */
1754 for (j
= 0; standard_class_atoms
[j
].init
; j
++) {
1755 atom
= OFFSET_TO_ATOM(rt
, standard_class_atoms
[j
].atomOffset
);
1756 ida
= EnumerateIfResolved(cx
, obj
, atom
, ida
, &i
, &found
);
1761 init
= standard_class_atoms
[j
].init
;
1763 for (k
= 0; standard_class_names
[k
].init
; k
++) {
1764 if (standard_class_names
[k
].init
== init
) {
1765 atom
= StdNameToAtom(cx
, &standard_class_names
[k
]);
1766 ida
= AddAtomToArray(cx
, atom
, ida
, &i
);
1772 if (init
== js_InitObjectClass
) {
1773 for (k
= 0; object_prototype_names
[k
].init
; k
++) {
1774 atom
= StdNameToAtom(cx
, &object_prototype_names
[k
]);
1775 ida
= AddAtomToArray(cx
, atom
, ida
, &i
);
1783 /* Trim to exact length. */
1784 return SetIdArrayLength(cx
, ida
, i
);
1789 #undef EAGER_CLASS_ATOM
1790 #undef EAGER_ATOM_CLASP
1793 JS_PUBLIC_API(JSBool
)
1794 JS_GetClassObject(JSContext
*cx
, JSObject
*obj
, JSProtoKey key
,
1798 return js_GetClassObject(cx
, obj
, key
, objp
);
1801 JS_PUBLIC_API(JSObject
*)
1802 JS_GetScopeChain(JSContext
*cx
)
1807 fp
= js_GetTopStackFrame(cx
);
1810 * There is no code active on this context. In place of an actual
1811 * scope chain, use the context's global object, which is set in
1812 * js_InitFunctionAndObjectClasses, and which represents the default
1813 * scope chain for the embedding. See also js_FindClassObject.
1815 * For embeddings that use the inner and outer object hooks, the inner
1816 * object represents the ultimate global object, with the outer object
1817 * acting as a stand-in.
1819 JSObject
*obj
= cx
->globalObject
;
1821 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_INACTIVE
);
1825 OBJ_TO_INNER_OBJECT(cx
, obj
);
1828 return js_GetScopeChain(cx
, fp
);
1831 JS_PUBLIC_API(JSObject
*)
1832 JS_GetGlobalForObject(JSContext
*cx
, JSObject
*obj
)
1836 while ((parent
= OBJ_GET_PARENT(cx
, obj
)) != NULL
)
1841 JS_PUBLIC_API(jsval
)
1842 JS_ComputeThis(JSContext
*cx
, jsval
*vp
)
1844 if (!js_ComputeThis(cx
, JS_FALSE
, vp
+ 2))
1849 JS_PUBLIC_API(void *)
1850 JS_malloc(JSContext
*cx
, size_t nbytes
)
1854 JS_ASSERT(nbytes
!= 0);
1855 JS_COUNT_OPERATION(cx
, JSOW_ALLOCATION
);
1861 JS_ReportOutOfMemory(cx
);
1864 js_UpdateMallocCounter(cx
, nbytes
);
1869 JS_PUBLIC_API(void *)
1870 JS_realloc(JSContext
*cx
, void *p
, size_t nbytes
)
1872 JS_COUNT_OPERATION(cx
, JSOW_ALLOCATION
);
1873 p
= realloc(p
, nbytes
);
1875 JS_ReportOutOfMemory(cx
);
1880 JS_free(JSContext
*cx
, void *p
)
1886 JS_PUBLIC_API(char *)
1887 JS_strdup(JSContext
*cx
, const char *s
)
1893 p
= JS_malloc(cx
, n
);
1896 return (char *)memcpy(p
, s
, n
);
1899 JS_PUBLIC_API(jsdouble
*)
1900 JS_NewDouble(JSContext
*cx
, jsdouble d
)
1903 return js_NewWeaklyRootedDouble(cx
, d
);
1906 JS_PUBLIC_API(JSBool
)
1907 JS_NewDoubleValue(JSContext
*cx
, jsdouble d
, jsval
*rval
)
1912 dp
= js_NewWeaklyRootedDouble(cx
, d
);
1915 *rval
= DOUBLE_TO_JSVAL(dp
);
1919 JS_PUBLIC_API(JSBool
)
1920 JS_NewNumberValue(JSContext
*cx
, jsdouble d
, jsval
*rval
)
1925 if (JSDOUBLE_IS_INT(d
, i
) && INT_FITS_IN_JSVAL(i
)) {
1926 *rval
= INT_TO_JSVAL(i
);
1929 return JS_NewDoubleValue(cx
, d
, rval
);
1933 JS_PUBLIC_API(JSBool
)
1934 JS_AddRoot(JSContext
*cx
, void *rp
)
1937 return js_AddRoot(cx
, rp
, NULL
);
1940 JS_PUBLIC_API(JSBool
)
1941 JS_AddNamedRootRT(JSRuntime
*rt
, void *rp
, const char *name
)
1943 return js_AddRootRT(rt
, rp
, name
);
1946 JS_PUBLIC_API(JSBool
)
1947 JS_RemoveRoot(JSContext
*cx
, void *rp
)
1950 return js_RemoveRoot(cx
->runtime
, rp
);
1953 JS_PUBLIC_API(JSBool
)
1954 JS_RemoveRootRT(JSRuntime
*rt
, void *rp
)
1956 return js_RemoveRoot(rt
, rp
);
1959 JS_PUBLIC_API(JSBool
)
1960 JS_AddNamedRoot(JSContext
*cx
, void *rp
, const char *name
)
1963 return js_AddRoot(cx
, rp
, name
);
1967 JS_ClearNewbornRoots(JSContext
*cx
)
1969 JS_CLEAR_WEAK_ROOTS(&cx
->weakRoots
);
1972 JS_PUBLIC_API(JSBool
)
1973 JS_EnterLocalRootScope(JSContext
*cx
)
1976 return js_EnterLocalRootScope(cx
);
1980 JS_LeaveLocalRootScope(JSContext
*cx
)
1983 js_LeaveLocalRootScope(cx
);
1987 JS_LeaveLocalRootScopeWithResult(JSContext
*cx
, jsval rval
)
1990 js_LeaveLocalRootScopeWithResult(cx
, rval
);
1994 JS_ForgetLocalRoot(JSContext
*cx
, void *thing
)
1997 js_ForgetLocalRoot(cx
, (jsval
) thing
);
2003 JS_DumpNamedRoots(JSRuntime
*rt
,
2004 void (*dump
)(const char *name
, void *rp
, void *data
),
2007 js_DumpNamedRoots(rt
, dump
, data
);
2012 JS_PUBLIC_API(uint32
)
2013 JS_MapGCRoots(JSRuntime
*rt
, JSGCRootMapFun map
, void *data
)
2015 return js_MapGCRoots(rt
, map
, data
);
2018 JS_PUBLIC_API(JSBool
)
2019 JS_LockGCThing(JSContext
*cx
, void *thing
)
2024 ok
= js_LockGCThingRT(cx
->runtime
, thing
);
2026 JS_ReportOutOfMemory(cx
);
2030 JS_PUBLIC_API(JSBool
)
2031 JS_LockGCThingRT(JSRuntime
*rt
, void *thing
)
2033 return js_LockGCThingRT(rt
, thing
);
2036 JS_PUBLIC_API(JSBool
)
2037 JS_UnlockGCThing(JSContext
*cx
, void *thing
)
2042 ok
= js_UnlockGCThingRT(cx
->runtime
, thing
);
2044 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_CANT_UNLOCK
);
2048 JS_PUBLIC_API(JSBool
)
2049 JS_UnlockGCThingRT(JSRuntime
*rt
, void *thing
)
2051 return js_UnlockGCThingRT(rt
, thing
);
2055 JS_SetExtraGCRoots(JSRuntime
*rt
, JSTraceDataOp traceOp
, void *data
)
2057 rt
->gcExtraRootsTraceOp
= traceOp
;
2058 rt
->gcExtraRootsData
= data
;
2062 JS_TraceRuntime(JSTracer
*trc
)
2064 JSBool allAtoms
= trc
->context
->runtime
->gcKeepAtoms
!= 0;
2066 js_TraceRuntime(trc
, allAtoms
);
2071 #ifdef HAVE_XPCONNECT
2072 #include "dump_xpc.h"
2076 JS_PrintTraceThingInfo(char *buf
, size_t bufsize
, JSTracer
*trc
,
2077 void *thing
, uint32 kind
, JSBool details
)
2086 case JSTRACE_OBJECT
:
2088 JSObject
*obj
= (JSObject
*)thing
;
2089 JSClass
*clasp
= STOBJ_GET_CLASS(obj
);
2092 #ifdef HAVE_XPCONNECT
2093 if (clasp
->flags
& JSCLASS_PRIVATE_IS_NSISUPPORTS
) {
2094 jsval privateValue
= STOBJ_GET_SLOT(obj
, JSSLOT_PRIVATE
);
2096 JS_ASSERT(clasp
->flags
& JSCLASS_HAS_PRIVATE
);
2097 if (!JSVAL_IS_VOID(privateValue
)) {
2098 void *privateThing
= JSVAL_TO_PRIVATE(privateValue
);
2099 const char *xpcClassName
= GetXPCObjectClassName(privateThing
);
2102 name
= xpcClassName
;
2109 case JSTRACE_STRING
:
2110 name
= JSSTRING_IS_DEPENDENT((JSString
*)thing
)
2115 case JSTRACE_DOUBLE
:
2119 #if JS_HAS_XML_SUPPORT
2131 if (n
> bufsize
- 1)
2133 memcpy(buf
, name
, n
+ 1);
2137 if (details
&& bufsize
> 2) {
2142 case JSTRACE_OBJECT
:
2144 JSObject
*obj
= (JSObject
*)thing
;
2145 JSClass
*clasp
= STOBJ_GET_CLASS(obj
);
2146 if (clasp
== &js_FunctionClass
) {
2147 JSFunction
*fun
= (JSFunction
*)
2148 JS_GetPrivate(trc
->context
, obj
);
2151 JS_snprintf(buf
, bufsize
, "<newborn>");
2152 } else if (FUN_OBJECT(fun
) != obj
) {
2153 JS_snprintf(buf
, bufsize
, "%p", fun
);
2155 if (fun
->atom
&& ATOM_IS_STRING(fun
->atom
))
2156 js_PutEscapedString(buf
, bufsize
,
2157 ATOM_TO_STRING(fun
->atom
), 0);
2159 } else if (clasp
->flags
& JSCLASS_HAS_PRIVATE
) {
2160 jsval privateValue
= STOBJ_GET_SLOT(obj
, JSSLOT_PRIVATE
);
2161 void *privateThing
= JSVAL_IS_VOID(privateValue
)
2163 : JSVAL_TO_PRIVATE(privateValue
);
2165 JS_snprintf(buf
, bufsize
, "%p", privateThing
);
2167 JS_snprintf(buf
, bufsize
, "<no private>");
2172 case JSTRACE_STRING
:
2173 js_PutEscapedString(buf
, bufsize
, (JSString
*)thing
, 0);
2176 case JSTRACE_DOUBLE
:
2177 JS_snprintf(buf
, bufsize
, "%g", *(jsdouble
*)thing
);
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 JS_malloc(cx
, 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 JS_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
, void *thing
, 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 JS_SET_TRACING_NAME(trc
, name
? name
: "unknown");
2470 js_CallValueTracerIfGCThing(trc
, (jsval
)thing
);
2473 extern JS_PUBLIC_API(JSBool
)
2474 JS_IsGCMarkingTracer(JSTracer
*trc
)
2476 return IS_GC_MARKING_TRACER(trc
);
2480 JS_GC(JSContext
*cx
)
2482 /* Don't nuke active arenas if executing or compiling. */
2483 if (cx
->stackPool
.current
== &cx
->stackPool
.first
)
2484 JS_FinishArenaPool(&cx
->stackPool
);
2485 if (cx
->tempPool
.current
== &cx
->tempPool
.first
)
2486 JS_FinishArenaPool(&cx
->tempPool
);
2487 js_GC(cx
, GC_NORMAL
);
2491 JS_MaybeGC(JSContext
*cx
)
2494 uint32 bytes
, lastBytes
;
2499 if (rt
->gcZeal
> 0) {
2505 bytes
= rt
->gcBytes
;
2506 lastBytes
= rt
->gcLastBytes
;
2509 * We run the GC if we used all available free GC cells and had to
2510 * allocate extra 1/3 of GC arenas since the last run of GC, or if
2511 * we have malloc'd more bytes through JS_malloc than we were told
2512 * to allocate by JS_NewRuntime.
2515 * bytes > 4/3 lastBytes
2516 * condition is the following. Bug 312238 changed bytes and lastBytes
2517 * to mean the total amount of memory that the GC uses now and right
2518 * after the last GC.
2520 * Before the bug the variables meant the size of allocated GC things
2521 * now and right after the last GC. That size did not include the
2522 * memory taken by free GC cells and the condition was
2523 * bytes > 3/2 lastBytes.
2524 * That is, we run the GC if we have half again as many bytes of
2525 * GC-things as the last time we GC'd. To be compatible we need to
2526 * express that condition through the new meaning of bytes and
2529 * We write the original condition as
2530 * B*(1-F) > 3/2 Bl*(1-Fl)
2531 * where B is the total memory size allocated by GC and F is the free
2532 * cell density currently and Sl and Fl are the size and the density
2533 * right after GC. The density by definition is memory taken by free
2534 * cells divided by total amount of memory. In other words, B and Bl
2535 * are bytes and lastBytes with the new meaning and B*(1-F) and
2536 * Bl*(1-Fl) are bytes and lastBytes with the original meaning.
2538 * Our task is to exclude F and Fl from the last statement. According
2539 * to the stats from bug 331966 comment 23, Fl is about 10-25% for a
2540 * typical run of the browser. It means that the original condition
2541 * implied that we did not run GC unless we exhausted the pool of
2542 * free cells. Indeed if we still have free cells, then B == Bl since
2543 * we did not yet allocated any new arenas and the condition means
2544 * 1 - F > 3/2 (1-Fl) or 3/2Fl > 1/2 + F
2545 * That implies 3/2 Fl > 1/2 or Fl > 1/3. That can not be fulfilled
2546 * for the state described by the stats. So we can write the original
2548 * F == 0 && B > 3/2 Bl(1-Fl)
2549 * Again using the stats we see that Fl is about 11% when the browser
2550 * starts up and when we are far from hitting rt->gcMaxBytes. With
2552 * F == 0 && B > 3/2 Bl(1-0.11)
2553 * or approximately F == 0 && B > 4/3 Bl.
2555 if ((bytes
> 8192 && bytes
> lastBytes
+ lastBytes
/ 3) ||
2556 rt
->gcMallocBytes
>= rt
->gcMaxMallocBytes
) {
2561 JS_PUBLIC_API(JSGCCallback
)
2562 JS_SetGCCallback(JSContext
*cx
, JSGCCallback cb
)
2565 return JS_SetGCCallbackRT(cx
->runtime
, cb
);
2568 JS_PUBLIC_API(JSGCCallback
)
2569 JS_SetGCCallbackRT(JSRuntime
*rt
, JSGCCallback cb
)
2573 oldcb
= rt
->gcCallback
;
2574 rt
->gcCallback
= cb
;
2578 JS_PUBLIC_API(JSBool
)
2579 JS_IsAboutToBeFinalized(JSContext
*cx
, void *thing
)
2582 return js_IsAboutToBeFinalized(cx
, thing
);
2586 JS_SetGCParameter(JSRuntime
*rt
, JSGCParamKey key
, uint32 value
)
2589 case JSGC_MAX_BYTES
:
2590 rt
->gcMaxBytes
= value
;
2592 case JSGC_MAX_MALLOC_BYTES
:
2593 rt
->gcMaxMallocBytes
= value
;
2595 case JSGC_STACKPOOL_LIFESPAN
:
2596 rt
->gcEmptyArenaPoolLifespan
= value
;
2602 JS_AddExternalStringFinalizer(JSStringFinalizeOp finalizer
)
2604 return js_ChangeExternalStringFinalizer(NULL
, finalizer
);
2608 JS_RemoveExternalStringFinalizer(JSStringFinalizeOp finalizer
)
2610 return js_ChangeExternalStringFinalizer(finalizer
, NULL
);
2613 JS_PUBLIC_API(JSString
*)
2614 JS_NewExternalString(JSContext
*cx
, jschar
*chars
, size_t length
, intN type
)
2619 JS_ASSERT((uintN
) type
< (uintN
) (GCX_NTYPES
- GCX_EXTERNAL_STRING
));
2621 str
= (JSString
*) js_NewGCThing(cx
, (uintN
) type
+ GCX_EXTERNAL_STRING
,
2625 JSFLATSTR_INIT(str
, chars
, length
);
2630 JS_GetExternalStringGCType(JSRuntime
*rt
, JSString
*str
)
2632 return js_GetExternalStringGCType(str
);
2636 JS_SetThreadStackLimit(JSContext
*cx
, jsuword limitAddr
)
2638 #if JS_STACK_GROWTH_DIRECTION > 0
2640 limitAddr
= (jsuword
)-1;
2642 cx
->stackLimit
= limitAddr
;
2646 JS_SetScriptStackQuota(JSContext
*cx
, size_t quota
)
2648 cx
->scriptStackQuota
= quota
;
2651 /************************************************************************/
2654 JS_DestroyIdArray(JSContext
*cx
, JSIdArray
*ida
)
2659 JS_PUBLIC_API(JSBool
)
2660 JS_ValueToId(JSContext
*cx
, jsval v
, jsid
*idp
)
2663 if (JSVAL_IS_INT(v
))
2664 *idp
= INT_JSVAL_TO_JSID(v
);
2665 #if JS_HAS_XML_SUPPORT
2666 else if (!JSVAL_IS_PRIMITIVE(v
))
2667 *idp
= OBJECT_JSVAL_TO_JSID(v
);
2670 return js_ValueToStringId(cx
, v
, idp
);
2674 JS_PUBLIC_API(JSBool
)
2675 JS_IdToValue(JSContext
*cx
, jsid id
, jsval
*vp
)
2678 *vp
= ID_TO_VALUE(id
);
2682 JS_PUBLIC_API(JSBool
)
2683 JS_PropertyStub(JSContext
*cx
, JSObject
*obj
, jsval id
, jsval
*vp
)
2688 JS_PUBLIC_API(JSBool
)
2689 JS_EnumerateStub(JSContext
*cx
, JSObject
*obj
)
2694 JS_PUBLIC_API(JSBool
)
2695 JS_ResolveStub(JSContext
*cx
, JSObject
*obj
, jsval id
)
2700 JS_PUBLIC_API(JSBool
)
2701 JS_ConvertStub(JSContext
*cx
, JSObject
*obj
, JSType type
, jsval
*vp
)
2703 return js_TryValueOf(cx
, obj
, type
, vp
);
2707 JS_FinalizeStub(JSContext
*cx
, JSObject
*obj
)
2711 JS_PUBLIC_API(JSObject
*)
2712 JS_InitClass(JSContext
*cx
, JSObject
*obj
, JSObject
*parent_proto
,
2713 JSClass
*clasp
, JSNative constructor
, uintN nargs
,
2714 JSPropertySpec
*ps
, JSFunctionSpec
*fs
,
2715 JSPropertySpec
*static_ps
, JSFunctionSpec
*static_fs
)
2719 JSObject
*proto
, *ctor
;
2720 JSTempValueRooter tvr
;
2726 atom
= js_Atomize(cx
, clasp
->name
, strlen(clasp
->name
), 0);
2731 * When initializing a standard class, if no parent_proto (grand-proto of
2732 * instances of the class, parent-proto of the class's prototype object)
2733 * is given, we must use Object.prototype if it is available. Otherwise,
2734 * we could look up the wrong binding for a class name in obj. Example:
2737 * print("hi there".join);
2739 * should print undefined, not Array.prototype.join. This is required by
2740 * ECMA-262, alas. It might have been better to make String readonly and
2741 * permanent in the global object, instead -- but that's too big a change
2742 * to swallow at this point.
2744 key
= JSCLASS_CACHED_PROTO_KEY(clasp
);
2745 if (key
!= JSProto_Null
&&
2747 !js_GetClassPrototype(cx
, obj
, INT_TO_JSID(JSProto_Object
),
2752 /* Create a prototype object for this class. */
2753 proto
= js_NewObject(cx
, clasp
, parent_proto
, obj
, 0);
2757 /* After this point, control must exit via label bad or out. */
2758 JS_PUSH_TEMP_ROOT_OBJECT(cx
, proto
, &tvr
);
2762 * Lacking a constructor, name the prototype (e.g., Math) unless this
2763 * class (a) is anonymous, i.e. for internal use only; (b) the class
2764 * of obj (the global object) is has a reserved slot indexed by key;
2765 * and (c) key is not the null key.
2767 if ((clasp
->flags
& JSCLASS_IS_ANONYMOUS
) &&
2768 (OBJ_GET_CLASS(cx
, obj
)->flags
& JSCLASS_IS_GLOBAL
) &&
2769 key
!= JSProto_Null
) {
2772 named
= OBJ_DEFINE_PROPERTY(cx
, obj
, ATOM_TO_JSID(atom
),
2773 OBJECT_TO_JSVAL(proto
),
2774 JS_PropertyStub
, JS_PropertyStub
,
2775 (clasp
->flags
& JSCLASS_IS_ANONYMOUS
)
2776 ? JSPROP_READONLY
| JSPROP_PERMANENT
2785 /* Define the constructor function in obj's scope. */
2786 fun
= js_DefineFunction(cx
, obj
, atom
, constructor
, nargs
,
2788 named
= (fun
!= NULL
);
2793 * Remember the class this function is a constructor for so that
2794 * we know to create an object of this class when we call the
2797 FUN_CLASP(fun
) = clasp
;
2800 * Optionally construct the prototype object, before the class has
2801 * been fully initialized. Allow the ctor to replace proto with a
2802 * different object, as is done for operator new -- and as at least
2803 * XML support requires.
2805 ctor
= FUN_OBJECT(fun
);
2806 if (clasp
->flags
& JSCLASS_CONSTRUCT_PROTOTYPE
) {
2807 cval
= OBJECT_TO_JSVAL(ctor
);
2808 if (!js_InternalConstruct(cx
, proto
, cval
, 0, NULL
, &rval
))
2810 if (!JSVAL_IS_PRIMITIVE(rval
) && JSVAL_TO_OBJECT(rval
) != proto
)
2811 proto
= JSVAL_TO_OBJECT(rval
);
2814 /* Connect constructor and prototype by named properties. */
2815 if (!js_SetClassPrototype(cx
, ctor
, proto
,
2816 JSPROP_READONLY
| JSPROP_PERMANENT
)) {
2820 /* Bootstrap Function.prototype (see also JS_InitStandardClasses). */
2821 if (OBJ_GET_CLASS(cx
, ctor
) == clasp
) {
2822 OBJ_SET_PROTO(cx
, ctor
, proto
);
2826 /* Add properties and methods to the prototype and the constructor. */
2827 if ((ps
&& !JS_DefineProperties(cx
, proto
, ps
)) ||
2828 (fs
&& !JS_DefineFunctions(cx
, proto
, fs
)) ||
2829 (static_ps
&& !JS_DefineProperties(cx
, ctor
, static_ps
)) ||
2830 (static_fs
&& !JS_DefineFunctions(cx
, ctor
, static_fs
))) {
2834 /* If this is a standard class, cache its prototype. */
2835 if (key
!= JSProto_Null
&& !js_SetClassObject(cx
, obj
, key
, ctor
))
2839 JS_POP_TEMP_ROOT(cx
, &tvr
);
2844 (void) OBJ_DELETE_PROPERTY(cx
, obj
, ATOM_TO_JSID(atom
), &rval
);
2849 #ifdef JS_THREADSAFE
2850 JS_PUBLIC_API(JSClass
*)
2851 JS_GetClass(JSContext
*cx
, JSObject
*obj
)
2853 return OBJ_GET_CLASS(cx
, obj
);
2856 JS_PUBLIC_API(JSClass
*)
2857 JS_GetClass(JSObject
*obj
)
2859 return LOCKED_OBJ_GET_CLASS(obj
);
2863 JS_PUBLIC_API(JSBool
)
2864 JS_InstanceOf(JSContext
*cx
, JSObject
*obj
, JSClass
*clasp
, jsval
*argv
)
2869 if (obj
&& OBJ_GET_CLASS(cx
, obj
) == clasp
)
2872 fun
= js_ValueToFunction(cx
, &argv
[-2], 0);
2874 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
,
2875 JSMSG_INCOMPATIBLE_PROTO
,
2876 clasp
->name
, JS_GetFunctionName(fun
),
2878 ? OBJ_GET_CLASS(cx
, obj
)->name
2885 JS_PUBLIC_API(JSBool
)
2886 JS_HasInstance(JSContext
*cx
, JSObject
*obj
, jsval v
, JSBool
*bp
)
2888 return js_HasInstance(cx
, obj
, v
, bp
);
2891 JS_PUBLIC_API(void *)
2892 JS_GetPrivate(JSContext
*cx
, JSObject
*obj
)
2896 JS_ASSERT(OBJ_GET_CLASS(cx
, obj
)->flags
& JSCLASS_HAS_PRIVATE
);
2897 v
= obj
->fslots
[JSSLOT_PRIVATE
];
2898 if (!JSVAL_IS_INT(v
))
2900 return JSVAL_TO_PRIVATE(v
);
2903 JS_PUBLIC_API(JSBool
)
2904 JS_SetPrivate(JSContext
*cx
, JSObject
*obj
, void *data
)
2906 JS_ASSERT(OBJ_GET_CLASS(cx
, obj
)->flags
& JSCLASS_HAS_PRIVATE
);
2907 obj
->fslots
[JSSLOT_PRIVATE
] = PRIVATE_TO_JSVAL(data
);
2911 JS_PUBLIC_API(void *)
2912 JS_GetInstancePrivate(JSContext
*cx
, JSObject
*obj
, JSClass
*clasp
,
2915 if (!JS_InstanceOf(cx
, obj
, clasp
, argv
))
2917 return JS_GetPrivate(cx
, obj
);
2920 JS_PUBLIC_API(JSObject
*)
2921 JS_GetPrototype(JSContext
*cx
, JSObject
*obj
)
2926 proto
= OBJ_GET_PROTO(cx
, obj
);
2928 /* Beware ref to dead object (we may be called from obj's finalizer). */
2929 return proto
&& proto
->map
? proto
: NULL
;
2932 JS_PUBLIC_API(JSBool
)
2933 JS_SetPrototype(JSContext
*cx
, JSObject
*obj
, JSObject
*proto
)
2936 JS_ASSERT(obj
!= proto
);
2939 * FIXME: bug 408416. The cycle-detection required for script-writeable
2940 * __proto__ lives in js_SetProtoOrParent over in jsobj.c, also known as
2941 * js_ObjectOps.setProto. This hook must detect cycles, to prevent scripts
2942 * from ilooping SpiderMonkey trivially. But the overhead of detecting
2943 * cycles is high enough, and the threat from JS-API-calling C++ code is
2944 * low enough, that it's not worth burdening the non-DEBUG callers. Same
2945 * goes for JS_SetParent, below.
2947 if (obj
->map
->ops
->setProto
)
2948 return obj
->map
->ops
->setProto(cx
, obj
, JSSLOT_PROTO
, proto
);
2950 if (OBJ_IS_NATIVE(obj
)) {
2951 JS_LOCK_OBJ(cx
, obj
);
2952 if (!js_GetMutableScope(cx
, obj
)) {
2953 JS_UNLOCK_OBJ(cx
, obj
);
2956 LOCKED_OBJ_SET_PROTO(obj
, proto
);
2957 JS_UNLOCK_OBJ(cx
, obj
);
2961 OBJ_SET_PROTO(cx
, obj
, proto
);
2965 JS_PUBLIC_API(JSObject
*)
2966 JS_GetParent(JSContext
*cx
, JSObject
*obj
)
2970 parent
= OBJ_GET_PARENT(cx
, obj
);
2972 /* Beware ref to dead object (we may be called from obj's finalizer). */
2973 return parent
&& parent
->map
? parent
: NULL
;
2976 JS_PUBLIC_API(JSBool
)
2977 JS_SetParent(JSContext
*cx
, JSObject
*obj
, JSObject
*parent
)
2980 JS_ASSERT(obj
!= parent
);
2982 /* FIXME: bug 408416, see JS_SetPrototype just above. */
2983 if (obj
->map
->ops
->setParent
)
2984 return obj
->map
->ops
->setParent(cx
, obj
, JSSLOT_PARENT
, parent
);
2986 OBJ_SET_PARENT(cx
, obj
, parent
);
2990 JS_PUBLIC_API(JSObject
*)
2991 JS_GetConstructor(JSContext
*cx
, JSObject
*proto
)
2997 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
);
2999 if (!OBJ_GET_PROPERTY(cx
, proto
,
3000 ATOM_TO_JSID(cx
->runtime
->atomState
.constructorAtom
),
3005 if (!VALUE_IS_FUNCTION(cx
, cval
)) {
3006 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_NO_CONSTRUCTOR
,
3007 OBJ_GET_CLASS(cx
, proto
)->name
);
3010 return JSVAL_TO_OBJECT(cval
);
3013 JS_PUBLIC_API(JSBool
)
3014 JS_GetObjectId(JSContext
*cx
, JSObject
*obj
, jsid
*idp
)
3016 JS_ASSERT(JSID_IS_OBJECT(obj
));
3017 *idp
= OBJECT_TO_JSID(obj
);
3021 JS_PUBLIC_API(JSObject
*)
3022 JS_NewObject(JSContext
*cx
, JSClass
*clasp
, JSObject
*proto
, JSObject
*parent
)
3026 clasp
= &js_ObjectClass
; /* default class is Object */
3027 return js_NewObject(cx
, clasp
, proto
, parent
, 0);
3030 JS_PUBLIC_API(JSObject
*)
3031 JS_NewObjectWithGivenProto(JSContext
*cx
, JSClass
*clasp
, JSObject
*proto
,
3036 clasp
= &js_ObjectClass
; /* default class is Object */
3037 return js_NewObjectWithGivenProto(cx
, clasp
, proto
, parent
, 0);
3040 JS_PUBLIC_API(JSBool
)
3041 JS_SealObject(JSContext
*cx
, JSObject
*obj
, JSBool deep
)
3048 if (OBJ_IS_DENSE_ARRAY(cx
, obj
) && !js_MakeArraySlow(cx
, obj
))
3051 if (!OBJ_IS_NATIVE(obj
)) {
3052 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
,
3053 JSMSG_CANT_SEAL_OBJECT
,
3054 OBJ_GET_CLASS(cx
, obj
)->name
);
3058 scope
= OBJ_SCOPE(obj
);
3060 #if defined JS_THREADSAFE && defined DEBUG
3061 /* Insist on scope being used exclusively by cx's thread. */
3062 if (scope
->title
.ownercx
!= cx
) {
3063 JS_LOCK_OBJ(cx
, obj
);
3064 JS_ASSERT(OBJ_SCOPE(obj
) == scope
);
3065 JS_ASSERT(scope
->title
.ownercx
== cx
);
3066 JS_UNLOCK_SCOPE(cx
, scope
);
3070 /* Nothing to do if obj's scope is already sealed. */
3071 if (SCOPE_IS_SEALED(scope
))
3074 /* XXX Enumerate lazy properties now, as they can't be added later. */
3075 ida
= JS_Enumerate(cx
, obj
);
3078 JS_DestroyIdArray(cx
, ida
);
3080 /* Ensure that obj has its own, mutable scope, and seal that scope. */
3081 JS_LOCK_OBJ(cx
, obj
);
3082 scope
= js_GetMutableScope(cx
, obj
);
3084 SCOPE_SET_SEALED(scope
);
3085 SCOPE_MAKE_UNIQUE_SHAPE(cx
, scope
);
3087 JS_UNLOCK_OBJ(cx
, obj
);
3091 /* If we are not sealing an entire object graph, we're done. */
3095 /* Walk slots in obj and if any value is a non-null object, seal it. */
3096 nslots
= scope
->map
.freeslot
;
3097 for (i
= 0; i
!= nslots
; ++i
) {
3098 v
= STOBJ_GET_SLOT(obj
, i
);
3099 if (JSVAL_IS_PRIMITIVE(v
))
3101 if (!JS_SealObject(cx
, JSVAL_TO_OBJECT(v
), deep
))
3107 JS_PUBLIC_API(JSObject
*)
3108 JS_ConstructObject(JSContext
*cx
, JSClass
*clasp
, JSObject
*proto
,
3113 clasp
= &js_ObjectClass
; /* default class is Object */
3114 return js_ConstructObject(cx
, clasp
, proto
, parent
, 0, NULL
);
3117 JS_PUBLIC_API(JSObject
*)
3118 JS_ConstructObjectWithArguments(JSContext
*cx
, JSClass
*clasp
, JSObject
*proto
,
3119 JSObject
*parent
, uintN argc
, jsval
*argv
)
3123 clasp
= &js_ObjectClass
; /* default class is Object */
3124 return js_ConstructObject(cx
, clasp
, proto
, parent
, argc
, argv
);
3128 DefinePropertyById(JSContext
*cx
, JSObject
*obj
, jsid id
, jsval value
,
3129 JSPropertyOp getter
, JSPropertyOp setter
, uintN attrs
,
3130 uintN flags
, intN tinyid
)
3132 if (flags
!= 0 && OBJ_IS_NATIVE(obj
)) {
3133 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
| JSRESOLVE_DECLARING
);
3134 return js_DefineNativeProperty(cx
, obj
, id
, value
, getter
, setter
,
3135 attrs
, flags
, tinyid
, NULL
);
3137 return OBJ_DEFINE_PROPERTY(cx
, obj
, id
, value
, getter
, setter
, attrs
,
3142 DefineProperty(JSContext
*cx
, JSObject
*obj
, const char *name
, jsval value
,
3143 JSPropertyOp getter
, JSPropertyOp setter
, uintN attrs
,
3144 uintN flags
, intN tinyid
)
3149 if (attrs
& JSPROP_INDEX
) {
3150 id
= INT_TO_JSID(JS_PTR_TO_INT32(name
));
3152 attrs
&= ~JSPROP_INDEX
;
3154 atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3157 id
= ATOM_TO_JSID(atom
);
3159 return DefinePropertyById(cx
, obj
, id
, value
, getter
, setter
, attrs
,
3163 #define AUTO_NAMELEN(s,n) (((n) == (size_t)-1) ? js_strlen(s) : (n))
3166 DefineUCProperty(JSContext
*cx
, JSObject
*obj
,
3167 const jschar
*name
, size_t namelen
, jsval value
,
3168 JSPropertyOp getter
, JSPropertyOp setter
, uintN attrs
,
3169 uintN flags
, intN tinyid
)
3173 atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
3176 if (flags
!= 0 && OBJ_IS_NATIVE(obj
)) {
3177 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
| JSRESOLVE_DECLARING
);
3178 return js_DefineNativeProperty(cx
, obj
, ATOM_TO_JSID(atom
), value
,
3179 getter
, setter
, attrs
, flags
, tinyid
,
3182 return OBJ_DEFINE_PROPERTY(cx
, obj
, ATOM_TO_JSID(atom
), value
,
3183 getter
, setter
, attrs
, NULL
);
3186 JS_PUBLIC_API(JSObject
*)
3187 JS_DefineObject(JSContext
*cx
, JSObject
*obj
, const char *name
, JSClass
*clasp
,
3188 JSObject
*proto
, uintN attrs
)
3194 clasp
= &js_ObjectClass
; /* default class is Object */
3195 nobj
= js_NewObject(cx
, clasp
, proto
, obj
, 0);
3198 if (!DefineProperty(cx
, obj
, name
, OBJECT_TO_JSVAL(nobj
), NULL
, NULL
, attrs
,
3200 cx
->weakRoots
.newborn
[GCX_OBJECT
] = NULL
;
3206 JS_PUBLIC_API(JSBool
)
3207 JS_DefineConstDoubles(JSContext
*cx
, JSObject
*obj
, JSConstDoubleSpec
*cds
)
3214 for (ok
= JS_TRUE
; cds
->name
; cds
++) {
3215 ok
= js_NewNumberInRootedValue(cx
, cds
->dval
, &value
);
3220 attrs
= JSPROP_READONLY
| JSPROP_PERMANENT
;
3221 ok
= DefineProperty(cx
, obj
, cds
->name
, value
, NULL
, NULL
, attrs
, 0, 0);
3228 JS_PUBLIC_API(JSBool
)
3229 JS_DefineProperties(JSContext
*cx
, JSObject
*obj
, JSPropertySpec
*ps
)
3234 for (ok
= JS_TRUE
; ps
->name
; ps
++) {
3235 ok
= DefineProperty(cx
, obj
, ps
->name
, JSVAL_VOID
,
3236 ps
->getter
, ps
->setter
, ps
->flags
,
3237 SPROP_HAS_SHORTID
, ps
->tinyid
);
3244 JS_PUBLIC_API(JSBool
)
3245 JS_DefineProperty(JSContext
*cx
, JSObject
*obj
, const char *name
, jsval value
,
3246 JSPropertyOp getter
, JSPropertyOp setter
, uintN attrs
)
3249 return DefineProperty(cx
, obj
, name
, value
, getter
, setter
, attrs
, 0, 0);
3252 JS_PUBLIC_API(JSBool
)
3253 JS_DefinePropertyById(JSContext
*cx
, JSObject
*obj
, jsid id
, jsval value
,
3254 JSPropertyOp getter
, JSPropertyOp setter
, uintN attrs
)
3257 return DefinePropertyById(cx
, obj
, id
, value
, getter
, setter
, attrs
, 0, 0);
3260 JS_PUBLIC_API(JSBool
)
3261 JS_DefinePropertyWithTinyId(JSContext
*cx
, JSObject
*obj
, const char *name
,
3262 int8 tinyid
, jsval value
,
3263 JSPropertyOp getter
, JSPropertyOp setter
,
3267 return DefineProperty(cx
, obj
, name
, value
, getter
, setter
, attrs
,
3268 SPROP_HAS_SHORTID
, tinyid
);
3272 LookupPropertyById(JSContext
*cx
, JSObject
*obj
, jsid id
, uintN flags
,
3273 JSObject
**objp
, JSProperty
**propp
)
3275 JSAutoResolveFlags
rf(cx
, flags
);
3276 return OBJ_LOOKUP_PROPERTY(cx
, obj
, id
, objp
, propp
);
3280 LookupProperty(JSContext
*cx
, JSObject
*obj
, const char *name
, uintN flags
,
3281 JSObject
**objp
, JSProperty
**propp
)
3285 atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3288 return LookupPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), flags
, objp
, propp
);
3292 LookupUCProperty(JSContext
*cx
, JSObject
*obj
,
3293 const jschar
*name
, size_t namelen
, uintN flags
,
3294 JSObject
**objp
, JSProperty
**propp
)
3298 atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
3301 return LookupPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), flags
, objp
, propp
);
3304 JS_PUBLIC_API(JSBool
)
3305 JS_AliasProperty(JSContext
*cx
, JSObject
*obj
, const char *name
,
3312 JSScopeProperty
*sprop
;
3315 if (!LookupProperty(cx
, obj
, name
, JSRESOLVE_QUALIFIED
, &obj2
, &prop
))
3318 js_ReportIsNotDefined(cx
, name
);
3321 if (obj2
!= obj
|| !OBJ_IS_NATIVE(obj
)) {
3322 OBJ_DROP_PROPERTY(cx
, obj2
, prop
);
3323 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_CANT_ALIAS
,
3324 alias
, name
, OBJ_GET_CLASS(cx
, obj2
)->name
);
3327 atom
= js_Atomize(cx
, alias
, strlen(alias
), 0);
3331 sprop
= (JSScopeProperty
*)prop
;
3332 ok
= (js_AddNativeProperty(cx
, obj
, ATOM_TO_JSID(atom
),
3333 sprop
->getter
, sprop
->setter
, sprop
->slot
,
3334 sprop
->attrs
, sprop
->flags
| SPROP_IS_ALIAS
,
3338 OBJ_DROP_PROPERTY(cx
, obj
, prop
);
3343 LookupResult(JSContext
*cx
, JSObject
*obj
, JSObject
*obj2
, JSProperty
*prop
)
3345 JSScopeProperty
*sprop
;
3349 /* XXX bad API: no way to tell "not defined" from "void value" */
3352 if (OBJ_IS_NATIVE(obj2
)) {
3353 /* Peek at the native property's slot value, without doing a Get. */
3354 sprop
= (JSScopeProperty
*)prop
;
3355 rval
= SPROP_HAS_VALID_SLOT(sprop
, OBJ_SCOPE(obj2
))
3356 ? LOCKED_OBJ_GET_SLOT(obj2
, sprop
->slot
)
3359 /* XXX bad API: no way to return "defined but value unknown" */
3362 OBJ_DROP_PROPERTY(cx
, obj2
, prop
);
3367 GetPropertyAttributes(JSContext
*cx
, JSObject
*obj
, JSAtom
*atom
,
3368 uintN
*attrsp
, JSBool
*foundp
,
3369 JSPropertyOp
*getterp
, JSPropertyOp
*setterp
)
3377 if (!LookupPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), JSRESOLVE_QUALIFIED
,
3382 if (!prop
|| obj
!= obj2
) {
3390 OBJ_DROP_PROPERTY(cx
, obj2
, prop
);
3395 ok
= OBJ_GET_ATTRIBUTES(cx
, obj
, ATOM_TO_JSID(atom
), prop
, attrsp
);
3396 if (ok
&& OBJ_IS_NATIVE(obj
)) {
3397 JSScopeProperty
*sprop
= (JSScopeProperty
*) prop
;
3400 *getterp
= sprop
->getter
;
3402 *setterp
= sprop
->setter
;
3404 OBJ_DROP_PROPERTY(cx
, obj
, prop
);
3409 SetPropertyAttributes(JSContext
*cx
, JSObject
*obj
, JSAtom
*atom
,
3410 uintN attrs
, JSBool
*foundp
)
3418 if (!LookupPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), JSRESOLVE_QUALIFIED
,
3422 if (!prop
|| obj
!= obj2
) {
3425 OBJ_DROP_PROPERTY(cx
, obj2
, prop
);
3430 ok
= OBJ_SET_ATTRIBUTES(cx
, obj
, ATOM_TO_JSID(atom
), prop
, &attrs
);
3431 OBJ_DROP_PROPERTY(cx
, obj
, prop
);
3435 JS_PUBLIC_API(JSBool
)
3436 JS_GetPropertyAttributes(JSContext
*cx
, JSObject
*obj
, const char *name
,
3437 uintN
*attrsp
, JSBool
*foundp
)
3440 return GetPropertyAttributes(cx
, obj
,
3441 js_Atomize(cx
, name
, strlen(name
), 0),
3442 attrsp
, foundp
, NULL
, NULL
);
3445 JS_PUBLIC_API(JSBool
)
3446 JS_GetPropertyAttrsGetterAndSetter(JSContext
*cx
, JSObject
*obj
,
3448 uintN
*attrsp
, JSBool
*foundp
,
3449 JSPropertyOp
*getterp
,
3450 JSPropertyOp
*setterp
)
3453 return GetPropertyAttributes(cx
, obj
,
3454 js_Atomize(cx
, name
, strlen(name
), 0),
3455 attrsp
, foundp
, getterp
, setterp
);
3458 JS_PUBLIC_API(JSBool
)
3459 JS_SetPropertyAttributes(JSContext
*cx
, JSObject
*obj
, const char *name
,
3460 uintN attrs
, JSBool
*foundp
)
3463 return SetPropertyAttributes(cx
, obj
,
3464 js_Atomize(cx
, name
, strlen(name
), 0),
3469 AlreadyHasOwnPropertyHelper(JSContext
*cx
, JSObject
*obj
, jsid id
,
3474 if (!OBJ_IS_NATIVE(obj
)) {
3478 if (!LookupPropertyById(cx
, obj
, id
,
3479 JSRESOLVE_QUALIFIED
| JSRESOLVE_DETECTING
,
3483 *foundp
= (obj
== obj2
);
3485 OBJ_DROP_PROPERTY(cx
, obj2
, prop
);
3489 JS_LOCK_OBJ(cx
, obj
);
3490 scope
= OBJ_SCOPE(obj
);
3491 *foundp
= (scope
->object
== obj
&& SCOPE_GET_PROPERTY(scope
, id
));
3492 JS_UNLOCK_SCOPE(cx
, scope
);
3496 JS_PUBLIC_API(JSBool
)
3497 JS_AlreadyHasOwnProperty(JSContext
*cx
, JSObject
*obj
, const char *name
,
3503 atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3506 return AlreadyHasOwnPropertyHelper(cx
, obj
, ATOM_TO_JSID(atom
), foundp
);
3509 JS_PUBLIC_API(JSBool
)
3510 JS_AlreadyHasOwnPropertyById(JSContext
*cx
, JSObject
*obj
, jsid id
,
3514 return AlreadyHasOwnPropertyHelper(cx
, obj
, id
, foundp
);
3517 JS_PUBLIC_API(JSBool
)
3518 JS_HasProperty(JSContext
*cx
, JSObject
*obj
, const char *name
, JSBool
*foundp
)
3525 ok
= LookupProperty(cx
, obj
, name
,
3526 JSRESOLVE_QUALIFIED
| JSRESOLVE_DETECTING
,
3529 *foundp
= (prop
!= NULL
);
3531 OBJ_DROP_PROPERTY(cx
, obj2
, prop
);
3536 JS_PUBLIC_API(JSBool
)
3537 JS_HasPropertyById(JSContext
*cx
, JSObject
*obj
, jsid id
, JSBool
*foundp
)
3544 ok
= LookupPropertyById(cx
, obj
, id
,
3545 JSRESOLVE_QUALIFIED
| JSRESOLVE_DETECTING
,
3548 *foundp
= (prop
!= NULL
);
3550 OBJ_DROP_PROPERTY(cx
, obj2
, prop
);
3555 JS_PUBLIC_API(JSBool
)
3556 JS_LookupProperty(JSContext
*cx
, JSObject
*obj
, const char *name
, jsval
*vp
)
3563 ok
= LookupProperty(cx
, obj
, name
, JSRESOLVE_QUALIFIED
, &obj2
, &prop
);
3565 *vp
= LookupResult(cx
, obj
, obj2
, prop
);
3569 JS_PUBLIC_API(JSBool
)
3570 JS_LookupPropertyById(JSContext
*cx
, JSObject
*obj
, jsid id
, jsval
*vp
)
3577 ok
= LookupPropertyById(cx
, obj
, id
, JSRESOLVE_QUALIFIED
, &obj2
, &prop
);
3579 *vp
= LookupResult(cx
, obj
, obj2
, prop
);
3583 JS_PUBLIC_API(JSBool
)
3584 JS_LookupPropertyWithFlags(JSContext
*cx
, JSObject
*obj
, const char *name
,
3585 uintN flags
, jsval
*vp
)
3590 atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3592 JS_LookupPropertyWithFlagsById(cx
, obj
, ATOM_TO_JSID(atom
), flags
,
3596 JS_PUBLIC_API(JSBool
)
3597 JS_LookupPropertyWithFlagsById(JSContext
*cx
, JSObject
*obj
, jsid id
,
3598 uintN flags
, JSObject
**objp
, jsval
*vp
)
3604 ok
= OBJ_IS_NATIVE(obj
)
3605 ? js_LookupPropertyWithFlags(cx
, obj
, id
, flags
, objp
, &prop
) >= 0
3606 : OBJ_LOOKUP_PROPERTY(cx
, obj
, id
, objp
, &prop
);
3608 *vp
= LookupResult(cx
, obj
, *objp
, prop
);
3612 JS_PUBLIC_API(JSBool
)
3613 JS_GetProperty(JSContext
*cx
, JSObject
*obj
, const char *name
, jsval
*vp
)
3618 atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3622 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
);
3623 return OBJ_GET_PROPERTY(cx
, obj
, ATOM_TO_JSID(atom
), vp
);
3626 JS_PUBLIC_API(JSBool
)
3627 JS_GetPropertyById(JSContext
*cx
, JSObject
*obj
, jsid id
, jsval
*vp
)
3630 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
);
3631 return OBJ_GET_PROPERTY(cx
, obj
, id
, vp
);
3634 JS_PUBLIC_API(JSBool
)
3635 JS_GetMethodById(JSContext
*cx
, JSObject
*obj
, jsid id
, JSObject
**objp
,
3638 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
);
3641 #if JS_HAS_XML_SUPPORT
3642 if (OBJECT_IS_XML(cx
, obj
)) {
3643 JSXMLObjectOps
*ops
;
3645 ops
= (JSXMLObjectOps
*) obj
->map
->ops
;
3646 obj
= ops
->getMethod(cx
, obj
, id
, vp
);
3652 if (!OBJ_GET_PROPERTY(cx
, obj
, id
, vp
))
3660 JS_PUBLIC_API(JSBool
)
3661 JS_GetMethod(JSContext
*cx
, JSObject
*obj
, const char *name
, JSObject
**objp
,
3666 atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3669 return JS_GetMethodById(cx
, obj
, ATOM_TO_JSID(atom
), objp
, vp
);
3672 JS_PUBLIC_API(JSBool
)
3673 JS_SetProperty(JSContext
*cx
, JSObject
*obj
, const char *name
, jsval
*vp
)
3678 atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3682 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
| JSRESOLVE_ASSIGNING
);
3683 return OBJ_SET_PROPERTY(cx
, obj
, ATOM_TO_JSID(atom
), vp
);
3686 JS_PUBLIC_API(JSBool
)
3687 JS_SetPropertyById(JSContext
*cx
, JSObject
*obj
, jsid id
, jsval
*vp
)
3690 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
| JSRESOLVE_ASSIGNING
);
3691 return OBJ_SET_PROPERTY(cx
, obj
, id
, vp
);
3694 JS_PUBLIC_API(JSBool
)
3695 JS_DeleteProperty(JSContext
*cx
, JSObject
*obj
, const char *name
)
3699 return JS_DeleteProperty2(cx
, obj
, name
, &junk
);
3702 JS_PUBLIC_API(JSBool
)
3703 JS_DeleteProperty2(JSContext
*cx
, JSObject
*obj
, const char *name
,
3709 atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3713 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
);
3714 return OBJ_DELETE_PROPERTY(cx
, obj
, ATOM_TO_JSID(atom
), rval
);
3717 JS_PUBLIC_API(JSBool
)
3718 JS_DeletePropertyById(JSContext
*cx
, JSObject
*obj
, jsid id
)
3722 return JS_DeletePropertyById2(cx
, obj
, id
, &junk
);
3725 JS_PUBLIC_API(JSBool
)
3726 JS_DeletePropertyById2(JSContext
*cx
, JSObject
*obj
, jsid id
, jsval
*rval
)
3729 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
);
3730 return OBJ_DELETE_PROPERTY(cx
, obj
, id
, rval
);
3733 JS_PUBLIC_API(JSBool
)
3734 JS_DefineUCProperty(JSContext
*cx
, JSObject
*obj
,
3735 const jschar
*name
, size_t namelen
, jsval value
,
3736 JSPropertyOp getter
, JSPropertyOp setter
,
3740 return DefineUCProperty(cx
, obj
, name
, namelen
, value
, getter
, setter
,
3744 JS_PUBLIC_API(JSBool
)
3745 JS_GetUCPropertyAttributes(JSContext
*cx
, JSObject
*obj
,
3746 const jschar
*name
, size_t namelen
,
3747 uintN
*attrsp
, JSBool
*foundp
)
3750 return GetPropertyAttributes(cx
, obj
,
3751 js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0),
3752 attrsp
, foundp
, NULL
, NULL
);
3755 JS_PUBLIC_API(JSBool
)
3756 JS_GetUCPropertyAttrsGetterAndSetter(JSContext
*cx
, JSObject
*obj
,
3757 const jschar
*name
, size_t namelen
,
3758 uintN
*attrsp
, JSBool
*foundp
,
3759 JSPropertyOp
*getterp
,
3760 JSPropertyOp
*setterp
)
3763 return GetPropertyAttributes(cx
, obj
,
3764 js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0),
3765 attrsp
, foundp
, getterp
, setterp
);
3768 JS_PUBLIC_API(JSBool
)
3769 JS_SetUCPropertyAttributes(JSContext
*cx
, JSObject
*obj
,
3770 const jschar
*name
, size_t namelen
,
3771 uintN attrs
, JSBool
*foundp
)
3774 return SetPropertyAttributes(cx
, obj
,
3775 js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0),
3779 JS_PUBLIC_API(JSBool
)
3780 JS_DefineUCPropertyWithTinyId(JSContext
*cx
, JSObject
*obj
,
3781 const jschar
*name
, size_t namelen
,
3782 int8 tinyid
, jsval value
,
3783 JSPropertyOp getter
, JSPropertyOp setter
,
3787 return DefineUCProperty(cx
, obj
, name
, namelen
, value
, getter
, setter
,
3788 attrs
, SPROP_HAS_SHORTID
, tinyid
);
3791 JS_PUBLIC_API(JSBool
)
3792 JS_AlreadyHasOwnUCProperty(JSContext
*cx
, JSObject
*obj
,
3793 const jschar
*name
, size_t namelen
,
3799 atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
3802 return AlreadyHasOwnPropertyHelper(cx
, obj
, ATOM_TO_JSID(atom
), foundp
);
3805 JS_PUBLIC_API(JSBool
)
3806 JS_HasUCProperty(JSContext
*cx
, JSObject
*obj
,
3807 const jschar
*name
, size_t namelen
,
3815 ok
= LookupUCProperty(cx
, obj
, name
, namelen
,
3816 JSRESOLVE_QUALIFIED
| JSRESOLVE_DETECTING
,
3819 *vp
= (prop
!= NULL
);
3821 OBJ_DROP_PROPERTY(cx
, obj2
, prop
);
3826 JS_PUBLIC_API(JSBool
)
3827 JS_LookupUCProperty(JSContext
*cx
, JSObject
*obj
,
3828 const jschar
*name
, size_t namelen
,
3836 ok
= LookupUCProperty(cx
, obj
, name
, namelen
, JSRESOLVE_QUALIFIED
,
3839 *vp
= LookupResult(cx
, obj
, obj2
, prop
);
3843 JS_PUBLIC_API(JSBool
)
3844 JS_GetUCProperty(JSContext
*cx
, JSObject
*obj
,
3845 const jschar
*name
, size_t namelen
,
3851 atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
3855 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
);
3856 return OBJ_GET_PROPERTY(cx
, obj
, ATOM_TO_JSID(atom
), vp
);
3859 JS_PUBLIC_API(JSBool
)
3860 JS_SetUCProperty(JSContext
*cx
, JSObject
*obj
,
3861 const jschar
*name
, size_t namelen
,
3867 atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
3871 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
| JSRESOLVE_ASSIGNING
);
3872 return OBJ_SET_PROPERTY(cx
, obj
, ATOM_TO_JSID(atom
), vp
);
3875 JS_PUBLIC_API(JSBool
)
3876 JS_DeleteUCProperty2(JSContext
*cx
, JSObject
*obj
,
3877 const jschar
*name
, size_t namelen
,
3883 atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
3887 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
);
3888 return OBJ_DELETE_PROPERTY(cx
, obj
, ATOM_TO_JSID(atom
), rval
);
3891 JS_PUBLIC_API(JSObject
*)
3892 JS_NewArrayObject(JSContext
*cx
, jsint length
, jsval
*vector
)
3895 /* NB: jsuint cast does ToUint32. */
3896 return js_NewArrayObject(cx
, (jsuint
)length
, vector
);
3899 JS_PUBLIC_API(JSBool
)
3900 JS_IsArrayObject(JSContext
*cx
, JSObject
*obj
)
3902 return OBJ_IS_ARRAY(cx
, obj
);
3905 JS_PUBLIC_API(JSBool
)
3906 JS_GetArrayLength(JSContext
*cx
, JSObject
*obj
, jsuint
*lengthp
)
3909 return js_GetLengthProperty(cx
, obj
, lengthp
);
3912 JS_PUBLIC_API(JSBool
)
3913 JS_SetArrayLength(JSContext
*cx
, JSObject
*obj
, jsuint length
)
3916 return js_SetLengthProperty(cx
, obj
, length
);
3919 JS_PUBLIC_API(JSBool
)
3920 JS_HasArrayLength(JSContext
*cx
, JSObject
*obj
, jsuint
*lengthp
)
3923 return js_HasLengthProperty(cx
, obj
, lengthp
);
3926 JS_PUBLIC_API(JSBool
)
3927 JS_DefineElement(JSContext
*cx
, JSObject
*obj
, jsint index
, jsval value
,
3928 JSPropertyOp getter
, JSPropertyOp setter
, uintN attrs
)
3930 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
| JSRESOLVE_DECLARING
);
3933 return OBJ_DEFINE_PROPERTY(cx
, obj
, INT_TO_JSID(index
), value
,
3934 getter
, setter
, attrs
, NULL
);
3937 JS_PUBLIC_API(JSBool
)
3938 JS_AliasElement(JSContext
*cx
, JSObject
*obj
, const char *name
, jsint alias
)
3942 JSScopeProperty
*sprop
;
3946 if (!LookupProperty(cx
, obj
, name
, JSRESOLVE_QUALIFIED
, &obj2
, &prop
))
3949 js_ReportIsNotDefined(cx
, name
);
3952 if (obj2
!= obj
|| !OBJ_IS_NATIVE(obj
)) {
3954 OBJ_DROP_PROPERTY(cx
, obj2
, prop
);
3955 JS_snprintf(numBuf
, sizeof numBuf
, "%ld", (long)alias
);
3956 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_CANT_ALIAS
,
3957 numBuf
, name
, OBJ_GET_CLASS(cx
, obj2
)->name
);
3960 sprop
= (JSScopeProperty
*)prop
;
3961 ok
= (js_AddNativeProperty(cx
, obj
, INT_TO_JSID(alias
),
3962 sprop
->getter
, sprop
->setter
, sprop
->slot
,
3963 sprop
->attrs
, sprop
->flags
| SPROP_IS_ALIAS
,
3966 OBJ_DROP_PROPERTY(cx
, obj
, prop
);
3970 JS_PUBLIC_API(JSBool
)
3971 JS_AlreadyHasOwnElement(JSContext
*cx
, JSObject
*obj
, jsint index
,
3974 return AlreadyHasOwnPropertyHelper(cx
, obj
, INT_TO_JSID(index
), foundp
);
3977 JS_PUBLIC_API(JSBool
)
3978 JS_HasElement(JSContext
*cx
, JSObject
*obj
, jsint index
, JSBool
*foundp
)
3985 ok
= LookupPropertyById(cx
, obj
, INT_TO_JSID(index
),
3986 JSRESOLVE_QUALIFIED
| JSRESOLVE_DETECTING
,
3989 *foundp
= (prop
!= NULL
);
3991 OBJ_DROP_PROPERTY(cx
, obj2
, prop
);
3996 JS_PUBLIC_API(JSBool
)
3997 JS_LookupElement(JSContext
*cx
, JSObject
*obj
, jsint index
, jsval
*vp
)
4004 ok
= LookupPropertyById(cx
, obj
, INT_TO_JSID(index
), JSRESOLVE_QUALIFIED
,
4007 *vp
= LookupResult(cx
, obj
, obj2
, prop
);
4011 JS_PUBLIC_API(JSBool
)
4012 JS_GetElement(JSContext
*cx
, JSObject
*obj
, jsint index
, jsval
*vp
)
4014 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
);
4017 return OBJ_GET_PROPERTY(cx
, obj
, INT_TO_JSID(index
), vp
);
4020 JS_PUBLIC_API(JSBool
)
4021 JS_SetElement(JSContext
*cx
, JSObject
*obj
, jsint index
, jsval
*vp
)
4023 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
| JSRESOLVE_ASSIGNING
);
4026 return OBJ_SET_PROPERTY(cx
, obj
, INT_TO_JSID(index
), vp
);
4029 JS_PUBLIC_API(JSBool
)
4030 JS_DeleteElement(JSContext
*cx
, JSObject
*obj
, jsint index
)
4034 return JS_DeleteElement2(cx
, obj
, index
, &junk
);
4037 JS_PUBLIC_API(JSBool
)
4038 JS_DeleteElement2(JSContext
*cx
, JSObject
*obj
, jsint index
, jsval
*rval
)
4040 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
);
4043 return OBJ_DELETE_PROPERTY(cx
, obj
, INT_TO_JSID(index
), rval
);
4047 JS_ClearScope(JSContext
*cx
, JSObject
*obj
)
4051 if (obj
->map
->ops
->clear
)
4052 obj
->map
->ops
->clear(cx
, obj
);
4054 /* Clear cached class objects on the global object. */
4055 if (OBJ_GET_CLASS(cx
, obj
)->flags
& JSCLASS_IS_GLOBAL
) {
4058 for (key
= JSProto_Null
; key
< JSProto_LIMIT
; key
++)
4059 JS_SetReservedSlot(cx
, obj
, key
, JSVAL_VOID
);
4063 JS_PUBLIC_API(JSIdArray
*)
4064 JS_Enumerate(JSContext
*cx
, JSObject
*obj
)
4067 jsval iter_state
, num_properties
;
4075 iter_state
= JSVAL_NULL
;
4077 /* Get the number of properties to enumerate. */
4078 if (!OBJ_ENUMERATE(cx
, obj
, JSENUMERATE_INIT
, &iter_state
, &num_properties
))
4080 if (!JSVAL_IS_INT(num_properties
)) {
4085 /* Grow as needed if we don't know the exact amount ahead of time. */
4086 n
= JSVAL_TO_INT(num_properties
);
4090 /* Create an array of jsids large enough to hold all the properties */
4091 ida
= NewIdArray(cx
, n
);
4096 vector
= &ida
->vector
[0];
4098 if (!OBJ_ENUMERATE(cx
, obj
, JSENUMERATE_NEXT
, &iter_state
, &id
))
4101 /* No more jsid's to enumerate ? */
4102 if (iter_state
== JSVAL_NULL
)
4105 if (i
== ida
->length
) {
4106 ida
= SetIdArrayLength(cx
, ida
, ida
->length
* 2);
4109 vector
= &ida
->vector
[0];
4113 return SetIdArrayLength(cx
, ida
, i
);
4116 if (iter_state
!= JSVAL_NULL
)
4117 OBJ_ENUMERATE(cx
, obj
, JSENUMERATE_DESTROY
, &iter_state
, 0);
4119 JS_DestroyIdArray(cx
, ida
);
4124 * XXX reverse iterator for properties, unreverse and meld with jsinterp.c's
4125 * prop_iterator_class somehow...
4126 * + preserve the OBJ_ENUMERATE API while optimizing the native object case
4127 * + native case here uses a JSScopeProperty *, but that iterates in reverse!
4128 * + so we make non-native match, by reverse-iterating after JS_Enumerating
4130 #define JSSLOT_ITER_INDEX (JSSLOT_PRIVATE + 1)
4132 #if JSSLOT_ITER_INDEX >= JS_INITIAL_NSLOTS
4133 # error "JSSLOT_ITER_INDEX botch!"
4137 prop_iter_finalize(JSContext
*cx
, JSObject
*obj
)
4143 v
= obj
->fslots
[JSSLOT_ITER_INDEX
];
4144 if (JSVAL_IS_VOID(v
))
4147 i
= JSVAL_TO_INT(v
);
4149 /* Non-native case: destroy the ida enumerated when obj was created. */
4150 ida
= (JSIdArray
*) JS_GetPrivate(cx
, obj
);
4152 JS_DestroyIdArray(cx
, ida
);
4157 prop_iter_trace(JSTracer
*trc
, JSObject
*obj
)
4161 JSScopeProperty
*sprop
;
4165 v
= obj
->fslots
[JSSLOT_PRIVATE
];
4166 JS_ASSERT(!JSVAL_IS_VOID(v
));
4168 i
= JSVAL_TO_INT(obj
->fslots
[JSSLOT_ITER_INDEX
]);
4170 /* Native case: just mark the next property to visit. */
4171 sprop
= (JSScopeProperty
*) JSVAL_TO_PRIVATE(v
);
4173 TRACE_SCOPE_PROPERTY(trc
, sprop
);
4175 /* Non-native case: mark each id in the JSIdArray private. */
4176 ida
= (JSIdArray
*) JSVAL_TO_PRIVATE(v
);
4177 for (i
= 0, n
= ida
->length
; i
< n
; i
++) {
4178 id
= ida
->vector
[i
];
4184 static JSClass prop_iter_class
= {
4186 JSCLASS_HAS_PRIVATE
| JSCLASS_HAS_RESERVED_SLOTS(1) |
4187 JSCLASS_MARK_IS_TRACE
,
4188 JS_PropertyStub
, JS_PropertyStub
, JS_PropertyStub
, JS_PropertyStub
,
4189 JS_EnumerateStub
, JS_ResolveStub
, JS_ConvertStub
, prop_iter_finalize
,
4190 NULL
, NULL
, NULL
, NULL
,
4191 NULL
, NULL
, JS_CLASS_TRACE(prop_iter_trace
), NULL
4194 JS_PUBLIC_API(JSObject
*)
4195 JS_NewPropertyIterator(JSContext
*cx
, JSObject
*obj
)
4204 iterobj
= js_NewObject(cx
, &prop_iter_class
, NULL
, obj
, 0);
4208 if (OBJ_IS_NATIVE(obj
)) {
4209 /* Native case: start with the last property in obj's own scope. */
4210 scope
= OBJ_SCOPE(obj
);
4211 pdata
= (scope
->object
== obj
) ? scope
->lastProp
: NULL
;
4214 JSTempValueRooter tvr
;
4217 * Non-native case: enumerate a JSIdArray and keep it via private.
4219 * Note: we have to make sure that we root obj around the call to
4220 * JS_Enumerate to protect against multiple allocations under it.
4222 JS_PUSH_SINGLE_TEMP_ROOT(cx
, OBJECT_TO_JSVAL(iterobj
), &tvr
);
4223 ida
= JS_Enumerate(cx
, obj
);
4224 JS_POP_TEMP_ROOT(cx
, &tvr
);
4228 index
= ida
->length
;
4231 /* iterobj can not escape to other threads here. */
4232 STOBJ_SET_SLOT(iterobj
, JSSLOT_PRIVATE
, PRIVATE_TO_JSVAL(pdata
));
4233 STOBJ_SET_SLOT(iterobj
, JSSLOT_ITER_INDEX
, INT_TO_JSVAL(index
));
4237 cx
->weakRoots
.newborn
[GCX_OBJECT
] = NULL
;
4241 JS_PUBLIC_API(JSBool
)
4242 JS_NextProperty(JSContext
*cx
, JSObject
*iterobj
, jsid
*idp
)
4247 JSScopeProperty
*sprop
;
4251 i
= JSVAL_TO_INT(OBJ_GET_SLOT(cx
, iterobj
, JSSLOT_ITER_INDEX
));
4253 /* Native case: private data is a property tree node pointer. */
4254 obj
= OBJ_GET_PARENT(cx
, iterobj
);
4255 JS_ASSERT(OBJ_IS_NATIVE(obj
));
4256 scope
= OBJ_SCOPE(obj
);
4257 JS_ASSERT(scope
->object
== obj
);
4258 sprop
= (JSScopeProperty
*) JS_GetPrivate(cx
, iterobj
);
4261 * If the next property mapped by scope in the property tree ancestor
4262 * line is not enumerable, or it's an alias, or one or more properties
4263 * were deleted from the "middle" of the scope-mapped ancestor line
4264 * and the next property was among those deleted, skip it and keep on
4265 * trying to find an enumerable property that is still in scope.
4268 (!(sprop
->attrs
& JSPROP_ENUMERATE
) ||
4269 (sprop
->flags
& SPROP_IS_ALIAS
) ||
4270 (SCOPE_HAD_MIDDLE_DELETE(scope
) &&
4271 !SCOPE_HAS_PROPERTY(scope
, sprop
)))) {
4272 sprop
= sprop
->parent
;
4278 if (!JS_SetPrivate(cx
, iterobj
, sprop
->parent
))
4283 /* Non-native case: use the ida enumerated when iterobj was created. */
4284 ida
= (JSIdArray
*) JS_GetPrivate(cx
, iterobj
);
4285 JS_ASSERT(i
<= ida
->length
);
4289 *idp
= ida
->vector
[--i
];
4290 STOBJ_SET_SLOT(iterobj
, JSSLOT_ITER_INDEX
, INT_TO_JSVAL(i
));
4296 JS_PUBLIC_API(JSBool
)
4297 JS_CheckAccess(JSContext
*cx
, JSObject
*obj
, jsid id
, JSAccessMode mode
,
4298 jsval
*vp
, uintN
*attrsp
)
4301 return OBJ_CHECK_ACCESS(cx
, obj
, id
, mode
, vp
, attrsp
);
4305 ReservedSlotIndexOK(JSContext
*cx
, JSObject
*obj
, JSClass
*clasp
,
4306 uint32 index
, uint32 limit
)
4308 /* Check the computed, possibly per-instance, upper bound. */
4309 if (clasp
->reserveSlots
)
4310 JS_LOCK_OBJ_VOID(cx
, obj
, limit
+= clasp
->reserveSlots(cx
, obj
));
4311 if (index
>= limit
) {
4312 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
,
4313 JSMSG_RESERVED_SLOT_RANGE
);
4319 JS_PUBLIC_API(JSBool
)
4320 JS_GetReservedSlot(JSContext
*cx
, JSObject
*obj
, uint32 index
, jsval
*vp
)
4326 clasp
= OBJ_GET_CLASS(cx
, obj
);
4327 limit
= JSCLASS_RESERVED_SLOTS(clasp
);
4328 if (index
>= limit
&& !ReservedSlotIndexOK(cx
, obj
, clasp
, index
, limit
))
4330 slot
= JSSLOT_START(clasp
) + index
;
4331 *vp
= OBJ_GET_REQUIRED_SLOT(cx
, obj
, slot
);
4335 JS_PUBLIC_API(JSBool
)
4336 JS_SetReservedSlot(JSContext
*cx
, JSObject
*obj
, uint32 index
, jsval v
)
4342 clasp
= OBJ_GET_CLASS(cx
, obj
);
4343 limit
= JSCLASS_RESERVED_SLOTS(clasp
);
4344 if (index
>= limit
&& !ReservedSlotIndexOK(cx
, obj
, clasp
, index
, limit
))
4346 slot
= JSSLOT_START(clasp
) + index
;
4347 return OBJ_SET_REQUIRED_SLOT(cx
, obj
, slot
, v
);
4350 #ifdef JS_THREADSAFE
4351 JS_PUBLIC_API(jsrefcount
)
4352 JS_HoldPrincipals(JSContext
*cx
, JSPrincipals
*principals
)
4354 return JS_ATOMIC_INCREMENT(&principals
->refcount
);
4357 JS_PUBLIC_API(jsrefcount
)
4358 JS_DropPrincipals(JSContext
*cx
, JSPrincipals
*principals
)
4360 jsrefcount rc
= JS_ATOMIC_DECREMENT(&principals
->refcount
);
4362 principals
->destroy(cx
, principals
);
4367 JS_PUBLIC_API(JSSecurityCallbacks
*)
4368 JS_SetRuntimeSecurityCallbacks(JSRuntime
*rt
, JSSecurityCallbacks
*callbacks
)
4370 JSSecurityCallbacks
*oldcallbacks
;
4372 oldcallbacks
= rt
->securityCallbacks
;
4373 rt
->securityCallbacks
= callbacks
;
4374 return oldcallbacks
;
4377 JS_PUBLIC_API(JSSecurityCallbacks
*)
4378 JS_GetRuntimeSecurityCallbacks(JSRuntime
*rt
)
4380 return rt
->securityCallbacks
;
4383 JS_PUBLIC_API(JSSecurityCallbacks
*)
4384 JS_SetContextSecurityCallbacks(JSContext
*cx
, JSSecurityCallbacks
*callbacks
)
4386 JSSecurityCallbacks
*oldcallbacks
;
4388 oldcallbacks
= cx
->securityCallbacks
;
4389 cx
->securityCallbacks
= callbacks
;
4390 return oldcallbacks
;
4393 JS_PUBLIC_API(JSSecurityCallbacks
*)
4394 JS_GetSecurityCallbacks(JSContext
*cx
)
4396 return cx
->securityCallbacks
4397 ? cx
->securityCallbacks
4398 : cx
->runtime
->securityCallbacks
;
4401 JS_PUBLIC_API(JSFunction
*)
4402 JS_NewFunction(JSContext
*cx
, JSNative native
, uintN nargs
, uintN flags
,
4403 JSObject
*parent
, const char *name
)
4412 atom
= js_Atomize(cx
, name
, strlen(name
), 0);
4416 return js_NewFunction(cx
, NULL
, native
, nargs
, flags
, parent
, atom
);
4419 JS_PUBLIC_API(JSObject
*)
4420 JS_CloneFunctionObject(JSContext
*cx
, JSObject
*funobj
, JSObject
*parent
)
4423 if (OBJ_GET_CLASS(cx
, funobj
) != &js_FunctionClass
) {
4424 /* Indicate we cannot clone this object. */
4427 return js_CloneFunctionObject(cx
, GET_FUNCTION_PRIVATE(cx
, funobj
), parent
);
4430 JS_PUBLIC_API(JSObject
*)
4431 JS_GetFunctionObject(JSFunction
*fun
)
4433 return FUN_OBJECT(fun
);
4436 JS_PUBLIC_API(const char *)
4437 JS_GetFunctionName(JSFunction
*fun
)
4440 ? JS_GetStringBytes(ATOM_TO_STRING(fun
->atom
))
4444 JS_PUBLIC_API(JSString
*)
4445 JS_GetFunctionId(JSFunction
*fun
)
4447 return fun
->atom
? ATOM_TO_STRING(fun
->atom
) : NULL
;
4450 JS_PUBLIC_API(uintN
)
4451 JS_GetFunctionFlags(JSFunction
*fun
)
4453 #ifdef MOZILLA_1_8_BRANCH
4454 uintN flags
= fun
->flags
;
4456 return JSFUN_DISJOINT_FLAGS(flags
) |
4457 (JSFUN_GETTER_TEST(flags
) ? JSFUN_GETTER
: 0) |
4458 (JSFUN_SETTER_TEST(flags
) ? JSFUN_SETTER
: 0) |
4459 (JSFUN_BOUND_METHOD_TEST(flags
) ? JSFUN_BOUND_METHOD
: 0) |
4460 (JSFUN_HEAVYWEIGHT_TEST(flags
) ? JSFUN_HEAVYWEIGHT
: 0);
4466 JS_PUBLIC_API(uint16
)
4467 JS_GetFunctionArity(JSFunction
*fun
)
4472 JS_PUBLIC_API(JSBool
)
4473 JS_ObjectIsFunction(JSContext
*cx
, JSObject
*obj
)
4475 return OBJ_GET_CLASS(cx
, obj
) == &js_FunctionClass
;
4480 js_generic_fast_native_method_dispatcher(JSContext
*cx
, uintN argc
, jsval
*vp
)
4485 JSFastNative native
;
4487 if (!JS_GetReservedSlot(cx
, JSVAL_TO_OBJECT(*vp
), 0, &fsv
))
4489 fs
= (JSFunctionSpec
*) JSVAL_TO_PRIVATE(fsv
);
4490 JS_ASSERT((~fs
->flags
& (JSFUN_FAST_NATIVE
| JSFUN_GENERIC_NATIVE
)) == 0);
4493 * We know that vp[2] is valid because JS_DefineFunctions, which is our
4494 * only (indirect) referrer, defined us as requiring at least one argument
4495 * (notice how it passes fs->nargs + 1 as the next-to-last argument to
4496 * JS_DefineFunction).
4498 if (JSVAL_IS_PRIMITIVE(vp
[2])) {
4500 * Make sure that this is an object or null, as required by the generic
4503 if (!js_ValueToObject(cx
, vp
[2], &tmp
))
4505 vp
[2] = OBJECT_TO_JSVAL(tmp
);
4509 * Copy all actual (argc) arguments down over our |this| parameter, vp[1],
4510 * which is almost always the class constructor object, e.g. Array. Then
4511 * call the corresponding prototype native method with our first argument
4514 memmove(vp
+ 1, vp
+ 2, argc
* sizeof(jsval
));
4517 * Follow Function.prototype.apply and .call by using the global object as
4518 * the 'this' param if no args.
4520 if (!js_ComputeThis(cx
, JS_FALSE
, vp
+ 2))
4523 * Protect against argc underflowing. By calling js_ComputeThis, we made
4524 * it as if the static was called with one parameter, the explicit |this|
4532 (fs
->flags
& JSFUN_TRACEABLE
)
4533 ? ((JSTraceableNative
*) fs
->call
)->native
4536 (JSFastNative
) fs
->call
;
4537 return native(cx
, argc
, vp
);
4541 js_generic_native_method_dispatcher(JSContext
*cx
, JSObject
*obj
,
4542 uintN argc
, jsval
*argv
, jsval
*rval
)
4548 if (!JS_GetReservedSlot(cx
, JSVAL_TO_OBJECT(argv
[-2]), 0, &fsv
))
4550 fs
= (JSFunctionSpec
*) JSVAL_TO_PRIVATE(fsv
);
4551 JS_ASSERT((fs
->flags
& (JSFUN_FAST_NATIVE
| JSFUN_GENERIC_NATIVE
)) ==
4552 JSFUN_GENERIC_NATIVE
);
4555 * We know that argv[0] is valid because JS_DefineFunctions, which is our
4556 * only (indirect) referrer, defined us as requiring at least one argument
4557 * (notice how it passes fs->nargs + 1 as the next-to-last argument to
4558 * JS_DefineFunction).
4560 if (JSVAL_IS_PRIMITIVE(argv
[0])) {
4562 * Make sure that this is an object or null, as required by the generic
4565 if (!js_ValueToObject(cx
, argv
[0], &tmp
))
4567 argv
[0] = OBJECT_TO_JSVAL(tmp
);
4571 * Copy all actual (argc) arguments down over our |this| parameter,
4572 * argv[-1], which is almost always the class constructor object, e.g.
4573 * Array. Then call the corresponding prototype native method with our
4574 * first argument passed as |this|.
4576 memmove(argv
- 1, argv
, argc
* sizeof(jsval
));
4579 * Follow Function.prototype.apply and .call by using the global object as
4580 * the 'this' param if no args.
4582 if (!js_ComputeThis(cx
, JS_TRUE
, argv
))
4584 js_GetTopStackFrame(cx
)->thisp
= JSVAL_TO_OBJECT(argv
[-1]);
4585 JS_ASSERT(cx
->fp
->argv
== argv
);
4588 * Protect against argc underflowing. By calling js_ComputeThis, we made
4589 * it as if the static was called with one parameter, the explicit |this|
4595 return fs
->call(cx
, JSVAL_TO_OBJECT(argv
[-1]), argc
, argv
, rval
);
4599 JS_PUBLIC_API(JSBool
)
4600 JS_DefineFunctions(JSContext
*cx
, JSObject
*obj
, JSFunctionSpec
*fs
)
4608 for (; fs
->name
; fs
++) {
4612 * Define a generic arity N+1 static method for the arity N prototype
4613 * method if flags contains JSFUN_GENERIC_NATIVE.
4615 if (flags
& JSFUN_GENERIC_NATIVE
) {
4617 ctor
= JS_GetConstructor(cx
, obj
);
4622 flags
&= ~JSFUN_GENERIC_NATIVE
;
4623 fun
= JS_DefineFunction(cx
, ctor
, fs
->name
,
4624 (flags
& JSFUN_FAST_NATIVE
)
4626 js_generic_fast_native_method_dispatcher
4627 : js_generic_native_method_dispatcher
,
4629 flags
& ~JSFUN_TRACEABLE
);
4632 fun
->u
.n
.extra
= (uint16
)fs
->extra
;
4635 * As jsapi.h notes, fs must point to storage that lives as long
4636 * as fun->object lives.
4638 if (!JS_SetReservedSlot(cx
, FUN_OBJECT(fun
), 0, PRIVATE_TO_JSVAL(fs
)))
4642 JS_ASSERT(!(flags
& JSFUN_FAST_NATIVE
) ||
4643 (uint16
)(fs
->extra
>> 16) <= fs
->nargs
);
4644 fun
= JS_DefineFunction(cx
, obj
, fs
->name
, fs
->call
, fs
->nargs
, flags
);
4647 fun
->u
.n
.extra
= (uint16
)fs
->extra
;
4652 JS_PUBLIC_API(JSFunction
*)
4653 JS_DefineFunction(JSContext
*cx
, JSObject
*obj
, const char *name
, JSNative call
,
4654 uintN nargs
, uintN attrs
)
4659 atom
= js_Atomize(cx
, name
, strlen(name
), 0);
4662 return js_DefineFunction(cx
, obj
, atom
, call
, nargs
, attrs
);
4665 JS_PUBLIC_API(JSFunction
*)
4666 JS_DefineUCFunction(JSContext
*cx
, JSObject
*obj
,
4667 const jschar
*name
, size_t namelen
, JSNative call
,
4668 uintN nargs
, uintN attrs
)
4672 atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
4675 return js_DefineFunction(cx
, obj
, atom
, call
, nargs
, attrs
);
4678 JS_PUBLIC_API(JSScript
*)
4679 JS_CompileScript(JSContext
*cx
, JSObject
*obj
,
4680 const char *bytes
, size_t length
,
4681 const char *filename
, uintN lineno
)
4687 chars
= js_InflateString(cx
, bytes
, &length
);
4690 script
= JS_CompileUCScript(cx
, obj
, chars
, length
, filename
, lineno
);
4695 JS_PUBLIC_API(JSScript
*)
4696 JS_CompileScriptForPrincipals(JSContext
*cx
, JSObject
*obj
,
4697 JSPrincipals
*principals
,
4698 const char *bytes
, size_t length
,
4699 const char *filename
, uintN lineno
)
4705 chars
= js_InflateString(cx
, bytes
, &length
);
4708 script
= JS_CompileUCScriptForPrincipals(cx
, obj
, principals
,
4709 chars
, length
, filename
, lineno
);
4714 JS_PUBLIC_API(JSScript
*)
4715 JS_CompileUCScript(JSContext
*cx
, JSObject
*obj
,
4716 const jschar
*chars
, size_t length
,
4717 const char *filename
, uintN lineno
)
4720 return JS_CompileUCScriptForPrincipals(cx
, obj
, NULL
, chars
, length
,
4724 #define LAST_FRAME_EXCEPTION_CHECK(cx,result) \
4726 if (!(result) && !((cx)->options & JSOPTION_DONT_REPORT_UNCAUGHT)) \
4727 js_ReportUncaughtException(cx); \
4730 #define LAST_FRAME_CHECKS(cx,result) \
4732 if (!JS_IsRunning(cx)) { \
4733 (cx)->weakRoots.lastInternalResult = JSVAL_NULL; \
4734 LAST_FRAME_EXCEPTION_CHECK(cx, result); \
4738 #define JS_OPTIONS_TO_TCFLAGS(cx) \
4739 ((((cx)->options & JSOPTION_COMPILE_N_GO) ? TCF_COMPILE_N_GO : 0) | \
4740 (((cx)->options & JSOPTION_NO_SCRIPT_RVAL) ? TCF_NO_SCRIPT_RVAL : 0))
4742 JS_PUBLIC_API(JSScript
*)
4743 JS_CompileUCScriptForPrincipals(JSContext
*cx
, JSObject
*obj
,
4744 JSPrincipals
*principals
,
4745 const jschar
*chars
, size_t length
,
4746 const char *filename
, uintN lineno
)
4752 tcflags
= JS_OPTIONS_TO_TCFLAGS(cx
);
4753 script
= js_CompileScript(cx
, obj
, NULL
, principals
, tcflags
,
4754 chars
, length
, NULL
, filename
, lineno
);
4755 LAST_FRAME_CHECKS(cx
, script
);
4759 JS_PUBLIC_API(JSBool
)
4760 JS_BufferIsCompilableUnit(JSContext
*cx
, JSObject
*obj
,
4761 const char *bytes
, size_t length
)
4765 JSExceptionState
*exnState
;
4767 JSErrorReporter older
;
4770 chars
= js_InflateString(cx
, bytes
, &length
);
4775 * Return true on any out-of-memory error, so our caller doesn't try to
4776 * collect more buffered source.
4779 exnState
= JS_SaveExceptionState(cx
);
4780 if (js_InitParseContext(cx
, &pc
, NULL
, NULL
, chars
, length
, NULL
, NULL
,
4782 older
= JS_SetErrorReporter(cx
, NULL
);
4783 if (!js_ParseScript(cx
, obj
, &pc
) &&
4784 (pc
.tokenStream
.flags
& TSF_UNEXPECTED_EOF
)) {
4786 * We ran into an error. If it was because we ran out of source,
4787 * we return false, so our caller will know to try to collect more
4792 JS_SetErrorReporter(cx
, older
);
4793 js_FinishParseContext(cx
, &pc
);
4796 JS_RestoreExceptionState(cx
, exnState
);
4800 JS_PUBLIC_API(JSScript
*)
4801 JS_CompileFile(JSContext
*cx
, JSObject
*obj
, const char *filename
)
4808 if (!filename
|| strcmp(filename
, "-") == 0) {
4811 fp
= fopen(filename
, "r");
4813 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_CANT_OPEN
,
4814 filename
, "No such file or directory");
4819 tcflags
= JS_OPTIONS_TO_TCFLAGS(cx
);
4820 script
= js_CompileScript(cx
, obj
, NULL
, NULL
, tcflags
,
4821 NULL
, 0, fp
, filename
, 1);
4824 LAST_FRAME_CHECKS(cx
, script
);
4828 JS_PUBLIC_API(JSScript
*)
4829 JS_CompileFileHandle(JSContext
*cx
, JSObject
*obj
, const char *filename
,
4832 return JS_CompileFileHandleForPrincipals(cx
, obj
, filename
, file
, NULL
);
4835 JS_PUBLIC_API(JSScript
*)
4836 JS_CompileFileHandleForPrincipals(JSContext
*cx
, JSObject
*obj
,
4837 const char *filename
, FILE *file
,
4838 JSPrincipals
*principals
)
4844 tcflags
= JS_OPTIONS_TO_TCFLAGS(cx
);
4845 script
= js_CompileScript(cx
, obj
, NULL
, principals
, tcflags
,
4846 NULL
, 0, file
, filename
, 1);
4847 LAST_FRAME_CHECKS(cx
, script
);
4851 JS_PUBLIC_API(JSObject
*)
4852 JS_NewScriptObject(JSContext
*cx
, JSScript
*script
)
4854 JSTempValueRooter tvr
;
4859 return js_NewObject(cx
, &js_ScriptClass
, NULL
, NULL
, 0);
4861 JS_ASSERT(!script
->u
.object
);
4863 JS_PUSH_TEMP_ROOT_SCRIPT(cx
, script
, &tvr
);
4864 obj
= js_NewObject(cx
, &js_ScriptClass
, NULL
, NULL
, 0);
4866 JS_SetPrivate(cx
, obj
, script
);
4867 script
->u
.object
= obj
;
4868 #ifdef CHECK_SCRIPT_OWNER
4869 script
->owner
= NULL
;
4872 JS_POP_TEMP_ROOT(cx
, &tvr
);
4876 JS_PUBLIC_API(JSObject
*)
4877 JS_GetScriptObject(JSScript
*script
)
4879 return script
->u
.object
;
4883 JS_DestroyScript(JSContext
*cx
, JSScript
*script
)
4886 js_DestroyScript(cx
, script
);
4889 JS_PUBLIC_API(JSFunction
*)
4890 JS_CompileFunction(JSContext
*cx
, JSObject
*obj
, const char *name
,
4891 uintN nargs
, const char **argnames
,
4892 const char *bytes
, size_t length
,
4893 const char *filename
, uintN lineno
)
4899 chars
= js_InflateString(cx
, bytes
, &length
);
4902 fun
= JS_CompileUCFunction(cx
, obj
, name
, nargs
, argnames
, chars
, length
,
4908 JS_PUBLIC_API(JSFunction
*)
4909 JS_CompileFunctionForPrincipals(JSContext
*cx
, JSObject
*obj
,
4910 JSPrincipals
*principals
, const char *name
,
4911 uintN nargs
, const char **argnames
,
4912 const char *bytes
, size_t length
,
4913 const char *filename
, uintN lineno
)
4919 chars
= js_InflateString(cx
, bytes
, &length
);
4922 fun
= JS_CompileUCFunctionForPrincipals(cx
, obj
, principals
, name
,
4923 nargs
, argnames
, chars
, length
,
4929 JS_PUBLIC_API(JSFunction
*)
4930 JS_CompileUCFunction(JSContext
*cx
, JSObject
*obj
, const char *name
,
4931 uintN nargs
, const char **argnames
,
4932 const jschar
*chars
, size_t length
,
4933 const char *filename
, uintN lineno
)
4936 return JS_CompileUCFunctionForPrincipals(cx
, obj
, NULL
, name
,
4942 JS_PUBLIC_API(JSFunction
*)
4943 JS_CompileUCFunctionForPrincipals(JSContext
*cx
, JSObject
*obj
,
4944 JSPrincipals
*principals
, const char *name
,
4945 uintN nargs
, const char **argnames
,
4946 const jschar
*chars
, size_t length
,
4947 const char *filename
, uintN lineno
)
4950 JSTempValueRooter tvr
;
4951 JSAtom
*funAtom
, *argAtom
;
4958 funAtom
= js_Atomize(cx
, name
, strlen(name
), 0);
4964 fun
= js_NewFunction(cx
, NULL
, NULL
, 0, JSFUN_INTERPRETED
, obj
, funAtom
);
4968 MUST_FLOW_THROUGH("out");
4969 JS_PUSH_TEMP_ROOT_OBJECT(cx
, FUN_OBJECT(fun
), &tvr
);
4970 for (i
= 0; i
< nargs
; i
++) {
4971 argAtom
= js_Atomize(cx
, argnames
[i
], strlen(argnames
[i
]), 0);
4976 if (!js_AddLocal(cx
, fun
, argAtom
, JSLOCAL_ARG
)) {
4982 if (!js_CompileFunctionBody(cx
, fun
, principals
, chars
, length
,
4983 filename
, lineno
)) {
4990 !OBJ_DEFINE_PROPERTY(cx
, obj
, ATOM_TO_JSID(funAtom
),
4991 OBJECT_TO_JSVAL(FUN_OBJECT(fun
)),
4992 NULL
, NULL
, JSPROP_ENUMERATE
, NULL
)) {
4996 #ifdef JS_SCOPE_DEPTH_METER
4998 JSObject
*pobj
= obj
;
5001 while ((pobj
= OBJ_GET_PARENT(cx
, pobj
)) != NULL
)
5003 JS_BASIC_STATS_ACCUM(&cx
->runtime
->hostenvScopeDepthStats
, depth
);
5008 cx
->weakRoots
.newborn
[JSTRACE_OBJECT
] = FUN_OBJECT(fun
);
5009 JS_POP_TEMP_ROOT(cx
, &tvr
);
5012 LAST_FRAME_CHECKS(cx
, fun
);
5016 JS_PUBLIC_API(JSString
*)
5017 JS_DecompileScript(JSContext
*cx
, JSScript
*script
, const char *name
,
5024 jp
= JS_NEW_PRINTER(cx
, name
, NULL
,
5025 indent
& ~JS_DONT_PRETTY_PRINT
,
5026 !(indent
& JS_DONT_PRETTY_PRINT
));
5029 if (js_DecompileScript(jp
, script
))
5030 str
= js_GetPrinterOutput(jp
);
5033 js_DestroyPrinter(jp
);
5037 JS_PUBLIC_API(JSString
*)
5038 JS_DecompileFunction(JSContext
*cx
, JSFunction
*fun
, uintN indent
)
5044 jp
= JS_NEW_PRINTER(cx
, "JS_DecompileFunction", fun
,
5045 indent
& ~JS_DONT_PRETTY_PRINT
,
5046 !(indent
& JS_DONT_PRETTY_PRINT
));
5049 if (js_DecompileFunction(jp
))
5050 str
= js_GetPrinterOutput(jp
);
5053 js_DestroyPrinter(jp
);
5057 JS_PUBLIC_API(JSString
*)
5058 JS_DecompileFunctionBody(JSContext
*cx
, JSFunction
*fun
, uintN indent
)
5064 jp
= JS_NEW_PRINTER(cx
, "JS_DecompileFunctionBody", fun
,
5065 indent
& ~JS_DONT_PRETTY_PRINT
,
5066 !(indent
& JS_DONT_PRETTY_PRINT
));
5069 if (js_DecompileFunctionBody(jp
))
5070 str
= js_GetPrinterOutput(jp
);
5073 js_DestroyPrinter(jp
);
5077 JS_PUBLIC_API(JSBool
)
5078 JS_ExecuteScript(JSContext
*cx
, JSObject
*obj
, JSScript
*script
, jsval
*rval
)
5083 ok
= js_Execute(cx
, obj
, script
, NULL
, 0, rval
);
5084 LAST_FRAME_CHECKS(cx
, ok
);
5088 JS_PUBLIC_API(JSBool
)
5089 JS_ExecuteScriptPart(JSContext
*cx
, JSObject
*obj
, JSScript
*script
,
5090 JSExecPart part
, jsval
*rval
)
5093 JSDebugHooks
*hooks
;
5096 /* Make a temporary copy of the JSScript structure and farble it a bit. */
5098 if (part
== JSEXEC_PROLOG
) {
5099 tmp
.length
= PTRDIFF(tmp
.main
, tmp
.code
, jsbytecode
);
5101 tmp
.length
-= PTRDIFF(tmp
.main
, tmp
.code
, jsbytecode
);
5102 tmp
.code
= tmp
.main
;
5105 /* Tell the debugger about our temporary copy of the script structure. */
5106 hooks
= cx
->debugHooks
;
5107 if (hooks
->newScriptHook
) {
5108 hooks
->newScriptHook(cx
, tmp
.filename
, tmp
.lineno
, &tmp
, NULL
,
5109 hooks
->newScriptHookData
);
5112 /* Execute the farbled struct and tell the debugger to forget about it. */
5113 ok
= JS_ExecuteScript(cx
, obj
, &tmp
, rval
);
5114 if (hooks
->destroyScriptHook
)
5115 hooks
->destroyScriptHook(cx
, &tmp
, hooks
->destroyScriptHookData
);
5119 /* Ancient uintN nbytes is part of API/ABI, so use size_t length local. */
5120 JS_PUBLIC_API(JSBool
)
5121 JS_EvaluateScript(JSContext
*cx
, JSObject
*obj
,
5122 const char *bytes
, uintN nbytes
,
5123 const char *filename
, uintN lineno
,
5126 size_t length
= nbytes
;
5131 chars
= js_InflateString(cx
, bytes
, &length
);
5134 ok
= JS_EvaluateUCScript(cx
, obj
, chars
, length
, filename
, lineno
, rval
);
5139 /* Ancient uintN nbytes is part of API/ABI, so use size_t length local. */
5140 JS_PUBLIC_API(JSBool
)
5141 JS_EvaluateScriptForPrincipals(JSContext
*cx
, JSObject
*obj
,
5142 JSPrincipals
*principals
,
5143 const char *bytes
, uintN nbytes
,
5144 const char *filename
, uintN lineno
,
5147 size_t length
= nbytes
;
5152 chars
= js_InflateString(cx
, bytes
, &length
);
5155 ok
= JS_EvaluateUCScriptForPrincipals(cx
, obj
, principals
, chars
, length
,
5156 filename
, lineno
, rval
);
5161 JS_PUBLIC_API(JSBool
)
5162 JS_EvaluateUCScript(JSContext
*cx
, JSObject
*obj
,
5163 const jschar
*chars
, uintN length
,
5164 const char *filename
, uintN lineno
,
5168 return JS_EvaluateUCScriptForPrincipals(cx
, obj
, NULL
, chars
, length
,
5169 filename
, lineno
, rval
);
5172 JS_PUBLIC_API(JSBool
)
5173 JS_EvaluateUCScriptForPrincipals(JSContext
*cx
, JSObject
*obj
,
5174 JSPrincipals
*principals
,
5175 const jschar
*chars
, uintN length
,
5176 const char *filename
, uintN lineno
,
5183 script
= js_CompileScript(cx
, obj
, NULL
, principals
,
5185 ? TCF_COMPILE_N_GO
| TCF_NO_SCRIPT_RVAL
5187 chars
, length
, NULL
, filename
, lineno
);
5189 LAST_FRAME_CHECKS(cx
, script
);
5192 ok
= js_Execute(cx
, obj
, script
, NULL
, 0, rval
);
5193 LAST_FRAME_CHECKS(cx
, ok
);
5194 JS_DestroyScript(cx
, script
);
5198 JS_PUBLIC_API(JSBool
)
5199 JS_CallFunction(JSContext
*cx
, JSObject
*obj
, JSFunction
*fun
, uintN argc
,
5200 jsval
*argv
, jsval
*rval
)
5205 ok
= js_InternalCall(cx
, obj
, OBJECT_TO_JSVAL(FUN_OBJECT(fun
)), argc
, argv
,
5207 LAST_FRAME_CHECKS(cx
, ok
);
5211 JS_PUBLIC_API(JSBool
)
5212 JS_CallFunctionName(JSContext
*cx
, JSObject
*obj
, const char *name
, uintN argc
,
5213 jsval
*argv
, jsval
*rval
)
5219 #if JS_HAS_XML_SUPPORT
5220 if (OBJECT_IS_XML(cx
, obj
)) {
5221 JSXMLObjectOps
*ops
;
5224 ops
= (JSXMLObjectOps
*) obj
->map
->ops
;
5225 atom
= js_Atomize(cx
, name
, strlen(name
), 0);
5228 obj
= ops
->getMethod(cx
, obj
, ATOM_TO_JSID(atom
), &fval
);
5233 if (!JS_GetProperty(cx
, obj
, name
, &fval
))
5235 ok
= js_InternalCall(cx
, obj
, fval
, argc
, argv
, rval
);
5236 LAST_FRAME_CHECKS(cx
, ok
);
5240 JS_PUBLIC_API(JSBool
)
5241 JS_CallFunctionValue(JSContext
*cx
, JSObject
*obj
, jsval fval
, uintN argc
,
5242 jsval
*argv
, jsval
*rval
)
5247 ok
= js_InternalCall(cx
, obj
, fval
, argc
, argv
, rval
);
5248 LAST_FRAME_CHECKS(cx
, ok
);
5253 JS_SetOperationCallback(JSContext
*cx
, JSOperationCallback callback
,
5254 uint32 operationLimit
)
5256 JS_ASSERT(callback
);
5257 JS_ASSERT(operationLimit
<= JS_MAX_OPERATION_LIMIT
);
5258 JS_ASSERT(operationLimit
> 0);
5260 cx
->operationCount
= (int32
) operationLimit
;
5261 cx
->operationLimit
= operationLimit
;
5262 cx
->operationCallbackIsSet
= 1;
5263 cx
->operationCallback
= callback
;
5267 JS_ClearOperationCallback(JSContext
*cx
)
5269 cx
->operationCount
= (int32
) JS_MAX_OPERATION_LIMIT
;
5270 cx
->operationLimit
= JS_MAX_OPERATION_LIMIT
;
5271 cx
->operationCallbackIsSet
= 0;
5272 cx
->operationCallback
= NULL
;
5275 JS_PUBLIC_API(JSOperationCallback
)
5276 JS_GetOperationCallback(JSContext
*cx
)
5278 JS_ASSERT(cx
->operationCallbackIsSet
|| !cx
->operationCallback
);
5279 return cx
->operationCallback
;
5282 JS_PUBLIC_API(uint32
)
5283 JS_GetOperationLimit(JSContext
*cx
)
5285 JS_ASSERT(cx
->operationCallbackIsSet
);
5286 return cx
->operationLimit
;
5290 JS_SetOperationLimit(JSContext
*cx
, uint32 operationLimit
)
5292 JS_ASSERT(operationLimit
<= JS_MAX_OPERATION_LIMIT
);
5293 JS_ASSERT(operationLimit
> 0);
5294 JS_ASSERT(cx
->operationCallbackIsSet
);
5296 cx
->operationLimit
= operationLimit
;
5297 if (cx
->operationCount
> (int32
) operationLimit
)
5298 cx
->operationCount
= (int32
) operationLimit
;
5301 JS_PUBLIC_API(JSBranchCallback
)
5302 JS_SetBranchCallback(JSContext
*cx
, JSBranchCallback cb
)
5304 JSBranchCallback oldcb
;
5306 if (cx
->operationCallbackIsSet
) {
5309 "JS API usage error: call to JS_SetOperationCallback is followed by\n"
5310 "invocation of deprecated JS_SetBranchCallback\n");
5313 cx
->operationCallbackIsSet
= 0;
5316 oldcb
= (JSBranchCallback
) cx
->operationCallback
;
5319 cx
->operationCount
= JSOW_SCRIPT_JUMP
;
5320 cx
->operationLimit
= JSOW_SCRIPT_JUMP
;
5321 cx
->operationCallback
= (JSOperationCallback
) cb
;
5323 JS_ClearOperationCallback(cx
);
5328 JS_PUBLIC_API(JSBool
)
5329 JS_IsRunning(JSContext
*cx
)
5331 /* The use of cx->fp below is safe: if we're on trace, it is skipped. */
5332 VOUCH_DOES_NOT_REQUIRE_STACK();
5334 return JS_ON_TRACE(cx
) || cx
->fp
!= NULL
;
5337 JS_PUBLIC_API(JSBool
)
5338 JS_IsConstructing(JSContext
*cx
)
5342 fp
= js_GetTopStackFrame(cx
);
5343 return fp
&& (fp
->flags
& JSFRAME_CONSTRUCTING
);
5346 JS_FRIEND_API(JSBool
)
5347 JS_IsAssigning(JSContext
*cx
)
5351 fp
= js_GetScriptedCaller(cx
, NULL
);
5352 if (!fp
|| !fp
->regs
)
5354 return (js_CodeSpec
[*fp
->regs
->pc
].format
& JOF_ASSIGNING
) != 0;
5358 JS_SetCallReturnValue2(JSContext
*cx
, jsval v
)
5360 #if JS_HAS_LVALUE_RETURN
5362 cx
->rval2set
= JS_TRUE
;
5366 JS_PUBLIC_API(JSStackFrame
*)
5367 JS_SaveFrameChain(JSContext
*cx
)
5371 fp
= js_GetTopStackFrame(cx
);
5375 JS_ASSERT(!fp
->dormantNext
);
5376 fp
->dormantNext
= cx
->dormantFrameChain
;
5377 cx
->dormantFrameChain
= fp
;
5383 JS_RestoreFrameChain(JSContext
*cx
, JSStackFrame
*fp
)
5385 JS_ASSERT(!JS_ON_TRACE(cx
));
5386 VOUCH_DOES_NOT_REQUIRE_STACK();
5391 JS_ASSERT(fp
== cx
->dormantFrameChain
);
5393 cx
->dormantFrameChain
= fp
->dormantNext
;
5394 fp
->dormantNext
= NULL
;
5397 /************************************************************************/
5399 JS_PUBLIC_API(JSString
*)
5400 JS_NewString(JSContext
*cx
, char *bytes
, size_t nbytes
)
5402 size_t length
= nbytes
;
5408 /* Make a UTF-16 vector from the 8-bit char codes in bytes. */
5409 chars
= js_InflateString(cx
, bytes
, &length
);
5413 /* Free chars (but not bytes, which caller frees on error) if we fail. */
5414 str
= js_NewString(cx
, chars
, length
);
5420 /* Hand off bytes to the deflated string cache, if possible. */
5421 if (!js_SetStringBytes(cx
, str
, bytes
, nbytes
))
5426 JS_PUBLIC_API(JSString
*)
5427 JS_NewStringCopyN(JSContext
*cx
, const char *s
, size_t n
)
5433 js
= js_InflateString(cx
, s
, &n
);
5436 str
= js_NewString(cx
, js
, n
);
5442 JS_PUBLIC_API(JSString
*)
5443 JS_NewStringCopyZ(JSContext
*cx
, const char *s
)
5451 return cx
->runtime
->emptyString
;
5453 js
= js_InflateString(cx
, s
, &n
);
5456 str
= js_NewString(cx
, js
, n
);
5462 JS_PUBLIC_API(JSString
*)
5463 JS_InternString(JSContext
*cx
, const char *s
)
5468 atom
= js_Atomize(cx
, s
, strlen(s
), ATOM_INTERNED
);
5471 return ATOM_TO_STRING(atom
);
5474 JS_PUBLIC_API(JSString
*)
5475 JS_NewUCString(JSContext
*cx
, jschar
*chars
, size_t length
)
5478 return js_NewString(cx
, chars
, length
);
5481 JS_PUBLIC_API(JSString
*)
5482 JS_NewUCStringCopyN(JSContext
*cx
, const jschar
*s
, size_t n
)
5485 return js_NewStringCopyN(cx
, s
, n
);
5488 JS_PUBLIC_API(JSString
*)
5489 JS_NewUCStringCopyZ(JSContext
*cx
, const jschar
*s
)
5493 return cx
->runtime
->emptyString
;
5494 return js_NewStringCopyZ(cx
, s
);
5497 JS_PUBLIC_API(JSString
*)
5498 JS_InternUCStringN(JSContext
*cx
, const jschar
*s
, size_t length
)
5503 atom
= js_AtomizeChars(cx
, s
, length
, ATOM_INTERNED
);
5506 return ATOM_TO_STRING(atom
);
5509 JS_PUBLIC_API(JSString
*)
5510 JS_InternUCString(JSContext
*cx
, const jschar
*s
)
5512 return JS_InternUCStringN(cx
, s
, js_strlen(s
));
5515 JS_PUBLIC_API(char *)
5516 JS_GetStringBytes(JSString
*str
)
5520 bytes
= js_GetStringBytes(NULL
, str
);
5521 return (char *)(bytes
? bytes
: "");
5524 JS_PUBLIC_API(jschar
*)
5525 JS_GetStringChars(JSString
*str
)
5531 * API botch (again, shades of JS_GetStringBytes): we have no cx to report
5532 * out-of-memory when undepending strings, so we replace js_UndependString
5533 * with explicit malloc call and ignore its errors.
5535 * If we fail to convert a dependent string into an independent one, our
5536 * caller will not be guaranteed a \u0000 terminator as a backstop. This
5537 * may break some clients who already misbehave on embedded NULs.
5539 * The gain of dependent strings, which cure quadratic and cubic growth
5540 * rate bugs in string concatenation, is worth this slight loss in API
5543 if (JSSTRING_IS_DEPENDENT(str
)) {
5544 n
= JSSTRDEP_LENGTH(str
);
5545 size
= (n
+ 1) * sizeof(jschar
);
5546 s
= (jschar
*) malloc(size
);
5548 memcpy(s
, JSSTRDEP_CHARS(str
), n
* sizeof *s
);
5550 JSFLATSTR_INIT(str
, s
, n
);
5552 s
= JSSTRDEP_CHARS(str
);
5555 JSFLATSTR_CLEAR_MUTABLE(str
);
5556 s
= JSFLATSTR_CHARS(str
);
5561 JS_PUBLIC_API(size_t)
5562 JS_GetStringLength(JSString
*str
)
5564 return JSSTRING_LENGTH(str
);
5568 JS_CompareStrings(JSString
*str1
, JSString
*str2
)
5570 return js_CompareStrings(str1
, str2
);
5573 JS_PUBLIC_API(JSString
*)
5574 JS_NewGrowableString(JSContext
*cx
, jschar
*chars
, size_t length
)
5579 str
= js_NewString(cx
, chars
, length
);
5582 JSFLATSTR_SET_MUTABLE(str
);
5586 JS_PUBLIC_API(JSString
*)
5587 JS_NewDependentString(JSContext
*cx
, JSString
*str
, size_t start
,
5591 return js_NewDependentString(cx
, str
, start
, length
);
5594 JS_PUBLIC_API(JSString
*)
5595 JS_ConcatStrings(JSContext
*cx
, JSString
*left
, JSString
*right
)
5598 return js_ConcatStrings(cx
, left
, right
);
5601 JS_PUBLIC_API(const jschar
*)
5602 JS_UndependString(JSContext
*cx
, JSString
*str
)
5605 return js_UndependString(cx
, str
);
5608 JS_PUBLIC_API(JSBool
)
5609 JS_MakeStringImmutable(JSContext
*cx
, JSString
*str
)
5612 return js_MakeStringImmutable(cx
, str
);
5615 JS_PUBLIC_API(JSBool
)
5616 JS_EncodeCharacters(JSContext
*cx
, const jschar
*src
, size_t srclen
, char *dst
,
5622 n
= js_GetDeflatedStringLength(cx
, src
, srclen
);
5623 if (n
== (size_t)-1) {
5631 return js_DeflateStringToBuffer(cx
, src
, srclen
, dst
, dstlenp
);
5634 JS_PUBLIC_API(JSBool
)
5635 JS_DecodeBytes(JSContext
*cx
, const char *src
, size_t srclen
, jschar
*dst
,
5638 return js_InflateStringToBuffer(cx
, src
, srclen
, dst
, dstlenp
);
5641 JS_PUBLIC_API(char *)
5642 JS_EncodeString(JSContext
*cx
, JSString
*str
)
5644 return js_DeflateString(cx
, JSSTRING_CHARS(str
), JSSTRING_LENGTH(str
));
5647 JS_PUBLIC_API(JSBool
)
5648 JS_Stringify(JSContext
*cx
, jsval
*vp
, JSObject
*replacer
,
5649 JSONWriteCallback callback
, void *data
)
5652 return js_Stringify(cx
, vp
, replacer
, callback
, data
, 0);
5655 JS_PUBLIC_API(JSBool
)
5656 JS_TryJSON(JSContext
*cx
, jsval
*vp
)
5659 return js_TryJSON(cx
, vp
);
5662 JS_PUBLIC_API(JSONParser
*)
5663 JS_BeginJSONParse(JSContext
*cx
, jsval
*vp
)
5666 return js_BeginJSONParse(cx
, vp
);
5669 JS_PUBLIC_API(JSBool
)
5670 JS_ConsumeJSONText(JSContext
*cx
, JSONParser
*jp
, const jschar
*data
, uint32 len
)
5673 return js_ConsumeJSONText(cx
, jp
, data
, len
);
5676 JS_PUBLIC_API(JSBool
)
5677 JS_FinishJSONParse(JSContext
*cx
, JSONParser
*jp
)
5680 return js_FinishJSONParse(cx
, jp
);
5684 * The following determines whether C Strings are to be treated as UTF-8
5685 * or ISO-8859-1. For correct operation, it must be set prior to the
5686 * first call to JS_NewRuntime.
5688 #ifndef JS_C_STRINGS_ARE_UTF8
5689 JSBool js_CStringsAreUTF8
= JS_FALSE
;
5692 JS_PUBLIC_API(JSBool
)
5693 JS_CStringsAreUTF8()
5695 return js_CStringsAreUTF8
;
5699 JS_SetCStringsAreUTF8()
5701 JS_ASSERT(!js_NewRuntimeWasCalled
);
5703 #ifndef JS_C_STRINGS_ARE_UTF8
5704 js_CStringsAreUTF8
= JS_TRUE
;
5708 /************************************************************************/
5711 JS_ReportError(JSContext
*cx
, const char *format
, ...)
5715 va_start(ap
, format
);
5716 js_ReportErrorVA(cx
, JSREPORT_ERROR
, format
, ap
);
5721 JS_ReportErrorNumber(JSContext
*cx
, JSErrorCallback errorCallback
,
5722 void *userRef
, const uintN errorNumber
, ...)
5726 va_start(ap
, errorNumber
);
5727 js_ReportErrorNumberVA(cx
, JSREPORT_ERROR
, errorCallback
, userRef
,
5728 errorNumber
, JS_TRUE
, ap
);
5733 JS_ReportErrorNumberUC(JSContext
*cx
, JSErrorCallback errorCallback
,
5734 void *userRef
, const uintN errorNumber
, ...)
5738 va_start(ap
, errorNumber
);
5739 js_ReportErrorNumberVA(cx
, JSREPORT_ERROR
, errorCallback
, userRef
,
5740 errorNumber
, JS_FALSE
, ap
);
5744 JS_PUBLIC_API(JSBool
)
5745 JS_ReportWarning(JSContext
*cx
, const char *format
, ...)
5750 va_start(ap
, format
);
5751 ok
= js_ReportErrorVA(cx
, JSREPORT_WARNING
, format
, ap
);
5756 JS_PUBLIC_API(JSBool
)
5757 JS_ReportErrorFlagsAndNumber(JSContext
*cx
, uintN flags
,
5758 JSErrorCallback errorCallback
, void *userRef
,
5759 const uintN errorNumber
, ...)
5764 va_start(ap
, errorNumber
);
5765 ok
= js_ReportErrorNumberVA(cx
, flags
, errorCallback
, userRef
,
5766 errorNumber
, JS_TRUE
, ap
);
5771 JS_PUBLIC_API(JSBool
)
5772 JS_ReportErrorFlagsAndNumberUC(JSContext
*cx
, uintN flags
,
5773 JSErrorCallback errorCallback
, void *userRef
,
5774 const uintN errorNumber
, ...)
5779 va_start(ap
, errorNumber
);
5780 ok
= js_ReportErrorNumberVA(cx
, flags
, errorCallback
, userRef
,
5781 errorNumber
, JS_FALSE
, ap
);
5787 JS_ReportOutOfMemory(JSContext
*cx
)
5789 js_ReportOutOfMemory(cx
);
5793 JS_ReportAllocationOverflow(JSContext
*cx
)
5795 js_ReportAllocationOverflow(cx
);
5798 JS_PUBLIC_API(JSErrorReporter
)
5799 JS_SetErrorReporter(JSContext
*cx
, JSErrorReporter er
)
5801 JSErrorReporter older
;
5803 older
= cx
->errorReporter
;
5804 cx
->errorReporter
= er
;
5808 /************************************************************************/
5811 * Regular Expressions.
5813 JS_PUBLIC_API(JSObject
*)
5814 JS_NewRegExpObject(JSContext
*cx
, char *bytes
, size_t length
, uintN flags
)
5820 chars
= js_InflateString(cx
, bytes
, &length
);
5823 obj
= js_NewRegExpObject(cx
, NULL
, chars
, length
, flags
);
5828 JS_PUBLIC_API(JSObject
*)
5829 JS_NewUCRegExpObject(JSContext
*cx
, jschar
*chars
, size_t length
, uintN flags
)
5832 return js_NewRegExpObject(cx
, NULL
, chars
, length
, flags
);
5836 JS_SetRegExpInput(JSContext
*cx
, JSString
*input
, JSBool multiline
)
5838 JSRegExpStatics
*res
;
5841 /* No locking required, cx is thread-private and input must be live. */
5842 res
= &cx
->regExpStatics
;
5844 res
->multiline
= multiline
;
5845 cx
->runtime
->gcPoke
= JS_TRUE
;
5849 JS_ClearRegExpStatics(JSContext
*cx
)
5851 JSRegExpStatics
*res
;
5853 /* No locking required, cx is thread-private and input must be live. */
5854 res
= &cx
->regExpStatics
;
5856 res
->multiline
= JS_FALSE
;
5857 res
->parenCount
= 0;
5858 res
->lastMatch
= res
->lastParen
= js_EmptySubString
;
5859 res
->leftContext
= res
->rightContext
= js_EmptySubString
;
5860 cx
->runtime
->gcPoke
= JS_TRUE
;
5864 JS_ClearRegExpRoots(JSContext
*cx
)
5866 JSRegExpStatics
*res
;
5868 /* No locking required, cx is thread-private and input must be live. */
5869 res
= &cx
->regExpStatics
;
5871 cx
->runtime
->gcPoke
= JS_TRUE
;
5874 /* TODO: compile, execute, get/set other statics... */
5876 /************************************************************************/
5879 JS_SetLocaleCallbacks(JSContext
*cx
, JSLocaleCallbacks
*callbacks
)
5881 cx
->localeCallbacks
= callbacks
;
5884 JS_PUBLIC_API(JSLocaleCallbacks
*)
5885 JS_GetLocaleCallbacks(JSContext
*cx
)
5887 return cx
->localeCallbacks
;
5890 /************************************************************************/
5892 JS_PUBLIC_API(JSBool
)
5893 JS_IsExceptionPending(JSContext
*cx
)
5895 return (JSBool
) cx
->throwing
;
5898 JS_PUBLIC_API(JSBool
)
5899 JS_GetPendingException(JSContext
*cx
, jsval
*vp
)
5904 *vp
= cx
->exception
;
5909 JS_SetPendingException(JSContext
*cx
, jsval v
)
5912 cx
->throwing
= JS_TRUE
;
5917 JS_ClearPendingException(JSContext
*cx
)
5919 cx
->throwing
= JS_FALSE
;
5920 cx
->exception
= JSVAL_VOID
;
5923 JS_PUBLIC_API(JSBool
)
5924 JS_ReportPendingException(JSContext
*cx
)
5931 * Set cx->generatingError to suppress the standard error-to-exception
5932 * conversion done by all {js,JS}_Report* functions except for OOM. The
5933 * cx->generatingError flag was added to suppress recursive divergence
5934 * under js_ErrorToException, but it serves for our purposes here too.
5936 save
= cx
->generatingError
;
5937 cx
->generatingError
= JS_TRUE
;
5938 ok
= js_ReportUncaughtException(cx
);
5939 cx
->generatingError
= save
;
5943 struct JSExceptionState
{
5948 JS_PUBLIC_API(JSExceptionState
*)
5949 JS_SaveExceptionState(JSContext
*cx
)
5951 JSExceptionState
*state
;
5954 state
= (JSExceptionState
*) JS_malloc(cx
, sizeof(JSExceptionState
));
5956 state
->throwing
= JS_GetPendingException(cx
, &state
->exception
);
5957 if (state
->throwing
&& JSVAL_IS_GCTHING(state
->exception
))
5958 js_AddRoot(cx
, &state
->exception
, "JSExceptionState.exception");
5964 JS_RestoreExceptionState(JSContext
*cx
, JSExceptionState
*state
)
5968 if (state
->throwing
)
5969 JS_SetPendingException(cx
, state
->exception
);
5971 JS_ClearPendingException(cx
);
5972 JS_DropExceptionState(cx
, state
);
5977 JS_DropExceptionState(JSContext
*cx
, JSExceptionState
*state
)
5981 if (state
->throwing
&& JSVAL_IS_GCTHING(state
->exception
))
5982 JS_RemoveRoot(cx
, &state
->exception
);
5987 JS_PUBLIC_API(JSErrorReport
*)
5988 JS_ErrorFromException(JSContext
*cx
, jsval v
)
5991 return js_ErrorFromException(cx
, v
);
5994 JS_PUBLIC_API(JSBool
)
5995 JS_ThrowReportedError(JSContext
*cx
, const char *message
,
5996 JSErrorReport
*reportp
)
5998 return JS_IsRunning(cx
) && js_ErrorToException(cx
, message
, reportp
);
6001 JS_PUBLIC_API(JSBool
)
6002 JS_ThrowStopIteration(JSContext
*cx
)
6004 return js_ThrowStopIteration(cx
);
6008 * Get the owning thread id of a context. Returns 0 if the context is not
6009 * owned by any thread.
6011 JS_PUBLIC_API(jsword
)
6012 JS_GetContextThread(JSContext
*cx
)
6014 #ifdef JS_THREADSAFE
6015 return JS_THREAD_ID(cx
);
6022 * Set the current thread as the owning thread of a context. Returns the
6023 * old owning thread id, or -1 if the operation failed.
6025 JS_PUBLIC_API(jsword
)
6026 JS_SetContextThread(JSContext
*cx
)
6028 #ifdef JS_THREADSAFE
6029 jsword old
= JS_THREAD_ID(cx
);
6030 if (!js_SetContextThread(cx
))
6038 JS_PUBLIC_API(jsword
)
6039 JS_ClearContextThread(JSContext
*cx
)
6041 #ifdef JS_THREADSAFE
6042 jsword old
= JS_THREAD_ID(cx
);
6043 js_ClearContextThread(cx
);
6052 JS_SetGCZeal(JSContext
*cx
, uint8 zeal
)
6054 cx
->runtime
->gcZeal
= zeal
;
6058 /************************************************************************/
6060 #if !defined(STATIC_JS_API) && defined(XP_WIN) && !defined (WINCE)
6062 #include <windows.h>
6065 * Initialization routine for the JS DLL.
6067 BOOL WINAPI
DllMain (HINSTANCE hDLL
, DWORD dwReason
, LPVOID lpReserved
)