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"
87 #include "jsstaticcheck.h"
89 #include "jswrapper.h"
90 #include "jstypedarray.h"
92 #include "jsatominlines.h"
93 #include "jscntxtinlines.h"
94 #include "jsobjinlines.h"
95 #include "jsscopeinlines.h"
96 #include "jscntxtinlines.h"
97 #include "jsregexpinlines.h"
98 #include "assembler/wtf/Platform.h"
101 #include "assembler/jit/ExecutableAllocator.h"
102 #include "methodjit/Logging.h"
105 #if JS_HAS_XML_SUPPORT
111 #ifdef HAVE_VA_LIST_AS_ARRAY
112 #define JS_ADDRESSOF_VA_LIST(ap) ((va_list *)(ap))
114 #define JS_ADDRESSOF_VA_LIST(ap) (&(ap))
117 #ifdef JS_USE_JSVAL_JSID_STRUCT_TYPES
118 JS_PUBLIC_DATA(jsid
) JS_DEFAULT_XML_NAMESPACE_ID
= { (size_t)JSID_TYPE_DEFAULT_XML_NAMESPACE
};
119 JS_PUBLIC_DATA(jsid
) JSID_VOID
= { (size_t)JSID_TYPE_VOID
};
122 #ifdef JS_USE_JSVAL_JSID_STRUCT_TYPES
123 JS_PUBLIC_DATA(jsval
) JSVAL_NULL
= { BUILD_JSVAL(JSVAL_TAG_NULL
, 0) };
124 JS_PUBLIC_DATA(jsval
) JSVAL_ZERO
= { BUILD_JSVAL(JSVAL_TAG_INT32
, 0) };
125 JS_PUBLIC_DATA(jsval
) JSVAL_ONE
= { BUILD_JSVAL(JSVAL_TAG_INT32
, 1) };
126 JS_PUBLIC_DATA(jsval
) JSVAL_FALSE
= { BUILD_JSVAL(JSVAL_TAG_BOOLEAN
, JS_FALSE
) };
127 JS_PUBLIC_DATA(jsval
) JSVAL_TRUE
= { BUILD_JSVAL(JSVAL_TAG_BOOLEAN
, JS_TRUE
) };
128 JS_PUBLIC_DATA(jsval
) JSVAL_VOID
= { BUILD_JSVAL(JSVAL_TAG_UNDEFINED
, 0) };
131 /* Make sure that jschar is two bytes unsigned integer */
132 JS_STATIC_ASSERT((jschar
)-1 > 0);
133 JS_STATIC_ASSERT(sizeof(jschar
) == 2);
142 JS_GetNaNValue(JSContext
*cx
)
144 return Jsvalify(cx
->runtime
->NaNValue
);
148 JS_GetNegativeInfinityValue(JSContext
*cx
)
150 return Jsvalify(cx
->runtime
->negativeInfinityValue
);
154 JS_GetPositiveInfinityValue(JSContext
*cx
)
156 return Jsvalify(cx
->runtime
->positiveInfinityValue
);
160 JS_GetEmptyStringValue(JSContext
*cx
)
162 return STRING_TO_JSVAL(cx
->runtime
->emptyString
);
166 TryArgumentFormatter(JSContext
*cx
, const char **formatp
, JSBool fromJS
, jsval
**vpp
, va_list *app
)
169 JSArgumentFormatMap
*map
;
172 for (map
= cx
->argumentFormatMap
; map
; map
= map
->next
) {
173 if (!strncmp(format
, map
->format
, map
->length
)) {
174 *formatp
= format
+ map
->length
;
175 return map
->formatter(cx
, format
, fromJS
, vpp
, app
);
178 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_BAD_CHAR
, format
);
182 JS_PUBLIC_API(JSBool
)
183 JS_ConvertArguments(JSContext
*cx
, uintN argc
, jsval
*argv
, const char *format
, ...)
188 va_start(ap
, format
);
189 ok
= JS_ConvertArgumentsVA(cx
, argc
, argv
, format
, ap
);
194 JS_PUBLIC_API(JSBool
)
195 JS_ConvertArgumentsVA(JSContext
*cx
, uintN argc
, jsval
*argv
, const char *format
, va_list ap
)
206 assertSameCompartment(cx
, JSValueArray(argv
- 2, argc
+ 2));
209 while ((c
= *format
++) != '\0') {
216 if (sp
== argv
+ argc
) {
218 fun
= js_ValueToFunction(cx
, Valueify(&argv
[-2]), 0);
221 JS_snprintf(numBuf
, sizeof numBuf
, "%u", argc
);
222 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
,
223 JSMSG_MORE_ARGS_NEEDED
,
224 JS_GetFunctionName(fun
), numBuf
,
225 (argc
== 1) ? "" : "s");
233 *va_arg(ap
, JSBool
*) = js_ValueToBoolean(Valueify(*sp
));
236 if (!JS_ValueToUint16(cx
, *sp
, va_arg(ap
, uint16
*)))
240 if (!JS_ValueToECMAInt32(cx
, *sp
, va_arg(ap
, int32
*)))
244 if (!JS_ValueToECMAUint32(cx
, *sp
, va_arg(ap
, uint32
*)))
248 if (!JS_ValueToInt32(cx
, *sp
, va_arg(ap
, int32
*)))
252 if (!JS_ValueToNumber(cx
, *sp
, va_arg(ap
, jsdouble
*)))
256 if (!JS_ValueToNumber(cx
, *sp
, &d
))
258 *va_arg(ap
, jsdouble
*) = js_DoubleToInteger(d
);
263 str
= js_ValueToString(cx
, Valueify(*sp
));
266 *sp
= STRING_TO_JSVAL(str
);
268 const char *bytes
= js_GetStringBytes(cx
, str
);
271 *va_arg(ap
, const char **) = bytes
;
272 } else if (c
== 'W') {
273 const jschar
*chars
= js_GetStringChars(cx
, str
);
276 *va_arg(ap
, const jschar
**) = chars
;
278 *va_arg(ap
, JSString
**) = str
;
282 if (!js_ValueToObjectOrNull(cx
, Valueify(*sp
), &obj
))
284 *sp
= OBJECT_TO_JSVAL(obj
);
285 *va_arg(ap
, JSObject
**) = obj
;
288 obj
= js_ValueToFunctionObject(cx
, Valueify(sp
), 0);
291 *sp
= OBJECT_TO_JSVAL(obj
);
292 *va_arg(ap
, JSFunction
**) = GET_FUNCTION_PRIVATE(cx
, obj
);
295 *va_arg(ap
, jsval
*) = *sp
;
301 if (!TryArgumentFormatter(cx
, &format
, JS_TRUE
, &sp
,
302 JS_ADDRESSOF_VA_LIST(ap
))) {
305 /* NB: the formatter already updated sp, so we continue here. */
313 JS_PUBLIC_API(JSBool
)
314 JS_AddArgumentFormatter(JSContext
*cx
, const char *format
, JSArgumentFormatter formatter
)
317 JSArgumentFormatMap
**mpp
, *map
;
319 length
= strlen(format
);
320 mpp
= &cx
->argumentFormatMap
;
321 while ((map
= *mpp
) != NULL
) {
322 /* Insert before any shorter string to match before prefixes. */
323 if (map
->length
< length
)
325 if (map
->length
== length
&& !strcmp(map
->format
, format
))
329 map
= (JSArgumentFormatMap
*) cx
->malloc(sizeof *map
);
332 map
->format
= format
;
333 map
->length
= length
;
337 map
->formatter
= formatter
;
342 JS_RemoveArgumentFormatter(JSContext
*cx
, const char *format
)
345 JSArgumentFormatMap
**mpp
, *map
;
347 length
= strlen(format
);
348 mpp
= &cx
->argumentFormatMap
;
349 while ((map
= *mpp
) != NULL
) {
350 if (map
->length
== length
&& !strcmp(map
->format
, format
)) {
359 JS_PUBLIC_API(JSBool
)
360 JS_ConvertValue(JSContext
*cx
, jsval v
, JSType type
, jsval
*vp
)
368 assertSameCompartment(cx
, v
);
375 ok
= js_ValueToObjectOrNull(cx
, Valueify(v
), &obj
);
377 *vp
= OBJECT_TO_JSVAL(obj
);
379 case JSTYPE_FUNCTION
:
381 obj
= js_ValueToFunctionObject(cx
, Valueify(vp
), JSV2F_SEARCH_STACK
);
385 str
= js_ValueToString(cx
, Valueify(v
));
388 *vp
= STRING_TO_JSVAL(str
);
391 ok
= JS_ValueToNumber(cx
, v
, &d
);
393 *vp
= DOUBLE_TO_JSVAL(d
);
396 *vp
= BOOLEAN_TO_JSVAL(js_ValueToBoolean(Valueify(v
)));
400 JS_snprintf(numBuf
, sizeof numBuf
, "%d", (int)type
);
401 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_BAD_TYPE
, numBuf
);
409 JS_PUBLIC_API(JSBool
)
410 JS_ValueToObject(JSContext
*cx
, jsval v
, JSObject
**objp
)
413 assertSameCompartment(cx
, v
);
414 return js_ValueToObjectOrNull(cx
, Valueify(v
), objp
);
417 JS_PUBLIC_API(JSFunction
*)
418 JS_ValueToFunction(JSContext
*cx
, jsval v
)
421 assertSameCompartment(cx
, v
);
422 return js_ValueToFunction(cx
, Valueify(&v
), JSV2F_SEARCH_STACK
);
425 JS_PUBLIC_API(JSFunction
*)
426 JS_ValueToConstructor(JSContext
*cx
, jsval v
)
429 assertSameCompartment(cx
, v
);
430 return js_ValueToFunction(cx
, Valueify(&v
), JSV2F_SEARCH_STACK
);
433 JS_PUBLIC_API(JSString
*)
434 JS_ValueToString(JSContext
*cx
, jsval v
)
437 assertSameCompartment(cx
, v
);
438 return js_ValueToString(cx
, Valueify(v
));
441 JS_PUBLIC_API(JSString
*)
442 JS_ValueToSource(JSContext
*cx
, jsval v
)
445 assertSameCompartment(cx
, v
);
446 return js_ValueToSource(cx
, Valueify(v
));
449 JS_PUBLIC_API(JSBool
)
450 JS_ValueToNumber(JSContext
*cx
, jsval v
, jsdouble
*dp
)
453 assertSameCompartment(cx
, v
);
455 AutoValueRooter
tvr(cx
, Valueify(v
));
456 return ValueToNumber(cx
, tvr
.value(), dp
);
459 JS_PUBLIC_API(JSBool
)
460 JS_DoubleIsInt32(jsdouble d
, jsint
*ip
)
462 return JSDOUBLE_IS_INT32(d
, (int32_t *)ip
);
465 JS_PUBLIC_API(JSBool
)
466 JS_ValueToECMAInt32(JSContext
*cx
, jsval v
, int32
*ip
)
469 assertSameCompartment(cx
, v
);
471 AutoValueRooter
tvr(cx
, Valueify(v
));
472 return ValueToECMAInt32(cx
, tvr
.value(), (int32_t *)ip
);
475 JS_PUBLIC_API(JSBool
)
476 JS_ValueToECMAUint32(JSContext
*cx
, jsval v
, uint32
*ip
)
479 assertSameCompartment(cx
, v
);
481 AutoValueRooter
tvr(cx
, Valueify(v
));
482 return ValueToECMAUint32(cx
, tvr
.value(), (uint32_t *)ip
);
485 JS_PUBLIC_API(JSBool
)
486 JS_ValueToInt32(JSContext
*cx
, jsval v
, int32
*ip
)
489 assertSameCompartment(cx
, v
);
491 AutoValueRooter
tvr(cx
, Valueify(v
));
492 return ValueToInt32(cx
, tvr
.value(), (int32_t *)ip
);
495 JS_PUBLIC_API(JSBool
)
496 JS_ValueToUint16(JSContext
*cx
, jsval v
, uint16
*ip
)
499 assertSameCompartment(cx
, v
);
501 AutoValueRooter
tvr(cx
, Valueify(v
));
502 return ValueToUint16(cx
, tvr
.value(), (uint16_t *)ip
);
505 JS_PUBLIC_API(JSBool
)
506 JS_ValueToBoolean(JSContext
*cx
, jsval v
, JSBool
*bp
)
509 assertSameCompartment(cx
, v
);
510 *bp
= js_ValueToBoolean(Valueify(v
));
514 JS_PUBLIC_API(JSType
)
515 JS_TypeOfValue(JSContext
*cx
, jsval v
)
518 assertSameCompartment(cx
, v
);
519 return TypeOfValue(cx
, Valueify(v
));
522 JS_PUBLIC_API(const char *)
523 JS_GetTypeName(JSContext
*cx
, JSType type
)
525 if ((uintN
)type
>= (uintN
)JSTYPE_LIMIT
)
527 return JS_TYPE_STR(type
);
530 JS_PUBLIC_API(JSBool
)
531 JS_StrictlyEqual(JSContext
*cx
, jsval v1
, jsval v2
)
533 assertSameCompartment(cx
, v1
, v2
);
534 return StrictlyEqual(cx
, Valueify(v1
), Valueify(v2
));
537 JS_PUBLIC_API(JSBool
)
538 JS_SameValue(JSContext
*cx
, jsval v1
, jsval v2
)
540 assertSameCompartment(cx
, v1
, v2
);
541 return SameValue(Valueify(v1
), Valueify(v2
), cx
);
544 /************************************************************************/
547 * Has a new runtime ever been created? This flag is used to detect unsafe
548 * changes to js_CStringsAreUTF8 after a runtime has been created, and to
549 * ensure that "first checks" on runtime creation are run only once.
552 static JSBool js_NewRuntimeWasCalled
= JS_FALSE
;
555 JSRuntime::JSRuntime()
556 : gcChunkAllocator(&defaultGCChunkAllocator
)
558 /* Initialize infallibly first, so we can goto bad and JS_DestroyRuntime. */
559 JS_INIT_CLIST(&contextList
);
560 JS_INIT_CLIST(&trapList
);
561 JS_INIT_CLIST(&watchPointList
);
565 JSRuntime::init(uint32 maxbytes
)
567 #ifdef JS_METHODJIT_SPEW
572 functionMeterFilename
= getenv("JS_FUNCTION_STATFILE");
573 if (functionMeterFilename
) {
574 if (!methodReadBarrierCountMap
.init())
576 if (!unjoinedFunctionCountMap
.init())
581 if (!(defaultCompartment
= new JSCompartment(this)) ||
582 !defaultCompartment
->init() ||
583 !compartments
.append(defaultCompartment
)) {
587 if (!js_InitGC(this, maxbytes
) || !js_InitAtomState(this))
591 regExpAllocator
= new JSC::ExecutableAllocator();
592 if (!regExpAllocator
)
596 deflatedStringCache
= new js::DeflatedStringCache();
597 if (!deflatedStringCache
|| !deflatedStringCache
->init())
600 wrapObjectCallback
= js::TransparentObjectWrapper
;
603 gcLock
= JS_NEW_LOCK();
606 gcDone
= JS_NEW_CONDVAR(gcLock
);
609 requestDone
= JS_NEW_CONDVAR(gcLock
);
612 /* this is asymmetric with JS_ShutDown: */
613 if (!js_SetupLocks(8, 16))
615 rtLock
= JS_NEW_LOCK();
618 stateChange
= JS_NEW_CONDVAR(gcLock
);
621 titleSharingDone
= JS_NEW_CONDVAR(gcLock
);
622 if (!titleSharingDone
)
624 titleSharingTodo
= NO_TITLE_SHARING_TODO
;
625 debuggerLock
= JS_NEW_LOCK();
629 return propertyTree
.init() && js_InitThreads(this);
632 JSRuntime::~JSRuntime()
635 /* Don't hurt everyone in leaky ol' Mozilla with a fatal JS_ASSERT! */
636 if (!JS_CLIST_IS_EMPTY(&contextList
)) {
637 JSContext
*cx
, *iter
= NULL
;
639 while ((cx
= js_ContextIterator(this, JS_TRUE
, &iter
)) != NULL
) {
641 "JS API usage error: found live context at %p\n",
646 "JS API usage error: %u context%s left in runtime upon JS_DestroyRuntime.\n",
647 cxcount
, (cxcount
== 1) ? "" : "s");
651 js_FinishThreads(this);
652 js_FreeRuntimeScriptState(this);
653 js_FinishAtomState(this);
656 * Finish the deflated string cache after the last GC and after
657 * calling js_FinishAtomState, which finalizes strings.
659 delete deflatedStringCache
;
661 delete regExpAllocator
;
666 JS_DESTROY_LOCK(gcLock
);
668 JS_DESTROY_CONDVAR(gcDone
);
670 JS_DESTROY_CONDVAR(requestDone
);
672 JS_DESTROY_LOCK(rtLock
);
674 JS_DESTROY_CONDVAR(stateChange
);
675 if (titleSharingDone
)
676 JS_DESTROY_CONDVAR(titleSharingDone
);
678 JS_DESTROY_LOCK(debuggerLock
);
680 propertyTree
.finish();
681 /* Delete all remaining Compartments. Ideally only the defaultCompartment should be left. */
682 for (JSCompartment
**c
= compartments
.begin(); c
!= compartments
.end(); ++c
)
684 compartments
.clear();
687 JS_PUBLIC_API(JSRuntime
*)
688 JS_NewRuntime(uint32 maxbytes
)
691 if (!js_NewRuntimeWasCalled
) {
693 * This code asserts that the numbers associated with the error names
694 * in jsmsg.def are monotonically increasing. It uses values for the
695 * error names enumerated in jscntxt.c. It's not a compile-time check
696 * but it's better than nothing.
699 #define MSG_DEF(name, number, count, exception, format) \
700 JS_ASSERT(name == errorNumber++);
704 #define MSG_DEF(name, number, count, exception, format) \
706 uintN numfmtspecs = 0; \
708 for (fmt = format; *fmt != '\0'; fmt++) { \
709 if (*fmt == '{' && isdigit(fmt[1])) \
712 JS_ASSERT(count == numfmtspecs); \
717 js_NewRuntimeWasCalled
= JS_TRUE
;
721 void *mem
= js_calloc(sizeof(JSRuntime
));
725 JSRuntime
*rt
= new (mem
) JSRuntime();
726 if (!rt
->init(maxbytes
)) {
727 JS_DestroyRuntime(rt
);
735 JS_CommenceRuntimeShutDown(JSRuntime
*rt
)
737 rt
->gcFlushCodeCaches
= true;
741 JS_DestroyRuntime(JSRuntime
*rt
)
749 namespace reprmeter
{
750 extern void js_DumpReprMeter();
762 extern void js_DumpOpMeters();
767 reprmeter::js_DumpReprMeter();
776 JS_PUBLIC_API(void *)
777 JS_GetRuntimePrivate(JSRuntime
*rt
)
783 JS_SetRuntimePrivate(JSRuntime
*rt
, void *data
)
789 JS_BeginRequest(JSContext
*cx
)
792 JS_ASSERT(CURRENT_THREAD_IS_ME(cx
->thread
));
793 JS_ASSERT(cx
->requestDepth
<= cx
->outstandingRequests
);
794 if (cx
->requestDepth
) {
795 JS_ASSERT(cx
->thread
->requestContext
== cx
);
797 cx
->outstandingRequests
++;
798 } else if (JSContext
*old
= cx
->thread
->requestContext
) {
799 JS_ASSERT(!cx
->prevRequestContext
);
800 JS_ASSERT(cx
->prevRequestDepth
== 0);
801 JS_ASSERT(old
!= cx
);
802 JS_ASSERT(old
->requestDepth
!= 0);
803 JS_ASSERT(old
->requestDepth
<= old
->outstandingRequests
);
805 /* Serialize access to JSContext::requestDepth from other threads. */
806 AutoLockGC
lock(cx
->runtime
);
807 cx
->prevRequestContext
= old
;
808 cx
->prevRequestDepth
= old
->requestDepth
;
809 cx
->requestDepth
= 1;
810 cx
->outstandingRequests
++;
811 old
->requestDepth
= 0;
812 cx
->thread
->requestContext
= cx
;
814 JSRuntime
*rt
= cx
->runtime
;
817 /* Wait until the GC is finished. */
818 if (rt
->gcThread
!= cx
->thread
) {
820 JS_AWAIT_GC_DONE(rt
);
823 /* Indicate that a request is running. */
824 cx
->requestDepth
= 1;
825 cx
->outstandingRequests
++;
826 cx
->thread
->requestContext
= cx
;
829 if (rt
->requestCount
== 1 && rt
->activityCallback
)
830 rt
->activityCallback(rt
->activityCallbackArg
, true);
837 StopRequest(JSContext
*cx
)
841 JS_ASSERT(CURRENT_THREAD_IS_ME(cx
->thread
));
842 JS_ASSERT(cx
->requestDepth
> 0);
843 JS_ASSERT(cx
->outstandingRequests
>= cx
->requestDepth
);
844 JS_ASSERT(cx
->thread
->requestContext
== cx
);
845 if (cx
->requestDepth
>= 2) {
847 cx
->outstandingRequests
--;
848 } else if (JSContext
*old
= cx
->prevRequestContext
) {
849 JS_ASSERT(cx
!= old
);
850 JS_ASSERT(old
->requestDepth
== 0);
851 JS_ASSERT(old
->outstandingRequests
>= cx
->prevRequestDepth
);
853 /* Serialize access to JSContext::requestDepth from other threads. */
854 AutoLockGC
lock(cx
->runtime
);
856 cx
->outstandingRequests
--;
857 cx
->requestDepth
= 0;
858 old
->requestDepth
= cx
->prevRequestDepth
;
859 cx
->prevRequestContext
= NULL
;
860 cx
->prevRequestDepth
= 0;
861 cx
->thread
->requestContext
= old
;
863 JS_ASSERT(cx
->prevRequestDepth
== 0);
864 LeaveTrace(cx
); /* for GC safety */
866 /* Lock before clearing to interlock with ClaimScope, in jslock.c. */
870 cx
->requestDepth
= 0;
871 cx
->outstandingRequests
--;
872 cx
->thread
->requestContext
= NULL
;
874 js_ShareWaitingTitles(cx
);
876 /* Give the GC a chance to run if this was the last request running. */
877 JS_ASSERT(rt
->requestCount
> 0);
879 if (rt
->requestCount
== 0) {
880 JS_NOTIFY_REQUEST_DONE(rt
);
881 if (rt
->activityCallback
)
882 rt
->activityCallback(rt
->activityCallbackArg
, false);
889 JS_EndRequest(JSContext
*cx
)
893 * We do not allow to use JS_EndRequest to exit the request when there are
894 * native frames on the stack that insist that the request must be on. But
895 * we do allow to call the API if the request was suspended.
897 JS_ASSERT_IF(cx
->requestDepth
== 1 && cx
->outstandingRequests
== 1,
898 cx
->checkRequestDepth
== 0);
903 /* Yield to pending GC operations, regardless of request depth */
905 JS_YieldRequest(JSContext
*cx
)
908 JS_ASSERT(cx
->thread
);
910 cx
= cx
->thread
->requestContext
;
913 JS_ResumeRequest(cx
, JS_SuspendRequest(cx
));
917 JS_PUBLIC_API(jsrefcount
)
918 JS_SuspendRequest(JSContext
*cx
)
921 jsrefcount saveDepth
= cx
->requestDepth
;
925 JS_THREAD_DATA(cx
)->conservativeGC
.enable();
927 cx
->outstandingRequests
++; /* compensate for StopRequest */
929 } while (cx
->requestDepth
);
938 JS_ResumeRequest(JSContext
*cx
, jsrefcount saveDepth
)
944 JS_ASSERT(cx
->outstandingRequests
!= 0);
947 cx
->outstandingRequests
--; /* compensate for JS_BeginRequest */
948 } while (--saveDepth
!= 0);
949 JS_THREAD_DATA(cx
)->conservativeGC
.disable();
954 JS_Lock(JSRuntime
*rt
)
960 JS_Unlock(JSRuntime
*rt
)
962 JS_UNLOCK_RUNTIME(rt
);
965 JS_PUBLIC_API(JSContextCallback
)
966 JS_SetContextCallback(JSRuntime
*rt
, JSContextCallback cxCallback
)
968 JSContextCallback old
;
970 old
= rt
->cxCallback
;
971 rt
->cxCallback
= cxCallback
;
975 JS_PUBLIC_API(JSContext
*)
976 JS_NewContext(JSRuntime
*rt
, size_t stackChunkSize
)
978 return js_NewContext(rt
, stackChunkSize
);
982 JS_DestroyContext(JSContext
*cx
)
984 js_DestroyContext(cx
, JSDCM_FORCE_GC
);
988 JS_DestroyContextNoGC(JSContext
*cx
)
990 js_DestroyContext(cx
, JSDCM_NO_GC
);
994 JS_DestroyContextMaybeGC(JSContext
*cx
)
996 js_DestroyContext(cx
, JSDCM_MAYBE_GC
);
999 JS_PUBLIC_API(void *)
1000 JS_GetContextPrivate(JSContext
*cx
)
1006 JS_SetContextPrivate(JSContext
*cx
, void *data
)
1011 JS_PUBLIC_API(JSRuntime
*)
1012 JS_GetRuntime(JSContext
*cx
)
1017 JS_PUBLIC_API(JSContext
*)
1018 JS_ContextIterator(JSRuntime
*rt
, JSContext
**iterp
)
1020 return js_ContextIterator(rt
, JS_TRUE
, iterp
);
1023 JS_PUBLIC_API(JSVersion
)
1024 JS_GetVersion(JSContext
*cx
)
1026 return JSVERSION_NUMBER(cx
);
1029 JS_PUBLIC_API(JSVersion
)
1030 JS_SetVersion(JSContext
*cx
, JSVersion version
)
1032 JSVersion oldVersion
;
1034 JS_ASSERT(version
!= JSVERSION_UNKNOWN
);
1035 JS_ASSERT((version
& ~JSVERSION_MASK
) == 0);
1037 oldVersion
= JSVERSION_NUMBER(cx
);
1038 if (version
== oldVersion
)
1041 /* We no longer support 1.4 or below. */
1042 if (version
!= JSVERSION_DEFAULT
&& version
<= JSVERSION_1_4
)
1045 cx
->version
= (cx
->version
& ~JSVERSION_MASK
) | version
;
1046 js_OnVersionChange(cx
);
1050 static struct v2smap
{
1054 {JSVERSION_1_0
, "1.0"},
1055 {JSVERSION_1_1
, "1.1"},
1056 {JSVERSION_1_2
, "1.2"},
1057 {JSVERSION_1_3
, "1.3"},
1058 {JSVERSION_1_4
, "1.4"},
1059 {JSVERSION_ECMA_3
, "ECMAv3"},
1060 {JSVERSION_1_5
, "1.5"},
1061 {JSVERSION_1_6
, "1.6"},
1062 {JSVERSION_1_7
, "1.7"},
1063 {JSVERSION_1_8
, "1.8"},
1064 {JSVERSION_ECMA_5
, "ECMAv5"},
1065 {JSVERSION_DEFAULT
, js_default_str
},
1066 {JSVERSION_UNKNOWN
, NULL
}, /* must be last, NULL is sentinel */
1069 JS_PUBLIC_API(const char *)
1070 JS_VersionToString(JSVersion version
)
1074 for (i
= 0; v2smap
[i
].string
; i
++)
1075 if (v2smap
[i
].version
== version
)
1076 return v2smap
[i
].string
;
1080 JS_PUBLIC_API(JSVersion
)
1081 JS_StringToVersion(const char *string
)
1085 for (i
= 0; v2smap
[i
].string
; i
++)
1086 if (strcmp(v2smap
[i
].string
, string
) == 0)
1087 return v2smap
[i
].version
;
1088 return JSVERSION_UNKNOWN
;
1091 JS_PUBLIC_API(uint32
)
1092 JS_GetOptions(JSContext
*cx
)
1097 JS_PUBLIC_API(uint32
)
1098 JS_SetOptions(JSContext
*cx
, uint32 options
)
1100 AutoLockGC
lock(cx
->runtime
);
1101 uint32 oldopts
= cx
->options
;
1102 cx
->options
= options
;
1103 js_SyncOptionsToVersion(cx
);
1104 cx
->updateJITEnabled();
1108 JS_PUBLIC_API(uint32
)
1109 JS_ToggleOptions(JSContext
*cx
, uint32 options
)
1111 AutoLockGC
lock(cx
->runtime
);
1112 uint32 oldopts
= cx
->options
;
1113 cx
->options
^= options
;
1114 js_SyncOptionsToVersion(cx
);
1115 cx
->updateJITEnabled();
1119 JS_PUBLIC_API(const char *)
1120 JS_GetImplementationVersion(void)
1122 return "JavaScript-C 1.8.0 pre-release 1 2007-10-03";
1125 JS_PUBLIC_API(JSCompartmentCallback
)
1126 JS_SetCompartmentCallback(JSRuntime
*rt
, JSCompartmentCallback callback
)
1128 JSCompartmentCallback old
= rt
->compartmentCallback
;
1129 rt
->compartmentCallback
= callback
;
1133 JS_PUBLIC_API(JSWrapObjectCallback
)
1134 JS_SetWrapObjectCallback(JSContext
*cx
, JSWrapObjectCallback callback
)
1136 JSRuntime
*rt
= cx
->runtime
;
1137 JSWrapObjectCallback old
= rt
->wrapObjectCallback
;
1138 rt
->wrapObjectCallback
= callback
;
1142 JS_PUBLIC_API(JSCrossCompartmentCall
*)
1143 JS_EnterCrossCompartmentCall(JSContext
*cx
, JSObject
*target
)
1148 AutoCompartment
*call
= new AutoCompartment(cx
, target
);
1151 if (!call
->enter()) {
1155 return reinterpret_cast<JSCrossCompartmentCall
*>(call
);
1159 JS_LeaveCrossCompartmentCall(JSCrossCompartmentCall
*call
)
1161 AutoCompartment
*realcall
= reinterpret_cast<AutoCompartment
*>(call
);
1162 CHECK_REQUEST(realcall
->context
);
1168 JSAutoCrossCompartmentCall::enter(JSContext
*cx
, JSObject
*target
)
1171 if (cx
->compartment
== target
->getCompartment(cx
))
1173 call
= JS_EnterCrossCompartmentCall(cx
, target
);
1174 return call
!= NULL
;
1177 JSAutoEnterCompartment::JSAutoEnterCompartment(JSContext
*cx
,
1178 JSCompartment
*newCompartment
)
1179 : cx(cx
), compartment(cx
->compartment
)
1181 cx
->compartment
= newCompartment
;
1184 JSAutoEnterCompartment::JSAutoEnterCompartment(JSContext
*cx
, JSObject
*target
)
1185 : cx(cx
), compartment(cx
->compartment
)
1187 cx
->compartment
= target
->getCompartment(cx
);
1190 JSAutoEnterCompartment::~JSAutoEnterCompartment()
1192 cx
->compartment
= compartment
;
1195 JS_PUBLIC_API(void *)
1196 JS_SetCompartmentPrivate(JSContext
*cx
, JSCompartment
*compartment
, void *data
)
1199 void *old
= compartment
->data
;
1200 compartment
->data
= data
;
1204 JS_PUBLIC_API(void *)
1205 JS_GetCompartmentPrivate(JSContext
*cx
, JSCompartment
*compartment
)
1208 return compartment
->data
;
1211 JS_PUBLIC_API(JSBool
)
1212 JS_WrapObject(JSContext
*cx
, JSObject
**objp
)
1215 return cx
->compartment
->wrap(cx
, objp
);
1218 JS_PUBLIC_API(JSBool
)
1219 JS_WrapValue(JSContext
*cx
, jsval
*vp
)
1222 return cx
->compartment
->wrap(cx
, Valueify(vp
));
1225 JS_PUBLIC_API(JSObject
*)
1226 JS_GetGlobalObject(JSContext
*cx
)
1228 return cx
->globalObject
;
1232 JS_SetGlobalObject(JSContext
*cx
, JSObject
*obj
)
1236 cx
->globalObject
= obj
;
1237 cx
->compartment
= obj
? obj
->getCompartment(cx
) : cx
->runtime
->defaultCompartment
;
1240 class AutoResolvingEntry
{
1242 AutoResolvingEntry() : entry(NULL
) {}
1245 * Returns false on error. But N.B. if obj[id] was already being resolved,
1246 * this is a no-op, and we silently treat that as success.
1248 bool start(JSContext
*cx
, JSObject
*obj
, jsid id
, uint32 flag
) {
1254 bool ok
= !!js_StartResolving(cx
, &key
, flag
, &entry
);
1255 JS_ASSERT_IF(!ok
, !entry
);
1259 ~AutoResolvingEntry() {
1261 js_StopResolving(cx
, &key
, flag
, NULL
, 0);
1268 JSResolvingEntry
*entry
;
1272 js_InitFunctionAndObjectClasses(JSContext
*cx
, JSObject
*obj
)
1274 JSObject
*fun_proto
, *obj_proto
;
1276 /* If cx has no global object, use obj so prototypes can be found. */
1277 if (!cx
->globalObject
)
1278 JS_SetGlobalObject(cx
, obj
);
1280 /* Record Function and Object in cx->resolvingTable. */
1281 AutoResolvingEntry e1
, e2
;
1282 JSAtom
**classAtoms
= cx
->runtime
->atomState
.classAtoms
;
1283 if (!e1
.start(cx
, obj
, ATOM_TO_JSID(classAtoms
[JSProto_Function
]), JSRESFLAG_LOOKUP
) ||
1284 !e2
.start(cx
, obj
, ATOM_TO_JSID(classAtoms
[JSProto_Object
]), JSRESFLAG_LOOKUP
)) {
1288 /* Initialize the function class first so constructors can be made. */
1289 if (!js_GetClassPrototype(cx
, obj
, JSProto_Function
, &fun_proto
))
1292 fun_proto
= js_InitFunctionClass(cx
, obj
);
1298 ctor
= JS_GetConstructor(cx
, fun_proto
);
1301 obj
->defineProperty(cx
, ATOM_TO_JSID(CLASS_ATOM(cx
, Function
)),
1302 ObjectValue(*ctor
), 0, 0, 0);
1305 /* Initialize the object class next so Object.prototype works. */
1306 if (!js_GetClassPrototype(cx
, obj
, JSProto_Object
, &obj_proto
))
1309 obj_proto
= js_InitObjectClass(cx
, obj
);
1313 /* Function.prototype and the global object delegate to Object.prototype. */
1314 fun_proto
->setProto(obj_proto
);
1315 if (!obj
->getProto())
1316 obj
->setProto(obj_proto
);
1321 JS_PUBLIC_API(JSBool
)
1322 JS_InitStandardClasses(JSContext
*cx
, JSObject
*obj
)
1326 if (cx
->globalObject
)
1327 assertSameCompartment(cx
, obj
);
1329 JS_SetGlobalObject(cx
, obj
);
1331 /* Define a top-level property 'undefined' with the undefined value. */
1332 JSAtom
*atom
= cx
->runtime
->atomState
.typeAtoms
[JSTYPE_VOID
];
1333 if (!obj
->defineProperty(cx
, ATOM_TO_JSID(atom
), UndefinedValue(),
1334 PropertyStub
, PropertyStub
,
1335 JSPROP_PERMANENT
| JSPROP_READONLY
)) {
1339 /* Function and Object require cooperative bootstrapping magic. */
1340 if (!js_InitFunctionAndObjectClasses(cx
, obj
))
1343 /* Initialize the rest of the standard objects and functions. */
1344 return js_InitArrayClass(cx
, obj
) &&
1345 js_InitBooleanClass(cx
, obj
) &&
1346 js_InitExceptionClasses(cx
, obj
) &&
1347 js_InitMathClass(cx
, obj
) &&
1348 js_InitNumberClass(cx
, obj
) &&
1349 js_InitJSONClass(cx
, obj
) &&
1350 js_InitRegExpClass(cx
, obj
) &&
1351 js_InitStringClass(cx
, obj
) &&
1352 js_InitTypedArrayClasses(cx
, obj
) &&
1353 #if JS_HAS_XML_SUPPORT
1354 js_InitXMLClasses(cx
, obj
) &&
1356 #if JS_HAS_GENERATORS
1357 js_InitIteratorClasses(cx
, obj
) &&
1359 js_InitDateClass(cx
, obj
) &&
1360 js_InitProxyClass(cx
, obj
);
1363 #define CLASP(name) (&js_##name##Class)
1364 #define TYPED_ARRAY_CLASP(type) (&TypedArray::fastClasses[TypedArray::type])
1365 #define EAGER_ATOM(name) ATOM_OFFSET(name), NULL
1366 #define EAGER_CLASS_ATOM(name) CLASS_ATOM_OFFSET(name), NULL
1367 #define EAGER_ATOM_AND_CLASP(name) EAGER_CLASS_ATOM(name), CLASP(name)
1368 #define LAZY_ATOM(name) ATOM_OFFSET(lazy.name), js_##name##_str
1370 typedef struct JSStdName
{
1372 size_t atomOffset
; /* offset of atom pointer in JSAtomState */
1373 const char *name
; /* null if atom is pre-pinned, else name */
1378 StdNameToAtom(JSContext
*cx
, JSStdName
*stdn
)
1384 offset
= stdn
->atomOffset
;
1385 atom
= OFFSET_TO_ATOM(cx
->runtime
, offset
);
1389 atom
= js_Atomize(cx
, name
, strlen(name
), ATOM_PINNED
);
1390 OFFSET_TO_ATOM(cx
->runtime
, offset
) = atom
;
1397 * Table of class initializers and their atom offsets in rt->atomState.
1398 * If you add a "standard" class, remember to update this table.
1400 static JSStdName standard_class_atoms
[] = {
1401 {js_InitFunctionAndObjectClasses
, EAGER_ATOM_AND_CLASP(Function
)},
1402 {js_InitFunctionAndObjectClasses
, EAGER_ATOM_AND_CLASP(Object
)},
1403 {js_InitArrayClass
, EAGER_ATOM_AND_CLASP(Array
)},
1404 {js_InitBooleanClass
, EAGER_ATOM_AND_CLASP(Boolean
)},
1405 {js_InitDateClass
, EAGER_ATOM_AND_CLASP(Date
)},
1406 {js_InitMathClass
, EAGER_ATOM_AND_CLASP(Math
)},
1407 {js_InitNumberClass
, EAGER_ATOM_AND_CLASP(Number
)},
1408 {js_InitStringClass
, EAGER_ATOM_AND_CLASP(String
)},
1409 {js_InitExceptionClasses
, EAGER_ATOM_AND_CLASP(Error
)},
1410 {js_InitRegExpClass
, EAGER_ATOM_AND_CLASP(RegExp
)},
1411 #if JS_HAS_XML_SUPPORT
1412 {js_InitXMLClass
, EAGER_ATOM_AND_CLASP(XML
)},
1413 {js_InitNamespaceClass
, EAGER_ATOM_AND_CLASP(Namespace
)},
1414 {js_InitQNameClass
, EAGER_ATOM_AND_CLASP(QName
)},
1416 #if JS_HAS_GENERATORS
1417 {js_InitIteratorClasses
, EAGER_ATOM_AND_CLASP(StopIteration
)},
1419 {js_InitJSONClass
, EAGER_ATOM_AND_CLASP(JSON
)},
1420 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(ArrayBuffer
), &js::ArrayBuffer::jsclass
},
1421 {NULL
, 0, NULL
, NULL
}
1425 * Table of top-level function and constant names and their init functions.
1426 * If you add a "standard" global function or property, remember to update
1429 static JSStdName standard_class_names
[] = {
1430 {js_InitObjectClass
, EAGER_ATOM(eval
), CLASP(Object
)},
1432 /* Global properties and functions defined by the Number class. */
1433 {js_InitNumberClass
, LAZY_ATOM(NaN
), CLASP(Number
)},
1434 {js_InitNumberClass
, LAZY_ATOM(Infinity
), CLASP(Number
)},
1435 {js_InitNumberClass
, LAZY_ATOM(isNaN
), CLASP(Number
)},
1436 {js_InitNumberClass
, LAZY_ATOM(isFinite
), CLASP(Number
)},
1437 {js_InitNumberClass
, LAZY_ATOM(parseFloat
), CLASP(Number
)},
1438 {js_InitNumberClass
, LAZY_ATOM(parseInt
), CLASP(Number
)},
1440 /* String global functions. */
1441 {js_InitStringClass
, LAZY_ATOM(escape
), CLASP(String
)},
1442 {js_InitStringClass
, LAZY_ATOM(unescape
), CLASP(String
)},
1443 {js_InitStringClass
, LAZY_ATOM(decodeURI
), CLASP(String
)},
1444 {js_InitStringClass
, LAZY_ATOM(encodeURI
), CLASP(String
)},
1445 {js_InitStringClass
, LAZY_ATOM(decodeURIComponent
), CLASP(String
)},
1446 {js_InitStringClass
, LAZY_ATOM(encodeURIComponent
), CLASP(String
)},
1448 {js_InitStringClass
, LAZY_ATOM(uneval
), CLASP(String
)},
1451 /* Exception constructors. */
1452 {js_InitExceptionClasses
, EAGER_CLASS_ATOM(Error
), CLASP(Error
)},
1453 {js_InitExceptionClasses
, EAGER_CLASS_ATOM(InternalError
), CLASP(Error
)},
1454 {js_InitExceptionClasses
, EAGER_CLASS_ATOM(EvalError
), CLASP(Error
)},
1455 {js_InitExceptionClasses
, EAGER_CLASS_ATOM(RangeError
), CLASP(Error
)},
1456 {js_InitExceptionClasses
, EAGER_CLASS_ATOM(ReferenceError
), CLASP(Error
)},
1457 {js_InitExceptionClasses
, EAGER_CLASS_ATOM(SyntaxError
), CLASP(Error
)},
1458 {js_InitExceptionClasses
, EAGER_CLASS_ATOM(TypeError
), CLASP(Error
)},
1459 {js_InitExceptionClasses
, EAGER_CLASS_ATOM(URIError
), CLASP(Error
)},
1461 #if JS_HAS_XML_SUPPORT
1462 {js_InitAnyNameClass
, EAGER_ATOM_AND_CLASP(AnyName
)},
1463 {js_InitAttributeNameClass
, EAGER_ATOM_AND_CLASP(AttributeName
)},
1464 {js_InitXMLClass
, LAZY_ATOM(XMLList
), CLASP(XML
)},
1465 {js_InitXMLClass
, LAZY_ATOM(isXMLName
), CLASP(XML
)},
1468 #if JS_HAS_GENERATORS
1469 {js_InitIteratorClasses
, EAGER_ATOM_AND_CLASP(Iterator
)},
1470 {js_InitIteratorClasses
, EAGER_ATOM_AND_CLASP(Generator
)},
1474 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(ArrayBuffer
), &js::ArrayBuffer::jsclass
},
1475 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(Int8Array
), TYPED_ARRAY_CLASP(TYPE_INT8
)},
1476 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(Uint8Array
), TYPED_ARRAY_CLASP(TYPE_UINT8
)},
1477 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(Int16Array
), TYPED_ARRAY_CLASP(TYPE_INT16
)},
1478 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(Uint16Array
), TYPED_ARRAY_CLASP(TYPE_UINT16
)},
1479 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(Int32Array
), TYPED_ARRAY_CLASP(TYPE_INT32
)},
1480 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(Uint32Array
), TYPED_ARRAY_CLASP(TYPE_UINT32
)},
1481 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(Float32Array
), TYPED_ARRAY_CLASP(TYPE_FLOAT32
)},
1482 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(Float64Array
), TYPED_ARRAY_CLASP(TYPE_FLOAT64
)},
1483 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(Uint8ClampedArray
),
1484 TYPED_ARRAY_CLASP(TYPE_UINT8_CLAMPED
)},
1486 {js_InitProxyClass
, EAGER_ATOM_AND_CLASP(Proxy
)},
1488 {NULL
, 0, NULL
, NULL
}
1491 static JSStdName object_prototype_names
[] = {
1492 /* Object.prototype properties (global delegates to Object.prototype). */
1493 {js_InitObjectClass
, EAGER_ATOM(proto
), CLASP(Object
)},
1495 {js_InitObjectClass
, EAGER_ATOM(toSource
), CLASP(Object
)},
1497 {js_InitObjectClass
, EAGER_ATOM(toString
), CLASP(Object
)},
1498 {js_InitObjectClass
, EAGER_ATOM(toLocaleString
), CLASP(Object
)},
1499 {js_InitObjectClass
, EAGER_ATOM(valueOf
), CLASP(Object
)},
1500 #if JS_HAS_OBJ_WATCHPOINT
1501 {js_InitObjectClass
, LAZY_ATOM(watch
), CLASP(Object
)},
1502 {js_InitObjectClass
, LAZY_ATOM(unwatch
), CLASP(Object
)},
1504 {js_InitObjectClass
, LAZY_ATOM(hasOwnProperty
), CLASP(Object
)},
1505 {js_InitObjectClass
, LAZY_ATOM(isPrototypeOf
), CLASP(Object
)},
1506 {js_InitObjectClass
, LAZY_ATOM(propertyIsEnumerable
), CLASP(Object
)},
1507 #if OLD_GETTER_SETTER_METHODS
1508 {js_InitObjectClass
, LAZY_ATOM(defineGetter
), CLASP(Object
)},
1509 {js_InitObjectClass
, LAZY_ATOM(defineSetter
), CLASP(Object
)},
1510 {js_InitObjectClass
, LAZY_ATOM(lookupGetter
), CLASP(Object
)},
1511 {js_InitObjectClass
, LAZY_ATOM(lookupSetter
), CLASP(Object
)},
1514 {NULL
, 0, NULL
, NULL
}
1517 JS_PUBLIC_API(JSBool
)
1518 JS_ResolveStandardClass(JSContext
*cx
, JSObject
*obj
, jsid id
, JSBool
*resolved
)
1527 assertSameCompartment(cx
, obj
, id
);
1528 *resolved
= JS_FALSE
;
1531 JS_ASSERT(rt
->state
!= JSRTS_DOWN
);
1532 if (rt
->state
== JSRTS_LANDING
|| !JSID_IS_ATOM(id
))
1535 idstr
= JSID_TO_STRING(id
);
1537 /* Check whether we're resolving 'undefined', and define it if so. */
1538 atom
= rt
->atomState
.typeAtoms
[JSTYPE_VOID
];
1539 if (idstr
== ATOM_TO_STRING(atom
)) {
1540 *resolved
= JS_TRUE
;
1541 return obj
->defineProperty(cx
, ATOM_TO_JSID(atom
), UndefinedValue(),
1542 PropertyStub
, PropertyStub
,
1543 JSPROP_PERMANENT
| JSPROP_READONLY
);
1546 /* Try for class constructors/prototypes named by well-known atoms. */
1548 for (i
= 0; standard_class_atoms
[i
].init
; i
++) {
1549 JS_ASSERT(standard_class_atoms
[i
].clasp
);
1550 atom
= OFFSET_TO_ATOM(rt
, standard_class_atoms
[i
].atomOffset
);
1551 if (idstr
== ATOM_TO_STRING(atom
)) {
1552 stdnm
= &standard_class_atoms
[i
];
1558 /* Try less frequently used top-level functions and constants. */
1559 for (i
= 0; standard_class_names
[i
].init
; i
++) {
1560 JS_ASSERT(standard_class_names
[i
].clasp
);
1561 atom
= StdNameToAtom(cx
, &standard_class_names
[i
]);
1564 if (idstr
== ATOM_TO_STRING(atom
)) {
1565 stdnm
= &standard_class_names
[i
];
1570 if (!stdnm
&& !obj
->getProto()) {
1572 * Try even less frequently used names delegated from the global
1573 * object to Object.prototype, but only if the Object class hasn't
1574 * yet been initialized.
1576 for (i
= 0; object_prototype_names
[i
].init
; i
++) {
1577 JS_ASSERT(object_prototype_names
[i
].clasp
);
1578 atom
= StdNameToAtom(cx
, &object_prototype_names
[i
]);
1581 if (idstr
== ATOM_TO_STRING(atom
)) {
1582 stdnm
= &object_prototype_names
[i
];
1591 * If this standard class is anonymous, then we don't want to resolve
1594 JS_ASSERT(obj
->getClass()->flags
& JSCLASS_IS_GLOBAL
);
1595 if (stdnm
->clasp
->flags
& JSCLASS_IS_ANONYMOUS
)
1598 JSProtoKey key
= JSCLASS_CACHED_PROTO_KEY(stdnm
->clasp
);
1599 if (obj
->getReservedSlot(key
).isObject())
1602 if (!stdnm
->init(cx
, obj
))
1604 *resolved
= JS_TRUE
;
1610 AlreadyHasOwnProperty(JSContext
*cx
, JSObject
*obj
, JSAtom
*atom
)
1612 JS_LOCK_OBJ(cx
, obj
);
1613 JSScope
*scope
= obj
->scope();
1614 bool found
= scope
->hasProperty(ATOM_TO_JSID(atom
));
1615 JS_UNLOCK_SCOPE(cx
, scope
);
1619 JS_PUBLIC_API(JSBool
)
1620 JS_EnumerateStandardClasses(JSContext
*cx
, JSObject
*obj
)
1627 assertSameCompartment(cx
, obj
);
1630 /* Check whether we need to bind 'undefined' and define it if so. */
1631 atom
= rt
->atomState
.typeAtoms
[JSTYPE_VOID
];
1632 if (!AlreadyHasOwnProperty(cx
, obj
, atom
) &&
1633 !obj
->defineProperty(cx
, ATOM_TO_JSID(atom
), UndefinedValue(),
1634 PropertyStub
, PropertyStub
,
1635 JSPROP_PERMANENT
| JSPROP_READONLY
)) {
1639 /* Initialize any classes that have not been resolved yet. */
1640 for (i
= 0; standard_class_atoms
[i
].init
; i
++) {
1641 atom
= OFFSET_TO_ATOM(rt
, standard_class_atoms
[i
].atomOffset
);
1642 if (!AlreadyHasOwnProperty(cx
, obj
, atom
) &&
1643 !standard_class_atoms
[i
].init(cx
, obj
)) {
1654 NewIdArray(JSContext
*cx
, jsint length
)
1659 cx
->calloc(offsetof(JSIdArray
, vector
) + length
* sizeof(jsval
));
1661 ida
->length
= length
;
1668 * Unlike realloc(3), this function frees ida on failure.
1671 SetIdArrayLength(JSContext
*cx
, JSIdArray
*ida
, jsint length
)
1675 rida
= (JSIdArray
*)
1677 offsetof(JSIdArray
, vector
) + length
* sizeof(jsval
));
1679 JS_DestroyIdArray(cx
, ida
);
1681 rida
->length
= length
;
1687 AddAtomToArray(JSContext
*cx
, JSAtom
*atom
, JSIdArray
*ida
, jsint
*ip
)
1692 length
= ida
->length
;
1694 ida
= SetIdArrayLength(cx
, ida
, JS_MAX(length
* 2, 8));
1697 JS_ASSERT(i
< ida
->length
);
1699 ida
->vector
[i
] = ATOM_TO_JSID(atom
);
1705 EnumerateIfResolved(JSContext
*cx
, JSObject
*obj
, JSAtom
*atom
, JSIdArray
*ida
,
1706 jsint
*ip
, JSBool
*foundp
)
1708 *foundp
= AlreadyHasOwnProperty(cx
, obj
, atom
);
1710 ida
= AddAtomToArray(cx
, atom
, ida
, ip
);
1714 JS_PUBLIC_API(JSIdArray
*)
1715 JS_EnumerateResolvedStandardClasses(JSContext
*cx
, JSObject
*obj
, JSIdArray
*ida
)
1724 assertSameCompartment(cx
, obj
, ida
);
1729 ida
= NewIdArray(cx
, 8);
1735 /* Check whether 'undefined' has been resolved and enumerate it if so. */
1736 atom
= rt
->atomState
.typeAtoms
[JSTYPE_VOID
];
1737 ida
= EnumerateIfResolved(cx
, obj
, atom
, ida
, &i
, &found
);
1741 /* Enumerate only classes that *have* been resolved. */
1742 for (j
= 0; standard_class_atoms
[j
].init
; j
++) {
1743 atom
= OFFSET_TO_ATOM(rt
, standard_class_atoms
[j
].atomOffset
);
1744 ida
= EnumerateIfResolved(cx
, obj
, atom
, ida
, &i
, &found
);
1749 init
= standard_class_atoms
[j
].init
;
1751 for (k
= 0; standard_class_names
[k
].init
; k
++) {
1752 if (standard_class_names
[k
].init
== init
) {
1753 atom
= StdNameToAtom(cx
, &standard_class_names
[k
]);
1754 ida
= AddAtomToArray(cx
, atom
, ida
, &i
);
1760 if (init
== js_InitObjectClass
) {
1761 for (k
= 0; object_prototype_names
[k
].init
; k
++) {
1762 atom
= StdNameToAtom(cx
, &object_prototype_names
[k
]);
1763 ida
= AddAtomToArray(cx
, atom
, ida
, &i
);
1771 /* Trim to exact length. */
1772 return SetIdArrayLength(cx
, ida
, i
);
1777 #undef EAGER_CLASS_ATOM
1778 #undef EAGER_ATOM_CLASP
1781 JS_PUBLIC_API(JSBool
)
1782 JS_GetClassObject(JSContext
*cx
, JSObject
*obj
, JSProtoKey key
, JSObject
**objp
)
1785 assertSameCompartment(cx
, obj
);
1786 return js_GetClassObject(cx
, obj
, key
, objp
);
1789 JS_PUBLIC_API(JSObject
*)
1790 JS_GetScopeChain(JSContext
*cx
)
1795 fp
= js_GetTopStackFrame(cx
);
1798 * There is no code active on this context. In place of an actual
1799 * scope chain, use the context's global object, which is set in
1800 * js_InitFunctionAndObjectClasses, and which represents the default
1801 * scope chain for the embedding. See also js_FindClassObject.
1803 * For embeddings that use the inner and outer object hooks, the inner
1804 * object represents the ultimate global object, with the outer object
1805 * acting as a stand-in.
1807 JSObject
*obj
= cx
->globalObject
;
1809 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_INACTIVE
);
1813 OBJ_TO_INNER_OBJECT(cx
, obj
);
1816 return js_GetScopeChain(cx
, fp
);
1819 JS_PUBLIC_API(JSObject
*)
1820 JS_GetGlobalForObject(JSContext
*cx
, JSObject
*obj
)
1822 assertSameCompartment(cx
, obj
);
1823 return obj
->getGlobal();
1826 JS_PUBLIC_API(JSObject
*)
1827 JS_GetGlobalForScopeChain(JSContext
*cx
)
1830 * This is essentially JS_GetScopeChain(cx)->getGlobal(), but without
1831 * falling off trace.
1833 * This use of cx->fp, possibly on trace, is deliberate:
1834 * cx->fp->scopeChain->getGlobal() returns the same object whether we're on
1835 * trace or not, since we do not trace calls across global objects.
1837 VOUCH_DOES_NOT_REQUIRE_STACK();
1840 return cx
->fp()->getScopeChain()->getGlobal();
1842 JSObject
*scope
= cx
->globalObject
;
1844 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_INACTIVE
);
1847 OBJ_TO_INNER_OBJECT(cx
, scope
);
1851 JS_PUBLIC_API(jsval
)
1852 JS_ComputeThis(JSContext
*cx
, jsval
*vp
)
1854 assertSameCompartment(cx
, JSValueArray(vp
, 2));
1855 if (!ComputeThisFromVp(cx
, Valueify(vp
)))
1860 JS_PUBLIC_API(void *)
1861 JS_malloc(JSContext
*cx
, size_t nbytes
)
1863 return cx
->malloc(nbytes
);
1866 JS_PUBLIC_API(void *)
1867 JS_realloc(JSContext
*cx
, void *p
, size_t nbytes
)
1869 return cx
->realloc(p
, nbytes
);
1873 JS_free(JSContext
*cx
, void *p
)
1879 JS_updateMallocCounter(JSContext
*cx
, size_t nbytes
)
1881 return cx
->updateMallocCounter(nbytes
);
1884 JS_PUBLIC_API(char *)
1885 JS_strdup(JSContext
*cx
, const char *s
)
1894 return (char *)memcpy(p
, s
, n
);
1897 JS_PUBLIC_API(JSBool
)
1898 JS_NewNumberValue(JSContext
*cx
, jsdouble d
, jsval
*rval
)
1900 d
= JS_CANONICALIZE_NAN(d
);
1901 Valueify(rval
)->setNumber(d
);
1907 JS_PUBLIC_API(JSBool
)
1908 JS_AddValueRoot(JSContext
*cx
, jsval
*vp
)
1911 return js_AddRoot(cx
, Valueify(vp
), NULL
);
1914 JS_PUBLIC_API(JSBool
)
1915 JS_AddStringRoot(JSContext
*cx
, JSString
**rp
)
1918 return js_AddGCThingRoot(cx
, (void **)rp
, NULL
);
1921 JS_PUBLIC_API(JSBool
)
1922 JS_AddObjectRoot(JSContext
*cx
, JSObject
**rp
)
1925 return js_AddGCThingRoot(cx
, (void **)rp
, NULL
);
1928 JS_PUBLIC_API(JSBool
)
1929 JS_AddGCThingRoot(JSContext
*cx
, void **rp
)
1932 return js_AddGCThingRoot(cx
, (void **)rp
, NULL
);
1935 JS_PUBLIC_API(JSBool
)
1936 JS_AddNamedValueRoot(JSContext
*cx
, jsval
*vp
, const char *name
)
1939 return js_AddRoot(cx
, Valueify(vp
), name
);
1942 JS_PUBLIC_API(JSBool
)
1943 JS_AddNamedStringRoot(JSContext
*cx
, JSString
**rp
, const char *name
)
1946 return js_AddGCThingRoot(cx
, (void **)rp
, name
);
1949 JS_PUBLIC_API(JSBool
)
1950 JS_AddNamedObjectRoot(JSContext
*cx
, JSObject
**rp
, const char *name
)
1953 return js_AddGCThingRoot(cx
, (void **)rp
, name
);
1956 JS_PUBLIC_API(JSBool
)
1957 JS_AddNamedGCThingRoot(JSContext
*cx
, void **rp
, const char *name
)
1960 return js_AddGCThingRoot(cx
, (void **)rp
, name
);
1963 JS_PUBLIC_API(JSBool
)
1964 JS_RemoveValueRoot(JSContext
*cx
, jsval
*vp
)
1967 return js_RemoveRoot(cx
->runtime
, (void *)vp
);
1970 JS_PUBLIC_API(JSBool
)
1971 JS_RemoveStringRoot(JSContext
*cx
, JSString
**rp
)
1974 return js_RemoveRoot(cx
->runtime
, (void *)rp
);
1977 JS_PUBLIC_API(JSBool
)
1978 JS_RemoveObjectRoot(JSContext
*cx
, JSObject
**rp
)
1981 return js_RemoveRoot(cx
->runtime
, (void *)rp
);
1984 JS_PUBLIC_API(JSBool
)
1985 JS_RemoveGCThingRoot(JSContext
*cx
, void **rp
)
1988 return js_RemoveRoot(cx
->runtime
, (void *)rp
);
1994 JS_DumpNamedRoots(JSRuntime
*rt
,
1995 void (*dump
)(const char *name
, void *rp
, JSGCRootType type
, 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
)
2031 js_UnlockGCThingRT(cx
->runtime
, thing
);
2035 JS_PUBLIC_API(JSBool
)
2036 JS_UnlockGCThingRT(JSRuntime
*rt
, void *thing
)
2038 js_UnlockGCThingRT(rt
, thing
);
2043 JS_SetExtraGCRoots(JSRuntime
*rt
, JSTraceDataOp traceOp
, void *data
)
2045 rt
->gcExtraRootsTraceOp
= traceOp
;
2046 rt
->gcExtraRootsData
= data
;
2050 JS_TraceRuntime(JSTracer
*trc
)
2052 LeaveTrace(trc
->context
);
2053 js_TraceRuntime(trc
);
2057 JS_CallTracer(JSTracer
*trc
, void *thing
, uint32 kind
)
2060 Mark(trc
, thing
, kind
);
2065 #ifdef HAVE_XPCONNECT
2066 #include "dump_xpc.h"
2070 JS_PrintTraceThingInfo(char *buf
, size_t bufsize
, JSTracer
*trc
, void *thing
, uint32 kind
,
2080 case JSTRACE_OBJECT
:
2082 JSObject
*obj
= (JSObject
*)thing
;
2083 Class
*clasp
= obj
->getClass();
2086 #ifdef HAVE_XPCONNECT
2087 if (clasp
->flags
& JSCLASS_PRIVATE_IS_NSISUPPORTS
) {
2088 void *privateThing
= obj
->getPrivate();
2090 const char *xpcClassName
= GetXPCObjectClassName(privateThing
);
2092 name
= xpcClassName
;
2099 case JSTRACE_STRING
:
2100 name
= ((JSString
*)thing
)->isDependent()
2105 #if JS_HAS_XML_SUPPORT
2117 if (n
> bufsize
- 1)
2119 memcpy(buf
, name
, n
+ 1);
2123 if (details
&& bufsize
> 2) {
2128 case JSTRACE_OBJECT
:
2130 JSObject
*obj
= (JSObject
*)thing
;
2131 Class
*clasp
= obj
->getClass();
2132 if (clasp
== &js_FunctionClass
) {
2133 JSFunction
*fun
= GET_FUNCTION_PRIVATE(trc
->context
, obj
);
2135 JS_snprintf(buf
, bufsize
, "<newborn>");
2136 } else if (FUN_OBJECT(fun
) != obj
) {
2137 JS_snprintf(buf
, bufsize
, "%p", fun
);
2140 js_PutEscapedString(buf
, bufsize
,
2141 ATOM_TO_STRING(fun
->atom
), 0);
2143 } else if (clasp
->flags
& JSCLASS_HAS_PRIVATE
) {
2144 JS_snprintf(buf
, bufsize
, "%p", obj
->getPrivate());
2146 JS_snprintf(buf
, bufsize
, "<no private>");
2151 case JSTRACE_STRING
:
2152 js_PutEscapedString(buf
, bufsize
, (JSString
*)thing
, 0);
2155 #if JS_HAS_XML_SUPPORT
2158 extern const char *js_xml_class_str
[];
2159 JSXML
*xml
= (JSXML
*)thing
;
2161 JS_snprintf(buf
, bufsize
, "%s", js_xml_class_str
[xml
->xml_class
]);
2170 buf
[bufsize
- 1] = '\0';
2173 typedef struct JSHeapDumpNode JSHeapDumpNode
;
2175 struct JSHeapDumpNode
{
2178 JSHeapDumpNode
*next
; /* next sibling */
2179 JSHeapDumpNode
*parent
; /* node with the thing that refer to thing
2181 char edgeName
[1]; /* name of the edge from parent->thing
2185 typedef struct JSDumpingTracer
{
2187 JSDHashTable visited
;
2191 void *thingToIgnore
;
2192 JSHeapDumpNode
*parentNode
;
2193 JSHeapDumpNode
**lastNodep
;
2198 DumpNotify(JSTracer
*trc
, void *thing
, uint32 kind
)
2200 JSDumpingTracer
*dtrc
;
2202 JSDHashEntryStub
*entry
;
2203 JSHeapDumpNode
*node
;
2204 const char *edgeName
;
2205 size_t edgeNameSize
;
2207 JS_ASSERT(trc
->callback
== DumpNotify
);
2208 dtrc
= (JSDumpingTracer
*)trc
;
2210 if (!dtrc
->ok
|| thing
== dtrc
->thingToIgnore
)
2216 * Check if we have already seen thing unless it is thingToFind to include
2217 * it to the graph each time we reach it and print all live things that
2218 * refer to thingToFind.
2220 * This does not print all possible paths leading to thingToFind since
2221 * when a thing A refers directly or indirectly to thingToFind and A is
2222 * present several times in the graph, we will print only the first path
2223 * leading to A and thingToFind, other ways to reach A will be ignored.
2225 if (dtrc
->thingToFind
!= thing
) {
2227 * The startThing check allows to avoid putting startThing into the
2228 * hash table before tracing startThing in JS_DumpHeap.
2230 if (thing
== dtrc
->startThing
)
2232 entry
= (JSDHashEntryStub
*)
2233 JS_DHashTableOperate(&dtrc
->visited
, thing
, JS_DHASH_ADD
);
2235 JS_ReportOutOfMemory(cx
);
2236 dtrc
->ok
= JS_FALSE
;
2244 if (dtrc
->base
.debugPrinter
) {
2245 dtrc
->base
.debugPrinter(trc
, dtrc
->buffer
, sizeof(dtrc
->buffer
));
2246 edgeName
= dtrc
->buffer
;
2247 } else if (dtrc
->base
.debugPrintIndex
!= (size_t)-1) {
2248 JS_snprintf(dtrc
->buffer
, sizeof(dtrc
->buffer
), "%s[%lu]",
2249 (const char *)dtrc
->base
.debugPrintArg
,
2250 dtrc
->base
.debugPrintIndex
);
2251 edgeName
= dtrc
->buffer
;
2253 edgeName
= (const char*)dtrc
->base
.debugPrintArg
;
2256 edgeNameSize
= strlen(edgeName
) + 1;
2257 node
= (JSHeapDumpNode
*)
2258 cx
->malloc(offsetof(JSHeapDumpNode
, edgeName
) + edgeNameSize
);
2260 dtrc
->ok
= JS_FALSE
;
2264 node
->thing
= thing
;
2267 node
->parent
= dtrc
->parentNode
;
2268 memcpy(node
->edgeName
, edgeName
, edgeNameSize
);
2270 JS_ASSERT(!*dtrc
->lastNodep
);
2271 *dtrc
->lastNodep
= node
;
2272 dtrc
->lastNodep
= &node
->next
;
2275 /* Dump node and the chain that leads to thing it contains. */
2277 DumpNode(JSDumpingTracer
*dtrc
, FILE* fp
, JSHeapDumpNode
*node
)
2279 JSHeapDumpNode
*prev
, *following
;
2282 enum { MAX_PARENTS_TO_PRINT
= 10 };
2284 JS_PrintTraceThingInfo(dtrc
->buffer
, sizeof dtrc
->buffer
,
2285 &dtrc
->base
, node
->thing
, node
->kind
, JS_TRUE
);
2286 if (fprintf(fp
, "%p %-22s via ", node
->thing
, dtrc
->buffer
) < 0)
2290 * We need to print the parent chain in the reverse order. To do it in
2291 * O(N) time where N is the chain length we first reverse the chain while
2292 * searching for the top and then print each node while restoring the
2295 chainLimit
= MAX_PARENTS_TO_PRINT
;
2298 following
= node
->parent
;
2299 node
->parent
= prev
;
2304 if (chainLimit
== 0) {
2305 if (fputs("...", fp
) < 0)
2316 /* Loop must continue even when !ok to restore the parent chain. */
2319 /* Print edge from some runtime root or startThing. */
2320 if (fputs(node
->edgeName
, fp
) < 0)
2323 JS_PrintTraceThingInfo(dtrc
->buffer
, sizeof dtrc
->buffer
,
2324 &dtrc
->base
, prev
->thing
, prev
->kind
,
2326 if (fprintf(fp
, "(%p %s).%s",
2327 prev
->thing
, dtrc
->buffer
, node
->edgeName
) < 0) {
2332 following
= node
->parent
;
2333 node
->parent
= prev
;
2338 return ok
&& putc('\n', fp
) >= 0;
2341 JS_PUBLIC_API(JSBool
)
2342 JS_DumpHeap(JSContext
*cx
, FILE *fp
, void* startThing
, uint32 startKind
,
2343 void *thingToFind
, size_t maxDepth
, void *thingToIgnore
)
2345 JSDumpingTracer dtrc
;
2346 JSHeapDumpNode
*node
, *children
, *next
, *parent
;
2348 JSBool thingToFindWasTraced
;
2353 JS_TRACER_INIT(&dtrc
.base
, cx
, DumpNotify
);
2354 if (!JS_DHashTableInit(&dtrc
.visited
, JS_DHashGetStubOps(),
2355 NULL
, sizeof(JSDHashEntryStub
),
2356 JS_DHASH_DEFAULT_CAPACITY(100))) {
2357 JS_ReportOutOfMemory(cx
);
2361 dtrc
.startThing
= startThing
;
2362 dtrc
.thingToFind
= thingToFind
;
2363 dtrc
.thingToIgnore
= thingToIgnore
;
2364 dtrc
.parentNode
= NULL
;
2366 dtrc
.lastNodep
= &node
;
2368 JS_ASSERT(startKind
== 0);
2369 JS_TraceRuntime(&dtrc
.base
);
2371 JS_TraceChildren(&dtrc
.base
, startThing
, startKind
);
2378 thingToFindWasTraced
= thingToFind
&& thingToFind
== startThing
;
2381 * Loop must continue even when !dtrc.ok to free all nodes allocated
2385 if (thingToFind
== NULL
|| thingToFind
== node
->thing
)
2386 dtrc
.ok
= DumpNode(&dtrc
, fp
, node
);
2388 /* Descend into children. */
2391 (thingToFind
!= node
->thing
|| !thingToFindWasTraced
)) {
2392 dtrc
.parentNode
= node
;
2394 dtrc
.lastNodep
= &children
;
2395 JS_TraceChildren(&dtrc
.base
, node
->thing
, node
->kind
);
2396 if (thingToFind
== node
->thing
)
2397 thingToFindWasTraced
= JS_TRUE
;
2398 if (children
!= NULL
) {
2406 /* Move to next or parents next and free the node. */
2409 parent
= node
->parent
;
2416 JS_ASSERT(depth
> 1);
2423 JS_ASSERT(depth
== 1);
2424 JS_DHashTableFinish(&dtrc
.visited
);
2431 JS_MarkGCThing(JSContext
*cx
, jsval v
, const char *name
, void *arg
)
2435 trc
= (JSTracer
*)arg
;
2437 trc
= cx
->runtime
->gcMarkingTracer
;
2439 JS_ASSERT(trc
== cx
->runtime
->gcMarkingTracer
);
2441 #ifdef JS_THREADSAFE
2442 JS_ASSERT(cx
->runtime
->gcThread
== trc
->context
->thread
);
2444 MarkValue(trc
, Valueify(v
), name
? name
: "unknown");
2447 extern JS_PUBLIC_API(JSBool
)
2448 JS_IsGCMarkingTracer(JSTracer
*trc
)
2450 return IS_GC_MARKING_TRACER(trc
);
2454 JS_GC(JSContext
*cx
)
2458 /* Don't nuke active arenas if executing or compiling. */
2459 if (cx
->tempPool
.current
== &cx
->tempPool
.first
)
2460 JS_FinishArenaPool(&cx
->tempPool
);
2461 js_GC(cx
, GC_NORMAL
);
2465 JS_MaybeGC(JSContext
*cx
)
2468 uint32 bytes
, lastBytes
;
2473 if (rt
->gcZeal
> 0) {
2479 bytes
= rt
->gcBytes
;
2480 lastBytes
= rt
->gcLastBytes
;
2483 * We run the GC if we used all available free GC cells and had to
2484 * allocate extra 1/3 of GC arenas since the last run of GC, or if
2485 * we have malloc'd more bytes through JS_malloc than we were told
2486 * to allocate by JS_NewRuntime.
2489 * bytes > 4/3 lastBytes
2490 * condition is the following. Bug 312238 changed bytes and lastBytes
2491 * to mean the total amount of memory that the GC uses now and right
2492 * after the last GC.
2494 * Before the bug the variables meant the size of allocated GC things
2495 * now and right after the last GC. That size did not include the
2496 * memory taken by free GC cells and the condition was
2497 * bytes > 3/2 lastBytes.
2498 * That is, we run the GC if we have half again as many bytes of
2499 * GC-things as the last time we GC'd. To be compatible we need to
2500 * express that condition through the new meaning of bytes and
2503 * We write the original condition as
2504 * B*(1-F) > 3/2 Bl*(1-Fl)
2505 * where B is the total memory size allocated by GC and F is the free
2506 * cell density currently and Sl and Fl are the size and the density
2507 * right after GC. The density by definition is memory taken by free
2508 * cells divided by total amount of memory. In other words, B and Bl
2509 * are bytes and lastBytes with the new meaning and B*(1-F) and
2510 * Bl*(1-Fl) are bytes and lastBytes with the original meaning.
2512 * Our task is to exclude F and Fl from the last statement. According
2513 * to the stats from bug 331966 comment 23, Fl is about 10-25% for a
2514 * typical run of the browser. It means that the original condition
2515 * implied that we did not run GC unless we exhausted the pool of
2516 * free cells. Indeed if we still have free cells, then B == Bl since
2517 * we did not yet allocated any new arenas and the condition means
2518 * 1 - F > 3/2 (1-Fl) or 3/2Fl > 1/2 + F
2519 * That implies 3/2 Fl > 1/2 or Fl > 1/3. That cannot be fulfilled
2520 * for the state described by the stats. So we can write the original
2522 * F == 0 && B > 3/2 Bl(1-Fl)
2523 * Again using the stats we see that Fl is about 11% when the browser
2524 * starts up and when we are far from hitting rt->gcMaxBytes. With
2526 * F == 0 && B > 3/2 Bl(1-0.11)
2527 * or approximately F == 0 && B > 4/3 Bl.
2529 if ((bytes
> 8192 && bytes
> lastBytes
+ lastBytes
/ 3) ||
2530 rt
->isGCMallocLimitReached()) {
2535 JS_PUBLIC_API(JSGCCallback
)
2536 JS_SetGCCallback(JSContext
*cx
, JSGCCallback cb
)
2539 return JS_SetGCCallbackRT(cx
->runtime
, cb
);
2542 JS_PUBLIC_API(JSGCCallback
)
2543 JS_SetGCCallbackRT(JSRuntime
*rt
, JSGCCallback cb
)
2547 oldcb
= rt
->gcCallback
;
2548 rt
->gcCallback
= cb
;
2552 JS_PUBLIC_API(JSBool
)
2553 JS_IsAboutToBeFinalized(JSContext
*cx
, void *thing
)
2556 JS_ASSERT(!cx
->runtime
->gcMarkingTracer
);
2557 return js_IsAboutToBeFinalized(thing
);
2561 JS_SetGCParameter(JSRuntime
*rt
, JSGCParamKey key
, uint32 value
)
2564 case JSGC_MAX_BYTES
:
2565 rt
->gcMaxBytes
= value
;
2567 case JSGC_MAX_MALLOC_BYTES
:
2568 rt
->setGCMaxMallocBytes(value
);
2570 case JSGC_STACKPOOL_LIFESPAN
:
2571 rt
->gcEmptyArenaPoolLifespan
= value
;
2574 JS_ASSERT(key
== JSGC_TRIGGER_FACTOR
);
2575 JS_ASSERT(value
>= 100);
2576 rt
->setGCTriggerFactor(value
);
2581 JS_PUBLIC_API(uint32
)
2582 JS_GetGCParameter(JSRuntime
*rt
, JSGCParamKey key
)
2585 case JSGC_MAX_BYTES
:
2586 return rt
->gcMaxBytes
;
2587 case JSGC_MAX_MALLOC_BYTES
:
2588 return rt
->gcMaxMallocBytes
;
2589 case JSGC_STACKPOOL_LIFESPAN
:
2590 return rt
->gcEmptyArenaPoolLifespan
;
2591 case JSGC_TRIGGER_FACTOR
:
2592 return rt
->gcTriggerFactor
;
2596 JS_ASSERT(key
== JSGC_NUMBER
);
2597 return rt
->gcNumber
;
2602 JS_SetGCParameterForThread(JSContext
*cx
, JSGCParamKey key
, uint32 value
)
2604 JS_ASSERT(key
== JSGC_MAX_CODE_CACHE_BYTES
);
2606 SetMaxCodeCacheBytes(cx
, value
);
2610 JS_PUBLIC_API(uint32
)
2611 JS_GetGCParameterForThread(JSContext
*cx
, JSGCParamKey key
)
2613 JS_ASSERT(key
== JSGC_MAX_CODE_CACHE_BYTES
);
2615 return JS_THREAD_DATA(cx
)->traceMonitor
.maxCodeCacheBytes
;
2622 JS_FlushCaches(JSContext
*cx
)
2630 JS_AddExternalStringFinalizer(JSStringFinalizeOp finalizer
)
2632 return js_ChangeExternalStringFinalizer(NULL
, finalizer
);
2636 JS_RemoveExternalStringFinalizer(JSStringFinalizeOp finalizer
)
2638 return js_ChangeExternalStringFinalizer(finalizer
, NULL
);
2641 JS_PUBLIC_API(JSString
*)
2642 JS_NewExternalString(JSContext
*cx
, jschar
*chars
, size_t length
, intN type
)
2645 JS_ASSERT(uintN(type
) < JS_EXTERNAL_STRING_LIMIT
);
2647 JSString
*str
= js_NewGCExternalString(cx
, uintN(type
));
2650 str
->initFlat(chars
, length
);
2651 cx
->updateMallocCounter((length
+ 1) * sizeof(jschar
));
2656 JS_GetExternalStringGCType(JSRuntime
*rt
, JSString
*str
)
2659 * No need to test this in js_GetExternalStringGCType, which asserts its
2660 * inverse instead of wasting cycles on testing a condition we can ensure
2661 * by auditing in-VM calls to the js_... helper.
2663 if (JSString::isStatic(str
))
2666 return js_GetExternalStringGCType(str
);
2670 JS_SetThreadStackLimit(JSContext
*cx
, jsuword limitAddr
)
2672 #if JS_STACK_GROWTH_DIRECTION > 0
2674 limitAddr
= jsuword(-1);
2676 cx
->stackLimit
= limitAddr
;
2680 JS_SetNativeStackQuota(JSContext
*cx
, size_t stackSize
)
2682 #ifdef JS_THREADSAFE
2683 JS_ASSERT(cx
->thread
);
2686 #if JS_STACK_GROWTH_DIRECTION > 0
2687 if (stackSize
== 0) {
2688 cx
->stackLimit
= jsuword(-1);
2690 jsuword stackBase
= reinterpret_cast<jsuword
>(JS_THREAD_DATA(cx
)->nativeStackBase
);
2691 JS_ASSERT(stackBase
<= size_t(-1) - stackSize
);
2692 cx
->stackLimit
= stackBase
+ stackSize
- 1;
2695 if (stackSize
== 0) {
2698 jsuword stackBase
= reinterpret_cast<jsuword
>(JS_THREAD_DATA(cx
)->nativeStackBase
);
2699 JS_ASSERT(stackBase
>= stackSize
);
2700 cx
->stackLimit
= stackBase
- (stackSize
- 1);
2706 JS_SetScriptStackQuota(JSContext
*cx
, size_t quota
)
2708 cx
->scriptStackQuota
= quota
;
2711 /************************************************************************/
2714 JS_DestroyIdArray(JSContext
*cx
, JSIdArray
*ida
)
2719 JS_PUBLIC_API(JSBool
)
2720 JS_ValueToId(JSContext
*cx
, jsval v
, jsid
*idp
)
2723 assertSameCompartment(cx
, v
);
2724 return ValueToId(cx
, Valueify(v
), idp
);
2727 JS_PUBLIC_API(JSBool
)
2728 JS_IdToValue(JSContext
*cx
, jsid id
, jsval
*vp
)
2731 *vp
= IdToJsval(id
);
2732 assertSameCompartment(cx
, *vp
);
2736 JS_PUBLIC_API(JSBool
)
2737 JS_PropertyStub(JSContext
*cx
, JSObject
*obj
, jsid id
, jsval
*vp
)
2742 JS_PUBLIC_API(JSBool
)
2743 JS_EnumerateStub(JSContext
*cx
, JSObject
*obj
)
2748 JS_PUBLIC_API(JSBool
)
2749 JS_ResolveStub(JSContext
*cx
, JSObject
*obj
, jsid id
)
2754 JS_PUBLIC_API(JSBool
)
2755 JS_ConvertStub(JSContext
*cx
, JSObject
*obj
, JSType type
, jsval
*vp
)
2757 JS_ASSERT(type
!= JSTYPE_OBJECT
&& type
!= JSTYPE_FUNCTION
);
2758 return js_TryValueOf(cx
, obj
, type
, Valueify(vp
));
2762 JS_FinalizeStub(JSContext
*cx
, JSObject
*obj
)
2765 JS_PUBLIC_API(JSObject
*)
2766 JS_InitClass(JSContext
*cx
, JSObject
*obj
, JSObject
*parent_proto
,
2767 JSClass
*clasp
, JSNative constructor
, uintN nargs
,
2768 JSPropertySpec
*ps
, JSFunctionSpec
*fs
,
2769 JSPropertySpec
*static_ps
, JSFunctionSpec
*static_fs
)
2772 assertSameCompartment(cx
, obj
, parent_proto
);
2773 return js_InitClass(cx
, obj
, parent_proto
, Valueify(clasp
),
2774 Valueify(constructor
), nargs
,
2775 ps
, fs
, static_ps
, static_fs
);
2778 #ifdef JS_THREADSAFE
2779 JS_PUBLIC_API(JSClass
*)
2780 JS_GetClass(JSContext
*cx
, JSObject
*obj
)
2782 return Jsvalify(obj
->getClass());
2785 JS_PUBLIC_API(JSClass
*)
2786 JS_GetClass(JSObject
*obj
)
2788 return Jsvalify(obj
->getClass());
2792 JS_PUBLIC_API(JSBool
)
2793 JS_InstanceOf(JSContext
*cx
, JSObject
*obj
, JSClass
*clasp
, jsval
*argv
)
2796 assertSameCompartment(cx
, obj
);
2797 return InstanceOf(cx
, obj
, Valueify(clasp
), Valueify(argv
));
2800 JS_PUBLIC_API(JSBool
)
2801 JS_HasInstance(JSContext
*cx
, JSObject
*obj
, jsval v
, JSBool
*bp
)
2803 assertSameCompartment(cx
, obj
, v
);
2804 return HasInstance(cx
, obj
, Valueify(&v
), bp
);
2807 JS_PUBLIC_API(void *)
2808 JS_GetPrivate(JSContext
*cx
, JSObject
*obj
)
2810 assertSameCompartment(cx
, obj
);
2811 return obj
->getPrivate();
2814 JS_PUBLIC_API(JSBool
)
2815 JS_SetPrivate(JSContext
*cx
, JSObject
*obj
, void *data
)
2817 assertSameCompartment(cx
, obj
);
2818 obj
->setPrivate(data
);
2822 JS_PUBLIC_API(void *)
2823 JS_GetInstancePrivate(JSContext
*cx
, JSObject
*obj
, JSClass
*clasp
, jsval
*argv
)
2825 if (!InstanceOf(cx
, obj
, Valueify(clasp
), Valueify(argv
)))
2827 return obj
->getPrivate();
2830 JS_PUBLIC_API(JSObject
*)
2831 JS_GetPrototype(JSContext
*cx
, JSObject
*obj
)
2836 assertSameCompartment(cx
, obj
);
2837 proto
= obj
->getProto();
2839 /* Beware ref to dead object (we may be called from obj's finalizer). */
2840 return proto
&& proto
->map
? proto
: NULL
;
2843 JS_PUBLIC_API(JSBool
)
2844 JS_SetPrototype(JSContext
*cx
, JSObject
*obj
, JSObject
*proto
)
2847 assertSameCompartment(cx
, obj
, proto
);
2848 return SetProto(cx
, obj
, proto
, JS_FALSE
);
2851 JS_PUBLIC_API(JSObject
*)
2852 JS_GetParent(JSContext
*cx
, JSObject
*obj
)
2854 assertSameCompartment(cx
, obj
);
2855 JSObject
*parent
= obj
->getParent();
2857 /* Beware ref to dead object (we may be called from obj's finalizer). */
2858 return parent
&& parent
->map
? parent
: NULL
;
2861 JS_PUBLIC_API(JSBool
)
2862 JS_SetParent(JSContext
*cx
, JSObject
*obj
, JSObject
*parent
)
2865 JS_ASSERT(parent
|| !obj
->getParent());
2866 assertSameCompartment(cx
, obj
, parent
);
2867 obj
->setParent(parent
);
2871 JS_PUBLIC_API(JSObject
*)
2872 JS_GetConstructor(JSContext
*cx
, JSObject
*proto
)
2877 assertSameCompartment(cx
, proto
);
2879 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
);
2881 if (!proto
->getProperty(cx
, ATOM_TO_JSID(cx
->runtime
->atomState
.constructorAtom
), &cval
))
2885 if (!IsFunctionObject(cval
, &funobj
)) {
2886 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_NO_CONSTRUCTOR
,
2887 proto
->getClass()->name
);
2890 return &cval
.toObject();
2893 JS_PUBLIC_API(JSBool
)
2894 JS_GetObjectId(JSContext
*cx
, JSObject
*obj
, jsid
*idp
)
2896 assertSameCompartment(cx
, obj
);
2897 *idp
= OBJECT_TO_JSID(obj
);
2901 JS_PUBLIC_API(JSObject
*)
2902 JS_NewGlobalObject(JSContext
*cx
, JSClass
*clasp
)
2905 JS_ASSERT(clasp
->flags
& JSCLASS_IS_GLOBAL
);
2906 JSObject
*obj
= NewNonFunction
<WithProto::Given
>(cx
, Valueify(clasp
), NULL
, NULL
);
2908 !js_SetReservedSlot(cx
, obj
, JSRESERVED_GLOBAL_COMPARTMENT
,
2909 PrivateValue(cx
->compartment
))) {
2915 JS_PUBLIC_API(JSObject
*)
2916 JS_NewCompartmentAndGlobalObject(JSContext
*cx
, JSClass
*clasp
, JSPrincipals
*principals
)
2919 JSCompartment
*compartment
= NewCompartment(cx
, principals
);
2923 JSCompartment
*saved
= cx
->compartment
;
2924 cx
->compartment
= compartment
;
2925 JSObject
*obj
= JS_NewGlobalObject(cx
, clasp
);
2926 cx
->compartment
= saved
;
2931 JS_PUBLIC_API(JSObject
*)
2932 JS_NewObject(JSContext
*cx
, JSClass
*jsclasp
, JSObject
*proto
, JSObject
*parent
)
2935 assertSameCompartment(cx
, proto
, parent
);
2937 Class
*clasp
= Valueify(jsclasp
);
2939 clasp
= &js_ObjectClass
; /* default class is Object */
2941 JS_ASSERT(clasp
!= &js_FunctionClass
);
2942 JS_ASSERT(!(clasp
->flags
& JSCLASS_IS_GLOBAL
));
2944 JSObject
*obj
= NewNonFunction
<WithProto::Class
>(cx
, clasp
, proto
, parent
);
2946 JS_ASSERT_IF(obj
, obj
->getParent());
2950 JS_PUBLIC_API(JSObject
*)
2951 JS_NewObjectWithGivenProto(JSContext
*cx
, JSClass
*jsclasp
, JSObject
*proto
, JSObject
*parent
)
2954 assertSameCompartment(cx
, proto
, parent
);
2956 Class
*clasp
= Valueify(jsclasp
);
2958 clasp
= &js_ObjectClass
; /* default class is Object */
2960 JS_ASSERT(clasp
!= &js_FunctionClass
);
2961 JS_ASSERT(!(clasp
->flags
& JSCLASS_IS_GLOBAL
));
2963 return NewNonFunction
<WithProto::Given
>(cx
, clasp
, proto
, parent
);
2966 JS_PUBLIC_API(JSBool
)
2967 JS_SealObject(JSContext
*cx
, JSObject
*obj
, JSBool deep
)
2970 assertSameCompartment(cx
, obj
);
2976 if (obj
->isDenseArray() && !obj
->makeDenseArraySlow(cx
))
2979 if (!obj
->isNative()) {
2980 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
,
2981 JSMSG_CANT_SEAL_OBJECT
,
2982 obj
->getClass()->name
);
2986 scope
= obj
->scope();
2988 #if defined JS_THREADSAFE && defined DEBUG
2989 /* Insist on scope being used exclusively by cx's thread. */
2990 if (scope
->title
.ownercx
!= cx
) {
2991 JS_LOCK_OBJ(cx
, obj
);
2992 JS_ASSERT(obj
->scope() == scope
);
2993 JS_ASSERT(scope
->title
.ownercx
== cx
);
2994 JS_UNLOCK_SCOPE(cx
, scope
);
2998 /* Nothing to do if obj's scope is already sealed. */
2999 if (scope
->sealed())
3002 /* XXX Enumerate lazy properties now, as they can't be added later. */
3003 ida
= JS_Enumerate(cx
, obj
);
3006 JS_DestroyIdArray(cx
, ida
);
3008 /* Ensure that obj has its own, mutable scope, and seal that scope. */
3009 JS_LOCK_OBJ(cx
, obj
);
3010 scope
= js_GetMutableScope(cx
, obj
);
3013 JS_UNLOCK_OBJ(cx
, obj
);
3017 /* If we are not sealing an entire object graph, we're done. */
3021 /* Walk slots in obj and if any value is a non-null object, seal it. */
3022 nslots
= scope
->freeslot
;
3023 for (i
= 0; i
!= nslots
; ++i
) {
3024 const Value
&v
= obj
->getSlot(i
);
3025 if (i
== JSSLOT_PRIVATE
&& (obj
->getClass()->flags
& JSCLASS_HAS_PRIVATE
))
3027 if (v
.isPrimitive())
3029 if (!JS_SealObject(cx
, &v
.toObject(), deep
))
3035 JS_PUBLIC_API(JSObject
*)
3036 JS_ConstructObject(JSContext
*cx
, JSClass
*jsclasp
, JSObject
*proto
, JSObject
*parent
)
3039 assertSameCompartment(cx
, proto
, parent
);
3040 Class
*clasp
= Valueify(jsclasp
);
3042 clasp
= &js_ObjectClass
; /* default class is Object */
3043 return js_ConstructObject(cx
, clasp
, proto
, parent
, 0, NULL
);
3046 JS_PUBLIC_API(JSObject
*)
3047 JS_ConstructObjectWithArguments(JSContext
*cx
, JSClass
*jsclasp
, JSObject
*proto
,
3048 JSObject
*parent
, uintN argc
, jsval
*argv
)
3051 assertSameCompartment(cx
, proto
, parent
, JSValueArray(argv
, argc
));
3052 Class
*clasp
= Valueify(jsclasp
);
3054 clasp
= &js_ObjectClass
; /* default class is Object */
3055 return js_ConstructObject(cx
, clasp
, proto
, parent
, argc
, Valueify(argv
));
3059 LookupPropertyById(JSContext
*cx
, JSObject
*obj
, jsid id
, uintN flags
,
3060 JSObject
**objp
, JSProperty
**propp
)
3063 assertSameCompartment(cx
, obj
, id
);
3065 JSAutoResolveFlags
rf(cx
, flags
);
3066 id
= js_CheckForStringIndex(id
);
3067 return obj
->lookupProperty(cx
, id
, objp
, propp
);
3070 #define AUTO_NAMELEN(s,n) (((n) == (size_t)-1) ? js_strlen(s) : (n))
3073 LookupResult(JSContext
*cx
, JSObject
*obj
, JSObject
*obj2
, jsid id
,
3074 JSProperty
*prop
, Value
*vp
)
3077 /* XXX bad API: no way to tell "not defined" from "void value" */
3082 if (obj2
->isNative()) {
3083 JSScopeProperty
*sprop
= (JSScopeProperty
*) prop
;
3085 if (sprop
->isMethod()) {
3086 AutoScopePropertyRooter
root(cx
, sprop
);
3087 JS_UNLOCK_OBJ(cx
, obj2
);
3088 vp
->setObject(sprop
->methodObject());
3089 return obj2
->scope()->methodReadBarrier(cx
, sprop
, vp
);
3092 /* Peek at the native property's slot value, without doing a Get. */
3093 if (SPROP_HAS_VALID_SLOT(sprop
, obj2
->scope()))
3094 *vp
= obj2
->lockedGetSlot(sprop
->slot
);
3096 vp
->setBoolean(true);
3097 JS_UNLOCK_OBJ(cx
, obj2
);
3098 } else if (obj2
->isDenseArray()) {
3099 return js_GetDenseArrayElementValue(cx
, obj2
, id
, vp
);
3101 /* XXX bad API: no way to return "defined but value unknown" */
3102 vp
->setBoolean(true);
3107 JS_PUBLIC_API(JSBool
)
3108 JS_LookupPropertyById(JSContext
*cx
, JSObject
*obj
, jsid id
, jsval
*vp
)
3112 return LookupPropertyById(cx
, obj
, id
, JSRESOLVE_QUALIFIED
, &obj2
, &prop
) &&
3113 LookupResult(cx
, obj
, obj2
, id
, prop
, Valueify(vp
));
3116 JS_PUBLIC_API(JSBool
)
3117 JS_LookupElement(JSContext
*cx
, JSObject
*obj
, jsint index
, jsval
*vp
)
3119 return JS_LookupPropertyById(cx
, obj
, INT_TO_JSID(index
), vp
);
3122 JS_PUBLIC_API(JSBool
)
3123 JS_LookupProperty(JSContext
*cx
, JSObject
*obj
, const char *name
, jsval
*vp
)
3125 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3126 return atom
&& JS_LookupPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), vp
);
3129 JS_PUBLIC_API(JSBool
)
3130 JS_LookupUCProperty(JSContext
*cx
, JSObject
*obj
, const jschar
*name
, size_t namelen
, jsval
*vp
)
3132 JSAtom
*atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
3133 return atom
&& JS_LookupPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), vp
);
3136 JS_PUBLIC_API(JSBool
)
3137 JS_LookupPropertyWithFlagsById(JSContext
*cx
, JSObject
*obj
, jsid id
, uintN flags
,
3138 JSObject
**objp
, jsval
*vp
)
3144 assertSameCompartment(cx
, obj
, id
);
3145 ok
= obj
->isNative()
3146 ? js_LookupPropertyWithFlags(cx
, obj
, id
, flags
, objp
, &prop
) >= 0
3147 : obj
->lookupProperty(cx
, id
, objp
, &prop
);
3148 return ok
&& LookupResult(cx
, obj
, *objp
, id
, prop
, Valueify(vp
));
3151 JS_PUBLIC_API(JSBool
)
3152 JS_LookupPropertyWithFlags(JSContext
*cx
, JSObject
*obj
, const char *name
, uintN flags
, jsval
*vp
)
3155 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3156 return atom
&& JS_LookupPropertyWithFlagsById(cx
, obj
, ATOM_TO_JSID(atom
), flags
, &obj2
, vp
);
3160 HasPropertyResult(JSContext
*cx
, JSObject
*obj2
, JSProperty
*prop
, JSBool
*foundp
)
3162 *foundp
= (prop
!= NULL
);
3164 obj2
->dropProperty(cx
, prop
);
3168 JS_PUBLIC_API(JSBool
)
3169 JS_HasPropertyById(JSContext
*cx
, JSObject
*obj
, jsid id
, JSBool
*foundp
)
3173 return LookupPropertyById(cx
, obj
, id
, JSRESOLVE_QUALIFIED
| JSRESOLVE_DETECTING
,
3175 HasPropertyResult(cx
, obj2
, prop
, foundp
);
3178 JS_PUBLIC_API(JSBool
)
3179 JS_HasElement(JSContext
*cx
, JSObject
*obj
, jsint index
, JSBool
*foundp
)
3181 return JS_HasPropertyById(cx
, obj
, INT_TO_JSID(index
), foundp
);
3184 JS_PUBLIC_API(JSBool
)
3185 JS_HasProperty(JSContext
*cx
, JSObject
*obj
, const char *name
, JSBool
*foundp
)
3187 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3188 return atom
&& JS_HasPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), foundp
);
3191 JS_PUBLIC_API(JSBool
)
3192 JS_HasUCProperty(JSContext
*cx
, JSObject
*obj
, const jschar
*name
, size_t namelen
, JSBool
*foundp
)
3194 JSAtom
*atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
3195 return atom
&& JS_HasPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), foundp
);
3198 JS_PUBLIC_API(JSBool
)
3199 JS_AlreadyHasOwnPropertyById(JSContext
*cx
, JSObject
*obj
, jsid id
, JSBool
*foundp
)
3202 assertSameCompartment(cx
, obj
, id
);
3204 if (!obj
->isNative()) {
3208 if (!LookupPropertyById(cx
, obj
, id
, JSRESOLVE_QUALIFIED
| JSRESOLVE_DETECTING
,
3212 *foundp
= (obj
== obj2
);
3214 obj2
->dropProperty(cx
, prop
);
3218 JS_LOCK_OBJ(cx
, obj
);
3219 JSScope
*scope
= obj
->scope();
3220 *foundp
= scope
->hasProperty(id
);
3221 JS_UNLOCK_SCOPE(cx
, scope
);
3225 JS_PUBLIC_API(JSBool
)
3226 JS_AlreadyHasOwnElement(JSContext
*cx
, JSObject
*obj
, jsint index
, JSBool
*foundp
)
3228 return JS_AlreadyHasOwnPropertyById(cx
, obj
, INT_TO_JSID(index
), foundp
);
3231 JS_PUBLIC_API(JSBool
)
3232 JS_AlreadyHasOwnProperty(JSContext
*cx
, JSObject
*obj
, const char *name
, JSBool
*foundp
)
3234 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3235 return atom
&& JS_AlreadyHasOwnPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), foundp
);
3238 JS_PUBLIC_API(JSBool
)
3239 JS_AlreadyHasOwnUCProperty(JSContext
*cx
, JSObject
*obj
, const jschar
*name
, size_t namelen
,
3242 JSAtom
*atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
3243 return atom
&& JS_AlreadyHasOwnPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), foundp
);
3247 DefinePropertyById(JSContext
*cx
, JSObject
*obj
, jsid id
, const Value
&value
,
3248 PropertyOp getter
, PropertyOp setter
, uintN attrs
,
3249 uintN flags
, intN tinyid
)
3252 assertSameCompartment(cx
, obj
, id
, value
,
3253 (attrs
& JSPROP_GETTER
)
3254 ? JS_FUNC_TO_DATA_PTR(JSObject
*, getter
)
3256 (attrs
& JSPROP_SETTER
)
3257 ? JS_FUNC_TO_DATA_PTR(JSObject
*, setter
)
3260 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
| JSRESOLVE_DECLARING
);
3261 if (flags
!= 0 && obj
->isNative()) {
3262 return !!js_DefineNativeProperty(cx
, obj
, id
, value
, getter
, setter
,
3263 attrs
, flags
, tinyid
, NULL
);
3265 return obj
->defineProperty(cx
, id
, value
, getter
, setter
, attrs
);
3268 JS_PUBLIC_API(JSBool
)
3269 JS_DefinePropertyById(JSContext
*cx
, JSObject
*obj
, jsid id
, jsval value
,
3270 JSPropertyOp getter
, JSPropertyOp setter
, uintN attrs
)
3272 return DefinePropertyById(cx
, obj
, id
, Valueify(value
), Valueify(getter
),
3273 Valueify(setter
), attrs
, 0, 0);
3276 JS_PUBLIC_API(JSBool
)
3277 JS_DefineElement(JSContext
*cx
, JSObject
*obj
, jsint index
, jsval value
,
3278 JSPropertyOp getter
, JSPropertyOp setter
, uintN attrs
)
3280 return DefinePropertyById(cx
, obj
, INT_TO_JSID(index
), Valueify(value
),
3281 Valueify(getter
), Valueify(setter
), attrs
, 0, 0);
3285 DefineProperty(JSContext
*cx
, JSObject
*obj
, const char *name
, const Value
&value
,
3286 PropertyOp getter
, PropertyOp setter
, uintN attrs
,
3287 uintN flags
, intN tinyid
)
3292 if (attrs
& JSPROP_INDEX
) {
3293 id
= INT_TO_JSID(intptr_t(name
));
3295 attrs
&= ~JSPROP_INDEX
;
3297 atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3300 id
= ATOM_TO_JSID(atom
);
3302 return DefinePropertyById(cx
, obj
, id
, value
, getter
, setter
, attrs
, flags
, tinyid
);
3305 JS_PUBLIC_API(JSBool
)
3306 JS_DefineProperty(JSContext
*cx
, JSObject
*obj
, const char *name
, jsval value
,
3307 JSPropertyOp getter
, JSPropertyOp setter
, uintN attrs
)
3309 return DefineProperty(cx
, obj
, name
, Valueify(value
), Valueify(getter
),
3310 Valueify(setter
), attrs
, 0, 0);
3313 JS_PUBLIC_API(JSBool
)
3314 JS_DefinePropertyWithTinyId(JSContext
*cx
, JSObject
*obj
, const char *name
, int8 tinyid
,
3315 jsval value
, JSPropertyOp getter
, JSPropertyOp setter
, uintN attrs
)
3317 return DefineProperty(cx
, obj
, name
, Valueify(value
), Valueify(getter
),
3318 Valueify(setter
), attrs
, JSScopeProperty::HAS_SHORTID
, tinyid
);
3322 DefineUCProperty(JSContext
*cx
, JSObject
*obj
, const jschar
*name
, size_t namelen
,
3323 const Value
&value
, PropertyOp getter
, PropertyOp setter
, uintN attrs
,
3324 uintN flags
, intN tinyid
)
3326 JSAtom
*atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
3327 return atom
&& DefinePropertyById(cx
, obj
, ATOM_TO_JSID(atom
), value
, getter
, setter
, attrs
,
3331 JS_PUBLIC_API(JSBool
)
3332 JS_DefineUCProperty(JSContext
*cx
, JSObject
*obj
, const jschar
*name
, size_t namelen
,
3333 jsval value
, JSPropertyOp getter
, JSPropertyOp setter
, uintN attrs
)
3335 return DefineUCProperty(cx
, obj
, name
, namelen
, Valueify(value
),
3336 Valueify(getter
), Valueify(setter
), attrs
, 0, 0);
3339 JS_PUBLIC_API(JSBool
)
3340 JS_DefineUCPropertyWithTinyId(JSContext
*cx
, JSObject
*obj
, const jschar
*name
, size_t namelen
,
3341 int8 tinyid
, jsval value
, JSPropertyOp getter
, JSPropertyOp setter
,
3344 return DefineUCProperty(cx
, obj
, name
, namelen
, Valueify(value
), Valueify(getter
),
3345 Valueify(setter
), attrs
, JSScopeProperty::HAS_SHORTID
, tinyid
);
3348 JS_PUBLIC_API(JSBool
)
3349 JS_DefineOwnProperty(JSContext
*cx
, JSObject
*obj
, jsid id
, jsval descriptor
, JSBool
*bp
)
3352 assertSameCompartment(cx
, obj
, id
, descriptor
);
3353 return js_DefineOwnProperty(cx
, obj
, id
, Valueify(descriptor
), bp
);
3356 JS_PUBLIC_API(JSObject
*)
3357 JS_DefineObject(JSContext
*cx
, JSObject
*obj
, const char *name
, JSClass
*jsclasp
,
3358 JSObject
*proto
, uintN attrs
)
3361 assertSameCompartment(cx
, obj
, proto
);
3363 Class
*clasp
= Valueify(jsclasp
);
3365 clasp
= &js_ObjectClass
; /* default class is Object */
3367 JSObject
*nobj
= NewObject
<WithProto::Class
>(cx
, clasp
, proto
, obj
);
3371 if (!DefineProperty(cx
, obj
, name
, ObjectValue(*nobj
), NULL
, NULL
, attrs
, 0, 0))
3377 JS_PUBLIC_API(JSBool
)
3378 JS_DefineConstDoubles(JSContext
*cx
, JSObject
*obj
, JSConstDoubleSpec
*cds
)
3384 for (ok
= JS_TRUE
; cds
->name
; cds
++) {
3385 Value value
= DoubleValue(cds
->dval
);
3388 attrs
= JSPROP_READONLY
| JSPROP_PERMANENT
;
3389 ok
= DefineProperty(cx
, obj
, cds
->name
, value
, NULL
, NULL
, attrs
, 0, 0);
3396 JS_PUBLIC_API(JSBool
)
3397 JS_DefineProperties(JSContext
*cx
, JSObject
*obj
, JSPropertySpec
*ps
)
3401 for (ok
= true; ps
->name
; ps
++) {
3402 ok
= DefineProperty(cx
, obj
, ps
->name
, UndefinedValue(),
3403 Valueify(ps
->getter
), Valueify(ps
->setter
),
3404 ps
->flags
, JSScopeProperty::HAS_SHORTID
, ps
->tinyid
);
3411 JS_PUBLIC_API(JSBool
)
3412 JS_AliasProperty(JSContext
*cx
, JSObject
*obj
, const char *name
, const char *alias
)
3417 JSScopeProperty
*sprop
;
3420 assertSameCompartment(cx
, obj
);
3422 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3425 if (!LookupPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), JSRESOLVE_QUALIFIED
, &obj2
, &prop
))
3428 js_ReportIsNotDefined(cx
, name
);
3431 if (obj2
!= obj
|| !obj
->isNative()) {
3432 obj2
->dropProperty(cx
, prop
);
3433 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_CANT_ALIAS
,
3434 alias
, name
, obj2
->getClass()->name
);
3437 atom
= js_Atomize(cx
, alias
, strlen(alias
), 0);
3441 sprop
= (JSScopeProperty
*)prop
;
3442 ok
= (js_AddNativeProperty(cx
, obj
, ATOM_TO_JSID(atom
),
3443 sprop
->getter(), sprop
->setter(), sprop
->slot
,
3444 sprop
->attributes(), sprop
->getFlags() | JSScopeProperty::ALIAS
,
3448 JS_UNLOCK_OBJ(cx
, obj
);
3452 JS_PUBLIC_API(JSBool
)
3453 JS_AliasElement(JSContext
*cx
, JSObject
*obj
, const char *name
, jsint alias
)
3457 JSScopeProperty
*sprop
;
3461 assertSameCompartment(cx
, obj
);
3463 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3466 if (!LookupPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), JSRESOLVE_QUALIFIED
, &obj2
, &prop
))
3469 js_ReportIsNotDefined(cx
, name
);
3472 if (obj2
!= obj
|| !obj
->isNative()) {
3474 obj2
->dropProperty(cx
, prop
);
3475 JS_snprintf(numBuf
, sizeof numBuf
, "%ld", (long)alias
);
3476 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_CANT_ALIAS
,
3477 numBuf
, name
, obj2
->getClass()->name
);
3480 sprop
= (JSScopeProperty
*)prop
;
3481 ok
= (js_AddNativeProperty(cx
, obj
, INT_TO_JSID(alias
),
3482 sprop
->getter(), sprop
->setter(), sprop
->slot
,
3483 sprop
->attributes(), sprop
->getFlags() | JSScopeProperty::ALIAS
,
3486 JS_UNLOCK_OBJ(cx
, obj
);
3491 GetPropertyDescriptorById(JSContext
*cx
, JSObject
*obj
, jsid id
, uintN flags
,
3492 JSBool own
, PropertyDescriptor
*desc
)
3497 if (!LookupPropertyById(cx
, obj
, id
, flags
, &obj2
, &prop
))
3500 if (!prop
|| (own
&& obj
!= obj2
)) {
3503 desc
->getter
= NULL
;
3504 desc
->setter
= NULL
;
3505 desc
->value
.setUndefined();
3507 obj2
->dropProperty(cx
, prop
);
3512 if (obj2
->isNative()) {
3513 JSScopeProperty
*sprop
= (JSScopeProperty
*) prop
;
3514 desc
->attrs
= sprop
->attributes();
3516 if (sprop
->isMethod()) {
3517 desc
->getter
= desc
->setter
= PropertyStub
;
3518 desc
->value
.setObject(sprop
->methodObject());
3520 desc
->getter
= sprop
->getter();
3521 desc
->setter
= sprop
->setter();
3522 if (SPROP_HAS_VALID_SLOT(sprop
, obj2
->scope()))
3523 desc
->value
= obj2
->lockedGetSlot(sprop
->slot
);
3525 desc
->value
.setUndefined();
3527 JS_UNLOCK_OBJ(cx
, obj2
);
3528 } else if (obj2
->isProxy()) {
3529 JSAutoResolveFlags
rf(cx
, flags
);
3531 ? JSProxy::getOwnPropertyDescriptor(cx
, obj2
, id
, desc
)
3532 : JSProxy::getPropertyDescriptor(cx
, obj2
, id
, desc
);
3534 if (!obj2
->getAttributes(cx
, id
, &desc
->attrs
))
3536 desc
->getter
= NULL
;
3537 desc
->setter
= NULL
;
3538 desc
->value
.setUndefined();
3543 JS_PUBLIC_API(JSBool
)
3544 JS_GetPropertyDescriptorById(JSContext
*cx
, JSObject
*obj
, jsid id
, uintN flags
,
3545 JSPropertyDescriptor
*desc
)
3547 return GetPropertyDescriptorById(cx
, obj
, id
, flags
, JS_FALSE
, Valueify(desc
));
3550 JS_PUBLIC_API(JSBool
)
3551 JS_GetPropertyAttrsGetterAndSetterById(JSContext
*cx
, JSObject
*obj
, jsid id
,
3552 uintN
*attrsp
, JSBool
*foundp
,
3553 JSPropertyOp
*getterp
, JSPropertyOp
*setterp
)
3555 PropertyDescriptor desc
;
3556 if (!GetPropertyDescriptorById(cx
, obj
, id
, JSRESOLVE_QUALIFIED
, JS_FALSE
, &desc
))
3559 *attrsp
= desc
.attrs
;
3560 *foundp
= (desc
.obj
!= NULL
);
3562 *getterp
= Jsvalify(desc
.getter
);
3564 *setterp
= Jsvalify(desc
.setter
);
3568 JS_PUBLIC_API(JSBool
)
3569 JS_GetPropertyAttributes(JSContext
*cx
, JSObject
*obj
, const char *name
,
3570 uintN
*attrsp
, JSBool
*foundp
)
3572 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3573 return atom
&& JS_GetPropertyAttrsGetterAndSetterById(cx
, obj
, ATOM_TO_JSID(atom
),
3574 attrsp
, foundp
, NULL
, NULL
);
3577 JS_PUBLIC_API(JSBool
)
3578 JS_GetUCPropertyAttributes(JSContext
*cx
, JSObject
*obj
, const jschar
*name
, size_t namelen
,
3579 uintN
*attrsp
, JSBool
*foundp
)
3581 JSAtom
*atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
3582 return atom
&& JS_GetPropertyAttrsGetterAndSetterById(cx
, obj
, ATOM_TO_JSID(atom
),
3583 attrsp
, foundp
, NULL
, NULL
);
3586 JS_PUBLIC_API(JSBool
)
3587 JS_GetPropertyAttrsGetterAndSetter(JSContext
*cx
, JSObject
*obj
, const char *name
,
3588 uintN
*attrsp
, JSBool
*foundp
,
3589 JSPropertyOp
*getterp
, JSPropertyOp
*setterp
)
3591 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3592 return atom
&& JS_GetPropertyAttrsGetterAndSetterById(cx
, obj
, ATOM_TO_JSID(atom
),
3593 attrsp
, foundp
, getterp
, setterp
);
3596 JS_PUBLIC_API(JSBool
)
3597 JS_GetUCPropertyAttrsGetterAndSetter(JSContext
*cx
, JSObject
*obj
,
3598 const jschar
*name
, size_t namelen
,
3599 uintN
*attrsp
, JSBool
*foundp
,
3600 JSPropertyOp
*getterp
, JSPropertyOp
*setterp
)
3602 JSAtom
*atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
3603 return atom
&& JS_GetPropertyAttrsGetterAndSetterById(cx
, obj
, ATOM_TO_JSID(atom
),
3604 attrsp
, foundp
, getterp
, setterp
);
3607 JS_PUBLIC_API(JSBool
)
3608 JS_GetOwnPropertyDescriptor(JSContext
*cx
, JSObject
*obj
, jsid id
, jsval
*vp
)
3611 return js_GetOwnPropertyDescriptor(cx
, obj
, id
, Valueify(vp
));
3615 SetPropertyAttributesById(JSContext
*cx
, JSObject
*obj
, jsid id
, uintN attrs
, JSBool
*foundp
)
3620 if (!LookupPropertyById(cx
, obj
, id
, JSRESOLVE_QUALIFIED
, &obj2
, &prop
))
3622 if (!prop
|| obj
!= obj2
) {
3625 obj2
->dropProperty(cx
, prop
);
3628 JSBool ok
= obj
->isNative()
3629 ? js_SetNativeAttributes(cx
, obj
, (JSScopeProperty
*) prop
, attrs
)
3630 : obj
->setAttributes(cx
, id
, &attrs
);
3636 JS_PUBLIC_API(JSBool
)
3637 JS_SetPropertyAttributes(JSContext
*cx
, JSObject
*obj
, const char *name
,
3638 uintN attrs
, JSBool
*foundp
)
3640 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3641 return atom
&& SetPropertyAttributesById(cx
, obj
, ATOM_TO_JSID(atom
), attrs
, foundp
);
3644 JS_PUBLIC_API(JSBool
)
3645 JS_SetUCPropertyAttributes(JSContext
*cx
, JSObject
*obj
, const jschar
*name
, size_t namelen
,
3646 uintN attrs
, JSBool
*foundp
)
3648 JSAtom
*atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
3649 return atom
&& SetPropertyAttributesById(cx
, obj
, ATOM_TO_JSID(atom
), attrs
, foundp
);
3652 JS_PUBLIC_API(JSBool
)
3653 JS_GetPropertyById(JSContext
*cx
, JSObject
*obj
, jsid id
, jsval
*vp
)
3656 assertSameCompartment(cx
, obj
, id
);
3657 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
);
3658 return obj
->getProperty(cx
, id
, Valueify(vp
));
3661 JS_PUBLIC_API(JSBool
)
3662 JS_GetElement(JSContext
*cx
, JSObject
*obj
, jsint index
, jsval
*vp
)
3664 return JS_GetPropertyById(cx
, obj
, INT_TO_JSID(index
), vp
);
3667 JS_PUBLIC_API(JSBool
)
3668 JS_GetProperty(JSContext
*cx
, JSObject
*obj
, const char *name
, jsval
*vp
)
3670 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3671 return atom
&& JS_GetPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), vp
);
3674 JS_PUBLIC_API(JSBool
)
3675 JS_GetUCProperty(JSContext
*cx
, JSObject
*obj
, const jschar
*name
, size_t namelen
, jsval
*vp
)
3677 JSAtom
*atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
3678 return atom
&& JS_GetPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), vp
);
3681 JS_PUBLIC_API(JSBool
)
3682 JS_GetMethodById(JSContext
*cx
, JSObject
*obj
, jsid id
, JSObject
**objp
, jsval
*vp
)
3685 assertSameCompartment(cx
, obj
, id
);
3686 if (!js_GetMethod(cx
, obj
, id
, JSGET_METHOD_BARRIER
, Valueify(vp
)))
3693 JS_PUBLIC_API(JSBool
)
3694 JS_GetMethod(JSContext
*cx
, JSObject
*obj
, const char *name
, JSObject
**objp
, jsval
*vp
)
3696 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3697 return atom
&& JS_GetMethodById(cx
, obj
, ATOM_TO_JSID(atom
), objp
, vp
);
3700 JS_PUBLIC_API(JSBool
)
3701 JS_SetPropertyById(JSContext
*cx
, JSObject
*obj
, jsid id
, jsval
*vp
)
3704 assertSameCompartment(cx
, obj
, id
);
3705 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
| JSRESOLVE_ASSIGNING
);
3706 return obj
->setProperty(cx
, id
, Valueify(vp
));
3709 JS_PUBLIC_API(JSBool
)
3710 JS_SetElement(JSContext
*cx
, JSObject
*obj
, jsint index
, jsval
*vp
)
3712 return JS_SetPropertyById(cx
, obj
, INT_TO_JSID(index
), vp
);
3715 JS_PUBLIC_API(JSBool
)
3716 JS_SetProperty(JSContext
*cx
, JSObject
*obj
, const char *name
, jsval
*vp
)
3718 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3719 return atom
&& JS_SetPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), vp
);
3722 JS_PUBLIC_API(JSBool
)
3723 JS_SetUCProperty(JSContext
*cx
, JSObject
*obj
, const jschar
*name
, size_t namelen
, jsval
*vp
)
3725 JSAtom
*atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
3726 return atom
&& JS_SetPropertyById(cx
, obj
, ATOM_TO_JSID(atom
), vp
);
3729 JS_PUBLIC_API(JSBool
)
3730 JS_DeletePropertyById2(JSContext
*cx
, JSObject
*obj
, jsid id
, jsval
*rval
)
3733 assertSameCompartment(cx
, obj
, id
);
3734 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
);
3735 return obj
->deleteProperty(cx
, id
, Valueify(rval
));
3738 JS_PUBLIC_API(JSBool
)
3739 JS_DeleteElement2(JSContext
*cx
, JSObject
*obj
, jsint index
, jsval
*rval
)
3741 return JS_DeletePropertyById2(cx
, obj
, INT_TO_JSID(index
), rval
);
3744 JS_PUBLIC_API(JSBool
)
3745 JS_DeleteProperty2(JSContext
*cx
, JSObject
*obj
, const char *name
, jsval
*rval
)
3747 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
3748 return atom
&& JS_DeletePropertyById2(cx
, obj
, ATOM_TO_JSID(atom
), rval
);
3751 JS_PUBLIC_API(JSBool
)
3752 JS_DeleteUCProperty2(JSContext
*cx
, JSObject
*obj
, const jschar
*name
, size_t namelen
, jsval
*rval
)
3754 JSAtom
*atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
3755 return atom
&& JS_DeletePropertyById2(cx
, obj
, ATOM_TO_JSID(atom
), rval
);
3758 JS_PUBLIC_API(JSBool
)
3759 JS_DeletePropertyById(JSContext
*cx
, JSObject
*obj
, jsid id
)
3762 return JS_DeletePropertyById2(cx
, obj
, id
, &junk
);
3765 JS_PUBLIC_API(JSBool
)
3766 JS_DeleteElement(JSContext
*cx
, JSObject
*obj
, jsint index
)
3769 return JS_DeleteElement2(cx
, obj
, index
, &junk
);
3772 JS_PUBLIC_API(JSBool
)
3773 JS_DeleteProperty(JSContext
*cx
, JSObject
*obj
, const char *name
)
3776 return JS_DeleteProperty2(cx
, obj
, name
, &junk
);
3780 JS_ClearScope(JSContext
*cx
, JSObject
*obj
)
3783 assertSameCompartment(cx
, obj
);
3785 JSFinalizeOp clearOp
= obj
->getOps()->clear
;
3789 if (obj
->isNative())
3790 js_ClearNative(cx
, obj
);
3792 /* Clear cached class objects on the global object. */
3793 if (obj
->getClass()->flags
& JSCLASS_IS_GLOBAL
) {
3796 for (key
= JSProto_Null
; key
< JSProto_LIMIT
* 3; key
++)
3797 JS_SetReservedSlot(cx
, obj
, key
, JSVAL_VOID
);
3803 JS_PUBLIC_API(JSIdArray
*)
3804 JS_Enumerate(JSContext
*cx
, JSObject
*obj
)
3807 assertSameCompartment(cx
, obj
);
3809 AutoIdVector
props(cx
);
3811 if (!GetPropertyNames(cx
, obj
, JSITER_OWNONLY
, props
) || !VectorToIdArray(cx
, props
, &ida
))
3813 for (size_t n
= 0; n
< size_t(ida
->length
); ++n
)
3814 JS_ASSERT(js_CheckForStringIndex(ida
->vector
[n
]) == ida
->vector
[n
]);
3819 * XXX reverse iterator for properties, unreverse and meld with jsinterp.c's
3820 * prop_iterator_class somehow...
3821 * + preserve the obj->enumerate API while optimizing the native object case
3822 * + native case here uses a JSScopeProperty *, but that iterates in reverse!
3823 * + so we make non-native match, by reverse-iterating after JS_Enumerating
3825 const uint32 JSSLOT_ITER_INDEX
= JSSLOT_PRIVATE
+ 1;
3826 JS_STATIC_ASSERT(JSSLOT_ITER_INDEX
< JS_INITIAL_NSLOTS
);
3829 prop_iter_finalize(JSContext
*cx
, JSObject
*obj
)
3831 void *pdata
= obj
->getPrivate();
3835 if (obj
->fslots
[JSSLOT_ITER_INDEX
].toInt32() >= 0) {
3836 /* Non-native case: destroy the ida enumerated when obj was created. */
3837 JSIdArray
*ida
= (JSIdArray
*) pdata
;
3838 JS_DestroyIdArray(cx
, ida
);
3843 prop_iter_trace(JSTracer
*trc
, JSObject
*obj
)
3845 void *pdata
= obj
->getPrivate();
3849 if (obj
->fslots
[JSSLOT_ITER_INDEX
].toInt32() < 0) {
3850 /* Native case: just mark the next property to visit. */
3851 ((JSScopeProperty
*) pdata
)->trace(trc
);
3853 /* Non-native case: mark each id in the JSIdArray private. */
3854 JSIdArray
*ida
= (JSIdArray
*) pdata
;
3855 MarkIdRange(trc
, ida
->length
, ida
->vector
, "prop iter");
3859 static Class prop_iter_class
= {
3861 JSCLASS_HAS_PRIVATE
| JSCLASS_HAS_RESERVED_SLOTS(1) |
3862 JSCLASS_MARK_IS_TRACE
,
3863 PropertyStub
, /* addProperty */
3864 PropertyStub
, /* delProperty */
3865 PropertyStub
, /* getProperty */
3866 PropertyStub
, /* setProperty */
3871 NULL
, /* reserved0 */
3872 NULL
, /* checkAccess */
3874 NULL
, /* construct */
3875 NULL
, /* xdrObject */
3876 NULL
, /* hasInstance */
3877 JS_CLASS_TRACE(prop_iter_trace
)
3880 JS_PUBLIC_API(JSObject
*)
3881 JS_NewPropertyIterator(JSContext
*cx
, JSObject
*obj
)
3890 assertSameCompartment(cx
, obj
);
3891 iterobj
= NewNonFunction
<WithProto::Class
>(cx
, &prop_iter_class
, NULL
, obj
);
3895 if (obj
->isNative()) {
3896 /* Native case: start with the last property in obj's own scope. */
3897 scope
= obj
->scope();
3898 pdata
= scope
->lastProperty();
3902 * Non-native case: enumerate a JSIdArray and keep it via private.
3904 * Note: we have to make sure that we root obj around the call to
3905 * JS_Enumerate to protect against multiple allocations under it.
3907 AutoObjectRooter
tvr(cx
, iterobj
);
3908 ida
= JS_Enumerate(cx
, obj
);
3912 index
= ida
->length
;
3915 /* iterobj cannot escape to other threads here. */
3916 iterobj
->setPrivate(pdata
);
3917 iterobj
->fslots
[JSSLOT_ITER_INDEX
].setInt32(index
);
3921 JS_PUBLIC_API(JSBool
)
3922 JS_NextProperty(JSContext
*cx
, JSObject
*iterobj
, jsid
*idp
)
3926 JSScopeProperty
*sprop
;
3930 assertSameCompartment(cx
, iterobj
);
3931 i
= iterobj
->fslots
[JSSLOT_ITER_INDEX
].toInt32();
3933 /* Native case: private data is a property tree node pointer. */
3934 obj
= iterobj
->getParent();
3935 JS_ASSERT(obj
->isNative());
3936 sprop
= (JSScopeProperty
*) iterobj
->getPrivate();
3939 * If the next property in the property tree ancestor line is
3940 * not enumerable, or it's an alias, skip it and keep on trying
3941 * to find an enumerable property that is still in scope.
3943 while (sprop
&& (!sprop
->enumerable() || sprop
->isAlias()))
3944 sprop
= sprop
->parent
;
3949 iterobj
->setPrivate(sprop
->parent
);
3953 /* Non-native case: use the ida enumerated when iterobj was created. */
3954 ida
= (JSIdArray
*) iterobj
->getPrivate();
3955 JS_ASSERT(i
<= ida
->length
);
3959 *idp
= ida
->vector
[--i
];
3960 iterobj
->setSlot(JSSLOT_ITER_INDEX
, Int32Value(i
));
3966 JS_PUBLIC_API(JSBool
)
3967 JS_GetReservedSlot(JSContext
*cx
, JSObject
*obj
, uint32 index
, jsval
*vp
)
3970 assertSameCompartment(cx
, obj
);
3971 return js_GetReservedSlot(cx
, obj
, index
, Valueify(vp
));
3974 JS_PUBLIC_API(JSBool
)
3975 JS_SetReservedSlot(JSContext
*cx
, JSObject
*obj
, uint32 index
, jsval v
)
3978 assertSameCompartment(cx
, obj
, v
);
3979 return js_SetReservedSlot(cx
, obj
, index
, Valueify(v
));
3982 JS_PUBLIC_API(JSObject
*)
3983 JS_NewArrayObject(JSContext
*cx
, jsint length
, jsval
*vector
)
3986 /* NB: jsuint cast does ToUint32. */
3987 assertSameCompartment(cx
, JSValueArray(vector
, vector
? (jsuint
)length
: 0));
3988 return js_NewArrayObject(cx
, (jsuint
)length
, Valueify(vector
));
3991 JS_PUBLIC_API(JSBool
)
3992 JS_IsArrayObject(JSContext
*cx
, JSObject
*obj
)
3994 assertSameCompartment(cx
, obj
);
3995 return obj
->wrappedObject(cx
)->isArray();
3998 JS_PUBLIC_API(JSBool
)
3999 JS_GetArrayLength(JSContext
*cx
, JSObject
*obj
, jsuint
*lengthp
)
4002 assertSameCompartment(cx
, obj
);
4003 return js_GetLengthProperty(cx
, obj
, lengthp
);
4006 JS_PUBLIC_API(JSBool
)
4007 JS_SetArrayLength(JSContext
*cx
, JSObject
*obj
, jsuint length
)
4010 assertSameCompartment(cx
, obj
);
4011 return js_SetLengthProperty(cx
, obj
, length
);
4014 JS_PUBLIC_API(JSBool
)
4015 JS_HasArrayLength(JSContext
*cx
, JSObject
*obj
, jsuint
*lengthp
)
4018 assertSameCompartment(cx
, obj
);
4019 return js_HasLengthProperty(cx
, obj
, lengthp
);
4022 JS_PUBLIC_API(JSBool
)
4023 JS_CheckAccess(JSContext
*cx
, JSObject
*obj
, jsid id
, JSAccessMode mode
,
4024 jsval
*vp
, uintN
*attrsp
)
4027 assertSameCompartment(cx
, obj
, id
);
4028 return CheckAccess(cx
, obj
, id
, mode
, Valueify(vp
), attrsp
);
4031 #ifdef JS_THREADSAFE
4032 JS_PUBLIC_API(jsrefcount
)
4033 JS_HoldPrincipals(JSContext
*cx
, JSPrincipals
*principals
)
4035 return JS_ATOMIC_INCREMENT(&principals
->refcount
);
4038 JS_PUBLIC_API(jsrefcount
)
4039 JS_DropPrincipals(JSContext
*cx
, JSPrincipals
*principals
)
4041 jsrefcount rc
= JS_ATOMIC_DECREMENT(&principals
->refcount
);
4043 principals
->destroy(cx
, principals
);
4048 JS_PUBLIC_API(JSSecurityCallbacks
*)
4049 JS_SetRuntimeSecurityCallbacks(JSRuntime
*rt
, JSSecurityCallbacks
*callbacks
)
4051 JSSecurityCallbacks
*oldcallbacks
;
4053 oldcallbacks
= rt
->securityCallbacks
;
4054 rt
->securityCallbacks
= callbacks
;
4055 return oldcallbacks
;
4058 JS_PUBLIC_API(JSSecurityCallbacks
*)
4059 JS_GetRuntimeSecurityCallbacks(JSRuntime
*rt
)
4061 return rt
->securityCallbacks
;
4064 JS_PUBLIC_API(JSSecurityCallbacks
*)
4065 JS_SetContextSecurityCallbacks(JSContext
*cx
, JSSecurityCallbacks
*callbacks
)
4067 JSSecurityCallbacks
*oldcallbacks
;
4069 oldcallbacks
= cx
->securityCallbacks
;
4070 cx
->securityCallbacks
= callbacks
;
4071 return oldcallbacks
;
4074 JS_PUBLIC_API(JSSecurityCallbacks
*)
4075 JS_GetSecurityCallbacks(JSContext
*cx
)
4077 return cx
->securityCallbacks
4078 ? cx
->securityCallbacks
4079 : cx
->runtime
->securityCallbacks
;
4082 JS_PUBLIC_API(JSFunction
*)
4083 JS_NewFunction(JSContext
*cx
, JSNative native
, uintN nargs
, uintN flags
,
4084 JSObject
*parent
, const char *name
)
4089 assertSameCompartment(cx
, parent
);
4094 atom
= js_Atomize(cx
, name
, strlen(name
), 0);
4098 return js_NewFunction(cx
, NULL
, Valueify(native
), nargs
, flags
, parent
, atom
);
4101 JS_PUBLIC_API(JSObject
*)
4102 JS_CloneFunctionObject(JSContext
*cx
, JSObject
*funobj
, JSObject
*parent
)
4105 assertSameCompartment(cx
, parent
); // XXX no funobj for now
4108 parent
= js_GetScopeChain(cx
, cx
->fp());
4110 parent
= cx
->globalObject
;
4114 if (funobj
->getClass() != &js_FunctionClass
) {
4116 * We cannot clone this object, so fail (we used to return funobj, bad
4117 * idea, but we changed incompatibly to teach any abusers a lesson!).
4119 Value v
= ObjectValue(*funobj
);
4120 js_ReportIsNotFunction(cx
, &v
, 0);
4124 JSFunction
*fun
= GET_FUNCTION_PRIVATE(cx
, funobj
);
4125 JSObject
*clone
= CloneFunctionObject(cx
, fun
, parent
);
4130 * A flat closure carries its own environment, so why clone it? In case
4131 * someone wants to mutate its fixed slots or add ad-hoc properties. API
4132 * compatibility suggests we not return funobj and let callers mutate the
4133 * returned object at will.
4135 * But it's worse than that: API compatibility according to the test for
4136 * bug 300079 requires we get "upvars" from parent and its ancestors! So
4137 * we do that (grudgingly!). The scope chain ancestors are searched as if
4138 * they were activations, respecting the skip field in each upvar's cookie
4139 * but looking up the property by name instead of frame slot.
4141 if (FUN_FLAT_CLOSURE(fun
)) {
4142 JS_ASSERT(funobj
->dslots
);
4143 if (!js_EnsureReservedSlots(cx
, clone
,
4144 fun
->countInterpretedReservedSlots())) {
4148 JSUpvarArray
*uva
= fun
->u
.i
.script
->upvars();
4149 JS_ASSERT(uva
->length
<= clone
->dslots
[-1].toPrivateUint32());
4151 void *mark
= JS_ARENA_MARK(&cx
->tempPool
);
4152 jsuword
*names
= js_GetLocalNameArray(cx
, fun
, &cx
->tempPool
);
4156 uint32 i
= 0, n
= uva
->length
;
4157 for (; i
< n
; i
++) {
4158 JSObject
*obj
= parent
;
4159 int skip
= uva
->vector
[i
].level();
4160 while (--skip
> 0) {
4162 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
,
4163 JSMSG_BAD_CLONE_FUNOBJ_SCOPE
);
4166 obj
= obj
->getParent();
4169 JSAtom
*atom
= JS_LOCAL_NAME_TO_ATOM(names
[i
]);
4170 if (!obj
->getProperty(cx
, ATOM_TO_JSID(atom
), &clone
->dslots
[i
]))
4175 JS_ARENA_RELEASE(&cx
->tempPool
, mark
);
4183 JS_PUBLIC_API(JSObject
*)
4184 JS_GetFunctionObject(JSFunction
*fun
)
4186 return FUN_OBJECT(fun
);
4189 JS_PUBLIC_API(const char *)
4190 JS_GetFunctionName(JSFunction
*fun
)
4193 ? JS_GetStringBytes(ATOM_TO_STRING(fun
->atom
))
4197 JS_PUBLIC_API(JSString
*)
4198 JS_GetFunctionId(JSFunction
*fun
)
4200 return fun
->atom
? ATOM_TO_STRING(fun
->atom
) : NULL
;
4203 JS_PUBLIC_API(uintN
)
4204 JS_GetFunctionFlags(JSFunction
*fun
)
4209 JS_PUBLIC_API(uint16
)
4210 JS_GetFunctionArity(JSFunction
*fun
)
4215 JS_PUBLIC_API(JSBool
)
4216 JS_ObjectIsFunction(JSContext
*cx
, JSObject
*obj
)
4218 return obj
->getClass() == &js_FunctionClass
;
4222 js_generic_fast_native_method_dispatcher(JSContext
*cx
, uintN argc
, Value
*vp
)
4228 fs
= (JSFunctionSpec
*) vp
->toObject().getReservedSlot(0).toPrivate();
4229 JS_ASSERT((~fs
->flags
& (JSFUN_FAST_NATIVE
| JSFUN_GENERIC_NATIVE
)) == 0);
4232 js_ReportMissingArg(cx
, *vp
, 0);
4236 if (vp
[2].isPrimitive()) {
4238 * Make sure that this is an object or null, as required by the generic
4241 if (!js_ValueToObjectOrNull(cx
, vp
[2], &tmp
))
4243 vp
[2].setObjectOrNull(tmp
);
4247 * Copy all actual (argc) arguments down over our |this| parameter, vp[1],
4248 * which is almost always the class constructor object, e.g. Array. Then
4249 * call the corresponding prototype native method with our first argument
4252 memmove(vp
+ 1, vp
+ 2, argc
* sizeof(jsval
));
4255 * Follow Function.prototype.apply and .call by using the global object as
4256 * the 'this' param if no args.
4258 if (!ComputeThisFromArgv(cx
, vp
+ 2))
4261 /* Clear the last parameter in case too few arguments were passed. */
4262 vp
[2 + --argc
].setUndefined();
4266 (fs
->flags
& JSFUN_TRCINFO
)
4267 ? (FastNative
) JS_FUNC_TO_DATA_PTR(JSNativeTraceInfo
*, fs
->call
)->native
4270 (FastNative
) fs
->call
;
4271 return native(cx
, argc
, vp
);
4275 js_generic_native_method_dispatcher(JSContext
*cx
, JSObject
*obj
,
4276 uintN argc
, Value
*argv
, Value
*rval
)
4281 fs
= (JSFunctionSpec
*) argv
[-2].toObject().getReservedSlot(0).toPrivate();
4282 JS_ASSERT((fs
->flags
& (JSFUN_FAST_NATIVE
| JSFUN_GENERIC_NATIVE
)) ==
4283 JSFUN_GENERIC_NATIVE
);
4286 js_ReportMissingArg(cx
, *(argv
- 2), 0);
4290 if (argv
[0].isPrimitive()) {
4292 * Make sure that this is an object or null, as required by the generic
4295 if (!js_ValueToObjectOrNull(cx
, argv
[0], &tmp
))
4297 argv
[0].setObjectOrNull(tmp
);
4301 * Copy all actual (argc) arguments down over our |this| parameter,
4302 * argv[-1], which is almost always the class constructor object, e.g.
4303 * Array. Then call the corresponding prototype native method with our
4304 * first argument passed as |this|.
4306 memmove(argv
- 1, argv
, argc
* sizeof(jsval
));
4309 * Follow Function.prototype.apply and .call by using the global object as
4310 * the 'this' param if no args.
4312 if (!ComputeThisFromArgv(cx
, argv
))
4314 js_GetTopStackFrame(cx
)->setThisValue(argv
[-1]);
4315 JS_ASSERT(cx
->fp()->argv
== argv
);
4317 /* Clear the last parameter in case too few arguments were passed. */
4318 argv
[--argc
].setUndefined();
4320 return fs
->call(cx
, &argv
[-1].toObject(), argc
, Jsvalify(argv
), Jsvalify(rval
));
4323 JS_PUBLIC_API(JSBool
)
4324 JS_DefineFunctions(JSContext
*cx
, JSObject
*obj
, JSFunctionSpec
*fs
)
4331 assertSameCompartment(cx
, obj
);
4333 for (; fs
->name
; fs
++) {
4337 * Define a generic arity N+1 static method for the arity N prototype
4338 * method if flags contains JSFUN_GENERIC_NATIVE.
4340 if (flags
& JSFUN_GENERIC_NATIVE
) {
4342 ctor
= JS_GetConstructor(cx
, obj
);
4347 flags
&= ~JSFUN_GENERIC_NATIVE
;
4348 fun
= JS_DefineFunction(cx
, ctor
, fs
->name
,
4349 (flags
& JSFUN_FAST_NATIVE
)
4350 ? (JSNative
) js_generic_fast_native_method_dispatcher
4351 : Jsvalify(js_generic_native_method_dispatcher
),
4353 flags
& ~JSFUN_TRCINFO
);
4356 fun
->u
.n
.extra
= (uint16
)fs
->extra
;
4359 * As jsapi.h notes, fs must point to storage that lives as long
4360 * as fun->object lives.
4362 Value priv
= PrivateValue(fs
);
4363 if (!js_SetReservedSlot(cx
, FUN_OBJECT(fun
), 0, priv
))
4367 JS_ASSERT(!(flags
& JSFUN_FAST_NATIVE
) ||
4368 (uint16
)(fs
->extra
>> 16) <= fs
->nargs
);
4369 fun
= JS_DefineFunction(cx
, obj
, fs
->name
, fs
->call
, fs
->nargs
, flags
);
4372 fun
->u
.n
.extra
= (uint16
)fs
->extra
;
4377 JS_PUBLIC_API(JSFunction
*)
4378 JS_DefineFunction(JSContext
*cx
, JSObject
*obj
, const char *name
, JSNative call
,
4379 uintN nargs
, uintN attrs
)
4382 assertSameCompartment(cx
, obj
);
4383 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
4384 return atom
? js_DefineFunction(cx
, obj
, atom
, Valueify(call
), nargs
, attrs
) : NULL
;
4387 JS_PUBLIC_API(JSFunction
*)
4388 JS_DefineUCFunction(JSContext
*cx
, JSObject
*obj
,
4389 const jschar
*name
, size_t namelen
, JSNative call
,
4390 uintN nargs
, uintN attrs
)
4393 assertSameCompartment(cx
, obj
);
4394 JSAtom
*atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
), 0);
4395 return atom
? js_DefineFunction(cx
, obj
, atom
, Valueify(call
), nargs
, attrs
) : NULL
;
4399 LAST_FRAME_EXCEPTION_CHECK(JSContext
*cx
, bool result
)
4401 if (!result
&& !(cx
->options
& JSOPTION_DONT_REPORT_UNCAUGHT
))
4402 js_ReportUncaughtException(cx
);
4406 LAST_FRAME_CHECKS(JSContext
*cx
, bool result
)
4408 if (!JS_IsRunning(cx
)) {
4409 LAST_FRAME_EXCEPTION_CHECK(cx
, result
);
4413 inline static uint32
4414 JS_OPTIONS_TO_TCFLAGS(JSContext
*cx
)
4416 return ((cx
->options
& JSOPTION_COMPILE_N_GO
) ? TCF_COMPILE_N_GO
: 0) |
4417 ((cx
->options
& JSOPTION_NO_SCRIPT_RVAL
) ? TCF_NO_SCRIPT_RVAL
: 0);
4420 JS_PUBLIC_API(JSScript
*)
4421 JS_CompileUCScriptForPrincipals(JSContext
*cx
, JSObject
*obj
, JSPrincipals
*principals
,
4422 const jschar
*chars
, size_t length
,
4423 const char *filename
, uintN lineno
)
4426 assertSameCompartment(cx
, obj
, principals
);
4428 uint32 tcflags
= JS_OPTIONS_TO_TCFLAGS(cx
) | TCF_NEED_MUTABLE_SCRIPT
;
4429 JSScript
*script
= Compiler::compileScript(cx
, obj
, NULL
, principals
, tcflags
,
4430 chars
, length
, NULL
, filename
, lineno
);
4431 if (script
&& !js_NewScriptObject(cx
, script
)) {
4432 js_DestroyScript(cx
, script
);
4435 LAST_FRAME_CHECKS(cx
, script
);
4439 JS_PUBLIC_API(JSScript
*)
4440 JS_CompileUCScript(JSContext
*cx
, JSObject
*obj
, const jschar
*chars
, size_t length
,
4441 const char *filename
, uintN lineno
)
4443 return JS_CompileUCScriptForPrincipals(cx
, obj
, NULL
, chars
, length
, filename
, lineno
);
4446 JS_PUBLIC_API(JSScript
*)
4447 JS_CompileScriptForPrincipals(JSContext
*cx
, JSObject
*obj
,
4448 JSPrincipals
*principals
,
4449 const char *bytes
, size_t length
,
4450 const char *filename
, uintN lineno
)
4454 jschar
*chars
= js_InflateString(cx
, bytes
, &length
);
4457 JSScript
*script
= JS_CompileUCScriptForPrincipals(cx
, obj
, principals
, chars
, length
, filename
, lineno
);
4462 JS_PUBLIC_API(JSScript
*)
4463 JS_CompileScript(JSContext
*cx
, JSObject
*obj
, const char *bytes
, size_t length
,
4464 const char *filename
, uintN lineno
)
4466 return JS_CompileScriptForPrincipals(cx
, obj
, NULL
, bytes
, length
, filename
, lineno
);
4469 JS_PUBLIC_API(JSBool
)
4470 JS_BufferIsCompilableUnit(JSContext
*cx
, JSObject
*obj
, const char *bytes
, size_t length
)
4474 JSExceptionState
*exnState
;
4475 JSErrorReporter older
;
4478 assertSameCompartment(cx
, obj
);
4479 chars
= js_InflateString(cx
, bytes
, &length
);
4484 * Return true on any out-of-memory error, so our caller doesn't try to
4485 * collect more buffered source.
4488 exnState
= JS_SaveExceptionState(cx
);
4491 if (parser
.init(chars
, length
, NULL
, NULL
, 1)) {
4492 older
= JS_SetErrorReporter(cx
, NULL
);
4493 if (!parser
.parse(obj
) &&
4494 parser
.tokenStream
.isUnexpectedEOF()) {
4496 * We ran into an error. If it was because we ran out of
4497 * source, we return false so our caller knows to try to
4498 * collect more buffered source.
4502 JS_SetErrorReporter(cx
, older
);
4506 JS_RestoreExceptionState(cx
, exnState
);
4510 JS_PUBLIC_API(JSScript
*)
4511 JS_CompileFile(JSContext
*cx
, JSObject
*obj
, const char *filename
)
4518 assertSameCompartment(cx
, obj
);
4519 if (!filename
|| strcmp(filename
, "-") == 0) {
4522 fp
= fopen(filename
, "r");
4524 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_CANT_OPEN
,
4525 filename
, "No such file or directory");
4530 tcflags
= JS_OPTIONS_TO_TCFLAGS(cx
) | TCF_NEED_MUTABLE_SCRIPT
;
4531 script
= Compiler::compileScript(cx
, obj
, NULL
, NULL
, tcflags
,
4532 NULL
, 0, fp
, filename
, 1);
4535 if (script
&& !js_NewScriptObject(cx
, script
)) {
4536 js_DestroyScript(cx
, script
);
4539 LAST_FRAME_CHECKS(cx
, script
);
4543 JS_PUBLIC_API(JSScript
*)
4544 JS_CompileFileHandleForPrincipals(JSContext
*cx
, JSObject
*obj
, const char *filename
, FILE *file
,
4545 JSPrincipals
*principals
)
4551 assertSameCompartment(cx
, obj
, principals
);
4552 tcflags
= JS_OPTIONS_TO_TCFLAGS(cx
) | TCF_NEED_MUTABLE_SCRIPT
;
4553 script
= Compiler::compileScript(cx
, obj
, NULL
, principals
, tcflags
,
4554 NULL
, 0, file
, filename
, 1);
4555 if (script
&& !js_NewScriptObject(cx
, script
)) {
4556 js_DestroyScript(cx
, script
);
4559 LAST_FRAME_CHECKS(cx
, script
);
4563 JS_PUBLIC_API(JSScript
*)
4564 JS_CompileFileHandle(JSContext
*cx
, JSObject
*obj
, const char *filename
, FILE *file
)
4566 return JS_CompileFileHandleForPrincipals(cx
, obj
, filename
, file
, NULL
);
4569 JS_PUBLIC_API(JSObject
*)
4570 JS_NewScriptObject(JSContext
*cx
, JSScript
*script
)
4573 assertSameCompartment(cx
, script
);
4575 return NewNonFunction
<WithProto::Class
>(cx
, &js_ScriptClass
, NULL
, NULL
);
4578 * This function should only ever be applied to JSScripts that had
4579 * script objects allocated for them when they were created, as
4580 * described in the comment for JSScript::u.object.
4582 JS_ASSERT(script
->u
.object
);
4583 return script
->u
.object
;
4586 JS_PUBLIC_API(JSObject
*)
4587 JS_GetScriptObject(JSScript
*script
)
4590 * This function should only ever be applied to JSScripts that had
4591 * script objects allocated for them when they were created, as
4592 * described in the comment for JSScript::u.object.
4594 JS_ASSERT(script
->u
.object
);
4595 return script
->u
.object
;
4599 JS_DestroyScript(JSContext
*cx
, JSScript
*script
)
4604 * Originally, JSScript lifetimes were managed explicitly, and this function
4605 * was used to free a JSScript. Now, this function does nothing, and the
4606 * garbage collector manages JSScripts; you must root the JSScript's script
4607 * object (obtained via JS_GetScriptObject) to keep it alive.
4609 * However, since the script objects have taken over this responsibility, it
4610 * follows that every script passed here must have a script object.
4612 JS_ASSERT(script
->u
.object
);
4615 JS_PUBLIC_API(JSFunction
*)
4616 JS_CompileUCFunctionForPrincipals(JSContext
*cx
, JSObject
*obj
,
4617 JSPrincipals
*principals
, const char *name
,
4618 uintN nargs
, const char **argnames
,
4619 const jschar
*chars
, size_t length
,
4620 const char *filename
, uintN lineno
)
4623 JSAtom
*funAtom
, *argAtom
;
4627 assertSameCompartment(cx
, obj
, principals
);
4631 funAtom
= js_Atomize(cx
, name
, strlen(name
), 0);
4637 fun
= js_NewFunction(cx
, NULL
, NULL
, 0, JSFUN_INTERPRETED
, obj
, funAtom
);
4642 AutoObjectRooter
tvr(cx
, FUN_OBJECT(fun
));
4643 MUST_FLOW_THROUGH("out");
4645 for (i
= 0; i
< nargs
; i
++) {
4646 argAtom
= js_Atomize(cx
, argnames
[i
], strlen(argnames
[i
]), 0);
4651 if (!js_AddLocal(cx
, fun
, argAtom
, JSLOCAL_ARG
)) {
4657 if (!Compiler::compileFunctionBody(cx
, fun
, principals
,
4658 chars
, length
, filename
, lineno
)) {
4663 if (obj
&& funAtom
&&
4664 !obj
->defineProperty(cx
, ATOM_TO_JSID(funAtom
), ObjectValue(*fun
),
4665 NULL
, NULL
, JSPROP_ENUMERATE
)) {
4669 #ifdef JS_SCOPE_DEPTH_METER
4671 JSObject
*pobj
= obj
;
4674 while ((pobj
= pobj
->getParent()) != NULL
)
4676 JS_BASIC_STATS_ACCUM(&cx
->runtime
->hostenvScopeDepthStats
, depth
);
4682 LAST_FRAME_CHECKS(cx
, fun
);
4686 JS_PUBLIC_API(JSFunction
*)
4687 JS_CompileUCFunction(JSContext
*cx
, JSObject
*obj
, const char *name
,
4688 uintN nargs
, const char **argnames
,
4689 const jschar
*chars
, size_t length
,
4690 const char *filename
, uintN lineno
)
4692 return JS_CompileUCFunctionForPrincipals(cx
, obj
, NULL
, name
, nargs
, argnames
,
4693 chars
, length
, filename
, lineno
);
4696 JS_PUBLIC_API(JSFunction
*)
4697 JS_CompileFunctionForPrincipals(JSContext
*cx
, JSObject
*obj
,
4698 JSPrincipals
*principals
, const char *name
,
4699 uintN nargs
, const char **argnames
,
4700 const char *bytes
, size_t length
,
4701 const char *filename
, uintN lineno
)
4703 jschar
*chars
= js_InflateString(cx
, bytes
, &length
);
4706 JSFunction
*fun
= JS_CompileUCFunctionForPrincipals(cx
, obj
, principals
, name
,
4707 nargs
, argnames
, chars
, length
,
4713 JS_PUBLIC_API(JSFunction
*)
4714 JS_CompileFunction(JSContext
*cx
, JSObject
*obj
, const char *name
,
4715 uintN nargs
, const char **argnames
,
4716 const char *bytes
, size_t length
,
4717 const char *filename
, uintN lineno
)
4719 return JS_CompileFunctionForPrincipals(cx
, obj
, NULL
, name
, nargs
, argnames
, bytes
, length
,
4723 JS_PUBLIC_API(JSString
*)
4724 JS_DecompileScript(JSContext
*cx
, JSScript
*script
, const char *name
, uintN indent
)
4730 assertSameCompartment(cx
, script
);
4731 jp
= js_NewPrinter(cx
, name
, NULL
,
4732 indent
& ~JS_DONT_PRETTY_PRINT
,
4733 !(indent
& JS_DONT_PRETTY_PRINT
),
4737 if (js_DecompileScript(jp
, script
))
4738 str
= js_GetPrinterOutput(jp
);
4741 js_DestroyPrinter(jp
);
4745 JS_PUBLIC_API(JSString
*)
4746 JS_DecompileFunction(JSContext
*cx
, JSFunction
*fun
, uintN indent
)
4749 assertSameCompartment(cx
, fun
);
4750 return js_DecompileToString(cx
, "JS_DecompileFunction", fun
,
4751 indent
& ~JS_DONT_PRETTY_PRINT
,
4752 !(indent
& JS_DONT_PRETTY_PRINT
),
4753 false, false, js_DecompileFunction
);
4756 JS_PUBLIC_API(JSString
*)
4757 JS_DecompileFunctionBody(JSContext
*cx
, JSFunction
*fun
, uintN indent
)
4760 assertSameCompartment(cx
, fun
);
4761 return js_DecompileToString(cx
, "JS_DecompileFunctionBody", fun
,
4762 indent
& ~JS_DONT_PRETTY_PRINT
,
4763 !(indent
& JS_DONT_PRETTY_PRINT
),
4764 false, false, js_DecompileFunctionBody
);
4767 JS_PUBLIC_API(JSBool
)
4768 JS_ExecuteScript(JSContext
*cx
, JSObject
*obj
, JSScript
*script
, jsval
*rval
)
4773 assertSameCompartment(cx
, obj
, script
);
4774 /* This should receive only scripts handed out via the JSAPI. */
4775 JS_ASSERT(script
== JSScript::emptyScript() || script
->u
.object
);
4776 ok
= Execute(cx
, obj
, script
, NULL
, 0, Valueify(rval
));
4777 LAST_FRAME_CHECKS(cx
, ok
);
4781 JS_PUBLIC_API(JSBool
)
4782 JS_EvaluateUCScriptForPrincipals(JSContext
*cx
, JSObject
*obj
,
4783 JSPrincipals
*principals
,
4784 const jschar
*chars
, uintN length
,
4785 const char *filename
, uintN lineno
,
4792 script
= Compiler::compileScript(cx
, obj
, NULL
, principals
,
4794 ? TCF_COMPILE_N_GO
| TCF_NO_SCRIPT_RVAL
4796 chars
, length
, NULL
, filename
, lineno
);
4798 LAST_FRAME_CHECKS(cx
, script
);
4801 ok
= Execute(cx
, obj
, script
, NULL
, 0, Valueify(rval
));
4802 LAST_FRAME_CHECKS(cx
, ok
);
4803 js_DestroyScript(cx
, script
);
4807 JS_PUBLIC_API(JSBool
)
4808 JS_EvaluateUCScript(JSContext
*cx
, JSObject
*obj
, const jschar
*chars
, uintN length
,
4809 const char *filename
, uintN lineno
, jsval
*rval
)
4811 return JS_EvaluateUCScriptForPrincipals(cx
, obj
, NULL
, chars
, length
, filename
, lineno
, rval
);
4814 /* Ancient uintN nbytes is part of API/ABI, so use size_t length local. */
4815 JS_PUBLIC_API(JSBool
)
4816 JS_EvaluateScriptForPrincipals(JSContext
*cx
, JSObject
*obj
, JSPrincipals
*principals
,
4817 const char *bytes
, uintN nbytes
,
4818 const char *filename
, uintN lineno
, jsval
*rval
)
4820 size_t length
= nbytes
;
4821 jschar
*chars
= js_InflateString(cx
, bytes
, &length
);
4824 JSBool ok
= JS_EvaluateUCScriptForPrincipals(cx
, obj
, principals
, chars
, length
,
4825 filename
, lineno
, rval
);
4830 JS_PUBLIC_API(JSBool
)
4831 JS_EvaluateScript(JSContext
*cx
, JSObject
*obj
, const char *bytes
, uintN nbytes
,
4832 const char *filename
, uintN lineno
, jsval
*rval
)
4834 return JS_EvaluateScriptForPrincipals(cx
, obj
, NULL
, bytes
, nbytes
, filename
, lineno
, rval
);
4837 JS_PUBLIC_API(JSBool
)
4838 JS_CallFunction(JSContext
*cx
, JSObject
*obj
, JSFunction
*fun
, uintN argc
, jsval
*argv
,
4844 assertSameCompartment(cx
, obj
, fun
, JSValueArray(argv
, argc
));
4845 ok
= InternalCall(cx
, obj
, ObjectValue(*fun
), argc
, Valueify(argv
), Valueify(rval
));
4846 LAST_FRAME_CHECKS(cx
, ok
);
4850 JS_PUBLIC_API(JSBool
)
4851 JS_CallFunctionName(JSContext
*cx
, JSObject
*obj
, const char *name
, uintN argc
, jsval
*argv
,
4855 assertSameCompartment(cx
, obj
, JSValueArray(argv
, argc
));
4857 AutoValueRooter
tvr(cx
);
4858 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
4860 js_GetMethod(cx
, obj
, ATOM_TO_JSID(atom
), JSGET_NO_METHOD_BARRIER
, tvr
.addr()) &&
4861 InternalCall(cx
, obj
, tvr
.value(), argc
, Valueify(argv
), Valueify(rval
));
4862 LAST_FRAME_CHECKS(cx
, ok
);
4866 JS_PUBLIC_API(JSBool
)
4867 JS_CallFunctionValue(JSContext
*cx
, JSObject
*obj
, jsval fval
, uintN argc
, jsval
*argv
,
4873 assertSameCompartment(cx
, obj
, fval
, JSValueArray(argv
, argc
));
4874 ok
= InternalCall(cx
, obj
, Valueify(fval
), argc
, Valueify(argv
), Valueify(rval
));
4875 LAST_FRAME_CHECKS(cx
, ok
);
4879 JS_PUBLIC_API(JSObject
*)
4880 JS_New(JSContext
*cx
, JSObject
*ctor
, uintN argc
, jsval
*argv
)
4883 assertSameCompartment(cx
, ctor
, JSValueArray(argv
, argc
));
4885 // This is not a simple variation of JS_CallFunctionValue because JSOP_NEW
4886 // is not a simple variation of JSOP_CALL. We have to determine what class
4887 // of object to create, create it, and clamp the return value to an object,
4888 // among other details. js_InvokeConstructor does the hard work.
4889 InvokeArgsGuard args
;
4890 if (!cx
->stack().pushInvokeArgs(cx
, argc
, args
))
4893 args
.callee().setObject(*ctor
);
4894 args
.thisv().setNull();
4895 memcpy(args
.argv(), argv
, argc
* sizeof(jsval
));
4897 bool ok
= InvokeConstructor(cx
, args
);
4898 JSObject
*obj
= ok
? args
.rval().toObjectOrNull() : NULL
;
4900 LAST_FRAME_CHECKS(cx
, ok
);
4904 JS_PUBLIC_API(JSOperationCallback
)
4905 JS_SetOperationCallback(JSContext
*cx
, JSOperationCallback callback
)
4907 #ifdef JS_THREADSAFE
4908 JS_ASSERT(CURRENT_THREAD_IS_ME(cx
->thread
));
4910 JSOperationCallback old
= cx
->operationCallback
;
4911 cx
->operationCallback
= callback
;
4915 JS_PUBLIC_API(JSOperationCallback
)
4916 JS_GetOperationCallback(JSContext
*cx
)
4918 return cx
->operationCallback
;
4922 JS_TriggerOperationCallback(JSContext
*cx
)
4925 * We allow for cx to come from another thread. Thus we must deal with
4926 * possible JS_ClearContextThread calls when accessing cx->thread. But we
4927 * assume that the calling thread is in a request so JSThread cannot be
4931 #ifdef JS_THREADSAFE
4932 JSThread
*thread
= cx
->thread
;
4937 td
= JS_THREAD_DATA(cx
);
4939 td
->triggerOperationCallback();
4943 JS_TriggerAllOperationCallbacks(JSRuntime
*rt
)
4945 js_TriggerAllOperationCallbacks(rt
, JS_FALSE
);
4948 JS_PUBLIC_API(JSBool
)
4949 JS_IsRunning(JSContext
*cx
)
4952 * The use of cx->fp below is safe. Rationale: Here we don't care if the
4953 * interpreter state is stale. We just want to know if there *is* any
4954 * interpreter state.
4956 VOUCH_DOES_NOT_REQUIRE_STACK();
4959 JS_ASSERT_IF(JS_TRACE_MONITOR(cx
).tracecx
== cx
, cx
->hasfp());
4961 JSStackFrame
*fp
= cx
->maybefp();
4962 while (fp
&& fp
->isDummyFrame())
4967 JS_PUBLIC_API(JSBool
)
4968 JS_IsConstructing(JSContext
*cx
)
4970 return cx
->isConstructing();
4973 JS_PUBLIC_API(JSStackFrame
*)
4974 JS_SaveFrameChain(JSContext
*cx
)
4977 JSStackFrame
*fp
= js_GetTopStackFrame(cx
);
4980 cx
->saveActiveSegment();
4985 JS_RestoreFrameChain(JSContext
*cx
, JSStackFrame
*fp
)
4988 JS_ASSERT_NOT_ON_TRACE(cx
);
4989 JS_ASSERT(!cx
->hasfp());
4992 cx
->restoreSegment();
4995 /************************************************************************/
4997 JS_PUBLIC_API(JSString
*)
4998 JS_NewString(JSContext
*cx
, char *bytes
, size_t nbytes
)
5000 size_t length
= nbytes
;
5006 /* Make a UTF-16 vector from the 8-bit char codes in bytes. */
5007 chars
= js_InflateString(cx
, bytes
, &length
);
5011 /* Free chars (but not bytes, which caller frees on error) if we fail. */
5012 str
= js_NewString(cx
, chars
, length
);
5018 /* Hand off bytes to the deflated string cache, if possible. */
5019 if (!cx
->runtime
->deflatedStringCache
->setBytes(cx
, str
, bytes
))
5024 JS_PUBLIC_API(JSString
*)
5025 JS_NewStringCopyN(JSContext
*cx
, const char *s
, size_t n
)
5031 js
= js_InflateString(cx
, s
, &n
);
5034 str
= js_NewString(cx
, js
, n
);
5040 JS_PUBLIC_API(JSString
*)
5041 JS_NewStringCopyZ(JSContext
*cx
, const char *s
)
5049 return cx
->runtime
->emptyString
;
5051 js
= js_InflateString(cx
, s
, &n
);
5054 str
= js_NewString(cx
, js
, n
);
5060 JS_PUBLIC_API(JSBool
)
5061 JS_StringHasBeenInterned(JSString
*str
)
5063 return str
->isAtomized();
5066 JS_PUBLIC_API(JSString
*)
5067 JS_InternString(JSContext
*cx
, const char *s
)
5072 atom
= js_Atomize(cx
, s
, strlen(s
), ATOM_INTERNED
);
5075 return ATOM_TO_STRING(atom
);
5078 JS_PUBLIC_API(JSString
*)
5079 JS_NewUCString(JSContext
*cx
, jschar
*chars
, size_t length
)
5082 return js_NewString(cx
, chars
, length
);
5085 JS_PUBLIC_API(JSString
*)
5086 JS_NewUCStringCopyN(JSContext
*cx
, const jschar
*s
, size_t n
)
5089 return js_NewStringCopyN(cx
, s
, n
);
5092 JS_PUBLIC_API(JSString
*)
5093 JS_NewUCStringCopyZ(JSContext
*cx
, const jschar
*s
)
5097 return cx
->runtime
->emptyString
;
5098 return js_NewStringCopyZ(cx
, s
);
5101 JS_PUBLIC_API(JSString
*)
5102 JS_InternUCStringN(JSContext
*cx
, const jschar
*s
, size_t length
)
5107 atom
= js_AtomizeChars(cx
, s
, length
, ATOM_INTERNED
);
5110 return ATOM_TO_STRING(atom
);
5113 JS_PUBLIC_API(JSString
*)
5114 JS_InternUCString(JSContext
*cx
, const jschar
*s
)
5116 return JS_InternUCStringN(cx
, s
, js_strlen(s
));
5119 JS_PUBLIC_API(char *)
5120 JS_GetStringBytes(JSString
*str
)
5124 bytes
= js_GetStringBytes(NULL
, str
);
5125 return (char *)(bytes
? bytes
: "");
5128 JS_PUBLIC_API(jschar
*)
5129 JS_GetStringChars(JSString
*str
)
5134 str
->ensureNotRope();
5137 * API botch (again, shades of JS_GetStringBytes): we have no cx to report
5138 * out-of-memory when undepending strings, so we replace JSString::undepend
5139 * with explicit malloc call and ignore its errors.
5141 * If we fail to convert a dependent string into an independent one, our
5142 * caller will not be guaranteed a \u0000 terminator as a backstop. This
5143 * may break some clients who already misbehave on embedded NULs.
5145 * The gain of dependent strings, which cure quadratic and cubic growth
5146 * rate bugs in string concatenation, is worth this slight loss in API
5149 if (str
->isDependent()) {
5150 n
= str
->dependentLength();
5151 size
= (n
+ 1) * sizeof(jschar
);
5152 s
= (jschar
*) js_malloc(size
);
5154 memcpy(s
, str
->dependentChars(), n
* sizeof *s
);
5156 str
->initFlat(s
, n
);
5158 s
= str
->dependentChars();
5161 str
->flatClearMutable();
5162 s
= str
->flatChars();
5167 JS_PUBLIC_API(size_t)
5168 JS_GetStringLength(JSString
*str
)
5170 return str
->length();
5173 JS_PUBLIC_API(const char *)
5174 JS_GetStringBytesZ(JSContext
*cx
, JSString
*str
)
5176 assertSameCompartment(cx
, str
);
5177 return js_GetStringBytes(cx
, str
);
5180 JS_PUBLIC_API(const jschar
*)
5181 JS_GetStringCharsZ(JSContext
*cx
, JSString
*str
)
5183 assertSameCompartment(cx
, str
);
5184 return str
->undepend(cx
);
5188 JS_CompareStrings(JSString
*str1
, JSString
*str2
)
5190 return js_CompareStrings(str1
, str2
);
5193 JS_PUBLIC_API(JSString
*)
5194 JS_NewGrowableString(JSContext
*cx
, jschar
*chars
, size_t length
)
5197 return js_NewString(cx
, chars
, length
);
5200 JS_PUBLIC_API(JSString
*)
5201 JS_NewDependentString(JSContext
*cx
, JSString
*str
, size_t start
, size_t length
)
5204 return js_NewDependentString(cx
, str
, start
, length
);
5207 JS_PUBLIC_API(JSString
*)
5208 JS_ConcatStrings(JSContext
*cx
, JSString
*left
, JSString
*right
)
5211 return js_ConcatStrings(cx
, left
, right
);
5214 JS_PUBLIC_API(const jschar
*)
5215 JS_UndependString(JSContext
*cx
, JSString
*str
)
5218 return str
->undepend(cx
);
5221 JS_PUBLIC_API(JSBool
)
5222 JS_MakeStringImmutable(JSContext
*cx
, JSString
*str
)
5225 return js_MakeStringImmutable(cx
, str
);
5228 JS_PUBLIC_API(JSBool
)
5229 JS_EncodeCharacters(JSContext
*cx
, const jschar
*src
, size_t srclen
, char *dst
, size_t *dstlenp
)
5234 n
= js_GetDeflatedStringLength(cx
, src
, srclen
);
5235 if (n
== (size_t)-1) {
5243 return js_DeflateStringToBuffer(cx
, src
, srclen
, dst
, dstlenp
);
5246 JS_PUBLIC_API(JSBool
)
5247 JS_DecodeBytes(JSContext
*cx
, const char *src
, size_t srclen
, jschar
*dst
, size_t *dstlenp
)
5249 return js_InflateStringToBuffer(cx
, src
, srclen
, dst
, dstlenp
);
5252 JS_PUBLIC_API(char *)
5253 JS_EncodeString(JSContext
*cx
, JSString
*str
)
5255 return js_DeflateString(cx
, str
->chars(), str
->length());
5258 JS_PUBLIC_API(JSBool
)
5259 JS_Stringify(JSContext
*cx
, jsval
*vp
, JSObject
*replacer
, jsval space
,
5260 JSONWriteCallback callback
, void *data
)
5263 assertSameCompartment(cx
, replacer
, space
);
5264 JSCharBuffer
cb(cx
);
5265 if (!js_Stringify(cx
, Valueify(vp
), replacer
, Valueify(space
), cb
))
5267 return callback(cb
.begin(), cb
.length(), data
);
5270 JS_PUBLIC_API(JSBool
)
5271 JS_TryJSON(JSContext
*cx
, jsval
*vp
)
5274 assertSameCompartment(cx
, *vp
);
5275 return js_TryJSON(cx
, Valueify(vp
));
5278 JS_PUBLIC_API(JSONParser
*)
5279 JS_BeginJSONParse(JSContext
*cx
, jsval
*vp
)
5282 return js_BeginJSONParse(cx
, Valueify(vp
));
5285 JS_PUBLIC_API(JSBool
)
5286 JS_ConsumeJSONText(JSContext
*cx
, JSONParser
*jp
, const jschar
*data
, uint32 len
)
5289 return js_ConsumeJSONText(cx
, jp
, data
, len
);
5292 JS_PUBLIC_API(JSBool
)
5293 JS_FinishJSONParse(JSContext
*cx
, JSONParser
*jp
, jsval reviver
)
5296 assertSameCompartment(cx
, reviver
);
5297 return js_FinishJSONParse(cx
, jp
, Valueify(reviver
));
5301 * The following determines whether C Strings are to be treated as UTF-8
5302 * or ISO-8859-1. For correct operation, it must be set prior to the
5303 * first call to JS_NewRuntime.
5305 #ifndef JS_C_STRINGS_ARE_UTF8
5306 JSBool js_CStringsAreUTF8
= JS_FALSE
;
5309 JS_PUBLIC_API(JSBool
)
5310 JS_CStringsAreUTF8()
5312 return js_CStringsAreUTF8
;
5316 JS_SetCStringsAreUTF8()
5318 JS_ASSERT(!js_NewRuntimeWasCalled
);
5320 #ifndef JS_C_STRINGS_ARE_UTF8
5321 js_CStringsAreUTF8
= JS_TRUE
;
5325 /************************************************************************/
5328 JS_ReportError(JSContext
*cx
, const char *format
, ...)
5332 va_start(ap
, format
);
5333 js_ReportErrorVA(cx
, JSREPORT_ERROR
, format
, ap
);
5338 JS_ReportErrorNumber(JSContext
*cx
, JSErrorCallback errorCallback
,
5339 void *userRef
, const uintN errorNumber
, ...)
5343 va_start(ap
, errorNumber
);
5344 js_ReportErrorNumberVA(cx
, JSREPORT_ERROR
, errorCallback
, userRef
,
5345 errorNumber
, JS_TRUE
, ap
);
5350 JS_ReportErrorNumberUC(JSContext
*cx
, JSErrorCallback errorCallback
,
5351 void *userRef
, const uintN errorNumber
, ...)
5355 va_start(ap
, errorNumber
);
5356 js_ReportErrorNumberVA(cx
, JSREPORT_ERROR
, errorCallback
, userRef
,
5357 errorNumber
, JS_FALSE
, ap
);
5361 JS_PUBLIC_API(JSBool
)
5362 JS_ReportWarning(JSContext
*cx
, const char *format
, ...)
5367 va_start(ap
, format
);
5368 ok
= js_ReportErrorVA(cx
, JSREPORT_WARNING
, format
, ap
);
5373 JS_PUBLIC_API(JSBool
)
5374 JS_ReportErrorFlagsAndNumber(JSContext
*cx
, uintN flags
,
5375 JSErrorCallback errorCallback
, void *userRef
,
5376 const uintN errorNumber
, ...)
5381 va_start(ap
, errorNumber
);
5382 ok
= js_ReportErrorNumberVA(cx
, flags
, errorCallback
, userRef
,
5383 errorNumber
, JS_TRUE
, ap
);
5388 JS_PUBLIC_API(JSBool
)
5389 JS_ReportErrorFlagsAndNumberUC(JSContext
*cx
, uintN flags
,
5390 JSErrorCallback errorCallback
, void *userRef
,
5391 const uintN errorNumber
, ...)
5396 va_start(ap
, errorNumber
);
5397 ok
= js_ReportErrorNumberVA(cx
, flags
, errorCallback
, userRef
,
5398 errorNumber
, JS_FALSE
, ap
);
5404 JS_ReportOutOfMemory(JSContext
*cx
)
5406 js_ReportOutOfMemory(cx
);
5410 JS_ReportAllocationOverflow(JSContext
*cx
)
5412 js_ReportAllocationOverflow(cx
);
5415 JS_PUBLIC_API(JSErrorReporter
)
5416 JS_SetErrorReporter(JSContext
*cx
, JSErrorReporter er
)
5418 JSErrorReporter older
;
5420 older
= cx
->errorReporter
;
5421 cx
->errorReporter
= er
;
5425 /************************************************************************/
5428 * Regular Expressions.
5430 JS_PUBLIC_API(JSObject
*)
5431 JS_NewRegExpObject(JSContext
*cx
, char *bytes
, size_t length
, uintN flags
)
5434 jschar
*chars
= js_InflateString(cx
, bytes
, &length
);
5437 JSObject
*obj
= RegExp::createObject(cx
, chars
, length
, flags
);
5442 JS_PUBLIC_API(JSObject
*)
5443 JS_NewUCRegExpObject(JSContext
*cx
, jschar
*chars
, size_t length
, uintN flags
)
5446 return RegExp::createObject(cx
, chars
, length
, flags
);
5450 JS_SetRegExpInput(JSContext
*cx
, JSString
*input
, JSBool multiline
)
5453 assertSameCompartment(cx
, input
);
5455 /* No locking required, cx is thread-private and input must be live. */
5456 cx
->regExpStatics
.reset(input
, !!multiline
);
5460 JS_ClearRegExpStatics(JSContext
*cx
)
5462 /* No locking required, cx is thread-private and input must be live. */
5463 cx
->regExpStatics
.clear();
5467 JS_ClearRegExpRoots(JSContext
*cx
)
5469 /* No locking required, cx is thread-private and input must be live. */
5470 cx
->regExpStatics
.clear();
5473 JS_PUBLIC_API(JSBool
)
5474 JS_ExecuteRegExp(JSContext
*cx
, JSObject
*obj
, jschar
*chars
, size_t length
,
5475 size_t *indexp
, JSBool test
, jsval
*rval
)
5479 RegExp
*re
= RegExp::extractFrom(obj
);
5484 JSString
*str
= js_NewStringCopyN(cx
, chars
, length
);
5488 AutoValueRooter
v(cx
, StringValue(str
));
5490 return re
->execute(cx
, str
, indexp
, test
, Valueify(rval
));
5493 /* TODO: compile, get/set other statics... */
5495 /************************************************************************/
5498 JS_SetLocaleCallbacks(JSContext
*cx
, JSLocaleCallbacks
*callbacks
)
5500 cx
->localeCallbacks
= callbacks
;
5503 JS_PUBLIC_API(JSLocaleCallbacks
*)
5504 JS_GetLocaleCallbacks(JSContext
*cx
)
5506 return cx
->localeCallbacks
;
5509 /************************************************************************/
5511 JS_PUBLIC_API(JSBool
)
5512 JS_IsExceptionPending(JSContext
*cx
)
5514 return (JSBool
) cx
->throwing
;
5517 JS_PUBLIC_API(JSBool
)
5518 JS_GetPendingException(JSContext
*cx
, jsval
*vp
)
5523 Valueify(*vp
) = cx
->exception
;
5528 JS_SetPendingException(JSContext
*cx
, jsval v
)
5531 assertSameCompartment(cx
, v
);
5532 SetPendingException(cx
, Valueify(v
));
5536 JS_ClearPendingException(JSContext
*cx
)
5538 cx
->throwing
= JS_FALSE
;
5539 cx
->exception
.setUndefined();
5542 JS_PUBLIC_API(JSBool
)
5543 JS_ReportPendingException(JSContext
*cx
)
5551 * Set cx->generatingError to suppress the standard error-to-exception
5552 * conversion done by all {js,JS}_Report* functions except for OOM. The
5553 * cx->generatingError flag was added to suppress recursive divergence
5554 * under js_ErrorToException, but it serves for our purposes here too.
5556 save
= cx
->generatingError
;
5557 cx
->generatingError
= JS_TRUE
;
5558 ok
= js_ReportUncaughtException(cx
);
5559 cx
->generatingError
= save
;
5563 struct JSExceptionState
{
5568 JS_PUBLIC_API(JSExceptionState
*)
5569 JS_SaveExceptionState(JSContext
*cx
)
5571 JSExceptionState
*state
;
5574 state
= (JSExceptionState
*) cx
->malloc(sizeof(JSExceptionState
));
5576 state
->throwing
= JS_GetPendingException(cx
, &state
->exception
);
5577 if (state
->throwing
&& JSVAL_IS_GCTHING(state
->exception
))
5578 js_AddRoot(cx
, Valueify(&state
->exception
), "JSExceptionState.exception");
5584 JS_RestoreExceptionState(JSContext
*cx
, JSExceptionState
*state
)
5588 if (state
->throwing
)
5589 JS_SetPendingException(cx
, state
->exception
);
5591 JS_ClearPendingException(cx
);
5592 JS_DropExceptionState(cx
, state
);
5597 JS_DropExceptionState(JSContext
*cx
, JSExceptionState
*state
)
5601 if (state
->throwing
&& JSVAL_IS_GCTHING(state
->exception
)) {
5602 assertSameCompartment(cx
, state
->exception
);
5603 JS_RemoveValueRoot(cx
, &state
->exception
);
5609 JS_PUBLIC_API(JSErrorReport
*)
5610 JS_ErrorFromException(JSContext
*cx
, jsval v
)
5613 assertSameCompartment(cx
, v
);
5614 return js_ErrorFromException(cx
, v
);
5617 JS_PUBLIC_API(JSBool
)
5618 JS_ThrowReportedError(JSContext
*cx
, const char *message
,
5619 JSErrorReport
*reportp
)
5621 return JS_IsRunning(cx
) &&
5622 js_ErrorToException(cx
, message
, reportp
, NULL
, NULL
);
5625 JS_PUBLIC_API(JSBool
)
5626 JS_ThrowStopIteration(JSContext
*cx
)
5628 return js_ThrowStopIteration(cx
);
5632 * Get the owning thread id of a context. Returns 0 if the context is not
5633 * owned by any thread.
5635 JS_PUBLIC_API(jsword
)
5636 JS_GetContextThread(JSContext
*cx
)
5638 #ifdef JS_THREADSAFE
5639 return reinterpret_cast<jsword
>(JS_THREAD_ID(cx
));
5646 * Set the current thread as the owning thread of a context. Returns the
5647 * old owning thread id, or -1 if the operation failed.
5649 JS_PUBLIC_API(jsword
)
5650 JS_SetContextThread(JSContext
*cx
)
5652 #ifdef JS_THREADSAFE
5653 JS_ASSERT(cx
->requestDepth
== 0);
5655 JS_ASSERT(CURRENT_THREAD_IS_ME(cx
->thread
));
5656 return reinterpret_cast<jsword
>(cx
->thread
->id
);
5659 if (!js_InitContextThread(cx
)) {
5660 js_ReportOutOfMemory(cx
);
5664 /* Here the GC lock is still held after js_InitContextThread took it. */
5665 JS_UNLOCK_GC(cx
->runtime
);
5670 JS_PUBLIC_API(jsword
)
5671 JS_ClearContextThread(JSContext
*cx
)
5673 #ifdef JS_THREADSAFE
5675 * This must be called outside a request and, if cx is associated with a
5676 * thread, this must be called only from that thread. If not, this is a
5679 JS_ASSERT(cx
->requestDepth
== 0);
5682 JS_ASSERT(CURRENT_THREAD_IS_ME(cx
->thread
));
5683 void *old
= cx
->thread
->id
;
5686 * We must not race with a GC that accesses cx->thread for all threads,
5689 JSRuntime
*rt
= cx
->runtime
;
5690 AutoLockGC
lock(rt
);
5692 js_ClearContextThread(cx
);
5693 return reinterpret_cast<jsword
>(old
);
5699 #ifdef MOZ_TRACE_JSCALLS
5701 JS_SetFunctionCallback(JSContext
*cx
, JSFunctionCallback fcb
)
5703 cx
->functionCallback
= fcb
;
5706 JS_PUBLIC_API(JSFunctionCallback
)
5707 JS_GetFunctionCallback(JSContext
*cx
)
5709 return cx
->functionCallback
;
5715 JS_SetGCZeal(JSContext
*cx
, uint8 zeal
)
5717 cx
->runtime
->gcZeal
= zeal
;
5721 /************************************************************************/
5723 #if !defined(STATIC_EXPORTABLE_JS_API) && !defined(STATIC_JS_API) && defined(XP_WIN) && !defined (WINCE)
5725 #include <windows.h>
5728 * Initialization routine for the JS DLL.
5730 BOOL WINAPI
DllMain (HINSTANCE hDLL
, DWORD dwReason
, LPVOID lpReserved
)