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"
83 #include "jsstaticcheck.h"
85 #if !defined JS_THREADSAFE && defined JS_TRACER
89 #if JS_HAS_FILE_OBJECT
93 #if JS_HAS_XML_SUPPORT
97 #ifdef HAVE_VA_LIST_AS_ARRAY
98 #define JS_ADDRESSOF_VA_LIST(ap) ((va_list *)(ap))
100 #define JS_ADDRESSOF_VA_LIST(ap) (&(ap))
103 #if defined(JS_THREADSAFE)
104 #define CHECK_REQUEST(cx) \
105 JS_ASSERT((cx)->requestDepth || (cx)->thread == (cx)->runtime->gcThread)
107 #define CHECK_REQUEST(cx) ((void)0)
117 JS_GetNaNValue(JSContext
*cx
)
119 return DOUBLE_TO_JSVAL(cx
->runtime
->jsNaN
);
123 JS_GetNegativeInfinityValue(JSContext
*cx
)
125 return DOUBLE_TO_JSVAL(cx
->runtime
->jsNegativeInfinity
);
129 JS_GetPositiveInfinityValue(JSContext
*cx
)
131 return DOUBLE_TO_JSVAL(cx
->runtime
->jsPositiveInfinity
);
135 JS_GetEmptyStringValue(JSContext
*cx
)
137 return STRING_TO_JSVAL(cx
->runtime
->emptyString
);
141 TryArgumentFormatter(JSContext
*cx
, const char **formatp
, JSBool fromJS
,
142 jsval
**vpp
, va_list *app
)
145 JSArgumentFormatMap
*map
;
148 for (map
= cx
->argumentFormatMap
; map
; map
= map
->next
) {
149 if (!strncmp(format
, map
->format
, map
->length
)) {
150 *formatp
= format
+ map
->length
;
151 return map
->formatter(cx
, format
, fromJS
, vpp
, app
);
154 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_BAD_CHAR
, format
);
158 JS_PUBLIC_API(JSBool
)
159 JS_ConvertArguments(JSContext
*cx
, uintN argc
, jsval
*argv
, const char *format
,
165 va_start(ap
, format
);
166 ok
= JS_ConvertArgumentsVA(cx
, argc
, argv
, format
, ap
);
171 JS_PUBLIC_API(JSBool
)
172 JS_ConvertArgumentsVA(JSContext
*cx
, uintN argc
, jsval
*argv
,
173 const char *format
, va_list ap
)
186 while ((c
= *format
++) != '\0') {
193 if (sp
== argv
+ argc
) {
195 fun
= js_ValueToFunction(cx
, &argv
[-2], 0);
198 JS_snprintf(numBuf
, sizeof numBuf
, "%u", argc
);
199 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
,
200 JSMSG_MORE_ARGS_NEEDED
,
201 JS_GetFunctionName(fun
), numBuf
,
202 (argc
== 1) ? "" : "s");
210 *va_arg(ap
, JSBool
*) = js_ValueToBoolean(*sp
);
213 if (!JS_ValueToUint16(cx
, *sp
, va_arg(ap
, uint16
*)))
217 if (!JS_ValueToECMAInt32(cx
, *sp
, va_arg(ap
, int32
*)))
221 if (!JS_ValueToECMAUint32(cx
, *sp
, va_arg(ap
, uint32
*)))
225 if (!JS_ValueToInt32(cx
, *sp
, va_arg(ap
, int32
*)))
229 if (!JS_ValueToNumber(cx
, *sp
, va_arg(ap
, jsdouble
*)))
233 if (!JS_ValueToNumber(cx
, *sp
, &d
))
235 *va_arg(ap
, jsdouble
*) = js_DoubleToInteger(d
);
240 str
= js_ValueToString(cx
, *sp
);
243 *sp
= STRING_TO_JSVAL(str
);
245 const char *bytes
= js_GetStringBytes(cx
, str
);
248 *va_arg(ap
, const char **) = bytes
;
249 } else if (c
== 'W') {
250 const jschar
*chars
= js_GetStringChars(cx
, str
);
253 *va_arg(ap
, const jschar
**) = chars
;
255 *va_arg(ap
, JSString
**) = str
;
259 if (!js_ValueToObject(cx
, *sp
, &obj
))
261 *sp
= OBJECT_TO_JSVAL(obj
);
262 *va_arg(ap
, JSObject
**) = obj
;
265 obj
= js_ValueToFunctionObject(cx
, sp
, 0);
268 *sp
= OBJECT_TO_JSVAL(obj
);
269 *va_arg(ap
, JSFunction
**) = (JSFunction
*) JS_GetPrivate(cx
, obj
);
272 *va_arg(ap
, jsval
*) = *sp
;
278 if (!TryArgumentFormatter(cx
, &format
, JS_TRUE
, &sp
,
279 JS_ADDRESSOF_VA_LIST(ap
))) {
282 /* NB: the formatter already updated sp, so we continue here. */
290 JS_PUBLIC_API(jsval
*)
291 JS_PushArguments(JSContext
*cx
, void **markp
, const char *format
, ...)
296 va_start(ap
, format
);
297 argv
= JS_PushArgumentsVA(cx
, markp
, format
, ap
);
302 JS_PUBLIC_API(jsval
*)
303 JS_PushArgumentsVA(JSContext
*cx
, void **markp
, const char *format
, va_list ap
)
316 for (cp
= format
; (c
= *cp
) != '\0'; cp
++) {
318 * Count non-space non-star characters as individual jsval arguments.
319 * This may over-allocate stack, but we'll fix below.
321 if (isspace(c
) || c
== '*')
325 sp
= js_AllocStack(cx
, argc
, markp
);
329 while ((c
= *format
++) != '\0') {
330 if (isspace(c
) || c
== '*')
334 *sp
= BOOLEAN_TO_JSVAL((JSBool
) va_arg(ap
, int));
337 *sp
= INT_TO_JSVAL((uint16
) va_arg(ap
, unsigned int));
342 * Use JS_New{Double,Number}Value here and in the next two cases,
343 * not js_New{Double,Number}InRootedValue, as sp may point to an
346 if (!JS_NewNumberValue(cx
, (jsdouble
) va_arg(ap
, int32
), sp
))
350 if (!JS_NewNumberValue(cx
, (jsdouble
) va_arg(ap
, uint32
), sp
))
355 if (!JS_NewDoubleValue(cx
, va_arg(ap
, jsdouble
), sp
))
359 str
= JS_NewStringCopyZ(cx
, va_arg(ap
, char *));
362 *sp
= STRING_TO_JSVAL(str
);
365 str
= JS_NewUCStringCopyZ(cx
, va_arg(ap
, jschar
*));
368 *sp
= STRING_TO_JSVAL(str
);
371 str
= va_arg(ap
, JSString
*);
372 *sp
= STRING_TO_JSVAL(str
);
375 *sp
= OBJECT_TO_JSVAL(va_arg(ap
, JSObject
*));
378 fun
= va_arg(ap
, JSFunction
*);
379 *sp
= fun
? OBJECT_TO_JSVAL(FUN_OBJECT(fun
)) : JSVAL_NULL
;
382 *sp
= va_arg(ap
, jsval
);
386 if (!TryArgumentFormatter(cx
, &format
, JS_FALSE
, &sp
,
387 JS_ADDRESSOF_VA_LIST(ap
))) {
390 /* NB: the formatter already updated sp, so we continue here. */
397 * We may have overallocated stack due to a multi-character format code
398 * handled by a JSArgumentFormatter. Give back that stack space!
400 JS_ASSERT(sp
<= argv
+ argc
);
401 if (sp
< argv
+ argc
) {
402 /* Return slots not pushed to the current stack arena. */
403 cx
->stackPool
.current
->avail
= (jsuword
)sp
;
405 /* Reduce the count of slots the GC will scan in this stack segment. */
406 sh
= cx
->stackHeaders
;
407 JS_ASSERT(JS_STACK_SEGMENT(sh
) + sh
->nslots
== argv
+ argc
);
408 sh
->nslots
-= argc
- (sp
- argv
);
413 js_FreeStack(cx
, *markp
);
418 JS_PopArguments(JSContext
*cx
, void *mark
)
421 js_FreeStack(cx
, mark
);
424 JS_PUBLIC_API(JSBool
)
425 JS_AddArgumentFormatter(JSContext
*cx
, const char *format
,
426 JSArgumentFormatter formatter
)
429 JSArgumentFormatMap
**mpp
, *map
;
431 length
= strlen(format
);
432 mpp
= &cx
->argumentFormatMap
;
433 while ((map
= *mpp
) != NULL
) {
434 /* Insert before any shorter string to match before prefixes. */
435 if (map
->length
< length
)
437 if (map
->length
== length
&& !strcmp(map
->format
, format
))
441 map
= (JSArgumentFormatMap
*) JS_malloc(cx
, sizeof *map
);
444 map
->format
= format
;
445 map
->length
= length
;
449 map
->formatter
= formatter
;
454 JS_RemoveArgumentFormatter(JSContext
*cx
, const char *format
)
457 JSArgumentFormatMap
**mpp
, *map
;
459 length
= strlen(format
);
460 mpp
= &cx
->argumentFormatMap
;
461 while ((map
= *mpp
) != NULL
) {
462 if (map
->length
== length
&& !strcmp(map
->format
, format
)) {
471 JS_PUBLIC_API(JSBool
)
472 JS_ConvertValue(JSContext
*cx
, jsval v
, JSType type
, jsval
*vp
)
486 ok
= js_ValueToObject(cx
, v
, &obj
);
488 *vp
= OBJECT_TO_JSVAL(obj
);
490 case JSTYPE_FUNCTION
:
492 obj
= js_ValueToFunctionObject(cx
, vp
, JSV2F_SEARCH_STACK
);
496 str
= js_ValueToString(cx
, v
);
499 *vp
= STRING_TO_JSVAL(str
);
502 ok
= JS_ValueToNumber(cx
, v
, &d
);
504 dp
= js_NewWeaklyRootedDouble(cx
, d
);
507 *vp
= DOUBLE_TO_JSVAL(dp
);
511 *vp
= BOOLEAN_TO_JSVAL(js_ValueToBoolean(v
));
515 JS_snprintf(numBuf
, sizeof numBuf
, "%d", (int)type
);
516 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_BAD_TYPE
,
525 JS_PUBLIC_API(JSBool
)
526 JS_ValueToObject(JSContext
*cx
, jsval v
, JSObject
**objp
)
529 return js_ValueToObject(cx
, v
, objp
);
532 JS_PUBLIC_API(JSFunction
*)
533 JS_ValueToFunction(JSContext
*cx
, jsval v
)
536 return js_ValueToFunction(cx
, &v
, JSV2F_SEARCH_STACK
);
539 JS_PUBLIC_API(JSFunction
*)
540 JS_ValueToConstructor(JSContext
*cx
, jsval v
)
543 return js_ValueToFunction(cx
, &v
, JSV2F_SEARCH_STACK
);
546 JS_PUBLIC_API(JSString
*)
547 JS_ValueToString(JSContext
*cx
, jsval v
)
550 return js_ValueToString(cx
, v
);
553 JS_PUBLIC_API(JSBool
)
554 JS_ValueToNumber(JSContext
*cx
, jsval v
, jsdouble
*dp
)
556 JSTempValueRooter tvr
;
559 JS_PUSH_SINGLE_TEMP_ROOT(cx
, v
, &tvr
);
560 *dp
= js_ValueToNumber(cx
, &tvr
.u
.value
);
561 JS_POP_TEMP_ROOT(cx
, &tvr
);
562 return !JSVAL_IS_NULL(tvr
.u
.value
);
565 JS_PUBLIC_API(JSBool
)
566 JS_ValueToECMAInt32(JSContext
*cx
, jsval v
, int32
*ip
)
568 JSTempValueRooter tvr
;
571 JS_PUSH_SINGLE_TEMP_ROOT(cx
, v
, &tvr
);
572 *ip
= js_ValueToECMAInt32(cx
, &tvr
.u
.value
);
573 JS_POP_TEMP_ROOT(cx
, &tvr
);
574 return !JSVAL_IS_NULL(tvr
.u
.value
);
577 JS_PUBLIC_API(JSBool
)
578 JS_ValueToECMAUint32(JSContext
*cx
, jsval v
, uint32
*ip
)
580 JSTempValueRooter tvr
;
583 JS_PUSH_SINGLE_TEMP_ROOT(cx
, v
, &tvr
);
584 *ip
= js_ValueToECMAUint32(cx
, &tvr
.u
.value
);
585 JS_POP_TEMP_ROOT(cx
, &tvr
);
586 return !JSVAL_IS_NULL(tvr
.u
.value
);
589 JS_PUBLIC_API(JSBool
)
590 JS_ValueToInt32(JSContext
*cx
, jsval v
, int32
*ip
)
592 JSTempValueRooter tvr
;
595 JS_PUSH_SINGLE_TEMP_ROOT(cx
, v
, &tvr
);
596 *ip
= js_ValueToInt32(cx
, &tvr
.u
.value
);
597 JS_POP_TEMP_ROOT(cx
, &tvr
);
598 return !JSVAL_IS_NULL(tvr
.u
.value
);
601 JS_PUBLIC_API(JSBool
)
602 JS_ValueToUint16(JSContext
*cx
, jsval v
, uint16
*ip
)
604 JSTempValueRooter tvr
;
607 JS_PUSH_SINGLE_TEMP_ROOT(cx
, v
, &tvr
);
608 *ip
= js_ValueToUint16(cx
, &tvr
.u
.value
);
609 JS_POP_TEMP_ROOT(cx
, &tvr
);
610 return !JSVAL_IS_NULL(tvr
.u
.value
);
613 JS_PUBLIC_API(JSBool
)
614 JS_ValueToBoolean(JSContext
*cx
, jsval v
, JSBool
*bp
)
617 *bp
= js_ValueToBoolean(v
);
621 JS_PUBLIC_API(JSType
)
622 JS_TypeOfValue(JSContext
*cx
, jsval v
)
630 if (JSVAL_IS_OBJECT(v
)) {
631 type
= JSTYPE_OBJECT
; /* XXXbe JSTYPE_NULL for JS2 */
632 obj
= JSVAL_TO_OBJECT(v
);
636 wrapped
= js_GetWrappedObject(cx
, obj
);
641 #if JS_HAS_XML_SUPPORT
642 if (ops
== &js_XMLObjectOps
.base
) {
648 * ECMA 262, 11.4.3 says that any native object that implements
649 * [[Call]] should be of type "function". Note that RegExp and
650 * Script are both of type "function" for compatibility with
651 * older SpiderMonkeys.
653 clasp
= OBJ_GET_CLASS(cx
, obj
);
654 if ((ops
== &js_ObjectOps
)
656 ? clasp
== &js_ScriptClass
657 : clasp
== &js_FunctionClass
)
658 : ops
->call
!= NULL
) {
659 type
= JSTYPE_FUNCTION
;
662 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
);
664 if (!OBJ_GET_PROPERTY(cx
, obj
,
665 ATOM_TO_JSID(cx
->runtime
->atomState
668 JS_ClearPendingException(cx
);
669 } else if (VALUE_IS_FUNCTION(cx
, v
)) {
670 type
= JSTYPE_FUNCTION
;
676 } else if (JSVAL_IS_NUMBER(v
)) {
677 type
= JSTYPE_NUMBER
;
678 } else if (JSVAL_IS_STRING(v
)) {
679 type
= JSTYPE_STRING
;
680 } else if (JSVAL_IS_BOOLEAN(v
)) {
681 type
= JSTYPE_BOOLEAN
;
688 JS_PUBLIC_API(const char *)
689 JS_GetTypeName(JSContext
*cx
, JSType type
)
691 if ((uintN
)type
>= (uintN
)JSTYPE_LIMIT
)
693 return JS_TYPE_STR(type
);
696 /************************************************************************/
699 * Has a new runtime ever been created? This flag is used to detect unsafe
700 * changes to js_CStringsAreUTF8 after a runtime has been created, and to
701 * ensure that "first checks" on runtime creation are run only once.
704 static JSBool js_NewRuntimeWasCalled
= JS_FALSE
;
707 JS_PUBLIC_API(JSRuntime
*)
708 JS_NewRuntime(uint32 maxbytes
)
713 if (!js_NewRuntimeWasCalled
) {
715 * This code asserts that the numbers associated with the error names
716 * in jsmsg.def are monotonically increasing. It uses values for the
717 * error names enumerated in jscntxt.c. It's not a compile-time check
718 * but it's better than nothing.
721 #define MSG_DEF(name, number, count, exception, format) \
722 JS_ASSERT(name == errorNumber++);
726 #define MSG_DEF(name, number, count, exception, format) \
728 uintN numfmtspecs = 0; \
730 for (fmt = format; *fmt != '\0'; fmt++) { \
731 if (*fmt == '{' && isdigit(fmt[1])) \
734 JS_ASSERT(count == numfmtspecs); \
739 js_NewRuntimeWasCalled
= JS_TRUE
;
743 rt
= (JSRuntime
*) malloc(sizeof(JSRuntime
));
747 /* Initialize infallibly first, so we can goto bad and JS_DestroyRuntime. */
748 memset(rt
, 0, sizeof(JSRuntime
));
749 JS_INIT_CLIST(&rt
->contextList
);
750 JS_INIT_CLIST(&rt
->trapList
);
751 JS_INIT_CLIST(&rt
->watchPointList
);
755 if (!js_InitGC(rt
, maxbytes
))
757 if (!js_InitAtomState(rt
))
759 if (!js_InitDeflatedStringCache(rt
))
762 if (!js_InitThreadPrivateIndex(js_ThreadDestructorCB
))
764 rt
->gcLock
= JS_NEW_LOCK();
767 rt
->gcDone
= JS_NEW_CONDVAR(rt
->gcLock
);
770 rt
->requestDone
= JS_NEW_CONDVAR(rt
->gcLock
);
771 if (!rt
->requestDone
)
773 /* this is asymmetric with JS_ShutDown: */
774 if (!js_SetupLocks(8, 16))
776 rt
->rtLock
= JS_NEW_LOCK();
779 rt
->stateChange
= JS_NEW_CONDVAR(rt
->gcLock
);
780 if (!rt
->stateChange
)
782 rt
->titleSharingDone
= JS_NEW_CONDVAR(rt
->gcLock
);
783 if (!rt
->titleSharingDone
)
785 rt
->titleSharingTodo
= NO_TITLE_SHARING_TODO
;
786 rt
->debuggerLock
= JS_NEW_LOCK();
787 if (!rt
->debuggerLock
)
790 if (!js_InitPropertyTree(rt
))
793 #if !defined JS_THREADSAFE && defined JS_TRACER
794 js_InitJIT(&rt
->traceMonitor
);
800 JS_DestroyRuntime(rt
);
805 JS_DestroyRuntime(JSRuntime
*rt
)
808 /* Don't hurt everyone in leaky ol' Mozilla with a fatal JS_ASSERT! */
809 if (!JS_CLIST_IS_EMPTY(&rt
->contextList
)) {
810 JSContext
*cx
, *iter
= NULL
;
812 while ((cx
= js_ContextIterator(rt
, JS_TRUE
, &iter
)) != NULL
) {
814 "JS API usage error: found live context at %p\n",
819 "JS API usage error: %u context%s left in runtime upon JS_DestroyRuntime.\n",
820 cxcount
, (cxcount
== 1) ? "" : "s");
824 #if !defined JS_THREADSAFE && defined JS_TRACER
825 js_FinishJIT(&rt
->traceMonitor
);
828 js_FreeRuntimeScriptState(rt
);
829 js_FinishAtomState(rt
);
832 * Free unit string storage only after all strings have been finalized, so
833 * that js_FinalizeString can detect unit strings and avoid calling free
834 * on their chars storage.
836 js_FinishUnitStrings(rt
);
839 * Finish the deflated string cache after the last GC and after
840 * calling js_FinishAtomState, which finalizes strings.
842 js_FinishDeflatedStringCache(rt
);
846 JS_DESTROY_LOCK(rt
->gcLock
);
848 JS_DESTROY_CONDVAR(rt
->gcDone
);
850 JS_DESTROY_CONDVAR(rt
->requestDone
);
852 JS_DESTROY_LOCK(rt
->rtLock
);
854 JS_DESTROY_CONDVAR(rt
->stateChange
);
855 if (rt
->titleSharingDone
)
856 JS_DESTROY_CONDVAR(rt
->titleSharingDone
);
857 if (rt
->debuggerLock
)
858 JS_DESTROY_LOCK(rt
->debuggerLock
);
860 GSN_CACHE_CLEAR(&rt
->gsnCache
);
862 js_FinishPropertyTree(rt
);
870 extern void js_DumpOpMeters();
882 JS_PUBLIC_API(void *)
883 JS_GetRuntimePrivate(JSRuntime
*rt
)
889 JS_SetRuntimePrivate(JSRuntime
*rt
, void *data
)
895 JS_BeginRequest(JSContext
*cx
)
900 JS_ASSERT(cx
->thread
->id
== js_CurrentThreadId());
901 if (!cx
->requestDepth
) {
902 JS_ASSERT(cx
->gcLocalFreeLists
== &js_GCEmptyFreeListSet
);
904 /* Wait until the GC is finished. */
908 /* NB: we use cx->thread here, not js_GetCurrentThread(). */
909 if (rt
->gcThread
!= cx
->thread
) {
910 while (rt
->gcLevel
> 0)
911 JS_AWAIT_GC_DONE(rt
);
914 /* Indicate that a request is running. */
916 cx
->requestDepth
= 1;
917 cx
->outstandingRequests
++;
922 cx
->outstandingRequests
++;
927 JS_EndRequest(JSContext
*cx
)
931 JSTitle
*title
, **todop
;
935 JS_ASSERT(cx
->requestDepth
> 0);
936 JS_ASSERT(cx
->outstandingRequests
> 0);
937 if (cx
->requestDepth
== 1) {
938 /* Lock before clearing to interlock with ClaimScope, in jslock.c. */
941 cx
->requestDepth
= 0;
942 cx
->outstandingRequests
--;
944 /* See whether cx has any single-threaded titles to start sharing. */
945 todop
= &rt
->titleSharingTodo
;
947 while ((title
= *todop
) != NO_TITLE_SHARING_TODO
) {
948 if (title
->ownercx
!= cx
) {
949 todop
= &title
->u
.link
;
952 *todop
= title
->u
.link
;
953 title
->u
.link
= NULL
; /* null u.link for sanity ASAP */
956 * If js_DropObjectMap returns null, we held the last ref to scope.
957 * The waiting thread(s) must have been killed, after which the GC
958 * collected the object that held this scope. Unlikely, because it
959 * requires that the GC ran (e.g., from an operation callback)
960 * during this request, but possible.
962 if (js_DropObjectMap(cx
, TITLE_TO_MAP(title
), NULL
)) {
963 js_InitLock(&title
->lock
);
964 title
->u
.count
= 0; /* NULL may not pun as 0 */
965 js_FinishSharingTitle(cx
, title
); /* set ownercx = NULL */
970 JS_NOTIFY_ALL_CONDVAR(rt
->titleSharingDone
);
972 js_RevokeGCLocalFreeLists(cx
);
974 /* Give the GC a chance to run if this was the last request running. */
975 JS_ASSERT(rt
->requestCount
> 0);
977 if (rt
->requestCount
== 0)
978 JS_NOTIFY_REQUEST_DONE(rt
);
985 cx
->outstandingRequests
--;
989 /* Yield to pending GC operations, regardless of request depth */
991 JS_YieldRequest(JSContext
*cx
)
994 JS_ASSERT(cx
->thread
);
996 JS_ResumeRequest(cx
, JS_SuspendRequest(cx
));
1000 JS_PUBLIC_API(jsrefcount
)
1001 JS_SuspendRequest(JSContext
*cx
)
1003 #ifdef JS_THREADSAFE
1004 jsrefcount saveDepth
= cx
->requestDepth
;
1006 while (cx
->requestDepth
) {
1007 cx
->outstandingRequests
++; /* compensate for JS_EndRequest */
1017 JS_ResumeRequest(JSContext
*cx
, jsrefcount saveDepth
)
1019 #ifdef JS_THREADSAFE
1020 JS_ASSERT(!cx
->requestDepth
);
1021 while (--saveDepth
>= 0) {
1022 JS_BeginRequest(cx
);
1023 cx
->outstandingRequests
--; /* compensate for JS_BeginRequest */
1029 JS_Lock(JSRuntime
*rt
)
1031 JS_LOCK_RUNTIME(rt
);
1035 JS_Unlock(JSRuntime
*rt
)
1037 JS_UNLOCK_RUNTIME(rt
);
1040 JS_PUBLIC_API(JSContextCallback
)
1041 JS_SetContextCallback(JSRuntime
*rt
, JSContextCallback cxCallback
)
1043 JSContextCallback old
;
1045 old
= rt
->cxCallback
;
1046 rt
->cxCallback
= cxCallback
;
1050 JS_PUBLIC_API(JSContext
*)
1051 JS_NewContext(JSRuntime
*rt
, size_t stackChunkSize
)
1053 return js_NewContext(rt
, stackChunkSize
);
1057 JS_DestroyContext(JSContext
*cx
)
1059 js_DestroyContext(cx
, JSDCM_FORCE_GC
);
1063 JS_DestroyContextNoGC(JSContext
*cx
)
1065 js_DestroyContext(cx
, JSDCM_NO_GC
);
1069 JS_DestroyContextMaybeGC(JSContext
*cx
)
1071 js_DestroyContext(cx
, JSDCM_MAYBE_GC
);
1074 JS_PUBLIC_API(void *)
1075 JS_GetContextPrivate(JSContext
*cx
)
1081 JS_SetContextPrivate(JSContext
*cx
, void *data
)
1086 JS_PUBLIC_API(JSRuntime
*)
1087 JS_GetRuntime(JSContext
*cx
)
1092 JS_PUBLIC_API(JSContext
*)
1093 JS_ContextIterator(JSRuntime
*rt
, JSContext
**iterp
)
1095 return js_ContextIterator(rt
, JS_TRUE
, iterp
);
1098 JS_PUBLIC_API(JSVersion
)
1099 JS_GetVersion(JSContext
*cx
)
1101 return JSVERSION_NUMBER(cx
);
1104 JS_PUBLIC_API(JSVersion
)
1105 JS_SetVersion(JSContext
*cx
, JSVersion version
)
1107 JSVersion oldVersion
;
1109 JS_ASSERT(version
!= JSVERSION_UNKNOWN
);
1110 JS_ASSERT((version
& ~JSVERSION_MASK
) == 0);
1112 oldVersion
= JSVERSION_NUMBER(cx
);
1113 if (version
== oldVersion
)
1116 /* We no longer support 1.4 or below. */
1117 if (version
!= JSVERSION_DEFAULT
&& version
<= JSVERSION_1_4
)
1120 cx
->version
= (cx
->version
& ~JSVERSION_MASK
) | version
;
1121 js_OnVersionChange(cx
);
1125 static struct v2smap
{
1129 {JSVERSION_1_0
, "1.0"},
1130 {JSVERSION_1_1
, "1.1"},
1131 {JSVERSION_1_2
, "1.2"},
1132 {JSVERSION_1_3
, "1.3"},
1133 {JSVERSION_1_4
, "1.4"},
1134 {JSVERSION_ECMA_3
, "ECMAv3"},
1135 {JSVERSION_1_5
, "1.5"},
1136 {JSVERSION_1_6
, "1.6"},
1137 {JSVERSION_1_7
, "1.7"},
1138 {JSVERSION_1_8
, "1.8"},
1139 {JSVERSION_DEFAULT
, js_default_str
},
1140 {JSVERSION_UNKNOWN
, NULL
}, /* must be last, NULL is sentinel */
1143 JS_PUBLIC_API(const char *)
1144 JS_VersionToString(JSVersion version
)
1148 for (i
= 0; v2smap
[i
].string
; i
++)
1149 if (v2smap
[i
].version
== version
)
1150 return v2smap
[i
].string
;
1154 JS_PUBLIC_API(JSVersion
)
1155 JS_StringToVersion(const char *string
)
1159 for (i
= 0; v2smap
[i
].string
; i
++)
1160 if (strcmp(v2smap
[i
].string
, string
) == 0)
1161 return v2smap
[i
].version
;
1162 return JSVERSION_UNKNOWN
;
1165 JS_PUBLIC_API(uint32
)
1166 JS_GetOptions(JSContext
*cx
)
1171 #define SYNC_OPTIONS_TO_VERSION(cx) \
1173 if ((cx)->options & JSOPTION_XML) \
1174 (cx)->version |= JSVERSION_HAS_XML; \
1176 (cx)->version &= ~JSVERSION_HAS_XML; \
1179 JS_PUBLIC_API(uint32
)
1180 JS_SetOptions(JSContext
*cx
, uint32 options
)
1182 uint32 oldopts
= cx
->options
;
1183 cx
->options
= options
;
1184 SYNC_OPTIONS_TO_VERSION(cx
);
1188 JS_PUBLIC_API(uint32
)
1189 JS_ToggleOptions(JSContext
*cx
, uint32 options
)
1191 uint32 oldopts
= cx
->options
;
1192 cx
->options
^= options
;
1193 SYNC_OPTIONS_TO_VERSION(cx
);
1197 JS_PUBLIC_API(const char *)
1198 JS_GetImplementationVersion(void)
1200 return "JavaScript-C 1.8.0 pre-release 1 2007-10-03";
1204 JS_PUBLIC_API(JSObject
*)
1205 JS_GetGlobalObject(JSContext
*cx
)
1207 return cx
->globalObject
;
1211 JS_SetGlobalObject(JSContext
*cx
, JSObject
*obj
)
1213 cx
->globalObject
= obj
;
1215 #if JS_HAS_XML_SUPPORT
1216 cx
->xmlSettingFlags
= 0;
1223 js_InitFunctionAndObjectClasses(JSContext
*cx
, JSObject
*obj
)
1225 JSDHashTable
*table
;
1229 JSResolvingEntry
*entry
;
1230 JSObject
*fun_proto
, *obj_proto
;
1232 /* If cx has no global object, use obj so prototypes can be found. */
1233 if (!cx
->globalObject
)
1234 JS_SetGlobalObject(cx
, obj
);
1236 /* Record Function and Object in cx->resolvingTable, if we are resolving. */
1237 table
= cx
->resolvingTable
;
1238 resolving
= (table
&& table
->entryCount
);
1242 key
.id
= ATOM_TO_JSID(rt
->atomState
.classAtoms
[JSProto_Function
]);
1243 entry
= (JSResolvingEntry
*)
1244 JS_DHashTableOperate(table
, &key
, JS_DHASH_ADD
);
1245 if (entry
&& entry
->key
.obj
&& (entry
->flags
& JSRESFLAG_LOOKUP
)) {
1246 /* Already resolving Function, record Object too. */
1247 JS_ASSERT(entry
->key
.obj
== obj
);
1248 key
.id
= ATOM_TO_JSID(rt
->atomState
.classAtoms
[JSProto_Object
]);
1249 entry
= (JSResolvingEntry
*)
1250 JS_DHashTableOperate(table
, &key
, JS_DHASH_ADD
);
1253 JS_ReportOutOfMemory(cx
);
1256 JS_ASSERT(!entry
->key
.obj
&& entry
->flags
== 0);
1258 entry
->flags
= JSRESFLAG_LOOKUP
;
1260 key
.id
= ATOM_TO_JSID(rt
->atomState
.classAtoms
[JSProto_Object
]);
1261 if (!js_StartResolving(cx
, &key
, JSRESFLAG_LOOKUP
, &entry
))
1264 key
.id
= ATOM_TO_JSID(rt
->atomState
.classAtoms
[JSProto_Function
]);
1265 if (!js_StartResolving(cx
, &key
, JSRESFLAG_LOOKUP
, &entry
)) {
1266 key
.id
= ATOM_TO_JSID(rt
->atomState
.classAtoms
[JSProto_Object
]);
1267 JS_DHashTableOperate(table
, &key
, JS_DHASH_REMOVE
);
1271 table
= cx
->resolvingTable
;
1274 /* Initialize the function class first so constructors can be made. */
1275 if (!js_GetClassPrototype(cx
, obj
, INT_TO_JSID(JSProto_Function
),
1281 fun_proto
= js_InitFunctionClass(cx
, obj
);
1287 ctor
= JS_GetConstructor(cx
, fun_proto
);
1292 OBJ_DEFINE_PROPERTY(cx
, obj
, ATOM_TO_JSID(CLASS_ATOM(cx
, Function
)),
1293 OBJECT_TO_JSVAL(ctor
), 0, 0, 0, NULL
);
1296 /* Initialize the object class next so Object.prototype works. */
1297 if (!js_GetClassPrototype(cx
, obj
, INT_TO_JSID(JSProto_Object
),
1303 obj_proto
= js_InitObjectClass(cx
, obj
);
1309 /* Function.prototype and the global object delegate to Object.prototype. */
1310 OBJ_SET_PROTO(cx
, fun_proto
, obj_proto
);
1311 if (!OBJ_GET_PROTO(cx
, obj
))
1312 OBJ_SET_PROTO(cx
, obj
, obj_proto
);
1315 /* If resolving, remove the other entry (Object or Function) from table. */
1316 JS_DHashTableOperate(table
, &key
, JS_DHASH_REMOVE
);
1318 /* If not resolving, remove the first entry added above, for Object. */
1319 JS_ASSERT(key
.id
== \
1320 ATOM_TO_JSID(rt
->atomState
.classAtoms
[JSProto_Function
]));
1321 key
.id
= ATOM_TO_JSID(rt
->atomState
.classAtoms
[JSProto_Object
]);
1322 JS_DHashTableOperate(table
, &key
, JS_DHASH_REMOVE
);
1329 JS_PUBLIC_API(JSBool
)
1330 JS_InitStandardClasses(JSContext
*cx
, JSObject
*obj
)
1336 /* Define a top-level property 'undefined' with the undefined value. */
1337 atom
= cx
->runtime
->atomState
.typeAtoms
[JSTYPE_VOID
];
1338 if (!OBJ_DEFINE_PROPERTY(cx
, obj
, ATOM_TO_JSID(atom
), JSVAL_VOID
,
1339 NULL
, NULL
, JSPROP_PERMANENT
, NULL
)) {
1343 /* Function and Object require cooperative bootstrapping magic. */
1344 if (!js_InitFunctionAndObjectClasses(cx
, obj
))
1347 /* Initialize the rest of the standard objects and functions. */
1348 return js_InitArrayClass(cx
, obj
) &&
1349 js_InitBlockClass(cx
, obj
) &&
1350 js_InitBooleanClass(cx
, obj
) &&
1351 js_InitCallClass(cx
, obj
) &&
1352 js_InitExceptionClasses(cx
, obj
) &&
1353 js_InitMathClass(cx
, obj
) &&
1354 js_InitNumberClass(cx
, obj
) &&
1355 js_InitJSONClass(cx
, obj
) &&
1356 js_InitRegExpClass(cx
, obj
) &&
1357 js_InitStringClass(cx
, obj
) &&
1358 js_InitEval(cx
, obj
) &&
1359 #if JS_HAS_SCRIPT_OBJECT
1360 js_InitScriptClass(cx
, obj
) &&
1362 #if JS_HAS_XML_SUPPORT
1363 js_InitXMLClasses(cx
, obj
) &&
1365 #if JS_HAS_FILE_OBJECT
1366 js_InitFileClass(cx
, obj
) &&
1368 #if JS_HAS_GENERATORS
1369 js_InitIteratorClasses(cx
, obj
) &&
1371 js_InitDateClass(cx
, obj
);
1374 #define CLASP(name) (&js_##name##Class)
1375 #define EXT_CLASP(name) (&js_##name##Class.base)
1376 #define EAGER_ATOM(name) ATOM_OFFSET(name), NULL
1377 #define EAGER_CLASS_ATOM(name) CLASS_ATOM_OFFSET(name), NULL
1378 #define EAGER_ATOM_AND_CLASP(name) EAGER_CLASS_ATOM(name), CLASP(name)
1379 #define EAGER_ATOM_AND_EXT_CLASP(name) EAGER_CLASS_ATOM(name), EXT_CLASP(name)
1380 #define LAZY_ATOM(name) ATOM_OFFSET(lazy.name), js_##name##_str
1382 typedef struct JSStdName
{
1384 size_t atomOffset
; /* offset of atom pointer in JSAtomState */
1385 const char *name
; /* null if atom is pre-pinned, else name */
1390 StdNameToAtom(JSContext
*cx
, JSStdName
*stdn
)
1396 offset
= stdn
->atomOffset
;
1397 atom
= OFFSET_TO_ATOM(cx
->runtime
, offset
);
1401 atom
= js_Atomize(cx
, name
, strlen(name
), ATOM_PINNED
);
1402 OFFSET_TO_ATOM(cx
->runtime
, offset
) = atom
;
1409 * Table of class initializers and their atom offsets in rt->atomState.
1410 * If you add a "standard" class, remember to update this table.
1412 static JSStdName standard_class_atoms
[] = {
1413 {js_InitFunctionAndObjectClasses
, EAGER_ATOM_AND_CLASP(Function
)},
1414 {js_InitFunctionAndObjectClasses
, EAGER_ATOM_AND_CLASP(Object
)},
1415 {js_InitArrayClass
, EAGER_ATOM_AND_CLASP(Array
)},
1416 {js_InitBlockClass
, EAGER_ATOM_AND_CLASP(Block
)},
1417 {js_InitBooleanClass
, EAGER_ATOM_AND_CLASP(Boolean
)},
1418 {js_InitDateClass
, EAGER_ATOM_AND_CLASP(Date
)},
1419 {js_InitMathClass
, EAGER_ATOM_AND_CLASP(Math
)},
1420 {js_InitNumberClass
, EAGER_ATOM_AND_CLASP(Number
)},
1421 {js_InitStringClass
, EAGER_ATOM_AND_CLASP(String
)},
1422 {js_InitCallClass
, EAGER_ATOM_AND_CLASP(Call
)},
1423 {js_InitExceptionClasses
, EAGER_ATOM_AND_CLASP(Error
)},
1424 {js_InitRegExpClass
, EAGER_ATOM_AND_CLASP(RegExp
)},
1425 #if JS_HAS_SCRIPT_OBJECT
1426 {js_InitScriptClass
, EAGER_ATOM_AND_CLASP(Script
)},
1428 #if JS_HAS_XML_SUPPORT
1429 {js_InitXMLClass
, EAGER_ATOM_AND_CLASP(XML
)},
1430 {js_InitNamespaceClass
, EAGER_ATOM_AND_EXT_CLASP(Namespace
)},
1431 {js_InitQNameClass
, EAGER_ATOM_AND_EXT_CLASP(QName
)},
1433 #if JS_HAS_FILE_OBJECT
1434 {js_InitFileClass
, EAGER_ATOM_AND_CLASP(File
)},
1436 #if JS_HAS_GENERATORS
1437 {js_InitIteratorClasses
, EAGER_ATOM_AND_CLASP(StopIteration
)},
1439 {js_InitJSONClass
, EAGER_ATOM_AND_CLASP(JSON
)},
1440 {NULL
, 0, NULL
, NULL
}
1444 * Table of top-level function and constant names and their init functions.
1445 * If you add a "standard" global function or property, remember to update
1448 static JSStdName standard_class_names
[] = {
1449 /* ECMA requires that eval be a direct property of the global object. */
1450 {js_InitEval
, EAGER_ATOM(eval
), NULL
},
1452 /* Global properties and functions defined by the Number class. */
1453 {js_InitNumberClass
, LAZY_ATOM(NaN
), NULL
},
1454 {js_InitNumberClass
, LAZY_ATOM(Infinity
), NULL
},
1455 {js_InitNumberClass
, LAZY_ATOM(isNaN
), NULL
},
1456 {js_InitNumberClass
, LAZY_ATOM(isFinite
), NULL
},
1457 {js_InitNumberClass
, LAZY_ATOM(parseFloat
), NULL
},
1458 {js_InitNumberClass
, LAZY_ATOM(parseInt
), NULL
},
1460 /* String global functions. */
1461 {js_InitStringClass
, LAZY_ATOM(escape
), NULL
},
1462 {js_InitStringClass
, LAZY_ATOM(unescape
), NULL
},
1463 {js_InitStringClass
, LAZY_ATOM(decodeURI
), NULL
},
1464 {js_InitStringClass
, LAZY_ATOM(encodeURI
), NULL
},
1465 {js_InitStringClass
, LAZY_ATOM(decodeURIComponent
), NULL
},
1466 {js_InitStringClass
, LAZY_ATOM(encodeURIComponent
), NULL
},
1468 {js_InitStringClass
, LAZY_ATOM(uneval
), NULL
},
1471 /* Exception constructors. */
1472 {js_InitExceptionClasses
, EAGER_CLASS_ATOM(Error
), CLASP(Error
)},
1473 {js_InitExceptionClasses
, EAGER_CLASS_ATOM(InternalError
), CLASP(Error
)},
1474 {js_InitExceptionClasses
, EAGER_CLASS_ATOM(EvalError
), CLASP(Error
)},
1475 {js_InitExceptionClasses
, EAGER_CLASS_ATOM(RangeError
), CLASP(Error
)},
1476 {js_InitExceptionClasses
, EAGER_CLASS_ATOM(ReferenceError
), CLASP(Error
)},
1477 {js_InitExceptionClasses
, EAGER_CLASS_ATOM(SyntaxError
), CLASP(Error
)},
1478 {js_InitExceptionClasses
, EAGER_CLASS_ATOM(TypeError
), CLASP(Error
)},
1479 {js_InitExceptionClasses
, EAGER_CLASS_ATOM(URIError
), CLASP(Error
)},
1481 #if JS_HAS_XML_SUPPORT
1482 {js_InitAnyNameClass
, EAGER_ATOM_AND_CLASP(AnyName
)},
1483 {js_InitAttributeNameClass
, EAGER_ATOM_AND_CLASP(AttributeName
)},
1484 {js_InitXMLClass
, LAZY_ATOM(XMLList
), &js_XMLClass
},
1485 {js_InitXMLClass
, LAZY_ATOM(isXMLName
), NULL
},
1488 #if JS_HAS_GENERATORS
1489 {js_InitIteratorClasses
, EAGER_ATOM_AND_CLASP(Iterator
)},
1490 {js_InitIteratorClasses
, EAGER_ATOM_AND_CLASP(Generator
)},
1493 {NULL
, 0, NULL
, NULL
}
1496 static JSStdName object_prototype_names
[] = {
1497 /* Object.prototype properties (global delegates to Object.prototype). */
1498 {js_InitObjectClass
, EAGER_ATOM(proto
), NULL
},
1499 {js_InitObjectClass
, EAGER_ATOM(parent
), NULL
},
1500 {js_InitObjectClass
, EAGER_ATOM(count
), NULL
},
1502 {js_InitObjectClass
, EAGER_ATOM(toSource
), NULL
},
1504 {js_InitObjectClass
, EAGER_ATOM(toString
), NULL
},
1505 {js_InitObjectClass
, EAGER_ATOM(toLocaleString
), NULL
},
1506 {js_InitObjectClass
, EAGER_ATOM(valueOf
), NULL
},
1507 #if JS_HAS_OBJ_WATCHPOINT
1508 {js_InitObjectClass
, LAZY_ATOM(watch
), NULL
},
1509 {js_InitObjectClass
, LAZY_ATOM(unwatch
), NULL
},
1511 {js_InitObjectClass
, LAZY_ATOM(hasOwnProperty
), NULL
},
1512 {js_InitObjectClass
, LAZY_ATOM(isPrototypeOf
), NULL
},
1513 {js_InitObjectClass
, LAZY_ATOM(propertyIsEnumerable
), NULL
},
1514 #if JS_HAS_GETTER_SETTER
1515 {js_InitObjectClass
, LAZY_ATOM(defineGetter
), NULL
},
1516 {js_InitObjectClass
, LAZY_ATOM(defineSetter
), NULL
},
1517 {js_InitObjectClass
, LAZY_ATOM(lookupGetter
), NULL
},
1518 {js_InitObjectClass
, LAZY_ATOM(lookupSetter
), NULL
},
1521 {NULL
, 0, NULL
, NULL
}
1524 JS_PUBLIC_API(JSBool
)
1525 JS_ResolveStandardClass(JSContext
*cx
, JSObject
*obj
, jsval id
,
1535 *resolved
= JS_FALSE
;
1538 JS_ASSERT(rt
->state
!= JSRTS_DOWN
);
1539 if (rt
->state
== JSRTS_LANDING
|| !JSVAL_IS_STRING(id
))
1542 idstr
= JSVAL_TO_STRING(id
);
1544 /* Check whether we're resolving 'undefined', and define it if so. */
1545 atom
= rt
->atomState
.typeAtoms
[JSTYPE_VOID
];
1546 if (idstr
== ATOM_TO_STRING(atom
)) {
1547 *resolved
= JS_TRUE
;
1548 return OBJ_DEFINE_PROPERTY(cx
, obj
, ATOM_TO_JSID(atom
), JSVAL_VOID
,
1549 NULL
, NULL
, JSPROP_PERMANENT
, NULL
);
1552 /* Try for class constructors/prototypes named by well-known atoms. */
1554 for (i
= 0; standard_class_atoms
[i
].init
; i
++) {
1555 atom
= OFFSET_TO_ATOM(rt
, standard_class_atoms
[i
].atomOffset
);
1556 if (idstr
== ATOM_TO_STRING(atom
)) {
1557 stdnm
= &standard_class_atoms
[i
];
1563 /* Try less frequently used top-level functions and constants. */
1564 for (i
= 0; standard_class_names
[i
].init
; i
++) {
1565 atom
= StdNameToAtom(cx
, &standard_class_names
[i
]);
1568 if (idstr
== ATOM_TO_STRING(atom
)) {
1569 stdnm
= &standard_class_names
[i
];
1574 if (!stdnm
&& !OBJ_GET_PROTO(cx
, obj
)) {
1576 * Try even less frequently used names delegated from the global
1577 * object to Object.prototype, but only if the Object class hasn't
1578 * yet been initialized.
1580 for (i
= 0; object_prototype_names
[i
].init
; i
++) {
1581 atom
= StdNameToAtom(cx
, &object_prototype_names
[i
]);
1584 if (idstr
== ATOM_TO_STRING(atom
)) {
1585 stdnm
= &standard_class_names
[i
];
1594 * If this standard class is anonymous and obj advertises itself as a
1595 * global object (in order to reserve slots for standard class object
1596 * pointers), then we don't want to resolve by name.
1598 * If inversely, either id does not name a class, or id does not name
1599 * an anonymous class, or the global does not reserve slots for class
1600 * objects, then we must call the init hook here.
1603 (stdnm
->clasp
->flags
& JSCLASS_IS_ANONYMOUS
) &&
1604 (OBJ_GET_CLASS(cx
, obj
)->flags
& JSCLASS_IS_GLOBAL
)) {
1608 if (!stdnm
->init(cx
, obj
))
1610 *resolved
= JS_TRUE
;
1616 AlreadyHasOwnProperty(JSContext
*cx
, JSObject
*obj
, JSAtom
*atom
)
1618 JSScopeProperty
*sprop
;
1621 JS_ASSERT(OBJ_IS_NATIVE(obj
));
1622 JS_LOCK_OBJ(cx
, obj
);
1623 scope
= OBJ_SCOPE(obj
);
1624 sprop
= SCOPE_GET_PROPERTY(scope
, ATOM_TO_JSID(atom
));
1625 JS_UNLOCK_SCOPE(cx
, scope
);
1626 return sprop
!= NULL
;
1629 JS_PUBLIC_API(JSBool
)
1630 JS_EnumerateStandardClasses(JSContext
*cx
, JSObject
*obj
)
1639 /* Check whether we need to bind 'undefined' and define it if so. */
1640 atom
= rt
->atomState
.typeAtoms
[JSTYPE_VOID
];
1641 if (!AlreadyHasOwnProperty(cx
, obj
, atom
) &&
1642 !OBJ_DEFINE_PROPERTY(cx
, obj
, ATOM_TO_JSID(atom
), JSVAL_VOID
,
1643 NULL
, NULL
, JSPROP_PERMANENT
, NULL
)) {
1647 /* Initialize any classes that have not been resolved yet. */
1648 for (i
= 0; standard_class_atoms
[i
].init
; i
++) {
1649 atom
= OFFSET_TO_ATOM(rt
, standard_class_atoms
[i
].atomOffset
);
1650 if (!AlreadyHasOwnProperty(cx
, obj
, atom
) &&
1651 !standard_class_atoms
[i
].init(cx
, obj
)) {
1660 NewIdArray(JSContext
*cx
, jsint length
)
1665 JS_malloc(cx
, offsetof(JSIdArray
, vector
) + length
* sizeof(jsval
));
1667 ida
->length
= length
;
1672 * Unlike realloc(3), this function frees ida on failure.
1675 SetIdArrayLength(JSContext
*cx
, JSIdArray
*ida
, jsint length
)
1679 rida
= (JSIdArray
*)
1681 offsetof(JSIdArray
, vector
) + length
* sizeof(jsval
));
1683 JS_DestroyIdArray(cx
, ida
);
1685 rida
->length
= length
;
1690 AddAtomToArray(JSContext
*cx
, JSAtom
*atom
, JSIdArray
*ida
, jsint
*ip
)
1695 length
= ida
->length
;
1697 ida
= SetIdArrayLength(cx
, ida
, JS_MAX(length
* 2, 8));
1700 JS_ASSERT(i
< ida
->length
);
1702 ida
->vector
[i
] = ATOM_TO_JSID(atom
);
1708 EnumerateIfResolved(JSContext
*cx
, JSObject
*obj
, JSAtom
*atom
, JSIdArray
*ida
,
1709 jsint
*ip
, JSBool
*foundp
)
1711 *foundp
= AlreadyHasOwnProperty(cx
, obj
, atom
);
1713 ida
= AddAtomToArray(cx
, atom
, ida
, ip
);
1717 JS_PUBLIC_API(JSIdArray
*)
1718 JS_EnumerateResolvedStandardClasses(JSContext
*cx
, JSObject
*obj
,
1732 ida
= NewIdArray(cx
, 8);
1738 /* Check whether 'undefined' has been resolved and enumerate it if so. */
1739 atom
= rt
->atomState
.typeAtoms
[JSTYPE_VOID
];
1740 ida
= EnumerateIfResolved(cx
, obj
, atom
, ida
, &i
, &found
);
1744 /* Enumerate only classes that *have* been resolved. */
1745 for (j
= 0; standard_class_atoms
[j
].init
; j
++) {
1746 atom
= OFFSET_TO_ATOM(rt
, standard_class_atoms
[j
].atomOffset
);
1747 ida
= EnumerateIfResolved(cx
, obj
, atom
, ida
, &i
, &found
);
1752 init
= standard_class_atoms
[j
].init
;
1754 for (k
= 0; standard_class_names
[k
].init
; k
++) {
1755 if (standard_class_names
[k
].init
== init
) {
1756 atom
= StdNameToAtom(cx
, &standard_class_names
[k
]);
1757 ida
= AddAtomToArray(cx
, atom
, ida
, &i
);
1763 if (init
== js_InitObjectClass
) {
1764 for (k
= 0; object_prototype_names
[k
].init
; k
++) {
1765 atom
= StdNameToAtom(cx
, &object_prototype_names
[k
]);
1766 ida
= AddAtomToArray(cx
, atom
, ida
, &i
);
1774 /* Trim to exact length. */
1775 return SetIdArrayLength(cx
, ida
, i
);
1780 #undef EAGER_CLASS_ATOM
1781 #undef EAGER_ATOM_CLASP
1784 JS_PUBLIC_API(JSBool
)
1785 JS_GetClassObject(JSContext
*cx
, JSObject
*obj
, JSProtoKey key
,
1789 return js_GetClassObject(cx
, obj
, key
, objp
);
1792 JS_PUBLIC_API(JSObject
*)
1793 JS_GetScopeChain(JSContext
*cx
)
1801 * There is no code active on this context. In place of an actual
1802 * scope chain, use the context's global object, which is set in
1803 * js_InitFunctionAndObjectClasses, and which represents the default
1804 * scope chain for the embedding. See also js_FindClassObject.
1806 * For embeddings that use the inner and outer object hooks, the inner
1807 * object represents the ultimate global object, with the outer object
1808 * acting as a stand-in.
1810 JSObject
*obj
= cx
->globalObject
;
1812 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_INACTIVE
);
1816 OBJ_TO_INNER_OBJECT(cx
, obj
);
1819 return js_GetScopeChain(cx
, fp
);
1822 JS_PUBLIC_API(JSObject
*)
1823 JS_GetGlobalForObject(JSContext
*cx
, JSObject
*obj
)
1827 while ((parent
= OBJ_GET_PARENT(cx
, obj
)) != NULL
)
1832 JS_PUBLIC_API(jsval
)
1833 JS_ComputeThis(JSContext
*cx
, jsval
*vp
)
1835 if (!js_ComputeThis(cx
, JS_FALSE
, vp
+ 2))
1840 JS_PUBLIC_API(void *)
1841 JS_malloc(JSContext
*cx
, size_t nbytes
)
1845 JS_ASSERT(nbytes
!= 0);
1846 JS_COUNT_OPERATION(cx
, JSOW_ALLOCATION
);
1852 JS_ReportOutOfMemory(cx
);
1855 js_UpdateMallocCounter(cx
, nbytes
);
1860 JS_PUBLIC_API(void *)
1861 JS_realloc(JSContext
*cx
, void *p
, size_t nbytes
)
1863 JS_COUNT_OPERATION(cx
, JSOW_ALLOCATION
);
1864 p
= realloc(p
, nbytes
);
1866 JS_ReportOutOfMemory(cx
);
1871 JS_free(JSContext
*cx
, void *p
)
1877 JS_PUBLIC_API(char *)
1878 JS_strdup(JSContext
*cx
, const char *s
)
1884 p
= JS_malloc(cx
, n
);
1887 return (char *)memcpy(p
, s
, n
);
1890 JS_PUBLIC_API(jsdouble
*)
1891 JS_NewDouble(JSContext
*cx
, jsdouble d
)
1894 return js_NewWeaklyRootedDouble(cx
, d
);
1897 JS_PUBLIC_API(JSBool
)
1898 JS_NewDoubleValue(JSContext
*cx
, jsdouble d
, jsval
*rval
)
1903 dp
= js_NewWeaklyRootedDouble(cx
, d
);
1906 *rval
= DOUBLE_TO_JSVAL(dp
);
1910 JS_PUBLIC_API(JSBool
)
1911 JS_NewNumberValue(JSContext
*cx
, jsdouble d
, jsval
*rval
)
1916 if (JSDOUBLE_IS_INT(d
, i
) && INT_FITS_IN_JSVAL(i
)) {
1917 *rval
= INT_TO_JSVAL(i
);
1920 return JS_NewDoubleValue(cx
, d
, rval
);
1924 JS_PUBLIC_API(JSBool
)
1925 JS_AddRoot(JSContext
*cx
, void *rp
)
1928 return js_AddRoot(cx
, rp
, NULL
);
1931 JS_PUBLIC_API(JSBool
)
1932 JS_AddNamedRootRT(JSRuntime
*rt
, void *rp
, const char *name
)
1934 return js_AddRootRT(rt
, rp
, name
);
1937 JS_PUBLIC_API(JSBool
)
1938 JS_RemoveRoot(JSContext
*cx
, void *rp
)
1941 return js_RemoveRoot(cx
->runtime
, rp
);
1944 JS_PUBLIC_API(JSBool
)
1945 JS_RemoveRootRT(JSRuntime
*rt
, void *rp
)
1947 return js_RemoveRoot(rt
, rp
);
1950 JS_PUBLIC_API(JSBool
)
1951 JS_AddNamedRoot(JSContext
*cx
, void *rp
, const char *name
)
1954 return js_AddRoot(cx
, rp
, name
);
1958 JS_ClearNewbornRoots(JSContext
*cx
)
1960 JS_CLEAR_WEAK_ROOTS(&cx
->weakRoots
);
1963 JS_PUBLIC_API(JSBool
)
1964 JS_EnterLocalRootScope(JSContext
*cx
)
1967 return js_EnterLocalRootScope(cx
);
1971 JS_LeaveLocalRootScope(JSContext
*cx
)
1974 js_LeaveLocalRootScope(cx
);
1978 JS_LeaveLocalRootScopeWithResult(JSContext
*cx
, jsval rval
)
1981 js_LeaveLocalRootScopeWithResult(cx
, rval
);
1985 JS_ForgetLocalRoot(JSContext
*cx
, void *thing
)
1988 js_ForgetLocalRoot(cx
, (jsval
) thing
);
1994 JS_DumpNamedRoots(JSRuntime
*rt
,
1995 void (*dump
)(const char *name
, void *rp
, void *data
),
1998 js_DumpNamedRoots(rt
, dump
, data
);
2003 JS_PUBLIC_API(uint32
)
2004 JS_MapGCRoots(JSRuntime
*rt
, JSGCRootMapFun map
, void *data
)
2006 return js_MapGCRoots(rt
, map
, data
);
2009 JS_PUBLIC_API(JSBool
)
2010 JS_LockGCThing(JSContext
*cx
, void *thing
)
2015 ok
= js_LockGCThingRT(cx
->runtime
, thing
);
2017 JS_ReportOutOfMemory(cx
);
2021 JS_PUBLIC_API(JSBool
)
2022 JS_LockGCThingRT(JSRuntime
*rt
, void *thing
)
2024 return js_LockGCThingRT(rt
, thing
);
2027 JS_PUBLIC_API(JSBool
)
2028 JS_UnlockGCThing(JSContext
*cx
, void *thing
)
2033 ok
= js_UnlockGCThingRT(cx
->runtime
, thing
);
2035 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_CANT_UNLOCK
);
2039 JS_PUBLIC_API(JSBool
)
2040 JS_UnlockGCThingRT(JSRuntime
*rt
, void *thing
)
2042 return js_UnlockGCThingRT(rt
, thing
);
2046 JS_SetExtraGCRoots(JSRuntime
*rt
, JSTraceDataOp traceOp
, void *data
)
2048 rt
->gcExtraRootsTraceOp
= traceOp
;
2049 rt
->gcExtraRootsData
= data
;
2053 JS_TraceRuntime(JSTracer
*trc
)
2055 JSBool allAtoms
= trc
->context
->runtime
->gcKeepAtoms
!= 0;
2057 js_TraceRuntime(trc
, allAtoms
);
2062 #ifdef HAVE_XPCONNECT
2063 #include "dump_xpc.h"
2067 JS_PrintTraceThingInfo(char *buf
, size_t bufsize
, JSTracer
*trc
,
2068 void *thing
, uint32 kind
, JSBool details
)
2077 case JSTRACE_OBJECT
:
2079 JSObject
*obj
= (JSObject
*)thing
;
2080 JSClass
*clasp
= STOBJ_GET_CLASS(obj
);
2083 #ifdef HAVE_XPCONNECT
2084 if (clasp
->flags
& JSCLASS_PRIVATE_IS_NSISUPPORTS
) {
2085 jsval privateValue
= STOBJ_GET_SLOT(obj
, JSSLOT_PRIVATE
);
2087 JS_ASSERT(clasp
->flags
& JSCLASS_HAS_PRIVATE
);
2088 if (!JSVAL_IS_VOID(privateValue
)) {
2089 void *privateThing
= JSVAL_TO_PRIVATE(privateValue
);
2090 const char *xpcClassName
= GetXPCObjectClassName(privateThing
);
2093 name
= xpcClassName
;
2100 case JSTRACE_STRING
:
2101 name
= JSSTRING_IS_DEPENDENT((JSString
*)thing
)
2106 case JSTRACE_DOUBLE
:
2110 #if JS_HAS_XML_SUPPORT
2122 if (n
> bufsize
- 1)
2124 memcpy(buf
, name
, n
+ 1);
2128 if (details
&& bufsize
> 2) {
2133 case JSTRACE_OBJECT
:
2135 JSObject
*obj
= (JSObject
*)thing
;
2136 JSClass
*clasp
= STOBJ_GET_CLASS(obj
);
2137 if (clasp
== &js_FunctionClass
) {
2138 JSFunction
*fun
= (JSFunction
*)
2139 JS_GetPrivate(trc
->context
, obj
);
2142 JS_snprintf(buf
, bufsize
, "<newborn>");
2143 } else if (FUN_OBJECT(fun
) != obj
) {
2144 JS_snprintf(buf
, bufsize
, "%p", fun
);
2146 if (fun
->atom
&& ATOM_IS_STRING(fun
->atom
))
2147 js_PutEscapedString(buf
, bufsize
,
2148 ATOM_TO_STRING(fun
->atom
), 0);
2150 } else if (clasp
->flags
& JSCLASS_HAS_PRIVATE
) {
2151 jsval privateValue
= STOBJ_GET_SLOT(obj
, JSSLOT_PRIVATE
);
2152 void *privateThing
= JSVAL_IS_VOID(privateValue
)
2154 : JSVAL_TO_PRIVATE(privateValue
);
2156 JS_snprintf(buf
, bufsize
, "%p", privateThing
);
2158 JS_snprintf(buf
, bufsize
, "<no private>");
2163 case JSTRACE_STRING
:
2164 js_PutEscapedString(buf
, bufsize
, (JSString
*)thing
, 0);
2167 case JSTRACE_DOUBLE
:
2168 JS_snprintf(buf
, bufsize
, "%g", *(jsdouble
*)thing
);
2171 #if JS_HAS_XML_SUPPORT
2174 extern const char *js_xml_class_str
[];
2175 JSXML
*xml
= (JSXML
*)thing
;
2177 JS_snprintf(buf
, bufsize
, "%s", js_xml_class_str
[xml
->xml_class
]);
2186 buf
[bufsize
- 1] = '\0';
2189 typedef struct JSHeapDumpNode JSHeapDumpNode
;
2191 struct JSHeapDumpNode
{
2194 JSHeapDumpNode
*next
; /* next sibling */
2195 JSHeapDumpNode
*parent
; /* node with the thing that refer to thing
2197 char edgeName
[1]; /* name of the edge from parent->thing
2201 typedef struct JSDumpingTracer
{
2203 JSDHashTable visited
;
2207 void *thingToIgnore
;
2208 JSHeapDumpNode
*parentNode
;
2209 JSHeapDumpNode
**lastNodep
;
2214 DumpNotify(JSTracer
*trc
, void *thing
, uint32 kind
)
2216 JSDumpingTracer
*dtrc
;
2218 JSDHashEntryStub
*entry
;
2219 JSHeapDumpNode
*node
;
2220 const char *edgeName
;
2221 size_t edgeNameSize
;
2223 JS_ASSERT(trc
->callback
== DumpNotify
);
2224 dtrc
= (JSDumpingTracer
*)trc
;
2226 if (!dtrc
->ok
|| thing
== dtrc
->thingToIgnore
)
2232 * Check if we have already seen thing unless it is thingToFind to include
2233 * it to the graph each time we reach it and print all live things that
2234 * refer to thingToFind.
2236 * This does not print all possible paths leading to thingToFind since
2237 * when a thing A refers directly or indirectly to thingToFind and A is
2238 * present several times in the graph, we will print only the first path
2239 * leading to A and thingToFind, other ways to reach A will be ignored.
2241 if (dtrc
->thingToFind
!= thing
) {
2243 * The startThing check allows to avoid putting startThing into the
2244 * hash table before tracing startThing in JS_DumpHeap.
2246 if (thing
== dtrc
->startThing
)
2248 entry
= (JSDHashEntryStub
*)
2249 JS_DHashTableOperate(&dtrc
->visited
, thing
, JS_DHASH_ADD
);
2251 JS_ReportOutOfMemory(cx
);
2252 dtrc
->ok
= JS_FALSE
;
2260 if (dtrc
->base
.debugPrinter
) {
2261 dtrc
->base
.debugPrinter(trc
, dtrc
->buffer
, sizeof(dtrc
->buffer
));
2262 edgeName
= dtrc
->buffer
;
2263 } else if (dtrc
->base
.debugPrintIndex
!= (size_t)-1) {
2264 JS_snprintf(dtrc
->buffer
, sizeof(dtrc
->buffer
), "%s[%lu]",
2265 (const char *)dtrc
->base
.debugPrintArg
,
2266 dtrc
->base
.debugPrintIndex
);
2267 edgeName
= dtrc
->buffer
;
2269 edgeName
= (const char*)dtrc
->base
.debugPrintArg
;
2272 edgeNameSize
= strlen(edgeName
) + 1;
2273 node
= (JSHeapDumpNode
*)
2274 JS_malloc(cx
, offsetof(JSHeapDumpNode
, edgeName
) + edgeNameSize
);
2276 dtrc
->ok
= JS_FALSE
;
2280 node
->thing
= thing
;
2283 node
->parent
= dtrc
->parentNode
;
2284 memcpy(node
->edgeName
, edgeName
, edgeNameSize
);
2286 JS_ASSERT(!*dtrc
->lastNodep
);
2287 *dtrc
->lastNodep
= node
;
2288 dtrc
->lastNodep
= &node
->next
;
2291 /* Dump node and the chain that leads to thing it contains. */
2293 DumpNode(JSDumpingTracer
*dtrc
, FILE* fp
, JSHeapDumpNode
*node
)
2295 JSHeapDumpNode
*prev
, *following
;
2298 enum { MAX_PARENTS_TO_PRINT
= 10 };
2300 JS_PrintTraceThingInfo(dtrc
->buffer
, sizeof dtrc
->buffer
,
2301 &dtrc
->base
, node
->thing
, node
->kind
, JS_TRUE
);
2302 if (fprintf(fp
, "%p %-22s via ", node
->thing
, dtrc
->buffer
) < 0)
2306 * We need to print the parent chain in the reverse order. To do it in
2307 * O(N) time where N is the chain length we first reverse the chain while
2308 * searching for the top and then print each node while restoring the
2311 chainLimit
= MAX_PARENTS_TO_PRINT
;
2314 following
= node
->parent
;
2315 node
->parent
= prev
;
2320 if (chainLimit
== 0) {
2321 if (fputs("...", fp
) < 0)
2332 /* Loop must continue even when !ok to restore the parent chain. */
2335 /* Print edge from some runtime root or startThing. */
2336 if (fputs(node
->edgeName
, fp
) < 0)
2339 JS_PrintTraceThingInfo(dtrc
->buffer
, sizeof dtrc
->buffer
,
2340 &dtrc
->base
, prev
->thing
, prev
->kind
,
2342 if (fprintf(fp
, "(%p %s).%s",
2343 prev
->thing
, dtrc
->buffer
, node
->edgeName
) < 0) {
2348 following
= node
->parent
;
2349 node
->parent
= prev
;
2354 return ok
&& putc('\n', fp
) >= 0;
2357 JS_PUBLIC_API(JSBool
)
2358 JS_DumpHeap(JSContext
*cx
, FILE *fp
, void* startThing
, uint32 startKind
,
2359 void *thingToFind
, size_t maxDepth
, void *thingToIgnore
)
2361 JSDumpingTracer dtrc
;
2362 JSHeapDumpNode
*node
, *children
, *next
, *parent
;
2364 JSBool thingToFindWasTraced
;
2369 JS_TRACER_INIT(&dtrc
.base
, cx
, DumpNotify
);
2370 if (!JS_DHashTableInit(&dtrc
.visited
, JS_DHashGetStubOps(),
2371 NULL
, sizeof(JSDHashEntryStub
),
2372 JS_DHASH_DEFAULT_CAPACITY(100))) {
2373 JS_ReportOutOfMemory(cx
);
2377 dtrc
.startThing
= startThing
;
2378 dtrc
.thingToFind
= thingToFind
;
2379 dtrc
.thingToIgnore
= thingToIgnore
;
2380 dtrc
.parentNode
= NULL
;
2382 dtrc
.lastNodep
= &node
;
2384 JS_ASSERT(startKind
== 0);
2385 JS_TraceRuntime(&dtrc
.base
);
2387 JS_TraceChildren(&dtrc
.base
, startThing
, startKind
);
2394 thingToFindWasTraced
= thingToFind
&& thingToFind
== startThing
;
2397 * Loop must continue even when !dtrc.ok to free all nodes allocated
2401 if (thingToFind
== NULL
|| thingToFind
== node
->thing
)
2402 dtrc
.ok
= DumpNode(&dtrc
, fp
, node
);
2404 /* Descend into children. */
2407 (thingToFind
!= node
->thing
|| !thingToFindWasTraced
)) {
2408 dtrc
.parentNode
= node
;
2410 dtrc
.lastNodep
= &children
;
2411 JS_TraceChildren(&dtrc
.base
, node
->thing
, node
->kind
);
2412 if (thingToFind
== node
->thing
)
2413 thingToFindWasTraced
= JS_TRUE
;
2414 if (children
!= NULL
) {
2422 /* Move to next or parents next and free the node. */
2425 parent
= node
->parent
;
2432 JS_ASSERT(depth
> 1);
2439 JS_ASSERT(depth
== 1);
2440 JS_DHashTableFinish(&dtrc
.visited
);
2447 JS_MarkGCThing(JSContext
*cx
, void *thing
, const char *name
, void *arg
)
2451 trc
= (JSTracer
*)arg
;
2453 trc
= cx
->runtime
->gcMarkingTracer
;
2455 JS_ASSERT(trc
== cx
->runtime
->gcMarkingTracer
);
2457 #ifdef JS_THREADSAFE
2458 JS_ASSERT(cx
->runtime
->gcThread
== trc
->context
->thread
);
2460 JS_SET_TRACING_NAME(trc
, name
? name
: "unknown");
2461 js_CallValueTracerIfGCThing(trc
, (jsval
)thing
);
2464 extern JS_PUBLIC_API(JSBool
)
2465 JS_IsGCMarkingTracer(JSTracer
*trc
)
2467 return IS_GC_MARKING_TRACER(trc
);
2471 JS_GC(JSContext
*cx
)
2473 /* Don't nuke active arenas if executing or compiling. */
2474 if (cx
->stackPool
.current
== &cx
->stackPool
.first
)
2475 JS_FinishArenaPool(&cx
->stackPool
);
2476 if (cx
->tempPool
.current
== &cx
->tempPool
.first
)
2477 JS_FinishArenaPool(&cx
->tempPool
);
2478 js_GC(cx
, GC_NORMAL
);
2482 JS_MaybeGC(JSContext
*cx
)
2485 uint32 bytes
, lastBytes
;
2490 if (rt
->gcZeal
> 0) {
2496 bytes
= rt
->gcBytes
;
2497 lastBytes
= rt
->gcLastBytes
;
2500 * We run the GC if we used all available free GC cells and had to
2501 * allocate extra 1/3 of GC arenas since the last run of GC, or if
2502 * we have malloc'd more bytes through JS_malloc than we were told
2503 * to allocate by JS_NewRuntime.
2506 * bytes > 4/3 lastBytes
2507 * condition is the following. Bug 312238 changed bytes and lastBytes
2508 * to mean the total amount of memory that the GC uses now and right
2509 * after the last GC.
2511 * Before the bug the variables meant the size of allocated GC things
2512 * now and right after the last GC. That size did not include the
2513 * memory taken by free GC cells and the condition was
2514 * bytes > 3/2 lastBytes.
2515 * That is, we run the GC if we have half again as many bytes of
2516 * GC-things as the last time we GC'd. To be compatible we need to
2517 * express that condition through the new meaning of bytes and
2520 * We write the original condition as
2521 * B*(1-F) > 3/2 Bl*(1-Fl)
2522 * where B is the total memory size allocated by GC and F is the free
2523 * cell density currently and Sl and Fl are the size and the density
2524 * right after GC. The density by definition is memory taken by free
2525 * cells divided by total amount of memory. In other words, B and Bl
2526 * are bytes and lastBytes with the new meaning and B*(1-F) and
2527 * Bl*(1-Fl) are bytes and lastBytes with the original meaning.
2529 * Our task is to exclude F and Fl from the last statement. According
2530 * to the stats from bug 331966 comment 23, Fl is about 10-25% for a
2531 * typical run of the browser. It means that the original condition
2532 * implied that we did not run GC unless we exhausted the pool of
2533 * free cells. Indeed if we still have free cells, then B == Bl since
2534 * we did not yet allocated any new arenas and the condition means
2535 * 1 - F > 3/2 (1-Fl) or 3/2Fl > 1/2 + F
2536 * That implies 3/2 Fl > 1/2 or Fl > 1/3. That can not be fulfilled
2537 * for the state described by the stats. So we can write the original
2539 * F == 0 && B > 3/2 Bl(1-Fl)
2540 * Again using the stats we see that Fl is about 11% when the browser
2541 * starts up and when we are far from hitting rt->gcMaxBytes. With
2543 * F == 0 && B > 3/2 Bl(1-0.11)
2544 * or approximately F == 0 && B > 4/3 Bl.
2546 if ((bytes
> 8192 && bytes
> lastBytes
+ lastBytes
/ 3) ||
2547 rt
->gcMallocBytes
>= rt
->gcMaxMallocBytes
) {
2552 JS_PUBLIC_API(JSGCCallback
)
2553 JS_SetGCCallback(JSContext
*cx
, JSGCCallback cb
)
2556 return JS_SetGCCallbackRT(cx
->runtime
, cb
);
2559 JS_PUBLIC_API(JSGCCallback
)
2560 JS_SetGCCallbackRT(JSRuntime
*rt
, JSGCCallback cb
)
2564 oldcb
= rt
->gcCallback
;
2565 rt
->gcCallback
= cb
;
2569 JS_PUBLIC_API(JSBool
)
2570 JS_IsAboutToBeFinalized(JSContext
*cx
, void *thing
)
2573 return js_IsAboutToBeFinalized(cx
, thing
);
2577 JS_SetGCParameter(JSRuntime
*rt
, JSGCParamKey key
, uint32 value
)
2580 case JSGC_MAX_BYTES
:
2581 rt
->gcMaxBytes
= value
;
2583 case JSGC_MAX_MALLOC_BYTES
:
2584 rt
->gcMaxMallocBytes
= value
;
2586 case JSGC_STACKPOOL_LIFESPAN
:
2587 rt
->gcEmptyArenaPoolLifespan
= value
;
2593 JS_AddExternalStringFinalizer(JSStringFinalizeOp finalizer
)
2595 return js_ChangeExternalStringFinalizer(NULL
, finalizer
);
2599 JS_RemoveExternalStringFinalizer(JSStringFinalizeOp finalizer
)
2601 return js_ChangeExternalStringFinalizer(finalizer
, NULL
);
2604 JS_PUBLIC_API(JSString
*)
2605 JS_NewExternalString(JSContext
*cx
, jschar
*chars
, size_t length
, intN type
)
2610 JS_ASSERT((uintN
) type
< (uintN
) (GCX_NTYPES
- GCX_EXTERNAL_STRING
));
2612 str
= (JSString
*) js_NewGCThing(cx
, (uintN
) type
+ GCX_EXTERNAL_STRING
,
2616 JSFLATSTR_INIT(str
, chars
, length
);
2621 JS_GetExternalStringGCType(JSRuntime
*rt
, JSString
*str
)
2623 return js_GetExternalStringGCType(str
);
2627 JS_SetThreadStackLimit(JSContext
*cx
, jsuword limitAddr
)
2629 #if JS_STACK_GROWTH_DIRECTION > 0
2631 limitAddr
= (jsuword
)-1;
2633 cx
->stackLimit
= limitAddr
;
2637 JS_SetScriptStackQuota(JSContext
*cx
, size_t quota
)
2639 cx
->scriptStackQuota
= quota
;
2642 /************************************************************************/
2645 JS_DestroyIdArray(JSContext
*cx
, JSIdArray
*ida
)
2650 JS_PUBLIC_API(JSBool
)
2651 JS_ValueToId(JSContext
*cx
, jsval v
, jsid
*idp
)
2654 if (JSVAL_IS_INT(v
))
2655 *idp
= INT_JSVAL_TO_JSID(v
);
2656 #if JS_HAS_XML_SUPPORT
2657 else if (!JSVAL_IS_PRIMITIVE(v
))
2658 *idp
= OBJECT_JSVAL_TO_JSID(v
);
2661 return js_ValueToStringId(cx
, v
, idp
);
2665 JS_PUBLIC_API(JSBool
)
2666 JS_IdToValue(JSContext
*cx
, jsid id
, jsval
*vp
)
2669 *vp
= ID_TO_VALUE(id
);
2673 JS_PUBLIC_API(JSBool
)
2674 JS_PropertyStub(JSContext
*cx
, JSObject
*obj
, jsval id
, jsval
*vp
)
2679 JS_PUBLIC_API(JSBool
)
2680 JS_EnumerateStub(JSContext
*cx
, JSObject
*obj
)
2685 JS_PUBLIC_API(JSBool
)
2686 JS_ResolveStub(JSContext
*cx
, JSObject
*obj
, jsval id
)
2691 JS_PUBLIC_API(JSBool
)
2692 JS_ConvertStub(JSContext
*cx
, JSObject
*obj
, JSType type
, jsval
*vp
)
2694 return js_TryValueOf(cx
, obj
, type
, vp
);
2698 JS_FinalizeStub(JSContext
*cx
, JSObject
*obj
)
2702 JS_PUBLIC_API(JSObject
*)
2703 JS_InitClass(JSContext
*cx
, JSObject
*obj
, JSObject
*parent_proto
,
2704 JSClass
*clasp
, JSNative constructor
, uintN nargs
,
2705 JSPropertySpec
*ps
, JSFunctionSpec
*fs
,
2706 JSPropertySpec
*static_ps
, JSFunctionSpec
*static_fs
)
2710 JSObject
*proto
, *ctor
;
2711 JSTempValueRooter tvr
;
2717 atom
= js_Atomize(cx
, clasp
->name
, strlen(clasp
->name
), 0);
2722 * When initializing a standard class, if no parent_proto (grand-proto of
2723 * instances of the class, parent-proto of the class's prototype object)
2724 * is given, we must use Object.prototype if it is available. Otherwise,
2725 * we could look up the wrong binding for a class name in obj. Example:
2728 * print("hi there".join);
2730 * should print undefined, not Array.prototype.join. This is required by
2731 * ECMA-262, alas. It might have been better to make String readonly and
2732 * permanent in the global object, instead -- but that's too big a change
2733 * to swallow at this point.
2735 key
= JSCLASS_CACHED_PROTO_KEY(clasp
);
2736 if (key
!= JSProto_Null
&&
2738 !js_GetClassPrototype(cx
, obj
, INT_TO_JSID(JSProto_Object
),
2743 /* Create a prototype object for this class. */
2744 proto
= js_NewObject(cx
, clasp
, parent_proto
, obj
, 0);
2748 /* After this point, control must exit via label bad or out. */
2749 JS_PUSH_TEMP_ROOT_OBJECT(cx
, proto
, &tvr
);
2753 * Lacking a constructor, name the prototype (e.g., Math) unless this
2754 * class (a) is anonymous, i.e. for internal use only; (b) the class
2755 * of obj (the global object) is has a reserved slot indexed by key;
2756 * and (c) key is not the null key.
2758 if ((clasp
->flags
& JSCLASS_IS_ANONYMOUS
) &&
2759 (OBJ_GET_CLASS(cx
, obj
)->flags
& JSCLASS_IS_GLOBAL
) &&
2760 key
!= JSProto_Null
) {
2763 named
= OBJ_DEFINE_PROPERTY(cx
, obj
, ATOM_TO_JSID(atom
),
2764 OBJECT_TO_JSVAL(proto
),
2765 JS_PropertyStub
, JS_PropertyStub
,
2766 (clasp
->flags
& JSCLASS_IS_ANONYMOUS
)
2767 ? JSPROP_READONLY
| JSPROP_PERMANENT
2776 /* Define the constructor function in obj's scope. */
2777 fun
= js_DefineFunction(cx
, obj
, atom
, constructor
, nargs
,
2779 named
= (fun
!= NULL
);
2784 * Remember the class this function is a constructor for so that
2785 * we know to create an object of this class when we call the
2788 FUN_CLASP(fun
) = clasp
;
2791 * Optionally construct the prototype object, before the class has
2792 * been fully initialized. Allow the ctor to replace proto with a
2793 * different object, as is done for operator new -- and as at least
2794 * XML support requires.
2796 ctor
= FUN_OBJECT(fun
);
2797 if (clasp
->flags
& JSCLASS_CONSTRUCT_PROTOTYPE
) {
2798 cval
= OBJECT_TO_JSVAL(ctor
);
2799 if (!js_InternalConstruct(cx
, proto
, cval
, 0, NULL
, &rval
))
2801 if (!JSVAL_IS_PRIMITIVE(rval
) && JSVAL_TO_OBJECT(rval
) != proto
)
2802 proto
= JSVAL_TO_OBJECT(rval
);
2805 /* Connect constructor and prototype by named properties. */
2806 if (!js_SetClassPrototype(cx
, ctor
, proto
,
2807 JSPROP_READONLY
| JSPROP_PERMANENT
)) {
2811 /* Bootstrap Function.prototype (see also JS_InitStandardClasses). */
2812 if (OBJ_GET_CLASS(cx
, ctor
) == clasp
) {
2813 OBJ_SET_PROTO(cx
, ctor
, proto
);
2817 /* Add properties and methods to the prototype and the constructor. */
2818 if ((ps
&& !JS_DefineProperties(cx
, proto
, ps
)) ||
2819 (fs
&& !JS_DefineFunctions(cx
, proto
, fs
)) ||
2820 (static_ps
&& !JS_DefineProperties(cx
, ctor
, static_ps
)) ||
2821 (static_fs
&& !JS_DefineFunctions(cx
, ctor
, static_fs
))) {
2825 /* If this is a standard class, cache its prototype. */
2826 if (key
!= JSProto_Null
&& !js_SetClassObject(cx
, obj
, key
, ctor
))
2830 JS_POP_TEMP_ROOT(cx
, &tvr
);
2835 (void) OBJ_DELETE_PROPERTY(cx
, obj
, ATOM_TO_JSID(atom
), &rval
);
2840 #ifdef JS_THREADSAFE
2841 JS_PUBLIC_API(JSClass
*)
2842 JS_GetClass(JSContext
*cx
, JSObject
*obj
)
2844 return OBJ_GET_CLASS(cx
, obj
);
2847 JS_PUBLIC_API(JSClass
*)
2848 JS_GetClass(JSObject
*obj
)
2850 return LOCKED_OBJ_GET_CLASS(obj
);
2854 JS_PUBLIC_API(JSBool
)
2855 JS_InstanceOf(JSContext
*cx
, JSObject
*obj
, JSClass
*clasp
, jsval
*argv
)
2860 if (obj
&& OBJ_GET_CLASS(cx
, obj
) == clasp
)
2863 fun
= js_ValueToFunction(cx
, &argv
[-2], 0);
2865 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
,
2866 JSMSG_INCOMPATIBLE_PROTO
,
2867 clasp
->name
, JS_GetFunctionName(fun
),
2869 ? OBJ_GET_CLASS(cx
, obj
)->name
2876 JS_PUBLIC_API(JSBool
)
2877 JS_HasInstance(JSContext
*cx
, JSObject
*obj
, jsval v
, JSBool
*bp
)
2879 return js_HasInstance(cx
, obj
, v
, bp
);
2882 JS_PUBLIC_API(void *)
2883 JS_GetPrivate(JSContext
*cx
, JSObject
*obj
)
2887 JS_ASSERT(OBJ_GET_CLASS(cx
, obj
)->flags
& JSCLASS_HAS_PRIVATE
);
2888 v
= obj
->fslots
[JSSLOT_PRIVATE
];
2889 if (!JSVAL_IS_INT(v
))
2891 return JSVAL_TO_PRIVATE(v
);
2894 JS_PUBLIC_API(JSBool
)
2895 JS_SetPrivate(JSContext
*cx
, JSObject
*obj
, void *data
)
2897 JS_ASSERT(OBJ_GET_CLASS(cx
, obj
)->flags
& JSCLASS_HAS_PRIVATE
);
2898 obj
->fslots
[JSSLOT_PRIVATE
] = PRIVATE_TO_JSVAL(data
);
2902 JS_PUBLIC_API(void *)
2903 JS_GetInstancePrivate(JSContext
*cx
, JSObject
*obj
, JSClass
*clasp
,
2906 if (!JS_InstanceOf(cx
, obj
, clasp
, argv
))
2908 return JS_GetPrivate(cx
, obj
);
2911 JS_PUBLIC_API(JSObject
*)
2912 JS_GetPrototype(JSContext
*cx
, JSObject
*obj
)
2917 proto
= OBJ_GET_PROTO(cx
, obj
);
2919 /* Beware ref to dead object (we may be called from obj's finalizer). */
2920 return proto
&& proto
->map
? proto
: NULL
;
2923 JS_PUBLIC_API(JSBool
)
2924 JS_SetPrototype(JSContext
*cx
, JSObject
*obj
, JSObject
*proto
)
2927 JS_ASSERT(obj
!= proto
);
2930 * FIXME: bug 408416. The cycle-detection required for script-writeable
2931 * __proto__ lives in js_SetProtoOrParent over in jsobj.c, also known as
2932 * js_ObjectOps.setProto. This hook must detect cycles, to prevent scripts
2933 * from ilooping SpiderMonkey trivially. But the overhead of detecting
2934 * cycles is high enough, and the threat from JS-API-calling C++ code is
2935 * low enough, that it's not worth burdening the non-DEBUG callers. Same
2936 * goes for JS_SetParent, below.
2938 if (obj
->map
->ops
->setProto
)
2939 return obj
->map
->ops
->setProto(cx
, obj
, JSSLOT_PROTO
, proto
);
2941 if (OBJ_IS_NATIVE(obj
)) {
2942 JS_LOCK_OBJ(cx
, obj
);
2943 if (!js_GetMutableScope(cx
, obj
)) {
2944 JS_UNLOCK_OBJ(cx
, obj
);
2947 LOCKED_OBJ_SET_PROTO(obj
, proto
);
2948 JS_UNLOCK_OBJ(cx
, obj
);
2952 OBJ_SET_PROTO(cx
, obj
, proto
);
2956 JS_PUBLIC_API(JSObject
*)
2957 JS_GetParent(JSContext
*cx
, JSObject
*obj
)
2961 parent
= OBJ_GET_PARENT(cx
, obj
);
2963 /* Beware ref to dead object (we may be called from obj's finalizer). */
2964 return parent
&& parent
->map
? parent
: NULL
;
2967 JS_PUBLIC_API(JSBool
)
2968 JS_SetParent(JSContext
*cx
, JSObject
*obj
, JSObject
*parent
)
2971 JS_ASSERT(obj
!= parent
);
2973 /* FIXME: bug 408416, see JS_SetPrototype just above. */
2974 if (obj
->map
->ops
->setParent
)
2975 return obj
->map
->ops
->setParent(cx
, obj
, JSSLOT_PARENT
, parent
);
2977 OBJ_SET_PARENT(cx
, obj
, parent
);
2981 JS_PUBLIC_API(JSObject
*)
2982 JS_GetConstructor(JSContext
*cx
, JSObject
*proto
)
2988 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
);
2990 if (!OBJ_GET_PROPERTY(cx
, proto
,
2991 ATOM_TO_JSID(cx
->runtime
->atomState
.constructorAtom
),
2996 if (!VALUE_IS_FUNCTION(cx
, cval
)) {
2997 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_NO_CONSTRUCTOR
,
2998 OBJ_GET_CLASS(cx
, proto
)->name
);
3001 return JSVAL_TO_OBJECT(cval
);
3004 JS_PUBLIC_API(JSBool
)
3005 JS_GetObjectId(JSContext
*cx
, JSObject
*obj
, jsid
*idp
)
3007 JS_ASSERT(JSID_IS_OBJECT(obj
));
3008 *idp
= OBJECT_TO_JSID(obj
);
3012 JS_PUBLIC_API(JSObject
*)
3013 JS_NewObject(JSContext
*cx
, JSClass
*clasp
, JSObject
*proto
, JSObject
*parent
)
3017 clasp
= &js_ObjectClass
; /* default class is Object */
3018 return js_NewObject(cx
, clasp
, proto
, parent
, 0);
3021 JS_PUBLIC_API(JSObject
*)
3022 JS_NewObjectWithGivenProto(JSContext
*cx
, JSClass
*clasp
, JSObject
*proto
,
3027 clasp
= &js_ObjectClass
; /* default class is Object */
3028 return js_NewObjectWithGivenProto(cx
, clasp
, proto
, parent
, 0);
3031 JS_PUBLIC_API(JSBool
)
3032 JS_SealObject(JSContext
*cx
, JSObject
*obj
, JSBool deep
)
3039 if (!OBJ_IS_NATIVE(obj
)) {
3040 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
,
3041 JSMSG_CANT_SEAL_OBJECT
,
3042 OBJ_GET_CLASS(cx
, obj
)->name
);
3046 scope
= OBJ_SCOPE(obj
);
3048 #if defined JS_THREADSAFE && defined DEBUG
3049 /* Insist on scope being used exclusively by cx's thread. */
3050 if (scope
->title
.ownercx
!= cx
) {
3051 JS_LOCK_OBJ(cx
, obj
);
3052 JS_ASSERT(OBJ_SCOPE(obj
) == scope
);
3053 JS_ASSERT(scope
->title
.ownercx
== cx
);
3054 JS_UNLOCK_SCOPE(cx
, scope
);
3058 /* Nothing to do if obj's scope is already sealed. */
3059 if (SCOPE_IS_SEALED(scope
))
3062 /* XXX Enumerate lazy properties now, as they can't be added later. */
3063 ida
= JS_Enumerate(cx
, obj
);
3066 JS_DestroyIdArray(cx
, ida
);
3068 /* Ensure that obj has its own, mutable scope, and seal that scope. */
3069 JS_LOCK_OBJ(cx
, obj
);
3070 scope
= js_GetMutableScope(cx
, obj
);
3072 SCOPE_SET_SEALED(scope
);
3073 SCOPE_MAKE_UNIQUE_SHAPE(cx
, scope
);
3075 JS_UNLOCK_OBJ(cx
, obj
);
3079 /* If we are not sealing an entire object graph, we're done. */
3083 /* Walk slots in obj and if any value is a non-null object, seal it. */
3084 nslots
= scope
->map
.freeslot
;
3085 for (i
= 0; i
!= nslots
; ++i
) {
3086 v
= STOBJ_GET_SLOT(obj
, i
);
3087 if (JSVAL_IS_PRIMITIVE(v
))
3089 if (!JS_SealObject(cx
, JSVAL_TO_OBJECT(v
), deep
))
3095 JS_PUBLIC_API(JSObject
*)
3096 JS_ConstructObject(JSContext
*cx
, JSClass
*clasp
, JSObject
*proto
,
3101 clasp
= &js_ObjectClass
; /* default class is Object */
3102 return js_ConstructObject(cx
, clasp
, proto
, parent
, 0, NULL
);
3105 JS_PUBLIC_API(JSObject
*)
3106 JS_ConstructObjectWithArguments(JSContext
*cx
, JSClass
*clasp
, JSObject
*proto
,
3107 JSObject
*parent
, uintN argc
, jsval
*argv
)
3111 clasp
= &js_ObjectClass
; /* default class is Object */
3112 return js_ConstructObject(cx
, clasp
, proto
, parent
, argc
, argv
);
3116 DefineProperty(JSContext
*cx
, JSObject
*obj
, const char *name
, jsval value
,
3117 JSPropertyOp getter
, JSPropertyOp setter
, uintN attrs
,
3118 uintN flags
, intN tinyid
)
3123 if (attrs
& JSPROP_INDEX
) {
3124 id
= INT_TO_JSID(JS_PTR_TO_INT32(name
));
3126 attrs
&= ~JSPROP_INDEX
;
3128 atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3131 id
= ATOM_TO_JSID(atom
);
3133 if (flags
!= 0 && OBJ_IS_NATIVE(obj
)) {
3134 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
| JSRESOLVE_DECLARING
);
3135 return js_DefineNativeProperty(cx
, obj
, id
, value
, getter
, setter
,
3136 attrs
, flags
, tinyid
, NULL
);
3138 return OBJ_DEFINE_PROPERTY(cx
, obj
, id
, value
, getter
, setter
, attrs
,
3142 #define AUTO_NAMELEN(s,n) (((n) == (size_t)-1) ? js_strlen(s) : (n))
3145 DefineUCProperty(JSContext
*cx
, JSObject
*obj
,
3146 const jschar
*name
, size_t namelen
, jsval value
,
3147 JSPropertyOp getter
, JSPropertyOp setter
, uintN attrs
,
3148 uintN flags
, intN tinyid
)
3152 atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
3155 if (flags
!= 0 && OBJ_IS_NATIVE(obj
)) {
3156 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
| JSRESOLVE_DECLARING
);
3157 return js_DefineNativeProperty(cx
, obj
, ATOM_TO_JSID(atom
), value
,
3158 getter
, setter
, attrs
, flags
, tinyid
,
3161 return OBJ_DEFINE_PROPERTY(cx
, obj
, ATOM_TO_JSID(atom
), value
,
3162 getter
, setter
, attrs
, NULL
);
3165 JS_PUBLIC_API(JSObject
*)
3166 JS_DefineObject(JSContext
*cx
, JSObject
*obj
, const char *name
, JSClass
*clasp
,
3167 JSObject
*proto
, uintN attrs
)
3173 clasp
= &js_ObjectClass
; /* default class is Object */
3174 nobj
= js_NewObject(cx
, clasp
, proto
, obj
, 0);
3177 if (!DefineProperty(cx
, obj
, name
, OBJECT_TO_JSVAL(nobj
), NULL
, NULL
, attrs
,
3179 cx
->weakRoots
.newborn
[GCX_OBJECT
] = NULL
;
3185 JS_PUBLIC_API(JSBool
)
3186 JS_DefineConstDoubles(JSContext
*cx
, JSObject
*obj
, JSConstDoubleSpec
*cds
)
3193 for (ok
= JS_TRUE
; cds
->name
; cds
++) {
3194 ok
= js_NewNumberInRootedValue(cx
, cds
->dval
, &value
);
3199 attrs
= JSPROP_READONLY
| JSPROP_PERMANENT
;
3200 ok
= DefineProperty(cx
, obj
, cds
->name
, value
, NULL
, NULL
, attrs
, 0, 0);
3207 JS_PUBLIC_API(JSBool
)
3208 JS_DefineProperties(JSContext
*cx
, JSObject
*obj
, JSPropertySpec
*ps
)
3213 for (ok
= JS_TRUE
; ps
->name
; ps
++) {
3214 ok
= DefineProperty(cx
, obj
, ps
->name
, JSVAL_VOID
,
3215 ps
->getter
, ps
->setter
, ps
->flags
,
3216 SPROP_HAS_SHORTID
, ps
->tinyid
);
3223 JS_PUBLIC_API(JSBool
)
3224 JS_DefineProperty(JSContext
*cx
, JSObject
*obj
, const char *name
, jsval value
,
3225 JSPropertyOp getter
, JSPropertyOp setter
, uintN attrs
)
3228 return DefineProperty(cx
, obj
, name
, value
, getter
, setter
, attrs
, 0, 0);
3231 JS_PUBLIC_API(JSBool
)
3232 JS_DefinePropertyWithTinyId(JSContext
*cx
, JSObject
*obj
, const char *name
,
3233 int8 tinyid
, jsval value
,
3234 JSPropertyOp getter
, JSPropertyOp setter
,
3238 return DefineProperty(cx
, obj
, name
, value
, getter
, setter
, attrs
,
3239 SPROP_HAS_SHORTID
, tinyid
);
3243 LookupPropertyById(JSContext
*cx
, JSObject
*obj
, jsid id
, uintN flags
,
3244 JSObject
**objp
, JSProperty
**propp
)
3246 JSAutoResolveFlags
rf(cx
, flags
);
3247 return OBJ_LOOKUP_PROPERTY(cx
, obj
, id
, objp
, propp
);
3251 LookupProperty(JSContext
*cx
, JSObject
*obj
, const char *name
, uintN flags
,
3252 JSObject
**objp
, JSProperty
**propp
)
3256 atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3259 return LookupPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), flags
, objp
, propp
);
3263 LookupUCProperty(JSContext
*cx
, JSObject
*obj
,
3264 const jschar
*name
, size_t namelen
, uintN flags
,
3265 JSObject
**objp
, JSProperty
**propp
)
3269 atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
3272 return LookupPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), flags
, objp
, propp
);
3275 JS_PUBLIC_API(JSBool
)
3276 JS_AliasProperty(JSContext
*cx
, JSObject
*obj
, const char *name
,
3283 JSScopeProperty
*sprop
;
3286 if (!LookupProperty(cx
, obj
, name
, JSRESOLVE_QUALIFIED
, &obj2
, &prop
))
3289 js_ReportIsNotDefined(cx
, name
);
3292 if (obj2
!= obj
|| !OBJ_IS_NATIVE(obj
)) {
3293 OBJ_DROP_PROPERTY(cx
, obj2
, prop
);
3294 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_CANT_ALIAS
,
3295 alias
, name
, OBJ_GET_CLASS(cx
, obj2
)->name
);
3298 atom
= js_Atomize(cx
, alias
, strlen(alias
), 0);
3302 sprop
= (JSScopeProperty
*)prop
;
3303 ok
= (js_AddNativeProperty(cx
, obj
, ATOM_TO_JSID(atom
),
3304 sprop
->getter
, sprop
->setter
, sprop
->slot
,
3305 sprop
->attrs
, sprop
->flags
| SPROP_IS_ALIAS
,
3309 OBJ_DROP_PROPERTY(cx
, obj
, prop
);
3314 LookupResult(JSContext
*cx
, JSObject
*obj
, JSObject
*obj2
, JSProperty
*prop
)
3316 JSScopeProperty
*sprop
;
3320 /* XXX bad API: no way to tell "not defined" from "void value" */
3323 if (OBJ_IS_NATIVE(obj2
)) {
3324 /* Peek at the native property's slot value, without doing a Get. */
3325 sprop
= (JSScopeProperty
*)prop
;
3326 rval
= SPROP_HAS_VALID_SLOT(sprop
, OBJ_SCOPE(obj2
))
3327 ? LOCKED_OBJ_GET_SLOT(obj2
, sprop
->slot
)
3330 /* XXX bad API: no way to return "defined but value unknown" */
3333 OBJ_DROP_PROPERTY(cx
, obj2
, prop
);
3338 GetPropertyAttributes(JSContext
*cx
, JSObject
*obj
, JSAtom
*atom
,
3339 uintN
*attrsp
, JSBool
*foundp
,
3340 JSPropertyOp
*getterp
, JSPropertyOp
*setterp
)
3348 if (!LookupPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), JSRESOLVE_QUALIFIED
,
3353 if (!prop
|| obj
!= obj2
) {
3361 OBJ_DROP_PROPERTY(cx
, obj2
, prop
);
3366 ok
= OBJ_GET_ATTRIBUTES(cx
, obj
, ATOM_TO_JSID(atom
), prop
, attrsp
);
3367 if (ok
&& OBJ_IS_NATIVE(obj
)) {
3368 JSScopeProperty
*sprop
= (JSScopeProperty
*) prop
;
3371 *getterp
= sprop
->getter
;
3373 *setterp
= sprop
->setter
;
3375 OBJ_DROP_PROPERTY(cx
, obj
, prop
);
3380 SetPropertyAttributes(JSContext
*cx
, JSObject
*obj
, JSAtom
*atom
,
3381 uintN attrs
, JSBool
*foundp
)
3389 if (!LookupPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), JSRESOLVE_QUALIFIED
,
3393 if (!prop
|| obj
!= obj2
) {
3396 OBJ_DROP_PROPERTY(cx
, obj2
, prop
);
3401 ok
= OBJ_SET_ATTRIBUTES(cx
, obj
, ATOM_TO_JSID(atom
), prop
, &attrs
);
3402 OBJ_DROP_PROPERTY(cx
, obj
, prop
);
3406 JS_PUBLIC_API(JSBool
)
3407 JS_GetPropertyAttributes(JSContext
*cx
, JSObject
*obj
, const char *name
,
3408 uintN
*attrsp
, JSBool
*foundp
)
3411 return GetPropertyAttributes(cx
, obj
,
3412 js_Atomize(cx
, name
, strlen(name
), 0),
3413 attrsp
, foundp
, NULL
, NULL
);
3416 JS_PUBLIC_API(JSBool
)
3417 JS_GetPropertyAttrsGetterAndSetter(JSContext
*cx
, JSObject
*obj
,
3419 uintN
*attrsp
, JSBool
*foundp
,
3420 JSPropertyOp
*getterp
,
3421 JSPropertyOp
*setterp
)
3424 return GetPropertyAttributes(cx
, obj
,
3425 js_Atomize(cx
, name
, strlen(name
), 0),
3426 attrsp
, foundp
, getterp
, setterp
);
3429 JS_PUBLIC_API(JSBool
)
3430 JS_SetPropertyAttributes(JSContext
*cx
, JSObject
*obj
, const char *name
,
3431 uintN attrs
, JSBool
*foundp
)
3434 return SetPropertyAttributes(cx
, obj
,
3435 js_Atomize(cx
, name
, strlen(name
), 0),
3440 AlreadyHasOwnPropertyHelper(JSContext
*cx
, JSObject
*obj
, jsid id
,
3445 if (!OBJ_IS_NATIVE(obj
)) {
3449 if (!LookupPropertyById(cx
, obj
, id
,
3450 JSRESOLVE_QUALIFIED
| JSRESOLVE_DETECTING
,
3454 *foundp
= (obj
== obj2
);
3456 OBJ_DROP_PROPERTY(cx
, obj2
, prop
);
3460 JS_LOCK_OBJ(cx
, obj
);
3461 scope
= OBJ_SCOPE(obj
);
3462 *foundp
= (scope
->object
== obj
&& SCOPE_GET_PROPERTY(scope
, id
));
3463 JS_UNLOCK_SCOPE(cx
, scope
);
3467 JS_PUBLIC_API(JSBool
)
3468 JS_AlreadyHasOwnProperty(JSContext
*cx
, JSObject
*obj
, const char *name
,
3474 atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3477 return AlreadyHasOwnPropertyHelper(cx
, obj
, ATOM_TO_JSID(atom
), foundp
);
3480 JS_PUBLIC_API(JSBool
)
3481 JS_HasProperty(JSContext
*cx
, JSObject
*obj
, const char *name
, JSBool
*foundp
)
3488 ok
= LookupProperty(cx
, obj
, name
,
3489 JSRESOLVE_QUALIFIED
| JSRESOLVE_DETECTING
,
3492 *foundp
= (prop
!= NULL
);
3494 OBJ_DROP_PROPERTY(cx
, obj2
, prop
);
3499 JS_PUBLIC_API(JSBool
)
3500 JS_LookupProperty(JSContext
*cx
, JSObject
*obj
, const char *name
, jsval
*vp
)
3507 ok
= LookupProperty(cx
, obj
, name
, JSRESOLVE_QUALIFIED
, &obj2
, &prop
);
3509 *vp
= LookupResult(cx
, obj
, obj2
, prop
);
3513 JS_PUBLIC_API(JSBool
)
3514 JS_LookupPropertyWithFlags(JSContext
*cx
, JSObject
*obj
, const char *name
,
3515 uintN flags
, jsval
*vp
)
3520 atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3522 JS_LookupPropertyByIdWithFlags(cx
, obj
, ATOM_TO_JSID(atom
), flags
,
3526 JS_PUBLIC_API(JSBool
)
3527 JS_LookupPropertyByIdWithFlags(JSContext
*cx
, JSObject
*obj
, jsid id
,
3528 uintN flags
, JSObject
**objp
, jsval
*vp
)
3534 ok
= OBJ_IS_NATIVE(obj
)
3535 ? js_LookupPropertyWithFlags(cx
, obj
, id
, flags
, objp
, &prop
) >= 0
3536 : OBJ_LOOKUP_PROPERTY(cx
, obj
, id
, objp
, &prop
);
3538 *vp
= LookupResult(cx
, obj
, *objp
, prop
);
3542 JS_PUBLIC_API(JSBool
)
3543 JS_GetProperty(JSContext
*cx
, JSObject
*obj
, const char *name
, jsval
*vp
)
3548 atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3552 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
);
3553 return OBJ_GET_PROPERTY(cx
, obj
, ATOM_TO_JSID(atom
), vp
);
3556 JS_PUBLIC_API(JSBool
)
3557 JS_GetMethodById(JSContext
*cx
, JSObject
*obj
, jsid id
, JSObject
**objp
,
3560 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
);
3563 #if JS_HAS_XML_SUPPORT
3564 if (OBJECT_IS_XML(cx
, obj
)) {
3565 JSXMLObjectOps
*ops
;
3567 ops
= (JSXMLObjectOps
*) obj
->map
->ops
;
3568 obj
= ops
->getMethod(cx
, obj
, id
, vp
);
3574 if (!OBJ_GET_PROPERTY(cx
, obj
, id
, vp
))
3582 JS_PUBLIC_API(JSBool
)
3583 JS_GetMethod(JSContext
*cx
, JSObject
*obj
, const char *name
, JSObject
**objp
,
3588 atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3591 return JS_GetMethodById(cx
, obj
, ATOM_TO_JSID(atom
), objp
, vp
);
3594 JS_PUBLIC_API(JSBool
)
3595 JS_SetProperty(JSContext
*cx
, JSObject
*obj
, const char *name
, jsval
*vp
)
3600 atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3604 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
| JSRESOLVE_ASSIGNING
);
3605 return OBJ_SET_PROPERTY(cx
, obj
, ATOM_TO_JSID(atom
), vp
);
3608 JS_PUBLIC_API(JSBool
)
3609 JS_DeleteProperty(JSContext
*cx
, JSObject
*obj
, const char *name
)
3614 return JS_DeleteProperty2(cx
, obj
, name
, &junk
);
3617 JS_PUBLIC_API(JSBool
)
3618 JS_DeleteProperty2(JSContext
*cx
, JSObject
*obj
, const char *name
,
3624 atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3628 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
);
3629 return OBJ_DELETE_PROPERTY(cx
, obj
, ATOM_TO_JSID(atom
), rval
);
3632 JS_PUBLIC_API(JSBool
)
3633 JS_DefineUCProperty(JSContext
*cx
, JSObject
*obj
,
3634 const jschar
*name
, size_t namelen
, jsval value
,
3635 JSPropertyOp getter
, JSPropertyOp setter
,
3639 return DefineUCProperty(cx
, obj
, name
, namelen
, value
, getter
, setter
,
3643 JS_PUBLIC_API(JSBool
)
3644 JS_GetUCPropertyAttributes(JSContext
*cx
, JSObject
*obj
,
3645 const jschar
*name
, size_t namelen
,
3646 uintN
*attrsp
, JSBool
*foundp
)
3649 return GetPropertyAttributes(cx
, obj
,
3650 js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0),
3651 attrsp
, foundp
, NULL
, NULL
);
3654 JS_PUBLIC_API(JSBool
)
3655 JS_GetUCPropertyAttrsGetterAndSetter(JSContext
*cx
, JSObject
*obj
,
3656 const jschar
*name
, size_t namelen
,
3657 uintN
*attrsp
, JSBool
*foundp
,
3658 JSPropertyOp
*getterp
,
3659 JSPropertyOp
*setterp
)
3662 return GetPropertyAttributes(cx
, obj
,
3663 js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0),
3664 attrsp
, foundp
, getterp
, setterp
);
3667 JS_PUBLIC_API(JSBool
)
3668 JS_SetUCPropertyAttributes(JSContext
*cx
, JSObject
*obj
,
3669 const jschar
*name
, size_t namelen
,
3670 uintN attrs
, JSBool
*foundp
)
3673 return SetPropertyAttributes(cx
, obj
,
3674 js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0),
3678 JS_PUBLIC_API(JSBool
)
3679 JS_DefineUCPropertyWithTinyId(JSContext
*cx
, JSObject
*obj
,
3680 const jschar
*name
, size_t namelen
,
3681 int8 tinyid
, jsval value
,
3682 JSPropertyOp getter
, JSPropertyOp setter
,
3686 return DefineUCProperty(cx
, obj
, name
, namelen
, value
, getter
, setter
,
3687 attrs
, SPROP_HAS_SHORTID
, tinyid
);
3690 JS_PUBLIC_API(JSBool
)
3691 JS_AlreadyHasOwnUCProperty(JSContext
*cx
, JSObject
*obj
,
3692 const jschar
*name
, size_t namelen
,
3698 atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
3701 return AlreadyHasOwnPropertyHelper(cx
, obj
, ATOM_TO_JSID(atom
), foundp
);
3704 JS_PUBLIC_API(JSBool
)
3705 JS_HasUCProperty(JSContext
*cx
, JSObject
*obj
,
3706 const jschar
*name
, size_t namelen
,
3714 ok
= LookupUCProperty(cx
, obj
, name
, namelen
,
3715 JSRESOLVE_QUALIFIED
| JSRESOLVE_DETECTING
,
3718 *vp
= (prop
!= NULL
);
3720 OBJ_DROP_PROPERTY(cx
, obj2
, prop
);
3725 JS_PUBLIC_API(JSBool
)
3726 JS_LookupUCProperty(JSContext
*cx
, JSObject
*obj
,
3727 const jschar
*name
, size_t namelen
,
3735 ok
= LookupUCProperty(cx
, obj
, name
, namelen
, JSRESOLVE_QUALIFIED
,
3738 *vp
= LookupResult(cx
, obj
, obj2
, prop
);
3742 JS_PUBLIC_API(JSBool
)
3743 JS_GetUCProperty(JSContext
*cx
, JSObject
*obj
,
3744 const jschar
*name
, size_t namelen
,
3750 atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
3754 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
);
3755 return OBJ_GET_PROPERTY(cx
, obj
, ATOM_TO_JSID(atom
), vp
);
3758 JS_PUBLIC_API(JSBool
)
3759 JS_SetUCProperty(JSContext
*cx
, JSObject
*obj
,
3760 const jschar
*name
, size_t namelen
,
3766 atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
3770 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
| JSRESOLVE_ASSIGNING
);
3771 return OBJ_SET_PROPERTY(cx
, obj
, ATOM_TO_JSID(atom
), vp
);
3774 JS_PUBLIC_API(JSBool
)
3775 JS_DeleteUCProperty2(JSContext
*cx
, JSObject
*obj
,
3776 const jschar
*name
, size_t namelen
,
3782 atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
3786 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
);
3787 return OBJ_DELETE_PROPERTY(cx
, obj
, ATOM_TO_JSID(atom
), rval
);
3790 JS_PUBLIC_API(JSObject
*)
3791 JS_NewArrayObject(JSContext
*cx
, jsint length
, jsval
*vector
)
3794 /* NB: jsuint cast does ToUint32. */
3795 return js_NewArrayObject(cx
, (jsuint
)length
, vector
);
3798 JS_PUBLIC_API(JSBool
)
3799 JS_IsArrayObject(JSContext
*cx
, JSObject
*obj
)
3801 return OBJ_IS_ARRAY(cx
, obj
);
3804 JS_PUBLIC_API(JSBool
)
3805 JS_GetArrayLength(JSContext
*cx
, JSObject
*obj
, jsuint
*lengthp
)
3808 return js_GetLengthProperty(cx
, obj
, lengthp
);
3811 JS_PUBLIC_API(JSBool
)
3812 JS_SetArrayLength(JSContext
*cx
, JSObject
*obj
, jsuint length
)
3815 return js_SetLengthProperty(cx
, obj
, length
);
3818 JS_PUBLIC_API(JSBool
)
3819 JS_HasArrayLength(JSContext
*cx
, JSObject
*obj
, jsuint
*lengthp
)
3822 return js_HasLengthProperty(cx
, obj
, lengthp
);
3825 JS_PUBLIC_API(JSBool
)
3826 JS_DefineElement(JSContext
*cx
, JSObject
*obj
, jsint index
, jsval value
,
3827 JSPropertyOp getter
, JSPropertyOp setter
, uintN attrs
)
3829 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
| JSRESOLVE_DECLARING
);
3832 return OBJ_DEFINE_PROPERTY(cx
, obj
, INT_TO_JSID(index
), value
,
3833 getter
, setter
, attrs
, NULL
);
3836 JS_PUBLIC_API(JSBool
)
3837 JS_AliasElement(JSContext
*cx
, JSObject
*obj
, const char *name
, jsint alias
)
3841 JSScopeProperty
*sprop
;
3845 if (!LookupProperty(cx
, obj
, name
, JSRESOLVE_QUALIFIED
, &obj2
, &prop
))
3848 js_ReportIsNotDefined(cx
, name
);
3851 if (obj2
!= obj
|| !OBJ_IS_NATIVE(obj
)) {
3853 OBJ_DROP_PROPERTY(cx
, obj2
, prop
);
3854 JS_snprintf(numBuf
, sizeof numBuf
, "%ld", (long)alias
);
3855 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_CANT_ALIAS
,
3856 numBuf
, name
, OBJ_GET_CLASS(cx
, obj2
)->name
);
3859 sprop
= (JSScopeProperty
*)prop
;
3860 ok
= (js_AddNativeProperty(cx
, obj
, INT_TO_JSID(alias
),
3861 sprop
->getter
, sprop
->setter
, sprop
->slot
,
3862 sprop
->attrs
, sprop
->flags
| SPROP_IS_ALIAS
,
3865 OBJ_DROP_PROPERTY(cx
, obj
, prop
);
3869 JS_PUBLIC_API(JSBool
)
3870 JS_AlreadyHasOwnElement(JSContext
*cx
, JSObject
*obj
, jsint index
,
3873 return AlreadyHasOwnPropertyHelper(cx
, obj
, INT_TO_JSID(index
), foundp
);
3876 JS_PUBLIC_API(JSBool
)
3877 JS_HasElement(JSContext
*cx
, JSObject
*obj
, jsint index
, JSBool
*foundp
)
3884 ok
= LookupPropertyById(cx
, obj
, INT_TO_JSID(index
),
3885 JSRESOLVE_QUALIFIED
| JSRESOLVE_DETECTING
,
3888 *foundp
= (prop
!= NULL
);
3890 OBJ_DROP_PROPERTY(cx
, obj2
, prop
);
3895 JS_PUBLIC_API(JSBool
)
3896 JS_LookupElement(JSContext
*cx
, JSObject
*obj
, jsint index
, jsval
*vp
)
3903 ok
= LookupPropertyById(cx
, obj
, INT_TO_JSID(index
), JSRESOLVE_QUALIFIED
,
3906 *vp
= LookupResult(cx
, obj
, obj2
, prop
);
3910 JS_PUBLIC_API(JSBool
)
3911 JS_GetElement(JSContext
*cx
, JSObject
*obj
, jsint index
, jsval
*vp
)
3913 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
);
3916 return OBJ_GET_PROPERTY(cx
, obj
, INT_TO_JSID(index
), vp
);
3919 JS_PUBLIC_API(JSBool
)
3920 JS_SetElement(JSContext
*cx
, JSObject
*obj
, jsint index
, jsval
*vp
)
3922 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
| JSRESOLVE_ASSIGNING
);
3925 return OBJ_SET_PROPERTY(cx
, obj
, INT_TO_JSID(index
), vp
);
3928 JS_PUBLIC_API(JSBool
)
3929 JS_DeleteElement(JSContext
*cx
, JSObject
*obj
, jsint index
)
3933 return JS_DeleteElement2(cx
, obj
, index
, &junk
);
3936 JS_PUBLIC_API(JSBool
)
3937 JS_DeleteElement2(JSContext
*cx
, JSObject
*obj
, jsint index
, jsval
*rval
)
3939 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
);
3942 return OBJ_DELETE_PROPERTY(cx
, obj
, INT_TO_JSID(index
), rval
);
3946 JS_ClearScope(JSContext
*cx
, JSObject
*obj
)
3950 if (obj
->map
->ops
->clear
)
3951 obj
->map
->ops
->clear(cx
, obj
);
3953 /* Clear cached class objects on the global object. */
3954 if (OBJ_GET_CLASS(cx
, obj
)->flags
& JSCLASS_IS_GLOBAL
) {
3957 for (key
= JSProto_Null
; key
< JSProto_LIMIT
; key
++)
3958 JS_SetReservedSlot(cx
, obj
, key
, JSVAL_VOID
);
3962 JS_PUBLIC_API(JSIdArray
*)
3963 JS_Enumerate(JSContext
*cx
, JSObject
*obj
)
3966 jsval iter_state
, num_properties
;
3974 iter_state
= JSVAL_NULL
;
3976 /* Get the number of properties to enumerate. */
3977 if (!OBJ_ENUMERATE(cx
, obj
, JSENUMERATE_INIT
, &iter_state
, &num_properties
))
3979 if (!JSVAL_IS_INT(num_properties
)) {
3984 /* Grow as needed if we don't know the exact amount ahead of time. */
3985 n
= JSVAL_TO_INT(num_properties
);
3989 /* Create an array of jsids large enough to hold all the properties */
3990 ida
= NewIdArray(cx
, n
);
3995 vector
= &ida
->vector
[0];
3997 if (!OBJ_ENUMERATE(cx
, obj
, JSENUMERATE_NEXT
, &iter_state
, &id
))
4000 /* No more jsid's to enumerate ? */
4001 if (iter_state
== JSVAL_NULL
)
4004 if (i
== ida
->length
) {
4005 ida
= SetIdArrayLength(cx
, ida
, ida
->length
* 2);
4008 vector
= &ida
->vector
[0];
4012 return SetIdArrayLength(cx
, ida
, i
);
4015 if (iter_state
!= JSVAL_NULL
)
4016 OBJ_ENUMERATE(cx
, obj
, JSENUMERATE_DESTROY
, &iter_state
, 0);
4018 JS_DestroyIdArray(cx
, ida
);
4023 * XXX reverse iterator for properties, unreverse and meld with jsinterp.c's
4024 * prop_iterator_class somehow...
4025 * + preserve the OBJ_ENUMERATE API while optimizing the native object case
4026 * + native case here uses a JSScopeProperty *, but that iterates in reverse!
4027 * + so we make non-native match, by reverse-iterating after JS_Enumerating
4029 #define JSSLOT_ITER_INDEX (JSSLOT_PRIVATE + 1)
4031 #if JSSLOT_ITER_INDEX >= JS_INITIAL_NSLOTS
4032 # error "JSSLOT_ITER_INDEX botch!"
4036 prop_iter_finalize(JSContext
*cx
, JSObject
*obj
)
4042 v
= obj
->fslots
[JSSLOT_ITER_INDEX
];
4043 if (JSVAL_IS_VOID(v
))
4046 i
= JSVAL_TO_INT(v
);
4048 /* Non-native case: destroy the ida enumerated when obj was created. */
4049 ida
= (JSIdArray
*) JS_GetPrivate(cx
, obj
);
4051 JS_DestroyIdArray(cx
, ida
);
4056 prop_iter_trace(JSTracer
*trc
, JSObject
*obj
)
4060 JSScopeProperty
*sprop
;
4064 v
= obj
->fslots
[JSSLOT_PRIVATE
];
4065 JS_ASSERT(!JSVAL_IS_VOID(v
));
4067 i
= JSVAL_TO_INT(obj
->fslots
[JSSLOT_ITER_INDEX
]);
4069 /* Native case: just mark the next property to visit. */
4070 sprop
= (JSScopeProperty
*) JSVAL_TO_PRIVATE(v
);
4072 TRACE_SCOPE_PROPERTY(trc
, sprop
);
4074 /* Non-native case: mark each id in the JSIdArray private. */
4075 ida
= (JSIdArray
*) JSVAL_TO_PRIVATE(v
);
4076 for (i
= 0, n
= ida
->length
; i
< n
; i
++) {
4077 id
= ida
->vector
[i
];
4083 static JSClass prop_iter_class
= {
4085 JSCLASS_HAS_PRIVATE
| JSCLASS_HAS_RESERVED_SLOTS(1) |
4086 JSCLASS_MARK_IS_TRACE
,
4087 JS_PropertyStub
, JS_PropertyStub
, JS_PropertyStub
, JS_PropertyStub
,
4088 JS_EnumerateStub
, JS_ResolveStub
, JS_ConvertStub
, prop_iter_finalize
,
4089 NULL
, NULL
, NULL
, NULL
,
4090 NULL
, NULL
, JS_CLASS_TRACE(prop_iter_trace
), NULL
4093 JS_PUBLIC_API(JSObject
*)
4094 JS_NewPropertyIterator(JSContext
*cx
, JSObject
*obj
)
4103 iterobj
= js_NewObject(cx
, &prop_iter_class
, NULL
, obj
, 0);
4107 if (OBJ_IS_NATIVE(obj
)) {
4108 /* Native case: start with the last property in obj's own scope. */
4109 scope
= OBJ_SCOPE(obj
);
4110 pdata
= (scope
->object
== obj
) ? scope
->lastProp
: NULL
;
4113 JSTempValueRooter tvr
;
4116 * Non-native case: enumerate a JSIdArray and keep it via private.
4118 * Note: we have to make sure that we root obj around the call to
4119 * JS_Enumerate to protect against multiple allocations under it.
4121 JS_PUSH_SINGLE_TEMP_ROOT(cx
, OBJECT_TO_JSVAL(iterobj
), &tvr
);
4122 ida
= JS_Enumerate(cx
, obj
);
4123 JS_POP_TEMP_ROOT(cx
, &tvr
);
4127 index
= ida
->length
;
4130 /* iterobj can not escape to other threads here. */
4131 STOBJ_SET_SLOT(iterobj
, JSSLOT_PRIVATE
, PRIVATE_TO_JSVAL(pdata
));
4132 STOBJ_SET_SLOT(iterobj
, JSSLOT_ITER_INDEX
, INT_TO_JSVAL(index
));
4136 cx
->weakRoots
.newborn
[GCX_OBJECT
] = NULL
;
4140 JS_PUBLIC_API(JSBool
)
4141 JS_NextProperty(JSContext
*cx
, JSObject
*iterobj
, jsid
*idp
)
4146 JSScopeProperty
*sprop
;
4150 i
= JSVAL_TO_INT(OBJ_GET_SLOT(cx
, iterobj
, JSSLOT_ITER_INDEX
));
4152 /* Native case: private data is a property tree node pointer. */
4153 obj
= OBJ_GET_PARENT(cx
, iterobj
);
4154 JS_ASSERT(OBJ_IS_NATIVE(obj
));
4155 scope
= OBJ_SCOPE(obj
);
4156 JS_ASSERT(scope
->object
== obj
);
4157 sprop
= (JSScopeProperty
*) JS_GetPrivate(cx
, iterobj
);
4160 * If the next property mapped by scope in the property tree ancestor
4161 * line is not enumerable, or it's an alias, or one or more properties
4162 * were deleted from the "middle" of the scope-mapped ancestor line
4163 * and the next property was among those deleted, skip it and keep on
4164 * trying to find an enumerable property that is still in scope.
4167 (!(sprop
->attrs
& JSPROP_ENUMERATE
) ||
4168 (sprop
->flags
& SPROP_IS_ALIAS
) ||
4169 (SCOPE_HAD_MIDDLE_DELETE(scope
) &&
4170 !SCOPE_HAS_PROPERTY(scope
, sprop
)))) {
4171 sprop
= sprop
->parent
;
4177 if (!JS_SetPrivate(cx
, iterobj
, sprop
->parent
))
4182 /* Non-native case: use the ida enumerated when iterobj was created. */
4183 ida
= (JSIdArray
*) JS_GetPrivate(cx
, iterobj
);
4184 JS_ASSERT(i
<= ida
->length
);
4188 *idp
= ida
->vector
[--i
];
4189 STOBJ_SET_SLOT(iterobj
, JSSLOT_ITER_INDEX
, INT_TO_JSVAL(i
));
4195 JS_PUBLIC_API(JSBool
)
4196 JS_CheckAccess(JSContext
*cx
, JSObject
*obj
, jsid id
, JSAccessMode mode
,
4197 jsval
*vp
, uintN
*attrsp
)
4200 return OBJ_CHECK_ACCESS(cx
, obj
, id
, mode
, vp
, attrsp
);
4204 ReservedSlotIndexOK(JSContext
*cx
, JSObject
*obj
, JSClass
*clasp
,
4205 uint32 index
, uint32 limit
)
4207 /* Check the computed, possibly per-instance, upper bound. */
4208 if (clasp
->reserveSlots
)
4209 JS_LOCK_OBJ_VOID(cx
, obj
, limit
+= clasp
->reserveSlots(cx
, obj
));
4210 if (index
>= limit
) {
4211 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
,
4212 JSMSG_RESERVED_SLOT_RANGE
);
4218 JS_PUBLIC_API(JSBool
)
4219 JS_GetReservedSlot(JSContext
*cx
, JSObject
*obj
, uint32 index
, jsval
*vp
)
4225 clasp
= OBJ_GET_CLASS(cx
, obj
);
4226 limit
= JSCLASS_RESERVED_SLOTS(clasp
);
4227 if (index
>= limit
&& !ReservedSlotIndexOK(cx
, obj
, clasp
, index
, limit
))
4229 slot
= JSSLOT_START(clasp
) + index
;
4230 *vp
= OBJ_GET_REQUIRED_SLOT(cx
, obj
, slot
);
4234 JS_PUBLIC_API(JSBool
)
4235 JS_SetReservedSlot(JSContext
*cx
, JSObject
*obj
, uint32 index
, jsval v
)
4241 clasp
= OBJ_GET_CLASS(cx
, obj
);
4242 limit
= JSCLASS_RESERVED_SLOTS(clasp
);
4243 if (index
>= limit
&& !ReservedSlotIndexOK(cx
, obj
, clasp
, index
, limit
))
4245 slot
= JSSLOT_START(clasp
) + index
;
4246 return OBJ_SET_REQUIRED_SLOT(cx
, obj
, slot
, v
);
4249 #ifdef JS_THREADSAFE
4250 JS_PUBLIC_API(jsrefcount
)
4251 JS_HoldPrincipals(JSContext
*cx
, JSPrincipals
*principals
)
4253 return JS_ATOMIC_INCREMENT(&principals
->refcount
);
4256 JS_PUBLIC_API(jsrefcount
)
4257 JS_DropPrincipals(JSContext
*cx
, JSPrincipals
*principals
)
4259 jsrefcount rc
= JS_ATOMIC_DECREMENT(&principals
->refcount
);
4261 principals
->destroy(cx
, principals
);
4266 JS_PUBLIC_API(JSSecurityCallbacks
*)
4267 JS_SetRuntimeSecurityCallbacks(JSRuntime
*rt
, JSSecurityCallbacks
*callbacks
)
4269 JSSecurityCallbacks
*oldcallbacks
;
4271 oldcallbacks
= rt
->securityCallbacks
;
4272 rt
->securityCallbacks
= callbacks
;
4273 return oldcallbacks
;
4276 JS_PUBLIC_API(JSSecurityCallbacks
*)
4277 JS_GetRuntimeSecurityCallbacks(JSRuntime
*rt
)
4279 return rt
->securityCallbacks
;
4282 JS_PUBLIC_API(JSSecurityCallbacks
*)
4283 JS_SetContextSecurityCallbacks(JSContext
*cx
, JSSecurityCallbacks
*callbacks
)
4285 JSSecurityCallbacks
*oldcallbacks
;
4287 oldcallbacks
= cx
->securityCallbacks
;
4288 cx
->securityCallbacks
= callbacks
;
4289 return oldcallbacks
;
4292 JS_PUBLIC_API(JSSecurityCallbacks
*)
4293 JS_GetSecurityCallbacks(JSContext
*cx
)
4295 return cx
->securityCallbacks
4296 ? cx
->securityCallbacks
4297 : cx
->runtime
->securityCallbacks
;
4300 JS_PUBLIC_API(JSFunction
*)
4301 JS_NewFunction(JSContext
*cx
, JSNative native
, uintN nargs
, uintN flags
,
4302 JSObject
*parent
, const char *name
)
4311 atom
= js_Atomize(cx
, name
, strlen(name
), 0);
4315 return js_NewFunction(cx
, NULL
, native
, nargs
, flags
, parent
, atom
);
4318 JS_PUBLIC_API(JSObject
*)
4319 JS_CloneFunctionObject(JSContext
*cx
, JSObject
*funobj
, JSObject
*parent
)
4322 if (OBJ_GET_CLASS(cx
, funobj
) != &js_FunctionClass
) {
4323 /* Indicate we cannot clone this object. */
4326 return js_CloneFunctionObject(cx
, GET_FUNCTION_PRIVATE(cx
, funobj
), parent
);
4329 JS_PUBLIC_API(JSObject
*)
4330 JS_GetFunctionObject(JSFunction
*fun
)
4332 return FUN_OBJECT(fun
);
4335 JS_PUBLIC_API(const char *)
4336 JS_GetFunctionName(JSFunction
*fun
)
4339 ? JS_GetStringBytes(ATOM_TO_STRING(fun
->atom
))
4343 JS_PUBLIC_API(JSString
*)
4344 JS_GetFunctionId(JSFunction
*fun
)
4346 return fun
->atom
? ATOM_TO_STRING(fun
->atom
) : NULL
;
4349 JS_PUBLIC_API(uintN
)
4350 JS_GetFunctionFlags(JSFunction
*fun
)
4352 #ifdef MOZILLA_1_8_BRANCH
4353 uintN flags
= fun
->flags
;
4355 return JSFUN_DISJOINT_FLAGS(flags
) |
4356 (JSFUN_GETTER_TEST(flags
) ? JSFUN_GETTER
: 0) |
4357 (JSFUN_SETTER_TEST(flags
) ? JSFUN_SETTER
: 0) |
4358 (JSFUN_BOUND_METHOD_TEST(flags
) ? JSFUN_BOUND_METHOD
: 0) |
4359 (JSFUN_HEAVYWEIGHT_TEST(flags
) ? JSFUN_HEAVYWEIGHT
: 0);
4365 JS_PUBLIC_API(uint16
)
4366 JS_GetFunctionArity(JSFunction
*fun
)
4371 JS_PUBLIC_API(JSBool
)
4372 JS_ObjectIsFunction(JSContext
*cx
, JSObject
*obj
)
4374 return OBJ_GET_CLASS(cx
, obj
) == &js_FunctionClass
;
4379 js_generic_fast_native_method_dispatcher(JSContext
*cx
, uintN argc
, jsval
*vp
)
4384 JSFastNative native
;
4386 if (!JS_GetReservedSlot(cx
, JSVAL_TO_OBJECT(*vp
), 0, &fsv
))
4388 fs
= (JSFunctionSpec
*) JSVAL_TO_PRIVATE(fsv
);
4389 JS_ASSERT((~fs
->flags
& (JSFUN_FAST_NATIVE
| JSFUN_GENERIC_NATIVE
)) == 0);
4392 * We know that vp[2] is valid because JS_DefineFunctions, which is our
4393 * only (indirect) referrer, defined us as requiring at least one argument
4394 * (notice how it passes fs->nargs + 1 as the next-to-last argument to
4395 * JS_DefineFunction).
4397 if (JSVAL_IS_PRIMITIVE(vp
[2])) {
4399 * Make sure that this is an object or null, as required by the generic
4402 if (!js_ValueToObject(cx
, vp
[2], &tmp
))
4404 vp
[2] = OBJECT_TO_JSVAL(tmp
);
4408 * Copy all actual (argc) arguments down over our |this| parameter, vp[1],
4409 * which is almost always the class constructor object, e.g. Array. Then
4410 * call the corresponding prototype native method with our first argument
4413 memmove(vp
+ 1, vp
+ 2, argc
* sizeof(jsval
));
4416 * Follow Function.prototype.apply and .call by using the global object as
4417 * the 'this' param if no args.
4419 if (!js_ComputeThis(cx
, JS_FALSE
, vp
+ 2))
4422 * Protect against argc underflowing. By calling js_ComputeThis, we made
4423 * it as if the static was called with one parameter, the explicit |this|
4431 (fs
->flags
& JSFUN_TRACEABLE
)
4432 ? ((JSTraceableNative
*) fs
->call
)->native
4435 (JSFastNative
) fs
->call
;
4436 return native(cx
, argc
, vp
);
4440 js_generic_native_method_dispatcher(JSContext
*cx
, JSObject
*obj
,
4441 uintN argc
, jsval
*argv
, jsval
*rval
)
4447 if (!JS_GetReservedSlot(cx
, JSVAL_TO_OBJECT(argv
[-2]), 0, &fsv
))
4449 fs
= (JSFunctionSpec
*) JSVAL_TO_PRIVATE(fsv
);
4450 JS_ASSERT((fs
->flags
& (JSFUN_FAST_NATIVE
| JSFUN_GENERIC_NATIVE
)) ==
4451 JSFUN_GENERIC_NATIVE
);
4454 * We know that argv[0] is valid because JS_DefineFunctions, which is our
4455 * only (indirect) referrer, defined us as requiring at least one argument
4456 * (notice how it passes fs->nargs + 1 as the next-to-last argument to
4457 * JS_DefineFunction).
4459 if (JSVAL_IS_PRIMITIVE(argv
[0])) {
4461 * Make sure that this is an object or null, as required by the generic
4464 if (!js_ValueToObject(cx
, argv
[0], &tmp
))
4466 argv
[0] = OBJECT_TO_JSVAL(tmp
);
4470 * Copy all actual (argc) arguments down over our |this| parameter,
4471 * argv[-1], which is almost always the class constructor object, e.g.
4472 * Array. Then call the corresponding prototype native method with our
4473 * first argument passed as |this|.
4475 memmove(argv
- 1, argv
, argc
* sizeof(jsval
));
4478 * Follow Function.prototype.apply and .call by using the global object as
4479 * the 'this' param if no args.
4481 JS_ASSERT(cx
->fp
->argv
== argv
);
4482 if (!js_ComputeThis(cx
, JS_TRUE
, argv
))
4484 cx
->fp
->thisp
= JSVAL_TO_OBJECT(argv
[-1]);
4487 * Protect against argc underflowing. By calling js_ComputeThis, we made
4488 * it as if the static was called with one parameter, the explicit |this|
4494 return fs
->call(cx
, JSVAL_TO_OBJECT(argv
[-1]), argc
, argv
, rval
);
4498 JS_PUBLIC_API(JSBool
)
4499 JS_DefineFunctions(JSContext
*cx
, JSObject
*obj
, JSFunctionSpec
*fs
)
4507 for (; fs
->name
; fs
++) {
4511 * Define a generic arity N+1 static method for the arity N prototype
4512 * method if flags contains JSFUN_GENERIC_NATIVE.
4514 if (flags
& JSFUN_GENERIC_NATIVE
) {
4516 ctor
= JS_GetConstructor(cx
, obj
);
4521 flags
&= ~JSFUN_GENERIC_NATIVE
;
4522 fun
= JS_DefineFunction(cx
, ctor
, fs
->name
,
4523 (flags
& JSFUN_FAST_NATIVE
)
4525 js_generic_fast_native_method_dispatcher
4526 : js_generic_native_method_dispatcher
,
4528 flags
& ~JSFUN_TRACEABLE
);
4531 fun
->u
.n
.extra
= (uint16
)fs
->extra
;
4534 * As jsapi.h notes, fs must point to storage that lives as long
4535 * as fun->object lives.
4537 if (!JS_SetReservedSlot(cx
, FUN_OBJECT(fun
), 0, PRIVATE_TO_JSVAL(fs
)))
4541 JS_ASSERT(!(flags
& JSFUN_FAST_NATIVE
) ||
4542 (uint16
)(fs
->extra
>> 16) <= fs
->nargs
);
4543 fun
= JS_DefineFunction(cx
, obj
, fs
->name
, fs
->call
, fs
->nargs
, flags
);
4546 fun
->u
.n
.extra
= (uint16
)fs
->extra
;
4551 JS_PUBLIC_API(JSFunction
*)
4552 JS_DefineFunction(JSContext
*cx
, JSObject
*obj
, const char *name
, JSNative call
,
4553 uintN nargs
, uintN attrs
)
4558 atom
= js_Atomize(cx
, name
, strlen(name
), 0);
4561 return js_DefineFunction(cx
, obj
, atom
, call
, nargs
, attrs
);
4564 JS_PUBLIC_API(JSFunction
*)
4565 JS_DefineUCFunction(JSContext
*cx
, JSObject
*obj
,
4566 const jschar
*name
, size_t namelen
, JSNative call
,
4567 uintN nargs
, uintN attrs
)
4571 atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
4574 return js_DefineFunction(cx
, obj
, atom
, call
, nargs
, attrs
);
4577 JS_PUBLIC_API(JSScript
*)
4578 JS_CompileScript(JSContext
*cx
, JSObject
*obj
,
4579 const char *bytes
, size_t length
,
4580 const char *filename
, uintN lineno
)
4586 chars
= js_InflateString(cx
, bytes
, &length
);
4589 script
= JS_CompileUCScript(cx
, obj
, chars
, length
, filename
, lineno
);
4594 JS_PUBLIC_API(JSScript
*)
4595 JS_CompileScriptForPrincipals(JSContext
*cx
, JSObject
*obj
,
4596 JSPrincipals
*principals
,
4597 const char *bytes
, size_t length
,
4598 const char *filename
, uintN lineno
)
4604 chars
= js_InflateString(cx
, bytes
, &length
);
4607 script
= JS_CompileUCScriptForPrincipals(cx
, obj
, principals
,
4608 chars
, length
, filename
, lineno
);
4613 JS_PUBLIC_API(JSScript
*)
4614 JS_CompileUCScript(JSContext
*cx
, JSObject
*obj
,
4615 const jschar
*chars
, size_t length
,
4616 const char *filename
, uintN lineno
)
4619 return JS_CompileUCScriptForPrincipals(cx
, obj
, NULL
, chars
, length
,
4623 #define LAST_FRAME_EXCEPTION_CHECK(cx,result) \
4625 if (!(result) && !((cx)->options & JSOPTION_DONT_REPORT_UNCAUGHT)) \
4626 js_ReportUncaughtException(cx); \
4629 #define LAST_FRAME_CHECKS(cx,result) \
4632 (cx)->weakRoots.lastInternalResult = JSVAL_NULL; \
4633 LAST_FRAME_EXCEPTION_CHECK(cx, result); \
4637 #define JS_OPTIONS_TO_TCFLAGS(cx) \
4638 ((((cx)->options & JSOPTION_COMPILE_N_GO) ? TCF_COMPILE_N_GO : 0) | \
4639 (((cx)->options & JSOPTION_NO_SCRIPT_RVAL) ? TCF_NO_SCRIPT_RVAL : 0))
4641 JS_PUBLIC_API(JSScript
*)
4642 JS_CompileUCScriptForPrincipals(JSContext
*cx
, JSObject
*obj
,
4643 JSPrincipals
*principals
,
4644 const jschar
*chars
, size_t length
,
4645 const char *filename
, uintN lineno
)
4651 tcflags
= JS_OPTIONS_TO_TCFLAGS(cx
);
4652 script
= js_CompileScript(cx
, obj
, NULL
, principals
, tcflags
,
4653 chars
, length
, NULL
, filename
, lineno
);
4654 LAST_FRAME_CHECKS(cx
, script
);
4658 JS_PUBLIC_API(JSBool
)
4659 JS_BufferIsCompilableUnit(JSContext
*cx
, JSObject
*obj
,
4660 const char *bytes
, size_t length
)
4664 JSExceptionState
*exnState
;
4666 JSErrorReporter older
;
4669 chars
= js_InflateString(cx
, bytes
, &length
);
4674 * Return true on any out-of-memory error, so our caller doesn't try to
4675 * collect more buffered source.
4678 exnState
= JS_SaveExceptionState(cx
);
4679 if (js_InitParseContext(cx
, &pc
, NULL
, NULL
, chars
, length
, NULL
, NULL
,
4681 older
= JS_SetErrorReporter(cx
, NULL
);
4682 if (!js_ParseScript(cx
, obj
, &pc
) &&
4683 (pc
.tokenStream
.flags
& TSF_UNEXPECTED_EOF
)) {
4685 * We ran into an error. If it was because we ran out of source,
4686 * we return false, so our caller will know to try to collect more
4691 JS_SetErrorReporter(cx
, older
);
4692 js_FinishParseContext(cx
, &pc
);
4695 JS_RestoreExceptionState(cx
, exnState
);
4699 JS_PUBLIC_API(JSScript
*)
4700 JS_CompileFile(JSContext
*cx
, JSObject
*obj
, const char *filename
)
4707 if (!filename
|| strcmp(filename
, "-") == 0) {
4710 fp
= fopen(filename
, "r");
4712 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_CANT_OPEN
,
4713 filename
, "No such file or directory");
4718 tcflags
= JS_OPTIONS_TO_TCFLAGS(cx
);
4719 script
= js_CompileScript(cx
, obj
, NULL
, NULL
, tcflags
,
4720 NULL
, 0, fp
, filename
, 1);
4723 LAST_FRAME_CHECKS(cx
, script
);
4727 JS_PUBLIC_API(JSScript
*)
4728 JS_CompileFileHandle(JSContext
*cx
, JSObject
*obj
, const char *filename
,
4731 return JS_CompileFileHandleForPrincipals(cx
, obj
, filename
, file
, NULL
);
4734 JS_PUBLIC_API(JSScript
*)
4735 JS_CompileFileHandleForPrincipals(JSContext
*cx
, JSObject
*obj
,
4736 const char *filename
, FILE *file
,
4737 JSPrincipals
*principals
)
4743 tcflags
= JS_OPTIONS_TO_TCFLAGS(cx
);
4744 script
= js_CompileScript(cx
, obj
, NULL
, principals
, tcflags
,
4745 NULL
, 0, file
, filename
, 1);
4746 LAST_FRAME_CHECKS(cx
, script
);
4750 JS_PUBLIC_API(JSObject
*)
4751 JS_NewScriptObject(JSContext
*cx
, JSScript
*script
)
4753 JSTempValueRooter tvr
;
4758 return js_NewObject(cx
, &js_ScriptClass
, NULL
, NULL
, 0);
4760 JS_ASSERT(!script
->u
.object
);
4762 JS_PUSH_TEMP_ROOT_SCRIPT(cx
, script
, &tvr
);
4763 obj
= js_NewObject(cx
, &js_ScriptClass
, NULL
, NULL
, 0);
4765 JS_SetPrivate(cx
, obj
, script
);
4766 script
->u
.object
= obj
;
4767 #ifdef CHECK_SCRIPT_OWNER
4768 script
->owner
= NULL
;
4771 JS_POP_TEMP_ROOT(cx
, &tvr
);
4775 JS_PUBLIC_API(JSObject
*)
4776 JS_GetScriptObject(JSScript
*script
)
4778 return script
->u
.object
;
4782 JS_DestroyScript(JSContext
*cx
, JSScript
*script
)
4785 js_DestroyScript(cx
, script
);
4788 JS_PUBLIC_API(JSFunction
*)
4789 JS_CompileFunction(JSContext
*cx
, JSObject
*obj
, const char *name
,
4790 uintN nargs
, const char **argnames
,
4791 const char *bytes
, size_t length
,
4792 const char *filename
, uintN lineno
)
4798 chars
= js_InflateString(cx
, bytes
, &length
);
4801 fun
= JS_CompileUCFunction(cx
, obj
, name
, nargs
, argnames
, chars
, length
,
4807 JS_PUBLIC_API(JSFunction
*)
4808 JS_CompileFunctionForPrincipals(JSContext
*cx
, JSObject
*obj
,
4809 JSPrincipals
*principals
, const char *name
,
4810 uintN nargs
, const char **argnames
,
4811 const char *bytes
, size_t length
,
4812 const char *filename
, uintN lineno
)
4818 chars
= js_InflateString(cx
, bytes
, &length
);
4821 fun
= JS_CompileUCFunctionForPrincipals(cx
, obj
, principals
, name
,
4822 nargs
, argnames
, chars
, length
,
4828 JS_PUBLIC_API(JSFunction
*)
4829 JS_CompileUCFunction(JSContext
*cx
, JSObject
*obj
, const char *name
,
4830 uintN nargs
, const char **argnames
,
4831 const jschar
*chars
, size_t length
,
4832 const char *filename
, uintN lineno
)
4835 return JS_CompileUCFunctionForPrincipals(cx
, obj
, NULL
, name
,
4841 JS_PUBLIC_API(JSFunction
*)
4842 JS_CompileUCFunctionForPrincipals(JSContext
*cx
, JSObject
*obj
,
4843 JSPrincipals
*principals
, const char *name
,
4844 uintN nargs
, const char **argnames
,
4845 const jschar
*chars
, size_t length
,
4846 const char *filename
, uintN lineno
)
4849 JSTempValueRooter tvr
;
4850 JSAtom
*funAtom
, *argAtom
;
4857 funAtom
= js_Atomize(cx
, name
, strlen(name
), 0);
4863 fun
= js_NewFunction(cx
, NULL
, NULL
, 0, JSFUN_INTERPRETED
, obj
, funAtom
);
4867 MUST_FLOW_THROUGH("out");
4868 JS_PUSH_TEMP_ROOT_OBJECT(cx
, FUN_OBJECT(fun
), &tvr
);
4869 for (i
= 0; i
< nargs
; i
++) {
4870 argAtom
= js_Atomize(cx
, argnames
[i
], strlen(argnames
[i
]), 0);
4875 if (!js_AddLocal(cx
, fun
, argAtom
, JSLOCAL_ARG
)) {
4881 if (!js_CompileFunctionBody(cx
, fun
, principals
, chars
, length
,
4882 filename
, lineno
)) {
4889 !OBJ_DEFINE_PROPERTY(cx
, obj
, ATOM_TO_JSID(funAtom
),
4890 OBJECT_TO_JSVAL(FUN_OBJECT(fun
)),
4891 NULL
, NULL
, JSPROP_ENUMERATE
, NULL
)) {
4895 #ifdef JS_SCOPE_DEPTH_METER
4897 JSObject
*pobj
= obj
;
4900 while ((pobj
= OBJ_GET_PARENT(cx
, pobj
)) != NULL
)
4902 JS_BASIC_STATS_ACCUM(&cx
->runtime
->hostenvScopeDepthStats
, depth
);
4907 cx
->weakRoots
.newborn
[JSTRACE_OBJECT
] = FUN_OBJECT(fun
);
4908 JS_POP_TEMP_ROOT(cx
, &tvr
);
4911 LAST_FRAME_CHECKS(cx
, fun
);
4915 JS_PUBLIC_API(JSString
*)
4916 JS_DecompileScript(JSContext
*cx
, JSScript
*script
, const char *name
,
4923 jp
= JS_NEW_PRINTER(cx
, name
, NULL
,
4924 indent
& ~JS_DONT_PRETTY_PRINT
,
4925 !(indent
& JS_DONT_PRETTY_PRINT
));
4928 if (js_DecompileScript(jp
, script
))
4929 str
= js_GetPrinterOutput(jp
);
4932 js_DestroyPrinter(jp
);
4936 JS_PUBLIC_API(JSString
*)
4937 JS_DecompileFunction(JSContext
*cx
, JSFunction
*fun
, uintN indent
)
4943 jp
= JS_NEW_PRINTER(cx
, "JS_DecompileFunction", fun
,
4944 indent
& ~JS_DONT_PRETTY_PRINT
,
4945 !(indent
& JS_DONT_PRETTY_PRINT
));
4948 if (js_DecompileFunction(jp
))
4949 str
= js_GetPrinterOutput(jp
);
4952 js_DestroyPrinter(jp
);
4956 JS_PUBLIC_API(JSString
*)
4957 JS_DecompileFunctionBody(JSContext
*cx
, JSFunction
*fun
, uintN indent
)
4963 jp
= JS_NEW_PRINTER(cx
, "JS_DecompileFunctionBody", fun
,
4964 indent
& ~JS_DONT_PRETTY_PRINT
,
4965 !(indent
& JS_DONT_PRETTY_PRINT
));
4968 if (js_DecompileFunctionBody(jp
))
4969 str
= js_GetPrinterOutput(jp
);
4972 js_DestroyPrinter(jp
);
4976 JS_PUBLIC_API(JSBool
)
4977 JS_ExecuteScript(JSContext
*cx
, JSObject
*obj
, JSScript
*script
, jsval
*rval
)
4982 ok
= js_Execute(cx
, obj
, script
, NULL
, 0, rval
);
4983 LAST_FRAME_CHECKS(cx
, ok
);
4987 JS_PUBLIC_API(JSBool
)
4988 JS_ExecuteScriptPart(JSContext
*cx
, JSObject
*obj
, JSScript
*script
,
4989 JSExecPart part
, jsval
*rval
)
4992 JSDebugHooks
*hooks
;
4995 /* Make a temporary copy of the JSScript structure and farble it a bit. */
4997 if (part
== JSEXEC_PROLOG
) {
4998 tmp
.length
= PTRDIFF(tmp
.main
, tmp
.code
, jsbytecode
);
5000 tmp
.length
-= PTRDIFF(tmp
.main
, tmp
.code
, jsbytecode
);
5001 tmp
.code
= tmp
.main
;
5004 /* Tell the debugger about our temporary copy of the script structure. */
5005 hooks
= cx
->debugHooks
;
5006 if (hooks
->newScriptHook
) {
5007 hooks
->newScriptHook(cx
, tmp
.filename
, tmp
.lineno
, &tmp
, NULL
,
5008 hooks
->newScriptHookData
);
5011 /* Execute the farbled struct and tell the debugger to forget about it. */
5012 ok
= JS_ExecuteScript(cx
, obj
, &tmp
, rval
);
5013 if (hooks
->destroyScriptHook
)
5014 hooks
->destroyScriptHook(cx
, &tmp
, hooks
->destroyScriptHookData
);
5018 /* Ancient uintN nbytes is part of API/ABI, so use size_t length local. */
5019 JS_PUBLIC_API(JSBool
)
5020 JS_EvaluateScript(JSContext
*cx
, JSObject
*obj
,
5021 const char *bytes
, uintN nbytes
,
5022 const char *filename
, uintN lineno
,
5025 size_t length
= nbytes
;
5030 chars
= js_InflateString(cx
, bytes
, &length
);
5033 ok
= JS_EvaluateUCScript(cx
, obj
, chars
, length
, filename
, lineno
, rval
);
5038 /* Ancient uintN nbytes is part of API/ABI, so use size_t length local. */
5039 JS_PUBLIC_API(JSBool
)
5040 JS_EvaluateScriptForPrincipals(JSContext
*cx
, JSObject
*obj
,
5041 JSPrincipals
*principals
,
5042 const char *bytes
, uintN nbytes
,
5043 const char *filename
, uintN lineno
,
5046 size_t length
= nbytes
;
5051 chars
= js_InflateString(cx
, bytes
, &length
);
5054 ok
= JS_EvaluateUCScriptForPrincipals(cx
, obj
, principals
, chars
, length
,
5055 filename
, lineno
, rval
);
5060 JS_PUBLIC_API(JSBool
)
5061 JS_EvaluateUCScript(JSContext
*cx
, JSObject
*obj
,
5062 const jschar
*chars
, uintN length
,
5063 const char *filename
, uintN lineno
,
5067 return JS_EvaluateUCScriptForPrincipals(cx
, obj
, NULL
, chars
, length
,
5068 filename
, lineno
, rval
);
5071 JS_PUBLIC_API(JSBool
)
5072 JS_EvaluateUCScriptForPrincipals(JSContext
*cx
, JSObject
*obj
,
5073 JSPrincipals
*principals
,
5074 const jschar
*chars
, uintN length
,
5075 const char *filename
, uintN lineno
,
5082 script
= js_CompileScript(cx
, obj
, NULL
, principals
,
5084 ? TCF_COMPILE_N_GO
| TCF_NO_SCRIPT_RVAL
5086 chars
, length
, NULL
, filename
, lineno
);
5088 LAST_FRAME_CHECKS(cx
, script
);
5091 ok
= js_Execute(cx
, obj
, script
, NULL
, 0, rval
);
5092 LAST_FRAME_CHECKS(cx
, ok
);
5093 JS_DestroyScript(cx
, script
);
5097 JS_PUBLIC_API(JSBool
)
5098 JS_CallFunction(JSContext
*cx
, JSObject
*obj
, JSFunction
*fun
, uintN argc
,
5099 jsval
*argv
, jsval
*rval
)
5104 ok
= js_InternalCall(cx
, obj
, OBJECT_TO_JSVAL(FUN_OBJECT(fun
)), argc
, argv
,
5106 LAST_FRAME_CHECKS(cx
, ok
);
5110 JS_PUBLIC_API(JSBool
)
5111 JS_CallFunctionName(JSContext
*cx
, JSObject
*obj
, const char *name
, uintN argc
,
5112 jsval
*argv
, jsval
*rval
)
5118 #if JS_HAS_XML_SUPPORT
5119 if (OBJECT_IS_XML(cx
, obj
)) {
5120 JSXMLObjectOps
*ops
;
5123 ops
= (JSXMLObjectOps
*) obj
->map
->ops
;
5124 atom
= js_Atomize(cx
, name
, strlen(name
), 0);
5127 obj
= ops
->getMethod(cx
, obj
, ATOM_TO_JSID(atom
), &fval
);
5132 if (!JS_GetProperty(cx
, obj
, name
, &fval
))
5134 ok
= js_InternalCall(cx
, obj
, fval
, argc
, argv
, rval
);
5135 LAST_FRAME_CHECKS(cx
, ok
);
5139 JS_PUBLIC_API(JSBool
)
5140 JS_CallFunctionValue(JSContext
*cx
, JSObject
*obj
, jsval fval
, uintN argc
,
5141 jsval
*argv
, jsval
*rval
)
5146 ok
= js_InternalCall(cx
, obj
, fval
, argc
, argv
, rval
);
5147 LAST_FRAME_CHECKS(cx
, ok
);
5152 JS_SetOperationCallback(JSContext
*cx
, JSOperationCallback callback
,
5153 uint32 operationLimit
)
5155 JS_ASSERT(callback
);
5156 JS_ASSERT(operationLimit
<= JS_MAX_OPERATION_LIMIT
);
5157 JS_ASSERT(operationLimit
> 0);
5159 cx
->operationCount
= (int32
) operationLimit
;
5160 cx
->operationLimit
= operationLimit
;
5161 cx
->operationCallbackIsSet
= 1;
5162 cx
->operationCallback
= callback
;
5166 JS_ClearOperationCallback(JSContext
*cx
)
5168 cx
->operationCount
= (int32
) JS_MAX_OPERATION_LIMIT
;
5169 cx
->operationLimit
= JS_MAX_OPERATION_LIMIT
;
5170 cx
->operationCallbackIsSet
= 0;
5171 cx
->operationCallback
= NULL
;
5174 JS_PUBLIC_API(JSOperationCallback
)
5175 JS_GetOperationCallback(JSContext
*cx
)
5177 JS_ASSERT(cx
->operationCallbackIsSet
|| !cx
->operationCallback
);
5178 return cx
->operationCallback
;
5181 JS_PUBLIC_API(uint32
)
5182 JS_GetOperationLimit(JSContext
*cx
)
5184 JS_ASSERT(cx
->operationCallbackIsSet
);
5185 return cx
->operationLimit
;
5189 JS_SetOperationLimit(JSContext
*cx
, uint32 operationLimit
)
5191 JS_ASSERT(operationLimit
<= JS_MAX_OPERATION_LIMIT
);
5192 JS_ASSERT(operationLimit
> 0);
5193 JS_ASSERT(cx
->operationCallbackIsSet
);
5195 cx
->operationLimit
= operationLimit
;
5196 if (cx
->operationCount
> (int32
) operationLimit
)
5197 cx
->operationCount
= (int32
) operationLimit
;
5200 JS_PUBLIC_API(JSBranchCallback
)
5201 JS_SetBranchCallback(JSContext
*cx
, JSBranchCallback cb
)
5203 JSBranchCallback oldcb
;
5205 if (cx
->operationCallbackIsSet
) {
5208 "JS API usage error: call to JS_SetOperationCallback is followed by\n"
5209 "invocation of deprecated JS_SetBranchCallback\n");
5212 cx
->operationCallbackIsSet
= 0;
5215 oldcb
= (JSBranchCallback
) cx
->operationCallback
;
5218 cx
->operationCount
= JSOW_SCRIPT_JUMP
;
5219 cx
->operationLimit
= JSOW_SCRIPT_JUMP
;
5220 cx
->operationCallback
= (JSOperationCallback
) cb
;
5222 JS_ClearOperationCallback(cx
);
5227 JS_PUBLIC_API(JSBool
)
5228 JS_IsRunning(JSContext
*cx
)
5230 return cx
->fp
!= NULL
;
5233 JS_PUBLIC_API(JSBool
)
5234 JS_IsConstructing(JSContext
*cx
)
5236 return cx
->fp
&& (cx
->fp
->flags
& JSFRAME_CONSTRUCTING
);
5239 JS_FRIEND_API(JSBool
)
5240 JS_IsAssigning(JSContext
*cx
)
5244 for (fp
= cx
->fp
; fp
&& !fp
->script
; fp
= fp
->down
)
5246 if (!fp
|| !fp
->regs
)
5248 return (js_CodeSpec
[*fp
->regs
->pc
].format
& JOF_ASSIGNING
) != 0;
5252 JS_SetCallReturnValue2(JSContext
*cx
, jsval v
)
5254 #if JS_HAS_LVALUE_RETURN
5256 cx
->rval2set
= JS_TRUE
;
5260 JS_PUBLIC_API(JSStackFrame
*)
5261 JS_SaveFrameChain(JSContext
*cx
)
5269 JS_ASSERT(!fp
->dormantNext
);
5270 fp
->dormantNext
= cx
->dormantFrameChain
;
5271 cx
->dormantFrameChain
= fp
;
5277 JS_RestoreFrameChain(JSContext
*cx
, JSStackFrame
*fp
)
5283 JS_ASSERT(fp
== cx
->dormantFrameChain
);
5285 cx
->dormantFrameChain
= fp
->dormantNext
;
5286 fp
->dormantNext
= NULL
;
5289 /************************************************************************/
5291 JS_PUBLIC_API(JSString
*)
5292 JS_NewString(JSContext
*cx
, char *bytes
, size_t nbytes
)
5294 size_t length
= nbytes
;
5300 /* Make a UTF-16 vector from the 8-bit char codes in bytes. */
5301 chars
= js_InflateString(cx
, bytes
, &length
);
5305 /* Free chars (but not bytes, which caller frees on error) if we fail. */
5306 str
= js_NewString(cx
, chars
, length
);
5312 /* Hand off bytes to the deflated string cache, if possible. */
5313 if (!js_SetStringBytes(cx
, str
, bytes
, nbytes
))
5318 JS_PUBLIC_API(JSString
*)
5319 JS_NewStringCopyN(JSContext
*cx
, const char *s
, size_t n
)
5325 js
= js_InflateString(cx
, s
, &n
);
5328 str
= js_NewString(cx
, js
, n
);
5334 JS_PUBLIC_API(JSString
*)
5335 JS_NewStringCopyZ(JSContext
*cx
, const char *s
)
5343 return cx
->runtime
->emptyString
;
5345 js
= js_InflateString(cx
, s
, &n
);
5348 str
= js_NewString(cx
, js
, n
);
5354 JS_PUBLIC_API(JSString
*)
5355 JS_InternString(JSContext
*cx
, const char *s
)
5360 atom
= js_Atomize(cx
, s
, strlen(s
), ATOM_INTERNED
);
5363 return ATOM_TO_STRING(atom
);
5366 JS_PUBLIC_API(JSString
*)
5367 JS_NewUCString(JSContext
*cx
, jschar
*chars
, size_t length
)
5370 return js_NewString(cx
, chars
, length
);
5373 JS_PUBLIC_API(JSString
*)
5374 JS_NewUCStringCopyN(JSContext
*cx
, const jschar
*s
, size_t n
)
5377 return js_NewStringCopyN(cx
, s
, n
);
5380 JS_PUBLIC_API(JSString
*)
5381 JS_NewUCStringCopyZ(JSContext
*cx
, const jschar
*s
)
5385 return cx
->runtime
->emptyString
;
5386 return js_NewStringCopyZ(cx
, s
);
5389 JS_PUBLIC_API(JSString
*)
5390 JS_InternUCStringN(JSContext
*cx
, const jschar
*s
, size_t length
)
5395 atom
= js_AtomizeChars(cx
, s
, length
, ATOM_INTERNED
);
5398 return ATOM_TO_STRING(atom
);
5401 JS_PUBLIC_API(JSString
*)
5402 JS_InternUCString(JSContext
*cx
, const jschar
*s
)
5404 return JS_InternUCStringN(cx
, s
, js_strlen(s
));
5407 JS_PUBLIC_API(char *)
5408 JS_GetStringBytes(JSString
*str
)
5412 bytes
= js_GetStringBytes(NULL
, str
);
5413 return (char *)(bytes
? bytes
: "");
5416 JS_PUBLIC_API(jschar
*)
5417 JS_GetStringChars(JSString
*str
)
5423 * API botch (again, shades of JS_GetStringBytes): we have no cx to report
5424 * out-of-memory when undepending strings, so we replace js_UndependString
5425 * with explicit malloc call and ignore its errors.
5427 * If we fail to convert a dependent string into an independent one, our
5428 * caller will not be guaranteed a \u0000 terminator as a backstop. This
5429 * may break some clients who already misbehave on embedded NULs.
5431 * The gain of dependent strings, which cure quadratic and cubic growth
5432 * rate bugs in string concatenation, is worth this slight loss in API
5435 if (JSSTRING_IS_DEPENDENT(str
)) {
5436 n
= JSSTRDEP_LENGTH(str
);
5437 size
= (n
+ 1) * sizeof(jschar
);
5438 s
= (jschar
*) malloc(size
);
5440 memcpy(s
, JSSTRDEP_CHARS(str
), n
* sizeof *s
);
5442 JSFLATSTR_INIT(str
, s
, n
);
5444 s
= JSSTRDEP_CHARS(str
);
5447 JSFLATSTR_CLEAR_MUTABLE(str
);
5448 s
= JSFLATSTR_CHARS(str
);
5453 JS_PUBLIC_API(size_t)
5454 JS_GetStringLength(JSString
*str
)
5456 return JSSTRING_LENGTH(str
);
5460 JS_CompareStrings(JSString
*str1
, JSString
*str2
)
5462 return js_CompareStrings(str1
, str2
);
5465 JS_PUBLIC_API(JSString
*)
5466 JS_NewGrowableString(JSContext
*cx
, jschar
*chars
, size_t length
)
5471 str
= js_NewString(cx
, chars
, length
);
5474 JSFLATSTR_SET_MUTABLE(str
);
5478 JS_PUBLIC_API(JSString
*)
5479 JS_NewDependentString(JSContext
*cx
, JSString
*str
, size_t start
,
5483 return js_NewDependentString(cx
, str
, start
, length
);
5486 JS_PUBLIC_API(JSString
*)
5487 JS_ConcatStrings(JSContext
*cx
, JSString
*left
, JSString
*right
)
5490 return js_ConcatStrings(cx
, left
, right
);
5493 JS_PUBLIC_API(const jschar
*)
5494 JS_UndependString(JSContext
*cx
, JSString
*str
)
5497 return js_UndependString(cx
, str
);
5500 JS_PUBLIC_API(JSBool
)
5501 JS_MakeStringImmutable(JSContext
*cx
, JSString
*str
)
5504 return js_MakeStringImmutable(cx
, str
);
5507 JS_PUBLIC_API(JSBool
)
5508 JS_EncodeCharacters(JSContext
*cx
, const jschar
*src
, size_t srclen
, char *dst
,
5514 n
= js_GetDeflatedStringLength(cx
, src
, srclen
);
5515 if (n
== (size_t)-1) {
5523 return js_DeflateStringToBuffer(cx
, src
, srclen
, dst
, dstlenp
);
5526 JS_PUBLIC_API(JSBool
)
5527 JS_DecodeBytes(JSContext
*cx
, const char *src
, size_t srclen
, jschar
*dst
,
5530 return js_InflateStringToBuffer(cx
, src
, srclen
, dst
, dstlenp
);
5533 JS_PUBLIC_API(char *)
5534 JS_EncodeString(JSContext
*cx
, JSString
*str
)
5536 return js_DeflateString(cx
, JSSTRING_CHARS(str
), JSSTRING_LENGTH(str
));
5539 JS_PUBLIC_API(JSBool
)
5540 JS_Stringify(JSContext
*cx
, jsval
*vp
, JSObject
*replacer
,
5541 JSONWriteCallback callback
, void *data
)
5544 return js_Stringify(cx
, vp
, replacer
, callback
, data
, 0);
5547 JS_PUBLIC_API(JSBool
)
5548 JS_TryJSON(JSContext
*cx
, jsval
*vp
)
5551 return js_TryJSON(cx
, vp
);
5554 JS_PUBLIC_API(JSONParser
*)
5555 JS_BeginJSONParse(JSContext
*cx
, jsval
*vp
)
5558 return js_BeginJSONParse(cx
, vp
);
5561 JS_PUBLIC_API(JSBool
)
5562 JS_ConsumeJSONText(JSContext
*cx
, JSONParser
*jp
, const jschar
*data
, uint32 len
)
5565 return js_ConsumeJSONText(cx
, jp
, data
, len
);
5568 JS_PUBLIC_API(JSBool
)
5569 JS_FinishJSONParse(JSContext
*cx
, JSONParser
*jp
)
5572 return js_FinishJSONParse(cx
, jp
);
5576 * The following determines whether C Strings are to be treated as UTF-8
5577 * or ISO-8859-1. For correct operation, it must be set prior to the
5578 * first call to JS_NewRuntime.
5580 #ifndef JS_C_STRINGS_ARE_UTF8
5581 JSBool js_CStringsAreUTF8
= JS_FALSE
;
5584 JS_PUBLIC_API(JSBool
)
5585 JS_CStringsAreUTF8()
5587 return js_CStringsAreUTF8
;
5591 JS_SetCStringsAreUTF8()
5593 JS_ASSERT(!js_NewRuntimeWasCalled
);
5595 #ifndef JS_C_STRINGS_ARE_UTF8
5596 js_CStringsAreUTF8
= JS_TRUE
;
5600 /************************************************************************/
5603 JS_ReportError(JSContext
*cx
, const char *format
, ...)
5607 va_start(ap
, format
);
5608 js_ReportErrorVA(cx
, JSREPORT_ERROR
, format
, ap
);
5613 JS_ReportErrorNumber(JSContext
*cx
, JSErrorCallback errorCallback
,
5614 void *userRef
, const uintN errorNumber
, ...)
5618 va_start(ap
, errorNumber
);
5619 js_ReportErrorNumberVA(cx
, JSREPORT_ERROR
, errorCallback
, userRef
,
5620 errorNumber
, JS_TRUE
, ap
);
5625 JS_ReportErrorNumberUC(JSContext
*cx
, JSErrorCallback errorCallback
,
5626 void *userRef
, const uintN errorNumber
, ...)
5630 va_start(ap
, errorNumber
);
5631 js_ReportErrorNumberVA(cx
, JSREPORT_ERROR
, errorCallback
, userRef
,
5632 errorNumber
, JS_FALSE
, ap
);
5636 JS_PUBLIC_API(JSBool
)
5637 JS_ReportWarning(JSContext
*cx
, const char *format
, ...)
5642 va_start(ap
, format
);
5643 ok
= js_ReportErrorVA(cx
, JSREPORT_WARNING
, format
, ap
);
5648 JS_PUBLIC_API(JSBool
)
5649 JS_ReportErrorFlagsAndNumber(JSContext
*cx
, uintN flags
,
5650 JSErrorCallback errorCallback
, void *userRef
,
5651 const uintN errorNumber
, ...)
5656 va_start(ap
, errorNumber
);
5657 ok
= js_ReportErrorNumberVA(cx
, flags
, errorCallback
, userRef
,
5658 errorNumber
, JS_TRUE
, ap
);
5663 JS_PUBLIC_API(JSBool
)
5664 JS_ReportErrorFlagsAndNumberUC(JSContext
*cx
, uintN flags
,
5665 JSErrorCallback errorCallback
, void *userRef
,
5666 const uintN errorNumber
, ...)
5671 va_start(ap
, errorNumber
);
5672 ok
= js_ReportErrorNumberVA(cx
, flags
, errorCallback
, userRef
,
5673 errorNumber
, JS_FALSE
, ap
);
5679 JS_ReportOutOfMemory(JSContext
*cx
)
5681 js_ReportOutOfMemory(cx
);
5685 JS_ReportAllocationOverflow(JSContext
*cx
)
5687 js_ReportAllocationOverflow(cx
);
5690 JS_PUBLIC_API(JSErrorReporter
)
5691 JS_SetErrorReporter(JSContext
*cx
, JSErrorReporter er
)
5693 JSErrorReporter older
;
5695 older
= cx
->errorReporter
;
5696 cx
->errorReporter
= er
;
5700 /************************************************************************/
5703 * Regular Expressions.
5705 JS_PUBLIC_API(JSObject
*)
5706 JS_NewRegExpObject(JSContext
*cx
, char *bytes
, size_t length
, uintN flags
)
5712 chars
= js_InflateString(cx
, bytes
, &length
);
5715 obj
= js_NewRegExpObject(cx
, NULL
, chars
, length
, flags
);
5720 JS_PUBLIC_API(JSObject
*)
5721 JS_NewUCRegExpObject(JSContext
*cx
, jschar
*chars
, size_t length
, uintN flags
)
5724 return js_NewRegExpObject(cx
, NULL
, chars
, length
, flags
);
5728 JS_SetRegExpInput(JSContext
*cx
, JSString
*input
, JSBool multiline
)
5730 JSRegExpStatics
*res
;
5733 /* No locking required, cx is thread-private and input must be live. */
5734 res
= &cx
->regExpStatics
;
5736 res
->multiline
= multiline
;
5737 cx
->runtime
->gcPoke
= JS_TRUE
;
5741 JS_ClearRegExpStatics(JSContext
*cx
)
5743 JSRegExpStatics
*res
;
5745 /* No locking required, cx is thread-private and input must be live. */
5746 res
= &cx
->regExpStatics
;
5748 res
->multiline
= JS_FALSE
;
5749 res
->parenCount
= 0;
5750 res
->lastMatch
= res
->lastParen
= js_EmptySubString
;
5751 res
->leftContext
= res
->rightContext
= js_EmptySubString
;
5752 cx
->runtime
->gcPoke
= JS_TRUE
;
5756 JS_ClearRegExpRoots(JSContext
*cx
)
5758 JSRegExpStatics
*res
;
5760 /* No locking required, cx is thread-private and input must be live. */
5761 res
= &cx
->regExpStatics
;
5763 cx
->runtime
->gcPoke
= JS_TRUE
;
5766 /* TODO: compile, execute, get/set other statics... */
5768 /************************************************************************/
5771 JS_SetLocaleCallbacks(JSContext
*cx
, JSLocaleCallbacks
*callbacks
)
5773 cx
->localeCallbacks
= callbacks
;
5776 JS_PUBLIC_API(JSLocaleCallbacks
*)
5777 JS_GetLocaleCallbacks(JSContext
*cx
)
5779 return cx
->localeCallbacks
;
5782 /************************************************************************/
5784 JS_PUBLIC_API(JSBool
)
5785 JS_IsExceptionPending(JSContext
*cx
)
5787 return (JSBool
) cx
->throwing
;
5790 JS_PUBLIC_API(JSBool
)
5791 JS_GetPendingException(JSContext
*cx
, jsval
*vp
)
5796 *vp
= cx
->exception
;
5801 JS_SetPendingException(JSContext
*cx
, jsval v
)
5804 cx
->throwing
= JS_TRUE
;
5809 JS_ClearPendingException(JSContext
*cx
)
5811 cx
->throwing
= JS_FALSE
;
5812 cx
->exception
= JSVAL_VOID
;
5815 JS_PUBLIC_API(JSBool
)
5816 JS_ReportPendingException(JSContext
*cx
)
5823 * Set cx->generatingError to suppress the standard error-to-exception
5824 * conversion done by all {js,JS}_Report* functions except for OOM. The
5825 * cx->generatingError flag was added to suppress recursive divergence
5826 * under js_ErrorToException, but it serves for our purposes here too.
5828 save
= cx
->generatingError
;
5829 cx
->generatingError
= JS_TRUE
;
5830 ok
= js_ReportUncaughtException(cx
);
5831 cx
->generatingError
= save
;
5835 struct JSExceptionState
{
5840 JS_PUBLIC_API(JSExceptionState
*)
5841 JS_SaveExceptionState(JSContext
*cx
)
5843 JSExceptionState
*state
;
5846 state
= (JSExceptionState
*) JS_malloc(cx
, sizeof(JSExceptionState
));
5848 state
->throwing
= JS_GetPendingException(cx
, &state
->exception
);
5849 if (state
->throwing
&& JSVAL_IS_GCTHING(state
->exception
))
5850 js_AddRoot(cx
, &state
->exception
, "JSExceptionState.exception");
5856 JS_RestoreExceptionState(JSContext
*cx
, JSExceptionState
*state
)
5860 if (state
->throwing
)
5861 JS_SetPendingException(cx
, state
->exception
);
5863 JS_ClearPendingException(cx
);
5864 JS_DropExceptionState(cx
, state
);
5869 JS_DropExceptionState(JSContext
*cx
, JSExceptionState
*state
)
5873 if (state
->throwing
&& JSVAL_IS_GCTHING(state
->exception
))
5874 JS_RemoveRoot(cx
, &state
->exception
);
5879 JS_PUBLIC_API(JSErrorReport
*)
5880 JS_ErrorFromException(JSContext
*cx
, jsval v
)
5883 return js_ErrorFromException(cx
, v
);
5886 JS_PUBLIC_API(JSBool
)
5887 JS_ThrowReportedError(JSContext
*cx
, const char *message
,
5888 JSErrorReport
*reportp
)
5890 return cx
->fp
&& js_ErrorToException(cx
, message
, reportp
);
5893 JS_PUBLIC_API(JSBool
)
5894 JS_ThrowStopIteration(JSContext
*cx
)
5896 return js_ThrowStopIteration(cx
);
5900 * Get the owning thread id of a context. Returns 0 if the context is not
5901 * owned by any thread.
5903 JS_PUBLIC_API(jsword
)
5904 JS_GetContextThread(JSContext
*cx
)
5906 #ifdef JS_THREADSAFE
5907 return JS_THREAD_ID(cx
);
5914 * Set the current thread as the owning thread of a context. Returns the
5915 * old owning thread id, or -1 if the operation failed.
5917 JS_PUBLIC_API(jsword
)
5918 JS_SetContextThread(JSContext
*cx
)
5920 #ifdef JS_THREADSAFE
5921 jsword old
= JS_THREAD_ID(cx
);
5922 if (!js_SetContextThread(cx
))
5930 JS_PUBLIC_API(jsword
)
5931 JS_ClearContextThread(JSContext
*cx
)
5933 #ifdef JS_THREADSAFE
5934 jsword old
= JS_THREAD_ID(cx
);
5935 js_ClearContextThread(cx
);
5944 JS_SetGCZeal(JSContext
*cx
, uint8 zeal
)
5946 cx
->runtime
->gcZeal
= zeal
;
5950 /************************************************************************/
5952 #if !defined(STATIC_JS_API) && defined(XP_WIN) && !defined (WINCE)
5954 #include <windows.h>
5957 * Initialization routine for the JS DLL.
5959 BOOL WINAPI
DllMain (HINSTANCE hDLL
, DWORD dwReason
, LPVOID lpReserved
)