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 ***** */
45 #include "mozilla/FloatingPoint.h"
62 #include "jsversion.h"
72 #include "jsnativestack.h"
83 #include "jsweakmap.h"
84 #include "jswrapper.h"
85 #include "jstypedarray.h"
88 #include "ds/LifoAlloc.h"
89 #include "builtin/MapObject.h"
90 #include "builtin/RegExp.h"
91 #include "frontend/BytecodeCompiler.h"
92 #include "frontend/BytecodeEmitter.h"
93 #include "gc/Marking.h"
94 #include "gc/Memory.h"
95 #include "js/MemoryMetrics.h"
96 #include "yarr/BumpPointerAllocator.h"
97 #include "vm/MethodGuard.h"
98 #include "vm/NumericConversions.h"
99 #include "vm/StringBuffer.h"
102 #include "jsatominlines.h"
103 #include "jsinferinlines.h"
104 #include "jsobjinlines.h"
105 #include "jsscopeinlines.h"
106 #include "jsscriptinlines.h"
108 #include "vm/ObjectImpl-inl.h"
109 #include "vm/RegExpObject-inl.h"
110 #include "vm/RegExpStatics-inl.h"
111 #include "vm/Stack-inl.h"
112 #include "vm/String-inl.h"
115 #include "assembler/jit/ExecutableAllocator.h"
116 #include "methodjit/Logging.h"
120 using namespace js::gc
;
121 using namespace js::types
;
124 * This class is a version-establising barrier at the head of a VM entry or
125 * re-entry. It ensures that:
127 * - |newVersion| is the starting (default) version used for the context.
128 * - The starting version state is not an override.
129 * - Overrides in the VM session are not propagated to the caller.
133 JSContext
* const cx
;
134 JSVersion oldDefaultVersion
;
135 bool oldHasVersionOverride
;
136 JSVersion oldVersionOverride
;
138 unsigned oldCompileOptions
;
140 JSVersion newVersion
;
143 explicit AutoVersionAPI(JSContext
*cx
, JSVersion newVersion
)
145 oldDefaultVersion(cx
->getDefaultVersion()),
146 oldHasVersionOverride(cx
->isVersionOverridden()),
147 oldVersionOverride(oldHasVersionOverride
? cx
->findVersion() : JSVERSION_UNKNOWN
)
149 , oldCompileOptions(cx
->getCompileOptions())
152 this->newVersion
= newVersion
;
153 cx
->clearVersionOverride();
154 cx
->setDefaultVersion(newVersion
);
158 cx
->setDefaultVersion(oldDefaultVersion
);
159 if (oldHasVersionOverride
)
160 cx
->overrideVersion(oldVersionOverride
);
162 cx
->clearVersionOverride();
163 JS_ASSERT(oldCompileOptions
== cx
->getCompileOptions());
166 /* The version that this scoped-entity establishes. */
167 JSVersion
version() const { return newVersion
; }
170 #ifdef HAVE_VA_LIST_AS_ARRAY
171 #define JS_ADDRESSOF_VA_LIST(ap) ((va_list *)(ap))
173 #define JS_ADDRESSOF_VA_LIST(ap) (&(ap))
176 #ifdef JS_USE_JSID_STRUCT_TYPES
177 jsid JS_DEFAULT_XML_NAMESPACE_ID
= { size_t(JSID_TYPE_DEFAULT_XML_NAMESPACE
) };
178 jsid JSID_VOID
= { size_t(JSID_TYPE_VOID
) };
179 jsid JSID_EMPTY
= { size_t(JSID_TYPE_OBJECT
) };
182 const jsval JSVAL_NULL
= IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_NULL
, 0));
183 const jsval JSVAL_ZERO
= IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_INT32
, 0));
184 const jsval JSVAL_ONE
= IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_INT32
, 1));
185 const jsval JSVAL_FALSE
= IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_BOOLEAN
, JS_FALSE
));
186 const jsval JSVAL_TRUE
= IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_BOOLEAN
, JS_TRUE
));
187 const jsval JSVAL_VOID
= IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_UNDEFINED
, 0));
189 /* Make sure that jschar is two bytes unsigned integer */
190 JS_STATIC_ASSERT((jschar
)-1 > 0);
191 JS_STATIC_ASSERT(sizeof(jschar
) == 2);
193 JS_PUBLIC_API(int64_t)
200 JS_GetNaNValue(JSContext
*cx
)
202 return cx
->runtime
->NaNValue
;
206 JS_GetNegativeInfinityValue(JSContext
*cx
)
208 return cx
->runtime
->negativeInfinityValue
;
212 JS_GetPositiveInfinityValue(JSContext
*cx
)
214 return cx
->runtime
->positiveInfinityValue
;
218 JS_GetEmptyStringValue(JSContext
*cx
)
220 return STRING_TO_JSVAL(cx
->runtime
->emptyString
);
223 JS_PUBLIC_API(JSString
*)
224 JS_GetEmptyString(JSRuntime
*rt
)
226 JS_ASSERT(rt
->hasContexts());
227 return rt
->emptyString
;
231 TryArgumentFormatter(JSContext
*cx
, const char **formatp
, JSBool fromJS
, jsval
**vpp
, va_list *app
)
234 JSArgumentFormatMap
*map
;
237 for (map
= cx
->argumentFormatMap
; map
; map
= map
->next
) {
238 if (!strncmp(format
, map
->format
, map
->length
)) {
239 *formatp
= format
+ map
->length
;
240 return map
->formatter(cx
, format
, fromJS
, vpp
, app
);
243 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_BAD_CHAR
, format
);
248 AssertNoGC(JSRuntime
*rt
)
250 JS_ASSERT(!rt
->gcRunning
);
254 AssertNoGC(JSContext
*cx
)
256 AssertNoGC(cx
->runtime
);
260 AssertNoGCOrFlatString(JSContext
*cx
, JSString
*str
)
263 * We allow some functions to be called during a GC as long as the argument
264 * is a flat string, since that will not cause allocation.
266 JS_ASSERT_IF(cx
->runtime
->gcRunning
, str
->isFlat());
269 JS_PUBLIC_API(JSBool
)
270 JS_ConvertArguments(JSContext
*cx
, unsigned argc
, jsval
*argv
, const char *format
, ...)
277 va_start(ap
, format
);
278 ok
= JS_ConvertArgumentsVA(cx
, argc
, argv
, format
, ap
);
283 JS_PUBLIC_API(JSBool
)
284 JS_ConvertArgumentsVA(JSContext
*cx
, unsigned argc
, jsval
*argv
, const char *format
, va_list ap
)
296 assertSameCompartment(cx
, JSValueArray(argv
- 2, argc
+ 2));
299 while ((c
= *format
++) != '\0') {
306 if (sp
== argv
+ argc
) {
308 fun
= js_ValueToFunction(cx
, &argv
[-2], 0);
311 JS_snprintf(numBuf
, sizeof numBuf
, "%u", argc
);
312 JSAutoByteString funNameBytes
;
313 if (const char *name
= GetFunctionNameBytes(cx
, fun
, &funNameBytes
)) {
314 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_MORE_ARGS_NEEDED
,
315 name
, numBuf
, (argc
== 1) ? "" : "s");
324 *va_arg(ap
, JSBool
*) = js_ValueToBoolean(*sp
);
327 if (!JS_ValueToUint16(cx
, *sp
, va_arg(ap
, uint16_t *)))
331 if (!JS_ValueToECMAInt32(cx
, *sp
, va_arg(ap
, int32_t *)))
335 if (!JS_ValueToECMAUint32(cx
, *sp
, va_arg(ap
, uint32_t *)))
339 if (!JS_ValueToInt32(cx
, *sp
, va_arg(ap
, int32_t *)))
343 if (!JS_ValueToNumber(cx
, *sp
, va_arg(ap
, double *)))
347 if (!JS_ValueToNumber(cx
, *sp
, &d
))
349 *va_arg(ap
, double *) = ToInteger(d
);
353 str
= ToString(cx
, *sp
);
356 *sp
= STRING_TO_JSVAL(str
);
358 JSFixedString
*fixed
= str
->ensureFixed(cx
);
361 *va_arg(ap
, const jschar
**) = fixed
->chars();
363 *va_arg(ap
, JSString
**) = str
;
367 if (!js_ValueToObjectOrNull(cx
, *sp
, &obj
))
369 *sp
= OBJECT_TO_JSVAL(obj
);
370 *va_arg(ap
, JSObject
**) = obj
;
373 obj
= js_ValueToFunction(cx
, sp
, 0);
376 *sp
= OBJECT_TO_JSVAL(obj
);
377 *va_arg(ap
, JSFunction
**) = obj
->toFunction();
380 *va_arg(ap
, jsval
*) = *sp
;
386 if (!TryArgumentFormatter(cx
, &format
, JS_TRUE
, &sp
,
387 JS_ADDRESSOF_VA_LIST(ap
))) {
390 /* NB: the formatter already updated sp, so we continue here. */
398 JS_PUBLIC_API(JSBool
)
399 JS_AddArgumentFormatter(JSContext
*cx
, const char *format
, JSArgumentFormatter formatter
)
402 JSArgumentFormatMap
**mpp
, *map
;
404 length
= strlen(format
);
405 mpp
= &cx
->argumentFormatMap
;
406 while ((map
= *mpp
) != NULL
) {
407 /* Insert before any shorter string to match before prefixes. */
408 if (map
->length
< length
)
410 if (map
->length
== length
&& !strcmp(map
->format
, format
))
414 map
= (JSArgumentFormatMap
*) cx
->malloc_(sizeof *map
);
417 map
->format
= format
;
418 map
->length
= length
;
422 map
->formatter
= formatter
;
427 JS_RemoveArgumentFormatter(JSContext
*cx
, const char *format
)
430 JSArgumentFormatMap
**mpp
, *map
;
432 length
= strlen(format
);
433 mpp
= &cx
->argumentFormatMap
;
434 while ((map
= *mpp
) != NULL
) {
435 if (map
->length
== length
&& !strcmp(map
->format
, format
)) {
444 JS_PUBLIC_API(JSBool
)
445 JS_ConvertValue(JSContext
*cx
, jsval v
, JSType type
, jsval
*vp
)
454 assertSameCompartment(cx
, v
);
461 ok
= js_ValueToObjectOrNull(cx
, v
, &obj
);
463 *vp
= OBJECT_TO_JSVAL(obj
);
465 case JSTYPE_FUNCTION
:
467 obj
= js_ValueToFunction(cx
, vp
, JSV2F_SEARCH_STACK
);
471 str
= ToString(cx
, v
);
474 *vp
= STRING_TO_JSVAL(str
);
477 ok
= JS_ValueToNumber(cx
, v
, &d
);
479 *vp
= DOUBLE_TO_JSVAL(d
);
482 *vp
= BOOLEAN_TO_JSVAL(js_ValueToBoolean(v
));
486 JS_snprintf(numBuf
, sizeof numBuf
, "%d", (int)type
);
487 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_BAD_TYPE
, numBuf
);
495 JS_PUBLIC_API(JSBool
)
496 JS_ValueToObject(JSContext
*cx
, jsval v
, JSObject
**objp
)
500 assertSameCompartment(cx
, v
);
501 return js_ValueToObjectOrNull(cx
, v
, objp
);
504 JS_PUBLIC_API(JSFunction
*)
505 JS_ValueToFunction(JSContext
*cx
, jsval v
)
509 assertSameCompartment(cx
, v
);
510 return js_ValueToFunction(cx
, &v
, JSV2F_SEARCH_STACK
);
513 JS_PUBLIC_API(JSFunction
*)
514 JS_ValueToConstructor(JSContext
*cx
, jsval v
)
518 assertSameCompartment(cx
, v
);
519 return js_ValueToFunction(cx
, &v
, JSV2F_SEARCH_STACK
);
522 JS_PUBLIC_API(JSString
*)
523 JS_ValueToString(JSContext
*cx
, jsval v
)
527 assertSameCompartment(cx
, v
);
528 return ToString(cx
, v
);
531 JS_PUBLIC_API(JSString
*)
532 JS_ValueToSource(JSContext
*cx
, jsval v
)
536 assertSameCompartment(cx
, v
);
537 return js_ValueToSource(cx
, v
);
540 JS_PUBLIC_API(JSBool
)
541 JS_ValueToNumber(JSContext
*cx
, jsval v
, double *dp
)
545 assertSameCompartment(cx
, v
);
547 return ToNumber(cx
, v
, dp
);
550 JS_PUBLIC_API(JSBool
)
551 JS_DoubleIsInt32(double d
, int32_t *ip
)
553 return MOZ_DOUBLE_IS_INT32(d
, ip
);
556 JS_PUBLIC_API(int32_t)
557 JS_DoubleToInt32(double d
)
562 JS_PUBLIC_API(uint32_t)
563 JS_DoubleToUint32(double d
)
568 JS_PUBLIC_API(JSBool
)
569 JS_ValueToECMAInt32(JSContext
*cx
, jsval v
, int32_t *ip
)
573 assertSameCompartment(cx
, v
);
575 RootedVarValue
value(cx
, v
);
576 return ToInt32(cx
, value
, ip
);
579 JS_PUBLIC_API(JSBool
)
580 JS_ValueToECMAUint32(JSContext
*cx
, jsval v
, uint32_t *ip
)
584 assertSameCompartment(cx
, v
);
586 return ToUint32(cx
, v
, (uint32_t *)ip
);
589 JS_PUBLIC_API(JSBool
)
590 JS_ValueToInt32(JSContext
*cx
, jsval v
, int32_t *ip
)
594 assertSameCompartment(cx
, v
);
596 return NonstandardToInt32(cx
, v
, (int32_t *)ip
);
599 JS_PUBLIC_API(JSBool
)
600 JS_ValueToUint16(JSContext
*cx
, jsval v
, uint16_t *ip
)
604 assertSameCompartment(cx
, v
);
606 return ValueToUint16(cx
, v
, (uint16_t *)ip
);
609 JS_PUBLIC_API(JSBool
)
610 JS_ValueToBoolean(JSContext
*cx
, jsval v
, JSBool
*bp
)
614 assertSameCompartment(cx
, v
);
615 *bp
= js_ValueToBoolean(v
);
619 JS_PUBLIC_API(JSType
)
620 JS_TypeOfValue(JSContext
*cx
, jsval v
)
624 assertSameCompartment(cx
, v
);
625 return TypeOfValue(cx
, v
);
628 JS_PUBLIC_API(const char *)
629 JS_GetTypeName(JSContext
*cx
, JSType type
)
631 if ((unsigned)type
>= (unsigned)JSTYPE_LIMIT
)
633 return JS_TYPE_STR(type
);
636 JS_PUBLIC_API(JSBool
)
637 JS_StrictlyEqual(JSContext
*cx
, jsval v1
, jsval v2
, JSBool
*equal
)
641 assertSameCompartment(cx
, v1
, v2
);
643 if (!StrictlyEqual(cx
, v1
, v2
, &eq
))
649 JS_PUBLIC_API(JSBool
)
650 JS_LooselyEqual(JSContext
*cx
, jsval v1
, jsval v2
, JSBool
*equal
)
654 assertSameCompartment(cx
, v1
, v2
);
656 if (!LooselyEqual(cx
, v1
, v2
, &eq
))
662 JS_PUBLIC_API(JSBool
)
663 JS_SameValue(JSContext
*cx
, jsval v1
, jsval v2
, JSBool
*same
)
667 assertSameCompartment(cx
, v1
, v2
);
669 if (!SameValue(cx
, v1
, v2
, &s
))
675 JS_PUBLIC_API(JSBool
)
676 JS_IsBuiltinEvalFunction(JSFunction
*fun
)
678 return IsAnyBuiltinEval(fun
);
681 JS_PUBLIC_API(JSBool
)
682 JS_IsBuiltinFunctionConstructor(JSFunction
*fun
)
684 return IsBuiltinFunctionConstructor(fun
);
687 /************************************************************************/
690 * Has a new runtime ever been created? This flag is used to detect unsafe
691 * changes to js_CStringsAreUTF8 after a runtime has been created, and to
692 * control things that should happen only once across all runtimes.
694 static JSBool js_NewRuntimeWasCalled
= JS_FALSE
;
696 static const JSSecurityCallbacks NullSecurityCallbacks
= { };
698 JSRuntime::JSRuntime()
699 : atomsCompartment(NULL
),
703 tempLifoAlloc(TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE
),
707 jaegerRuntime_(NULL
),
711 interpreterFrames(NULL
),
713 destroyCompartmentCallback(NULL
),
714 activityCallback(NULL
),
715 activityCallbackArg(NULL
),
720 checkRequestDepth(0),
723 gcSystemAvailableChunkListHead(NULL
),
724 gcUserAvailableChunkListHead(NULL
),
729 gcNumArenasFreeCommitted(0),
731 gcChunkAllocationSinceLastGC(false),
734 gcMode(JSGC_MODE_GLOBAL
),
737 gcStats(thisFromCtor()),
741 gcTriggerReason(gcreason::NO_REASON
),
742 gcStrictCompartmentChecking(false),
743 gcIncrementalState(gc::NO_INCREMENTAL
),
744 gcLastMarkSlice(false),
746 gcSliceBudget(SliceBudget::Unlimited
),
747 gcIncrementalEnabled(true),
748 gcExactScanningEnabled(true),
755 gcDeterministicOnly(false),
758 gcSliceCallback(NULL
),
759 gcFinalizeCallback(NULL
),
760 gcBlackRootsTraceOp(NULL
),
761 gcBlackRootsData(NULL
),
762 gcGrayRootsTraceOp(NULL
),
763 gcGrayRootsData(NULL
),
765 scriptAndCountsVector(NULL
),
766 NaNValue(UndefinedValue()),
767 negativeInfinityValue(UndefinedValue()),
768 positiveInfinityValue(UndefinedValue()),
771 profilingScripts(false),
772 alwaysPreserveCode(false),
773 hadOutOfMemory(false),
777 gcHelperThread(thisFromCtor()),
779 defaultFreeOp_(thisFromCtor(), false, false),
780 debuggerMutations(0),
781 securityCallbacks(const_cast<JSSecurityCallbacks
*>(&NullSecurityCallbacks
)),
782 destroyPrincipals(NULL
),
783 structuredCloneCallbacks(NULL
),
784 telemetryCallback(NULL
),
786 thousandsSeparator(0),
792 pendingProxyOperation(NULL
),
793 trustedPrincipals_(NULL
),
794 wrapObjectCallback(TransparentObjectWrapper
),
795 preWrapObjectCallback(NULL
),
796 preserveWrapperCallback(NULL
),
798 noGCOrAllocationCheck(0),
803 /* Initialize infallibly first, so we can goto bad and JS_DestroyRuntime. */
804 JS_INIT_CLIST(&contextList
);
805 JS_INIT_CLIST(&debuggerList
);
807 PodZero(&debugHooks
);
810 #if JS_STACK_GROWTH_DIRECTION > 0
811 nativeStackLimit
= UINTPTR_MAX
;
816 JSRuntime::init(uint32_t maxbytes
)
819 ownerThread_
= PR_GetCurrentThread();
822 #ifdef JS_METHODJIT_SPEW
826 if (!js_InitGC(this, maxbytes
))
829 if (!gcMarker
.init())
832 const char *size
= getenv("JSGC_MARK_STACK_LIMIT");
834 SetMarkStackLimit(this, atoi(size
));
836 if (!(atomsCompartment
= this->new_
<JSCompartment
>(this)) ||
837 !atomsCompartment
->init(NULL
) ||
838 !compartments
.append(atomsCompartment
)) {
839 Foreground::delete_(atomsCompartment
);
843 atomsCompartment
->isSystemCompartment
= true;
844 atomsCompartment
->setGCLastBytes(8192, 8192, GC_NORMAL
);
846 if (!js_InitAtomState(this))
849 if (!InitRuntimeNumberState(this))
852 dtoaState
= js_NewDtoaState();
856 if (!stackSpace
.init())
859 if (!scriptFilenameTable
.init())
862 nativeStackBase
= GetNativeStackBase();
866 JSRuntime::~JSRuntime()
869 * Even though all objects in the compartment are dead, we may have keep
870 * some filenames around because of gcKeepAtoms.
872 FreeScriptFilenames(this);
874 JS_ASSERT(onOwnerThread());
877 /* Don't hurt everyone in leaky ol' Mozilla with a fatal JS_ASSERT! */
878 if (!JS_CLIST_IS_EMPTY(&contextList
)) {
879 unsigned cxcount
= 0;
880 for (ContextIter
acx(this); !acx
.done(); acx
.next()) {
882 "JS API usage error: found live context at %p\n",
887 "JS API usage error: %u context%s left in runtime upon JS_DestroyRuntime.\n",
888 cxcount
, (cxcount
== 1) ? "" : "s");
892 FinishRuntimeNumberState(this);
893 js_FinishAtomState(this);
896 js_DestroyDtoaState(dtoaState
);
901 PR_DestroyLock(gcLock
);
907 delete_(jaegerRuntime_
);
909 delete_(execAlloc_
); /* Delete after jaegerRuntime_. */
914 JSRuntime::setOwnerThread()
916 JS_ASSERT(ownerThread_
== (void *)0xc1ea12); /* "clear" */
917 JS_ASSERT(requestDepth
== 0);
918 ownerThread_
= PR_GetCurrentThread();
919 nativeStackBase
= GetNativeStackBase();
920 if (nativeStackQuota
)
921 JS_SetNativeStackQuota(this, nativeStackQuota
);
925 JSRuntime::clearOwnerThread()
927 JS_ASSERT(onOwnerThread());
928 JS_ASSERT(requestDepth
== 0);
929 ownerThread_
= (void *)0xc1ea12; /* "clear" */
931 #if JS_STACK_GROWTH_DIRECTION > 0
932 nativeStackLimit
= UINTPTR_MAX
;
934 nativeStackLimit
= 0;
939 JSRuntime::onOwnerThread() const
941 return ownerThread_
== PR_GetCurrentThread();
943 #endif /* JS_THREADSAFE */
945 JS_PUBLIC_API(JSRuntime
*)
946 JS_NewRuntime(uint32_t maxbytes
)
948 if (!js_NewRuntimeWasCalled
) {
951 * This code asserts that the numbers associated with the error names
952 * in jsmsg.def are monotonically increasing. It uses values for the
953 * error names enumerated in jscntxt.c. It's not a compile-time check
954 * but it's better than nothing.
957 #define MSG_DEF(name, number, count, exception, format) \
958 JS_ASSERT(name == errorNumber++);
962 #define MSG_DEF(name, number, count, exception, format) \
964 unsigned numfmtspecs = 0; \
966 for (fmt = format; *fmt != '\0'; fmt++) { \
967 if (*fmt == '{' && isdigit(fmt[1])) \
970 JS_ASSERT(count == numfmtspecs); \
976 InitMemorySubsystem();
978 js_NewRuntimeWasCalled
= JS_TRUE
;
981 JSRuntime
*rt
= OffTheBooks::new_
<JSRuntime
>();
985 if (!rt
->init(maxbytes
)) {
986 JS_DestroyRuntime(rt
);
990 Probes::createRuntime(rt
);
995 JS_DestroyRuntime(JSRuntime
*rt
)
997 Probes::destroyRuntime(rt
);
998 Foreground::delete_(rt
);
1008 JS_PUBLIC_API(void *)
1009 JS_GetRuntimePrivate(JSRuntime
*rt
)
1015 JS_SetRuntimePrivate(JSRuntime
*rt
, void *data
)
1020 #ifdef JS_THREADSAFE
1022 StartRequest(JSContext
*cx
)
1024 JSRuntime
*rt
= cx
->runtime
;
1025 JS_ASSERT(rt
->onOwnerThread());
1027 if (rt
->requestDepth
) {
1030 /* Indicate that a request is running. */
1031 rt
->requestDepth
= 1;
1033 if (rt
->activityCallback
)
1034 rt
->activityCallback(rt
->activityCallbackArg
, true);
1039 StopRequest(JSContext
*cx
)
1041 JSRuntime
*rt
= cx
->runtime
;
1042 JS_ASSERT(rt
->onOwnerThread());
1043 JS_ASSERT(rt
->requestDepth
!= 0);
1044 if (rt
->requestDepth
!= 1) {
1047 rt
->conservativeGC
.updateForRequestEnd(rt
->suspendCount
);
1048 rt
->requestDepth
= 0;
1050 if (rt
->activityCallback
)
1051 rt
->activityCallback(rt
->activityCallbackArg
, false);
1054 #endif /* JS_THREADSAFE */
1057 JS_BeginRequest(JSContext
*cx
)
1059 #ifdef JS_THREADSAFE
1060 cx
->outstandingRequests
++;
1066 JS_EndRequest(JSContext
*cx
)
1068 #ifdef JS_THREADSAFE
1069 JS_ASSERT(cx
->outstandingRequests
!= 0);
1070 cx
->outstandingRequests
--;
1075 /* Yield to pending GC operations, regardless of request depth */
1077 JS_YieldRequest(JSContext
*cx
)
1079 #ifdef JS_THREADSAFE
1081 JS_ResumeRequest(cx
, JS_SuspendRequest(cx
));
1085 JS_PUBLIC_API(unsigned)
1086 JS_SuspendRequest(JSContext
*cx
)
1088 #ifdef JS_THREADSAFE
1089 JSRuntime
*rt
= cx
->runtime
;
1090 JS_ASSERT(rt
->onOwnerThread());
1092 unsigned saveDepth
= rt
->requestDepth
;
1097 rt
->requestDepth
= 1;
1106 JS_ResumeRequest(JSContext
*cx
, unsigned saveDepth
)
1108 #ifdef JS_THREADSAFE
1109 JSRuntime
*rt
= cx
->runtime
;
1110 JS_ASSERT(rt
->onOwnerThread());
1113 JS_ASSERT(saveDepth
>= 1);
1114 JS_ASSERT(!rt
->requestDepth
);
1115 JS_ASSERT(rt
->suspendCount
);
1117 rt
->requestDepth
= saveDepth
;
1122 JS_PUBLIC_API(JSBool
)
1123 JS_IsInRequest(JSRuntime
*rt
)
1125 #ifdef JS_THREADSAFE
1126 JS_ASSERT(rt
->onOwnerThread());
1127 return rt
->requestDepth
!= 0;
1133 JS_PUBLIC_API(JSBool
)
1134 JS_IsInSuspendedRequest(JSRuntime
*rt
)
1136 #ifdef JS_THREADSAFE
1137 JS_ASSERT(rt
->onOwnerThread());
1138 return rt
->suspendCount
!= 0;
1144 JS_PUBLIC_API(JSContextCallback
)
1145 JS_SetContextCallback(JSRuntime
*rt
, JSContextCallback cxCallback
)
1147 JSContextCallback old
;
1149 old
= rt
->cxCallback
;
1150 rt
->cxCallback
= cxCallback
;
1154 JS_PUBLIC_API(JSContext
*)
1155 JS_NewContext(JSRuntime
*rt
, size_t stackChunkSize
)
1157 return NewContext(rt
, stackChunkSize
);
1161 JS_DestroyContext(JSContext
*cx
)
1163 DestroyContext(cx
, DCM_FORCE_GC
);
1167 JS_DestroyContextNoGC(JSContext
*cx
)
1169 DestroyContext(cx
, DCM_NO_GC
);
1172 JS_PUBLIC_API(void *)
1173 JS_GetContextPrivate(JSContext
*cx
)
1179 JS_SetContextPrivate(JSContext
*cx
, void *data
)
1184 JS_PUBLIC_API(void *)
1185 JS_GetSecondContextPrivate(JSContext
*cx
)
1191 JS_SetSecondContextPrivate(JSContext
*cx
, void *data
)
1196 JS_PUBLIC_API(JSRuntime
*)
1197 JS_GetRuntime(JSContext
*cx
)
1202 JS_PUBLIC_API(JSContext
*)
1203 JS_ContextIterator(JSRuntime
*rt
, JSContext
**iterp
)
1205 JSContext
*cx
= *iterp
;
1206 JSCList
*next
= cx
? cx
->link
.next
: rt
->contextList
.next
;
1207 cx
= (next
== &rt
->contextList
) ? NULL
: JSContext::fromLinkField(next
);
1212 JS_PUBLIC_API(JSVersion
)
1213 JS_GetVersion(JSContext
*cx
)
1215 return VersionNumber(cx
->findVersion());
1218 JS_PUBLIC_API(JSVersion
)
1219 JS_SetVersion(JSContext
*cx
, JSVersion newVersion
)
1221 JS_ASSERT(VersionIsKnown(newVersion
));
1222 JS_ASSERT(!VersionHasFlags(newVersion
));
1223 JSVersion newVersionNumber
= newVersion
;
1226 unsigned coptsBefore
= cx
->getCompileOptions();
1228 JSVersion oldVersion
= cx
->findVersion();
1229 JSVersion oldVersionNumber
= VersionNumber(oldVersion
);
1230 if (oldVersionNumber
== newVersionNumber
)
1231 return oldVersionNumber
; /* No override actually occurs! */
1233 /* We no longer support 1.4 or below. */
1234 if (newVersionNumber
!= JSVERSION_DEFAULT
&& newVersionNumber
<= JSVERSION_1_4
)
1235 return oldVersionNumber
;
1237 VersionCopyFlags(&newVersion
, oldVersion
);
1238 cx
->maybeOverrideVersion(newVersion
);
1239 JS_ASSERT(cx
->getCompileOptions() == coptsBefore
);
1240 return oldVersionNumber
;
1243 static struct v2smap
{
1247 {JSVERSION_1_0
, "1.0"},
1248 {JSVERSION_1_1
, "1.1"},
1249 {JSVERSION_1_2
, "1.2"},
1250 {JSVERSION_1_3
, "1.3"},
1251 {JSVERSION_1_4
, "1.4"},
1252 {JSVERSION_ECMA_3
, "ECMAv3"},
1253 {JSVERSION_1_5
, "1.5"},
1254 {JSVERSION_1_6
, "1.6"},
1255 {JSVERSION_1_7
, "1.7"},
1256 {JSVERSION_1_8
, "1.8"},
1257 {JSVERSION_ECMA_5
, "ECMAv5"},
1258 {JSVERSION_DEFAULT
, js_default_str
},
1259 {JSVERSION_UNKNOWN
, NULL
}, /* must be last, NULL is sentinel */
1262 JS_PUBLIC_API(const char *)
1263 JS_VersionToString(JSVersion version
)
1267 for (i
= 0; v2smap
[i
].string
; i
++)
1268 if (v2smap
[i
].version
== version
)
1269 return v2smap
[i
].string
;
1273 JS_PUBLIC_API(JSVersion
)
1274 JS_StringToVersion(const char *string
)
1278 for (i
= 0; v2smap
[i
].string
; i
++)
1279 if (strcmp(v2smap
[i
].string
, string
) == 0)
1280 return v2smap
[i
].version
;
1281 return JSVERSION_UNKNOWN
;
1284 JS_PUBLIC_API(uint32_t)
1285 JS_GetOptions(JSContext
*cx
)
1288 * Can't check option/version synchronization here.
1289 * We may have been synchronized with a script version that was formerly on
1290 * the stack, but has now been popped.
1292 return cx
->allOptions();
1296 SetOptionsCommon(JSContext
*cx
, unsigned options
)
1298 JS_ASSERT((options
& JSALLOPTION_MASK
) == options
);
1299 unsigned oldopts
= cx
->allOptions();
1300 unsigned newropts
= options
& JSRUNOPTION_MASK
;
1301 unsigned newcopts
= options
& JSCOMPILEOPTION_MASK
;
1302 cx
->setRunOptions(newropts
);
1303 cx
->setCompileOptions(newcopts
);
1304 cx
->updateJITEnabled();
1308 JS_PUBLIC_API(uint32_t)
1309 JS_SetOptions(JSContext
*cx
, uint32_t options
)
1311 return SetOptionsCommon(cx
, options
);
1314 JS_PUBLIC_API(uint32_t)
1315 JS_ToggleOptions(JSContext
*cx
, uint32_t options
)
1317 unsigned oldopts
= cx
->allOptions();
1318 unsigned newopts
= oldopts
^ options
;
1319 return SetOptionsCommon(cx
, newopts
);
1323 JS_SetJitHardening(JSRuntime
*rt
, JSBool enabled
)
1325 rt
->setJitHardening(!!enabled
);
1328 JS_PUBLIC_API(const char *)
1329 JS_GetImplementationVersion(void)
1331 return "JavaScript-C 1.8.5+ 2011-04-16";
1335 JS_SetDestroyCompartmentCallback(JSRuntime
*rt
, JSDestroyCompartmentCallback callback
)
1337 rt
->destroyCompartmentCallback
= callback
;
1340 JS_PUBLIC_API(JSWrapObjectCallback
)
1341 JS_SetWrapObjectCallbacks(JSRuntime
*rt
,
1342 JSWrapObjectCallback callback
,
1343 JSPreWrapCallback precallback
)
1345 JSWrapObjectCallback old
= rt
->wrapObjectCallback
;
1346 rt
->wrapObjectCallback
= callback
;
1347 rt
->preWrapObjectCallback
= precallback
;
1351 JS_PUBLIC_API(JSCrossCompartmentCall
*)
1352 JS_EnterCrossCompartmentCall(JSContext
*cx
, JSObject
*target
)
1358 AutoCompartment
*call
= cx
->new_
<AutoCompartment
>(cx
, target
);
1361 if (!call
->enter()) {
1362 Foreground::delete_(call
);
1365 return reinterpret_cast<JSCrossCompartmentCall
*>(call
);
1370 // Declared in jscompartment.h
1371 Class dummy_class
= {
1373 JSCLASS_GLOBAL_FLAGS
,
1374 JS_PropertyStub
, JS_PropertyStub
,
1375 JS_PropertyStub
, JS_StrictPropertyStub
,
1376 JS_EnumerateStub
, JS_ResolveStub
,
1382 JS_PUBLIC_API(JSCrossCompartmentCall
*)
1383 JS_EnterCrossCompartmentCallScript(JSContext
*cx
, JSScript
*target
)
1387 JS_ASSERT(!target
->isCachedEval
);
1388 GlobalObject
*global
= target
->globalObject
;
1390 SwitchToCompartment
sc(cx
, target
->compartment());
1391 global
= GlobalObject::create(cx
, &dummy_class
);
1395 return JS_EnterCrossCompartmentCall(cx
, global
);
1398 JS_PUBLIC_API(JSCrossCompartmentCall
*)
1399 JS_EnterCrossCompartmentCallStackFrame(JSContext
*cx
, JSStackFrame
*target
)
1404 return JS_EnterCrossCompartmentCall(cx
, &Valueify(target
)->global());
1408 JS_LeaveCrossCompartmentCall(JSCrossCompartmentCall
*call
)
1410 AutoCompartment
*realcall
= reinterpret_cast<AutoCompartment
*>(call
);
1411 AssertNoGC(realcall
->context
);
1412 CHECK_REQUEST(realcall
->context
);
1414 Foreground::delete_(realcall
);
1418 JSAutoEnterCompartment::enter(JSContext
*cx
, JSObject
*target
)
1421 JS_ASSERT(state
== STATE_UNENTERED
);
1422 if (cx
->compartment
== target
->compartment()) {
1423 state
= STATE_SAME_COMPARTMENT
;
1427 JS_STATIC_ASSERT(sizeof(bytes
) == sizeof(AutoCompartment
));
1429 AutoCompartment
*call
= new (bytes
) AutoCompartment(cx
, target
);
1430 if (call
->enter()) {
1431 state
= STATE_OTHER_COMPARTMENT
;
1438 JSAutoEnterCompartment::enterAndIgnoreErrors(JSContext
*cx
, JSObject
*target
)
1440 (void) enter(cx
, target
);
1443 JSAutoEnterCompartment::~JSAutoEnterCompartment()
1445 if (state
== STATE_OTHER_COMPARTMENT
) {
1446 AutoCompartment
* ac
= getAutoCompartment();
1447 CHECK_REQUEST(ac
->context
);
1448 ac
->~AutoCompartment();
1455 AutoEnterScriptCompartment::enter(JSContext
*cx
, JSScript
*target
)
1458 if (cx
->compartment
== target
->compartment()) {
1459 call
= reinterpret_cast<JSCrossCompartmentCall
*>(1);
1462 call
= JS_EnterCrossCompartmentCallScript(cx
, target
);
1463 return call
!= NULL
;
1467 AutoEnterFrameCompartment::enter(JSContext
*cx
, JSStackFrame
*target
)
1470 if (cx
->compartment
== Valueify(target
)->scopeChain()->compartment()) {
1471 call
= reinterpret_cast<JSCrossCompartmentCall
*>(1);
1474 call
= JS_EnterCrossCompartmentCallStackFrame(cx
, target
);
1475 return call
!= NULL
;
1478 } /* namespace JS */
1481 JS_SetCompartmentPrivate(JSCompartment
*compartment
, void *data
)
1483 compartment
->data
= data
;
1486 JS_PUBLIC_API(void *)
1487 JS_GetCompartmentPrivate(JSCompartment
*compartment
)
1489 return compartment
->data
;
1492 JS_PUBLIC_API(JSBool
)
1493 JS_WrapObject(JSContext
*cx
, JSObject
**objp
)
1497 return cx
->compartment
->wrap(cx
, objp
);
1500 JS_PUBLIC_API(JSBool
)
1501 JS_WrapValue(JSContext
*cx
, jsval
*vp
)
1505 return cx
->compartment
->wrap(cx
, vp
);
1508 JS_PUBLIC_API(JSObject
*)
1509 JS_TransplantObject(JSContext
*cx
, JSObject
*origobj
, JSObject
*target
)
1513 // This function is called when an object moves between two
1514 // different compartments. In that case, we need to "move" the
1515 // window from origobj's compartment to target's compartment.
1516 JSCompartment
*destination
= target
->compartment();
1517 WrapperMap
&map
= destination
->crossCompartmentWrappers
;
1518 Value origv
= ObjectValue(*origobj
);
1521 if (origobj
->compartment() == destination
) {
1522 // If the original object is in the same compartment as the
1523 // destination, then we know that we won't find wrapper in the
1524 // destination's cross compartment map and that the same
1525 // object will continue to work. Note the rare case where
1526 // |origobj == target|. In that case, we can just treat this
1527 // as a same compartment navigation. The effect is to clear
1528 // all of the wrappers and their holders if they have
1529 // them. This would be cleaner as a separate API.
1530 if (origobj
!= target
&& !origobj
->swap(cx
, target
))
1533 } else if (WrapperMap::Ptr p
= map
.lookup(origv
)) {
1534 // There might already be a wrapper for the original object in
1535 // the new compartment. If there is, make it the primary outer
1536 // window proxy around the inner (accomplished by swapping
1537 // target's innards with the old, possibly security wrapper,
1539 obj
= &p
->value
.toObject();
1541 if (!obj
->swap(cx
, target
))
1544 // Otherwise, this is going to be our outer window proxy in
1545 // the new compartment.
1549 // Now, iterate through other scopes looking for references to the
1550 // old outer window. They need to be updated to point at the new
1551 // outer window. They also might transition between different
1552 // types of security wrappers based on whether the new compartment
1553 // is same origin with them.
1554 Value targetv
= ObjectValue(*obj
);
1555 CompartmentVector
&vector
= cx
->runtime
->compartments
;
1556 AutoValueVector
toTransplant(cx
);
1557 if (!toTransplant
.reserve(vector
.length()))
1560 for (JSCompartment
**p
= vector
.begin(), **end
= vector
.end(); p
!= end
; ++p
) {
1561 WrapperMap
&pmap
= (*p
)->crossCompartmentWrappers
;
1562 if (WrapperMap::Ptr wp
= pmap
.lookup(origv
)) {
1563 // We found a wrapper. Remember and root it.
1564 toTransplant
.infallibleAppend(wp
->value
);
1568 for (Value
*begin
= toTransplant
.begin(), *end
= toTransplant
.end(); begin
!= end
; ++begin
) {
1569 JSObject
*wobj
= &begin
->toObject();
1570 JSCompartment
*wcompartment
= wobj
->compartment();
1571 WrapperMap
&pmap
= wcompartment
->crossCompartmentWrappers
;
1572 JS_ASSERT(pmap
.lookup(origv
));
1575 // First, we wrap it in the new compartment. This will return
1577 AutoCompartment
ac(cx
, wobj
);
1578 JSObject
*tobj
= obj
;
1579 if (!ac
.enter() || !wcompartment
->wrap(cx
, &tobj
))
1582 // Now, because we need to maintain object identity, we do a
1583 // brain transplant on the old object. At the same time, we
1584 // update the entry in the compartment's wrapper map to point
1585 // to the old wrapper.
1586 JS_ASSERT(tobj
!= wobj
);
1587 if (!wobj
->swap(cx
, tobj
))
1589 pmap
.put(targetv
, ObjectValue(*wobj
));
1592 // Lastly, update the original object to point to the new one.
1593 if (origobj
->compartment() != destination
) {
1594 AutoCompartment
ac(cx
, origobj
);
1595 JSObject
*tobj
= obj
;
1596 if (!ac
.enter() || !JS_WrapObject(cx
, &tobj
))
1598 if (!origobj
->swap(cx
, tobj
))
1600 origobj
->compartment()->crossCompartmentWrappers
.put(targetv
, origv
);
1607 * The location object is special. There is the location object itself and
1608 * then the location object wrapper. Because there are no direct references to
1609 * the location object itself, we don't want the old obj (|origobj| here) to
1610 * become the new wrapper but the wrapper itself instead. This leads to very
1611 * subtle differences between js_TransplantObjectWithWrapper and
1612 * JS_TransplantObject.
1614 JS_FRIEND_API(JSObject
*)
1615 js_TransplantObjectWithWrapper(JSContext
*cx
,
1617 JSObject
*origwrapper
,
1618 JSObject
*targetobj
,
1619 JSObject
*targetwrapper
)
1624 JSCompartment
*destination
= targetobj
->compartment();
1625 WrapperMap
&map
= destination
->crossCompartmentWrappers
;
1627 // |origv| is the map entry we're looking up. The map entries are going to
1628 // be for the location object itself.
1629 Value origv
= ObjectValue(*origobj
);
1631 // There might already be a wrapper for the original object in the new
1633 if (WrapperMap::Ptr p
= map
.lookup(origv
)) {
1634 // There is. Make the existing wrapper a same compartment location
1635 // wrapper (swapping it with the given new wrapper).
1636 obj
= &p
->value
.toObject();
1638 if (!obj
->swap(cx
, targetwrapper
))
1641 // Otherwise, use the passed-in wrapper as the same compartment
1642 // location wrapper.
1643 obj
= targetwrapper
;
1646 // Now, iterate through other scopes looking for references to the old
1647 // location object. Note that the entries in the maps are for |origobj|
1648 // and not |origwrapper|. They need to be updated to point at the new
1650 Value targetv
= ObjectValue(*targetobj
);
1651 CompartmentVector
&vector
= cx
->runtime
->compartments
;
1652 AutoValueVector
toTransplant(cx
);
1653 if (!toTransplant
.reserve(vector
.length()))
1656 for (JSCompartment
**p
= vector
.begin(), **end
= vector
.end(); p
!= end
; ++p
) {
1657 WrapperMap
&pmap
= (*p
)->crossCompartmentWrappers
;
1658 if (WrapperMap::Ptr wp
= pmap
.lookup(origv
)) {
1659 // We found a wrapper. Remember and root it.
1660 toTransplant
.infallibleAppend(wp
->value
);
1664 for (Value
*begin
= toTransplant
.begin(), *end
= toTransplant
.end(); begin
!= end
; ++begin
) {
1665 JSObject
*wobj
= &begin
->toObject();
1666 JSCompartment
*wcompartment
= wobj
->compartment();
1667 WrapperMap
&pmap
= wcompartment
->crossCompartmentWrappers
;
1668 JS_ASSERT(pmap
.lookup(origv
));
1671 // First, we wrap it in the new compartment. This will return a
1673 AutoCompartment
ac(cx
, wobj
);
1675 JSObject
*tobj
= targetobj
;
1676 if (!ac
.enter() || !wcompartment
->wrap(cx
, &tobj
))
1679 // Now, because we need to maintain object identity, we do a brain
1680 // transplant on the old object. At the same time, we update the
1681 // entry in the compartment's wrapper map to point to the old
1683 JS_ASSERT(tobj
!= wobj
);
1684 if (!wobj
->swap(cx
, tobj
))
1686 pmap
.put(targetv
, ObjectValue(*wobj
));
1689 // Lastly, update the original object to point to the new one. However, as
1690 // mentioned above, we do the transplant on the wrapper, not the object
1691 // itself, since all of the references are to the object itself.
1693 AutoCompartment
ac(cx
, origobj
);
1694 JSObject
*tobj
= obj
;
1695 if (!ac
.enter() || !JS_WrapObject(cx
, &tobj
))
1697 if (!origwrapper
->swap(cx
, tobj
))
1699 origwrapper
->compartment()->crossCompartmentWrappers
.put(targetv
,
1700 ObjectValue(*origwrapper
));
1706 JS_PUBLIC_API(JSObject
*)
1707 JS_GetGlobalObject(JSContext
*cx
)
1709 return cx
->globalObject
;
1713 JS_SetGlobalObject(JSContext
*cx
, JSObject
*obj
)
1718 cx
->globalObject
= obj
;
1720 cx
->resetCompartment();
1723 JS_PUBLIC_API(JSBool
)
1724 JS_InitStandardClasses(JSContext
*cx
, JSObject
*obj
)
1726 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
1731 * JS_SetGlobalObject might or might not change cx's compartment, so call
1732 * it before assertSameCompartment. (The API contract is that *after* this,
1733 * cx and obj must be in the same compartment.)
1735 if (!cx
->globalObject
)
1736 JS_SetGlobalObject(cx
, obj
);
1738 assertSameCompartment(cx
, obj
);
1740 return GlobalObject::initStandardClasses(cx
, RootedVar
<GlobalObject
*>(cx
, &obj
->global()));
1743 #define CLASP(name) (&name##Class)
1744 #define TYPED_ARRAY_CLASP(type) (&TypedArray::classes[TypedArray::type])
1745 #define EAGER_ATOM(name) NAME_OFFSET(name)
1746 #define EAGER_CLASS_ATOM(name) CLASS_NAME_OFFSET(name)
1747 #define EAGER_ATOM_AND_CLASP(name) EAGER_CLASS_ATOM(name), CLASP(name)
1749 typedef struct JSStdName
{
1751 size_t atomOffset
; /* offset of atom pointer in JSAtomState */
1755 static PropertyName
*
1756 StdNameToPropertyName(JSContext
*cx
, JSStdName
*stdn
)
1758 return OFFSET_TO_NAME(cx
->runtime
, stdn
->atomOffset
);
1762 * Table of class initializers and their atom offsets in rt->atomState.
1763 * If you add a "standard" class, remember to update this table.
1765 static JSStdName standard_class_atoms
[] = {
1766 {js_InitFunctionClass
, EAGER_ATOM_AND_CLASP(Function
)},
1767 {js_InitObjectClass
, EAGER_ATOM_AND_CLASP(Object
)},
1768 {js_InitArrayClass
, EAGER_ATOM_AND_CLASP(Array
)},
1769 {js_InitBooleanClass
, EAGER_ATOM_AND_CLASP(Boolean
)},
1770 {js_InitDateClass
, EAGER_ATOM_AND_CLASP(Date
)},
1771 {js_InitMathClass
, EAGER_ATOM_AND_CLASP(Math
)},
1772 {js_InitNumberClass
, EAGER_ATOM_AND_CLASP(Number
)},
1773 {js_InitStringClass
, EAGER_ATOM_AND_CLASP(String
)},
1774 {js_InitExceptionClasses
, EAGER_ATOM_AND_CLASP(Error
)},
1775 {js_InitRegExpClass
, EAGER_ATOM_AND_CLASP(RegExp
)},
1776 #if JS_HAS_XML_SUPPORT
1777 {js_InitXMLClass
, EAGER_ATOM_AND_CLASP(XML
)},
1778 {js_InitNamespaceClass
, EAGER_ATOM_AND_CLASP(Namespace
)},
1779 {js_InitQNameClass
, EAGER_ATOM_AND_CLASP(QName
)},
1781 #if JS_HAS_GENERATORS
1782 {js_InitIteratorClasses
, EAGER_ATOM_AND_CLASP(StopIteration
)},
1784 {js_InitJSONClass
, EAGER_ATOM_AND_CLASP(JSON
)},
1785 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(ArrayBuffer
), &js::ArrayBufferObject::protoClass
},
1786 {js_InitWeakMapClass
, EAGER_CLASS_ATOM(WeakMap
), &js::WeakMapClass
},
1787 {js_InitMapClass
, EAGER_CLASS_ATOM(Map
), &js::MapObject::class_
},
1788 {js_InitSetClass
, EAGER_CLASS_ATOM(Set
), &js::SetObject::class_
},
1793 * Table of top-level function and constant names and their init functions.
1794 * If you add a "standard" global function or property, remember to update
1797 static JSStdName standard_class_names
[] = {
1798 {js_InitObjectClass
, EAGER_ATOM(eval
), CLASP(Object
)},
1800 /* Global properties and functions defined by the Number class. */
1801 {js_InitNumberClass
, EAGER_ATOM(NaN
), CLASP(Number
)},
1802 {js_InitNumberClass
, EAGER_ATOM(Infinity
), CLASP(Number
)},
1803 {js_InitNumberClass
, EAGER_ATOM(isNaN
), CLASP(Number
)},
1804 {js_InitNumberClass
, EAGER_ATOM(isFinite
), CLASP(Number
)},
1805 {js_InitNumberClass
, EAGER_ATOM(parseFloat
), CLASP(Number
)},
1806 {js_InitNumberClass
, EAGER_ATOM(parseInt
), CLASP(Number
)},
1808 /* String global functions. */
1809 {js_InitStringClass
, EAGER_ATOM(escape
), CLASP(String
)},
1810 {js_InitStringClass
, EAGER_ATOM(unescape
), CLASP(String
)},
1811 {js_InitStringClass
, EAGER_ATOM(decodeURI
), CLASP(String
)},
1812 {js_InitStringClass
, EAGER_ATOM(encodeURI
), CLASP(String
)},
1813 {js_InitStringClass
, EAGER_ATOM(decodeURIComponent
), CLASP(String
)},
1814 {js_InitStringClass
, EAGER_ATOM(encodeURIComponent
), CLASP(String
)},
1816 {js_InitStringClass
, EAGER_ATOM(uneval
), CLASP(String
)},
1819 /* Exception constructors. */
1820 {js_InitExceptionClasses
, EAGER_CLASS_ATOM(Error
), CLASP(Error
)},
1821 {js_InitExceptionClasses
, EAGER_CLASS_ATOM(InternalError
), CLASP(Error
)},
1822 {js_InitExceptionClasses
, EAGER_CLASS_ATOM(EvalError
), CLASP(Error
)},
1823 {js_InitExceptionClasses
, EAGER_CLASS_ATOM(RangeError
), CLASP(Error
)},
1824 {js_InitExceptionClasses
, EAGER_CLASS_ATOM(ReferenceError
), CLASP(Error
)},
1825 {js_InitExceptionClasses
, EAGER_CLASS_ATOM(SyntaxError
), CLASP(Error
)},
1826 {js_InitExceptionClasses
, EAGER_CLASS_ATOM(TypeError
), CLASP(Error
)},
1827 {js_InitExceptionClasses
, EAGER_CLASS_ATOM(URIError
), CLASP(Error
)},
1829 #if JS_HAS_XML_SUPPORT
1830 {js_InitXMLClass
, EAGER_ATOM(XMLList
), CLASP(XML
)},
1831 {js_InitXMLClass
, EAGER_ATOM(isXMLName
), CLASP(XML
)},
1834 #if JS_HAS_GENERATORS
1835 {js_InitIteratorClasses
, EAGER_ATOM_AND_CLASP(Iterator
)},
1839 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(ArrayBuffer
), &ArrayBufferClass
},
1840 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(Int8Array
), TYPED_ARRAY_CLASP(TYPE_INT8
)},
1841 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(Uint8Array
), TYPED_ARRAY_CLASP(TYPE_UINT8
)},
1842 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(Int16Array
), TYPED_ARRAY_CLASP(TYPE_INT16
)},
1843 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(Uint16Array
), TYPED_ARRAY_CLASP(TYPE_UINT16
)},
1844 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(Int32Array
), TYPED_ARRAY_CLASP(TYPE_INT32
)},
1845 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(Uint32Array
), TYPED_ARRAY_CLASP(TYPE_UINT32
)},
1846 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(Float32Array
), TYPED_ARRAY_CLASP(TYPE_FLOAT32
)},
1847 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(Float64Array
), TYPED_ARRAY_CLASP(TYPE_FLOAT64
)},
1848 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(Uint8ClampedArray
),
1849 TYPED_ARRAY_CLASP(TYPE_UINT8_CLAMPED
)},
1850 {js_InitTypedArrayClasses
, EAGER_CLASS_ATOM(DataView
), &DataViewClass
},
1852 {js_InitWeakMapClass
, EAGER_ATOM_AND_CLASP(WeakMap
)},
1853 {js_InitProxyClass
, EAGER_ATOM_AND_CLASP(Proxy
)},
1858 static JSStdName object_prototype_names
[] = {
1859 /* Object.prototype properties (global delegates to Object.prototype). */
1860 {js_InitObjectClass
, EAGER_ATOM(proto
), CLASP(Object
)},
1862 {js_InitObjectClass
, EAGER_ATOM(toSource
), CLASP(Object
)},
1864 {js_InitObjectClass
, EAGER_ATOM(toString
), CLASP(Object
)},
1865 {js_InitObjectClass
, EAGER_ATOM(toLocaleString
), CLASP(Object
)},
1866 {js_InitObjectClass
, EAGER_ATOM(valueOf
), CLASP(Object
)},
1867 #if JS_HAS_OBJ_WATCHPOINT
1868 {js_InitObjectClass
, EAGER_ATOM(watch
), CLASP(Object
)},
1869 {js_InitObjectClass
, EAGER_ATOM(unwatch
), CLASP(Object
)},
1871 {js_InitObjectClass
, EAGER_ATOM(hasOwnProperty
), CLASP(Object
)},
1872 {js_InitObjectClass
, EAGER_ATOM(isPrototypeOf
), CLASP(Object
)},
1873 {js_InitObjectClass
, EAGER_ATOM(propertyIsEnumerable
), CLASP(Object
)},
1874 #if OLD_GETTER_SETTER_METHODS
1875 {js_InitObjectClass
, EAGER_ATOM(defineGetter
), CLASP(Object
)},
1876 {js_InitObjectClass
, EAGER_ATOM(defineSetter
), CLASP(Object
)},
1877 {js_InitObjectClass
, EAGER_ATOM(lookupGetter
), CLASP(Object
)},
1878 {js_InitObjectClass
, EAGER_ATOM(lookupSetter
), CLASP(Object
)},
1884 JS_PUBLIC_API(JSBool
)
1885 JS_ResolveStandardClass(JSContext
*cx
, JSObject
*obj
, jsid id
, JSBool
*resolved
)
1893 RootObject
objRoot(cx
, &obj
);
1897 assertSameCompartment(cx
, obj
, id
);
1898 *resolved
= JS_FALSE
;
1901 if (!rt
->hasContexts() || !JSID_IS_ATOM(id
))
1904 idstr
= JSID_TO_STRING(id
);
1906 /* Check whether we're resolving 'undefined', and define it if so. */
1907 atom
= rt
->atomState
.typeAtoms
[JSTYPE_VOID
];
1908 if (idstr
== atom
) {
1909 *resolved
= JS_TRUE
;
1910 return obj
->defineProperty(cx
, atom
->asPropertyName(), UndefinedValue(),
1911 JS_PropertyStub
, JS_StrictPropertyStub
,
1912 JSPROP_PERMANENT
| JSPROP_READONLY
);
1915 /* Try for class constructors/prototypes named by well-known atoms. */
1917 for (i
= 0; standard_class_atoms
[i
].init
; i
++) {
1918 JS_ASSERT(standard_class_atoms
[i
].clasp
);
1919 atom
= OFFSET_TO_NAME(rt
, standard_class_atoms
[i
].atomOffset
);
1920 if (idstr
== atom
) {
1921 stdnm
= &standard_class_atoms
[i
];
1927 /* Try less frequently used top-level functions and constants. */
1928 for (i
= 0; standard_class_names
[i
].init
; i
++) {
1929 JS_ASSERT(standard_class_names
[i
].clasp
);
1930 atom
= StdNameToPropertyName(cx
, &standard_class_names
[i
]);
1933 if (idstr
== atom
) {
1934 stdnm
= &standard_class_names
[i
];
1939 if (!stdnm
&& !obj
->getProto()) {
1941 * Try even less frequently used names delegated from the global
1942 * object to Object.prototype, but only if the Object class hasn't
1943 * yet been initialized.
1945 for (i
= 0; object_prototype_names
[i
].init
; i
++) {
1946 JS_ASSERT(object_prototype_names
[i
].clasp
);
1947 atom
= StdNameToPropertyName(cx
, &object_prototype_names
[i
]);
1950 if (idstr
== atom
) {
1951 stdnm
= &object_prototype_names
[i
];
1960 * If this standard class is anonymous, then we don't want to resolve
1963 JS_ASSERT(obj
->isGlobal());
1964 if (stdnm
->clasp
->flags
& JSCLASS_IS_ANONYMOUS
)
1967 if (IsStandardClassResolved(obj
, stdnm
->clasp
))
1970 if (!stdnm
->init(cx
, obj
))
1972 *resolved
= JS_TRUE
;
1977 JS_PUBLIC_API(JSBool
)
1978 JS_EnumerateStandardClasses(JSContext
*cx
, JSObject
*obj_
)
1985 assertSameCompartment(cx
, obj_
);
1988 RootedVarObject
obj(cx
, obj_
);
1991 * Check whether we need to bind 'undefined' and define it if so.
1992 * Since ES5 15.1.1.3 undefined can't be deleted.
1994 PropertyName
*name
= rt
->atomState
.typeAtoms
[JSTYPE_VOID
];
1995 if (!obj
->nativeContains(cx
, NameToId(name
)) &&
1996 !obj
->defineProperty(cx
, name
, UndefinedValue(),
1997 JS_PropertyStub
, JS_StrictPropertyStub
,
1998 JSPROP_PERMANENT
| JSPROP_READONLY
)) {
2002 /* Initialize any classes that have not been initialized yet. */
2003 for (i
= 0; standard_class_atoms
[i
].init
; i
++) {
2004 if (!js::IsStandardClassResolved(obj
, standard_class_atoms
[i
].clasp
) &&
2005 !standard_class_atoms
[i
].init(cx
, obj
))
2015 NewIdArray(JSContext
*cx
, int length
)
2020 cx
->calloc_(offsetof(JSIdArray
, vector
) + length
* sizeof(jsval
));
2022 ida
->length
= length
;
2027 * Unlike realloc(3), this function frees ida on failure.
2030 SetIdArrayLength(JSContext
*cx
, JSIdArray
*ida
, int length
)
2034 rida
= (JSIdArray
*)
2036 offsetof(JSIdArray
, vector
) + length
* sizeof(jsval
));
2038 JS_DestroyIdArray(cx
, ida
);
2040 rida
->length
= length
;
2046 AddNameToArray(JSContext
*cx
, PropertyName
*name
, JSIdArray
*ida
, int *ip
)
2049 int length
= ida
->length
;
2051 ida
= SetIdArrayLength(cx
, ida
, JS_MAX(length
* 2, 8));
2054 JS_ASSERT(i
< ida
->length
);
2056 ida
->vector
[i
].init(NameToId(name
));
2062 EnumerateIfResolved(JSContext
*cx
, JSObject
*obj
, PropertyName
*name
, JSIdArray
*ida
,
2063 int *ip
, JSBool
*foundp
)
2065 *foundp
= obj
->nativeContains(cx
, NameToId(name
));
2067 ida
= AddNameToArray(cx
, name
, ida
, ip
);
2071 JS_PUBLIC_API(JSIdArray
*)
2072 JS_EnumerateResolvedStandardClasses(JSContext
*cx
, JSObject
*obj
, JSIdArray
*ida
)
2082 assertSameCompartment(cx
, obj
, ida
);
2087 ida
= NewIdArray(cx
, 8);
2093 /* Check whether 'undefined' has been resolved and enumerate it if so. */
2094 name
= rt
->atomState
.typeAtoms
[JSTYPE_VOID
];
2095 ida
= EnumerateIfResolved(cx
, obj
, name
, ida
, &i
, &found
);
2099 /* Enumerate only classes that *have* been resolved. */
2100 for (j
= 0; standard_class_atoms
[j
].init
; j
++) {
2101 name
= OFFSET_TO_NAME(rt
, standard_class_atoms
[j
].atomOffset
);
2102 ida
= EnumerateIfResolved(cx
, obj
, name
, ida
, &i
, &found
);
2107 init
= standard_class_atoms
[j
].init
;
2109 for (k
= 0; standard_class_names
[k
].init
; k
++) {
2110 if (standard_class_names
[k
].init
== init
) {
2111 name
= StdNameToPropertyName(cx
, &standard_class_names
[k
]);
2112 ida
= AddNameToArray(cx
, name
, ida
, &i
);
2118 if (init
== js_InitObjectClass
) {
2119 for (k
= 0; object_prototype_names
[k
].init
; k
++) {
2120 name
= StdNameToPropertyName(cx
, &object_prototype_names
[k
]);
2121 ida
= AddNameToArray(cx
, name
, ida
, &i
);
2129 /* Trim to exact length. */
2130 return SetIdArrayLength(cx
, ida
, i
);
2135 #undef EAGER_CLASS_ATOM
2136 #undef EAGER_ATOM_CLASP
2138 JS_PUBLIC_API(JSBool
)
2139 JS_GetClassObject(JSContext
*cx
, JSObject
*obj
, JSProtoKey key
, JSObject
**objp
)
2143 assertSameCompartment(cx
, obj
);
2144 return js_GetClassObject(cx
, obj
, key
, objp
);
2147 JS_PUBLIC_API(JSObject
*)
2148 JS_GetObjectPrototype(JSContext
*cx
, JSObject
*forObj
)
2151 assertSameCompartment(cx
, forObj
);
2152 return forObj
->global().getOrCreateObjectPrototype(cx
);
2155 JS_PUBLIC_API(JSObject
*)
2156 JS_GetFunctionPrototype(JSContext
*cx
, JSObject
*forObj
)
2159 assertSameCompartment(cx
, forObj
);
2160 return forObj
->global().getOrCreateFunctionPrototype(cx
);
2163 JS_PUBLIC_API(JSObject
*)
2164 JS_GetGlobalForObject(JSContext
*cx
, JSObject
*obj
)
2167 assertSameCompartment(cx
, obj
);
2168 return &obj
->global();
2171 JS_PUBLIC_API(JSObject
*)
2172 JS_GetGlobalForScopeChain(JSContext
*cx
)
2176 return GetGlobalForScopeChain(cx
);
2179 JS_PUBLIC_API(jsval
)
2180 JS_ComputeThis(JSContext
*cx
, jsval
*vp
)
2183 assertSameCompartment(cx
, JSValueArray(vp
, 2));
2184 CallReceiver call
= CallReceiverFromVp(vp
);
2185 if (!BoxNonStrictThis(cx
, call
))
2187 return call
.thisv();
2191 JS_MallocInCompartment(JSCompartment
*comp
, size_t nbytes
)
2193 comp
->mallocInCompartment(nbytes
);
2197 JS_FreeInCompartment(JSCompartment
*comp
, size_t nbytes
)
2199 comp
->freeInCompartment(nbytes
);
2202 JS_PUBLIC_API(void *)
2203 JS_malloc(JSContext
*cx
, size_t nbytes
)
2207 return cx
->malloc_(nbytes
);
2210 JS_PUBLIC_API(void *)
2211 JS_realloc(JSContext
*cx
, void *p
, size_t nbytes
)
2215 return cx
->realloc_(p
, nbytes
);
2219 JS_free(JSContext
*cx
, void *p
)
2221 return cx
->free_(p
);
2225 JS_freeop(JSFreeOp
*fop
, void *p
)
2227 return FreeOp::get(fop
)->free_(p
);
2230 JS_PUBLIC_API(JSFreeOp
*)
2231 JS_GetDefaultFreeOp(JSRuntime
*rt
)
2233 return rt
->defaultFreeOp();
2237 JS_updateMallocCounter(JSContext
*cx
, size_t nbytes
)
2239 return cx
->runtime
->updateMallocCounter(cx
, nbytes
);
2242 JS_PUBLIC_API(char *)
2243 JS_strdup(JSContext
*cx
, const char *s
)
2246 size_t n
= strlen(s
) + 1;
2247 void *p
= cx
->malloc_(n
);
2250 return (char *)js_memcpy(p
, s
, n
);
2253 JS_PUBLIC_API(JSBool
)
2254 JS_NewNumberValue(JSContext
*cx
, double d
, jsval
*rval
)
2257 d
= JS_CANONICALIZE_NAN(d
);
2264 JS_PUBLIC_API(JSBool
)
2265 JS_AddValueRoot(JSContext
*cx
, jsval
*vp
)
2269 return js_AddRoot(cx
, vp
, NULL
);
2272 JS_PUBLIC_API(JSBool
)
2273 JS_AddStringRoot(JSContext
*cx
, JSString
**rp
)
2277 return js_AddGCThingRoot(cx
, (void **)rp
, NULL
);
2280 JS_PUBLIC_API(JSBool
)
2281 JS_AddObjectRoot(JSContext
*cx
, JSObject
**rp
)
2285 return js_AddGCThingRoot(cx
, (void **)rp
, NULL
);
2288 JS_PUBLIC_API(JSBool
)
2289 JS_AddGCThingRoot(JSContext
*cx
, void **rp
)
2293 return js_AddGCThingRoot(cx
, (void **)rp
, NULL
);
2296 JS_PUBLIC_API(JSBool
)
2297 JS_AddNamedValueRoot(JSContext
*cx
, jsval
*vp
, const char *name
)
2301 return js_AddRoot(cx
, vp
, name
);
2304 JS_PUBLIC_API(JSBool
)
2305 JS_AddNamedStringRoot(JSContext
*cx
, JSString
**rp
, const char *name
)
2309 return js_AddGCThingRoot(cx
, (void **)rp
, name
);
2312 JS_PUBLIC_API(JSBool
)
2313 JS_AddNamedObjectRoot(JSContext
*cx
, JSObject
**rp
, const char *name
)
2317 return js_AddGCThingRoot(cx
, (void **)rp
, name
);
2320 JS_PUBLIC_API(JSBool
)
2321 JS_AddNamedScriptRoot(JSContext
*cx
, JSScript
**rp
, const char *name
)
2325 return js_AddGCThingRoot(cx
, (void **)rp
, name
);
2328 JS_PUBLIC_API(JSBool
)
2329 JS_AddNamedGCThingRoot(JSContext
*cx
, void **rp
, const char *name
)
2333 return js_AddGCThingRoot(cx
, (void **)rp
, name
);
2336 /* We allow unrooting from finalizers within the GC */
2339 JS_RemoveValueRoot(JSContext
*cx
, jsval
*vp
)
2342 js_RemoveRoot(cx
->runtime
, (void *)vp
);
2346 JS_RemoveStringRoot(JSContext
*cx
, JSString
**rp
)
2349 js_RemoveRoot(cx
->runtime
, (void *)rp
);
2353 JS_RemoveObjectRoot(JSContext
*cx
, JSObject
**rp
)
2356 js_RemoveRoot(cx
->runtime
, (void *)rp
);
2360 JS_RemoveScriptRoot(JSContext
*cx
, JSScript
**rp
)
2363 js_RemoveRoot(cx
->runtime
, (void *)rp
);
2367 JS_RemoveGCThingRoot(JSContext
*cx
, void **rp
)
2370 js_RemoveRoot(cx
->runtime
, (void *)rp
);
2374 JS_RemoveValueRootRT(JSRuntime
*rt
, jsval
*vp
)
2376 js_RemoveRoot(rt
, (void *)vp
);
2380 JS_RemoveStringRootRT(JSRuntime
*rt
, JSString
**rp
)
2382 js_RemoveRoot(rt
, (void *)rp
);
2386 JS_RemoveObjectRootRT(JSRuntime
*rt
, JSObject
**rp
)
2388 js_RemoveRoot(rt
, (void *)rp
);
2392 JS_RemoveScriptRoot(JSRuntime
*rt
, JSScript
**rp
)
2394 js_RemoveRoot(rt
, (void *)rp
);
2397 JS_NEVER_INLINE
JS_PUBLIC_API(void)
2398 JS_AnchorPtr(void *p
)
2405 JS_DumpNamedRoots(JSRuntime
*rt
,
2406 void (*dump
)(const char *name
, void *rp
, JSGCRootType type
, void *data
),
2409 js_DumpNamedRoots(rt
, dump
, data
);
2414 JS_PUBLIC_API(uint32_t)
2415 JS_MapGCRoots(JSRuntime
*rt
, JSGCRootMapFun map
, void *data
)
2417 return js_MapGCRoots(rt
, map
, data
);
2420 JS_PUBLIC_API(JSBool
)
2421 JS_LockGCThing(JSContext
*cx
, void *thing
)
2427 ok
= js_LockGCThingRT(cx
->runtime
, thing
);
2429 JS_ReportOutOfMemory(cx
);
2433 JS_PUBLIC_API(JSBool
)
2434 JS_LockGCThingRT(JSRuntime
*rt
, void *thing
)
2436 return js_LockGCThingRT(rt
, thing
);
2439 JS_PUBLIC_API(JSBool
)
2440 JS_UnlockGCThing(JSContext
*cx
, void *thing
)
2444 js_UnlockGCThingRT(cx
->runtime
, thing
);
2448 JS_PUBLIC_API(JSBool
)
2449 JS_UnlockGCThingRT(JSRuntime
*rt
, void *thing
)
2451 js_UnlockGCThingRT(rt
, thing
);
2456 JS_SetExtraGCRootsTracer(JSRuntime
*rt
, JSTraceDataOp traceOp
, void *data
)
2459 rt
->gcBlackRootsTraceOp
= traceOp
;
2460 rt
->gcBlackRootsData
= data
;
2464 JS_TracerInit(JSTracer
*trc
, JSRuntime
*rt
, JSTraceCallback callback
)
2466 InitTracer(trc
, rt
, callback
);
2470 JS_TraceRuntime(JSTracer
*trc
)
2472 AssertNoGC(trc
->runtime
);
2477 JS_TraceChildren(JSTracer
*trc
, void *thing
, JSGCTraceKind kind
)
2479 js::TraceChildren(trc
, thing
, kind
);
2483 JS_CallTracer(JSTracer
*trc
, void *thing
, JSGCTraceKind kind
)
2485 js::CallTracer(trc
, thing
, kind
);
2491 JS_PrintTraceThingInfo(char *buf
, size_t bufsize
, JSTracer
*trc
, void *thing
,
2492 JSGCTraceKind kind
, JSBool details
)
2494 const char *name
= NULL
; /* silence uninitialized warning */
2501 case JSTRACE_OBJECT
:
2503 name
= static_cast<JSObject
*>(thing
)->getClass()->name
;
2507 case JSTRACE_STRING
:
2508 name
= ((JSString
*)thing
)->isDependent()
2513 case JSTRACE_SCRIPT
:
2521 case JSTRACE_BASE_SHAPE
:
2522 name
= "base_shape";
2525 case JSTRACE_TYPE_OBJECT
:
2526 name
= "type_object";
2529 #if JS_HAS_XML_SUPPORT
2537 if (n
> bufsize
- 1)
2539 js_memcpy(buf
, name
, n
+ 1);
2544 if (details
&& bufsize
> 2) {
2546 case JSTRACE_OBJECT
:
2548 JSObject
*obj
= (JSObject
*)thing
;
2549 Class
*clasp
= obj
->getClass();
2550 if (clasp
== &FunctionClass
) {
2551 JSFunction
*fun
= obj
->toFunction();
2553 JS_snprintf(buf
, bufsize
, " <newborn>");
2554 } else if (fun
!= obj
) {
2555 JS_snprintf(buf
, bufsize
, " %p", fun
);
2560 PutEscapedString(buf
, bufsize
, fun
->atom
, 0);
2563 } else if (clasp
->flags
& JSCLASS_HAS_PRIVATE
) {
2564 JS_snprintf(buf
, bufsize
, " %p", obj
->getPrivate());
2566 JS_snprintf(buf
, bufsize
, " <no private>");
2571 case JSTRACE_STRING
:
2575 JSString
*str
= (JSString
*)thing
;
2576 if (str
->isLinear())
2577 PutEscapedString(buf
, bufsize
, &str
->asLinear(), 0);
2579 JS_snprintf(buf
, bufsize
, "<rope: length %d>", (int)str
->length());
2583 case JSTRACE_SCRIPT
:
2585 JSScript
*script
= static_cast<JSScript
*>(thing
);
2586 JS_snprintf(buf
, bufsize
, " %s:%u", script
->filename
, unsigned(script
->lineno
));
2591 case JSTRACE_BASE_SHAPE
:
2592 case JSTRACE_TYPE_OBJECT
:
2595 #if JS_HAS_XML_SUPPORT
2598 extern const char *js_xml_class_str
[];
2599 JSXML
*xml
= (JSXML
*)thing
;
2601 JS_snprintf(buf
, bufsize
, " %s", js_xml_class_str
[xml
->xml_class
]);
2607 buf
[bufsize
- 1] = '\0';
2610 extern JS_PUBLIC_API(const char *)
2611 JS_GetTraceEdgeName(JSTracer
*trc
, char *buffer
, int bufferSize
)
2613 if (trc
->debugPrinter
) {
2614 trc
->debugPrinter(trc
, buffer
, bufferSize
);
2617 if (trc
->debugPrintIndex
!= (size_t) - 1) {
2618 JS_snprintf(buffer
, bufferSize
, "%s[%lu]",
2619 (const char *)trc
->debugPrintArg
,
2620 trc
->debugPrintIndex
);
2623 return (const char*)trc
->debugPrintArg
;
2626 typedef struct JSHeapDumpNode JSHeapDumpNode
;
2628 struct JSHeapDumpNode
{
2631 JSHeapDumpNode
*next
; /* next sibling */
2632 JSHeapDumpNode
*parent
; /* node with the thing that refer to thing
2634 char edgeName
[1]; /* name of the edge from parent->thing
2638 typedef HashSet
<void *, PointerHasher
<void *, 3>, SystemAllocPolicy
> VisitedSet
;
2640 typedef struct JSDumpingTracer
{
2646 void *thingToIgnore
;
2647 JSHeapDumpNode
*parentNode
;
2648 JSHeapDumpNode
**lastNodep
;
2653 DumpNotify(JSTracer
*trc
, void **thingp
, JSGCTraceKind kind
)
2655 JS_ASSERT(trc
->callback
== DumpNotify
);
2657 JSDumpingTracer
*dtrc
= (JSDumpingTracer
*)trc
;
2658 void *thing
= *thingp
;
2660 if (!dtrc
->ok
|| thing
== dtrc
->thingToIgnore
)
2664 * Check if we have already seen thing unless it is thingToFind to include
2665 * it to the graph each time we reach it and print all live things that
2666 * refer to thingToFind.
2668 * This does not print all possible paths leading to thingToFind since
2669 * when a thing A refers directly or indirectly to thingToFind and A is
2670 * present several times in the graph, we will print only the first path
2671 * leading to A and thingToFind, other ways to reach A will be ignored.
2673 if (dtrc
->thingToFind
!= thing
) {
2675 * The startThing check allows to avoid putting startThing into the
2676 * hash table before tracing startThing in JS_DumpHeap.
2678 if (thing
== dtrc
->startThing
)
2680 VisitedSet::AddPtr p
= dtrc
->visited
.lookupForAdd(thing
);
2683 if (!dtrc
->visited
.add(p
, thing
)) {
2689 const char *edgeName
= JS_GetTraceEdgeName(&dtrc
->base
, dtrc
->buffer
, sizeof(dtrc
->buffer
));
2690 size_t edgeNameSize
= strlen(edgeName
) + 1;
2691 size_t bytes
= offsetof(JSHeapDumpNode
, edgeName
) + edgeNameSize
;
2692 JSHeapDumpNode
*node
= (JSHeapDumpNode
*) OffTheBooks::malloc_(bytes
);
2698 node
->thing
= thing
;
2701 node
->parent
= dtrc
->parentNode
;
2702 js_memcpy(node
->edgeName
, edgeName
, edgeNameSize
);
2704 JS_ASSERT(!*dtrc
->lastNodep
);
2705 *dtrc
->lastNodep
= node
;
2706 dtrc
->lastNodep
= &node
->next
;
2709 /* Dump node and the chain that leads to thing it contains. */
2711 DumpNode(JSDumpingTracer
*dtrc
, FILE* fp
, JSHeapDumpNode
*node
)
2713 JSHeapDumpNode
*prev
, *following
;
2715 enum { MAX_PARENTS_TO_PRINT
= 10 };
2717 JS_PrintTraceThingInfo(dtrc
->buffer
, sizeof dtrc
->buffer
,
2718 &dtrc
->base
, node
->thing
, node
->kind
, JS_TRUE
);
2719 if (fprintf(fp
, "%p %-22s via ", node
->thing
, dtrc
->buffer
) < 0)
2723 * We need to print the parent chain in the reverse order. To do it in
2724 * O(N) time where N is the chain length we first reverse the chain while
2725 * searching for the top and then print each node while restoring the
2728 chainLimit
= MAX_PARENTS_TO_PRINT
;
2731 following
= node
->parent
;
2732 node
->parent
= prev
;
2737 if (chainLimit
== 0) {
2738 if (fputs("...", fp
) < 0)
2749 /* Loop must continue even when !ok to restore the parent chain. */
2752 /* Print edge from some runtime root or startThing. */
2753 if (fputs(node
->edgeName
, fp
) < 0)
2756 JS_PrintTraceThingInfo(dtrc
->buffer
, sizeof dtrc
->buffer
,
2757 &dtrc
->base
, prev
->thing
, prev
->kind
,
2759 if (fprintf(fp
, "(%p %s).%s",
2760 prev
->thing
, dtrc
->buffer
, node
->edgeName
) < 0) {
2765 following
= node
->parent
;
2766 node
->parent
= prev
;
2771 return ok
&& putc('\n', fp
) >= 0;
2774 JS_PUBLIC_API(JSBool
)
2775 JS_DumpHeap(JSRuntime
*rt
, FILE *fp
, void* startThing
, JSGCTraceKind startKind
,
2776 void *thingToFind
, size_t maxDepth
, void *thingToIgnore
)
2781 JSDumpingTracer dtrc
;
2782 if (!dtrc
.visited
.init())
2784 JS_TracerInit(&dtrc
.base
, rt
, DumpNotify
);
2786 dtrc
.startThing
= startThing
;
2787 dtrc
.thingToFind
= thingToFind
;
2788 dtrc
.thingToIgnore
= thingToIgnore
;
2789 dtrc
.parentNode
= NULL
;
2790 JSHeapDumpNode
*node
= NULL
;
2791 dtrc
.lastNodep
= &node
;
2793 JS_ASSERT(startKind
== JSTRACE_OBJECT
);
2794 TraceRuntime(&dtrc
.base
);
2796 JS_TraceChildren(&dtrc
.base
, startThing
, startKind
);
2803 JSHeapDumpNode
*children
, *next
, *parent
;
2804 bool thingToFindWasTraced
= thingToFind
&& thingToFind
== startThing
;
2807 * Loop must continue even when !dtrc.ok to free all nodes allocated
2811 if (thingToFind
== NULL
|| thingToFind
== node
->thing
)
2812 dtrc
.ok
= DumpNode(&dtrc
, fp
, node
);
2814 /* Descend into children. */
2817 (thingToFind
!= node
->thing
|| !thingToFindWasTraced
)) {
2818 dtrc
.parentNode
= node
;
2820 dtrc
.lastNodep
= &children
;
2821 JS_TraceChildren(&dtrc
.base
, node
->thing
, node
->kind
);
2822 if (thingToFind
== node
->thing
)
2823 thingToFindWasTraced
= JS_TRUE
;
2824 if (children
!= NULL
) {
2832 /* Move to next or parents next and free the node. */
2835 parent
= node
->parent
;
2836 Foreground::free_(node
);
2842 JS_ASSERT(depth
> 1);
2848 JS_ASSERT(depth
== 1);
2854 extern JS_PUBLIC_API(JSBool
)
2855 JS_IsGCMarkingTracer(JSTracer
*trc
)
2857 return IS_GC_MARKING_TRACER(trc
);
2861 JS_GC(JSRuntime
*rt
)
2864 PrepareForFullGC(rt
);
2865 GC(rt
, GC_NORMAL
, gcreason::API
);
2869 JS_MaybeGC(JSContext
*cx
)
2875 JS_SetGCCallback(JSRuntime
*rt
, JSGCCallback cb
)
2878 rt
->gcCallback
= cb
;
2882 JS_SetFinalizeCallback(JSRuntime
*rt
, JSFinalizeCallback cb
)
2885 rt
->gcFinalizeCallback
= cb
;
2888 JS_PUBLIC_API(JSBool
)
2889 JS_IsAboutToBeFinalized(void *thing
)
2891 gc::Cell
*t
= static_cast<gc::Cell
*>(thing
);
2892 return IsAboutToBeFinalized(t
);
2896 JS_SetGCParameter(JSRuntime
*rt
, JSGCParamKey key
, uint32_t value
)
2899 case JSGC_MAX_BYTES
: {
2900 JS_ASSERT(value
>= rt
->gcBytes
);
2901 rt
->gcMaxBytes
= value
;
2904 case JSGC_MAX_MALLOC_BYTES
:
2905 rt
->setGCMaxMallocBytes(value
);
2907 case JSGC_SLICE_TIME_BUDGET
:
2908 rt
->gcSliceBudget
= SliceBudget::TimeBudget(value
);
2910 case JSGC_MARK_STACK_LIMIT
:
2911 js::SetMarkStackLimit(rt
, value
);
2914 JS_ASSERT(key
== JSGC_MODE
);
2915 rt
->gcMode
= JSGCMode(value
);
2916 JS_ASSERT(rt
->gcMode
== JSGC_MODE_GLOBAL
||
2917 rt
->gcMode
== JSGC_MODE_COMPARTMENT
||
2918 rt
->gcMode
== JSGC_MODE_INCREMENTAL
);
2923 JS_PUBLIC_API(uint32_t)
2924 JS_GetGCParameter(JSRuntime
*rt
, JSGCParamKey key
)
2927 case JSGC_MAX_BYTES
:
2928 return uint32_t(rt
->gcMaxBytes
);
2929 case JSGC_MAX_MALLOC_BYTES
:
2930 return rt
->gcMaxMallocBytes
;
2932 return uint32_t(rt
->gcBytes
);
2934 return uint32_t(rt
->gcMode
);
2935 case JSGC_UNUSED_CHUNKS
:
2936 return uint32_t(rt
->gcChunkPool
.getEmptyCount());
2937 case JSGC_TOTAL_CHUNKS
:
2938 return uint32_t(rt
->gcChunkSet
.count() + rt
->gcChunkPool
.getEmptyCount());
2939 case JSGC_SLICE_TIME_BUDGET
:
2940 return uint32_t(rt
->gcSliceBudget
> 0 ? rt
->gcSliceBudget
/ PRMJ_USEC_PER_MSEC
: 0);
2941 case JSGC_MARK_STACK_LIMIT
:
2942 return rt
->gcMarker
.sizeLimit();
2944 JS_ASSERT(key
== JSGC_NUMBER
);
2945 return uint32_t(rt
->gcNumber
);
2950 JS_SetGCParameterForThread(JSContext
*cx
, JSGCParamKey key
, uint32_t value
)
2952 JS_ASSERT(key
== JSGC_MAX_CODE_CACHE_BYTES
);
2955 JS_PUBLIC_API(uint32_t)
2956 JS_GetGCParameterForThread(JSContext
*cx
, JSGCParamKey key
)
2958 JS_ASSERT(key
== JSGC_MAX_CODE_CACHE_BYTES
);
2962 JS_PUBLIC_API(JSString
*)
2963 JS_NewExternalString(JSContext
*cx
, const jschar
*chars
, size_t length
,
2964 const JSStringFinalizer
*fin
)
2968 JSString
*s
= JSExternalString::new_(cx
, chars
, length
, fin
);
2969 Probes::createString(cx
, s
, length
);
2973 extern JS_PUBLIC_API(JSBool
)
2974 JS_IsExternalString(JSString
*str
)
2976 return str
->isExternal();
2979 extern JS_PUBLIC_API(const JSStringFinalizer
*)
2980 JS_GetExternalStringFinalizer(JSString
*str
)
2982 return str
->asExternal().externalFinalizer();
2986 JS_SetNativeStackQuota(JSRuntime
*rt
, size_t stackSize
)
2988 rt
->nativeStackQuota
= stackSize
;
2989 if (!rt
->nativeStackBase
)
2992 #if JS_STACK_GROWTH_DIRECTION > 0
2993 if (stackSize
== 0) {
2994 rt
->nativeStackLimit
= UINTPTR_MAX
;
2996 JS_ASSERT(rt
->nativeStackBase
<= size_t(-1) - stackSize
);
2997 rt
->nativeStackLimit
= rt
->nativeStackBase
+ stackSize
- 1;
3000 if (stackSize
== 0) {
3001 rt
->nativeStackLimit
= 0;
3003 JS_ASSERT(rt
->nativeStackBase
>= stackSize
);
3004 rt
->nativeStackLimit
= rt
->nativeStackBase
- (stackSize
- 1);
3009 /************************************************************************/
3012 JS_IdArrayLength(JSContext
*cx
, JSIdArray
*ida
)
3018 JS_IdArrayGet(JSContext
*cx
, JSIdArray
*ida
, int index
)
3020 JS_ASSERT(index
>= 0 && index
< ida
->length
);
3021 return ida
->vector
[index
];
3025 JS_DestroyIdArray(JSContext
*cx
, JSIdArray
*ida
)
3027 DestroyIdArray(cx
->runtime
->defaultFreeOp(), ida
);
3030 JS_PUBLIC_API(JSBool
)
3031 JS_ValueToId(JSContext
*cx
, jsval v
, jsid
*idp
)
3035 assertSameCompartment(cx
, v
);
3036 return ValueToId(cx
, v
, idp
);
3039 JS_PUBLIC_API(JSBool
)
3040 JS_IdToValue(JSContext
*cx
, jsid id
, jsval
*vp
)
3044 *vp
= IdToJsval(id
);
3045 assertSameCompartment(cx
, *vp
);
3049 JS_PUBLIC_API(JSBool
)
3050 JS_DefaultValue(JSContext
*cx
, JSObject
*obj
, JSType hint
, jsval
*vp
)
3054 JS_ASSERT(obj
!= NULL
);
3055 JS_ASSERT(hint
== JSTYPE_VOID
|| hint
== JSTYPE_STRING
|| hint
== JSTYPE_NUMBER
);
3056 return obj
->defaultValue(cx
, hint
, vp
);
3059 JS_PUBLIC_API(JSBool
)
3060 JS_PropertyStub(JSContext
*cx
, JSObject
*obj
, jsid id
, jsval
*vp
)
3065 JS_PUBLIC_API(JSBool
)
3066 JS_StrictPropertyStub(JSContext
*cx
, JSObject
*obj
, jsid id
, JSBool strict
, jsval
*vp
)
3071 JS_PUBLIC_API(JSBool
)
3072 JS_EnumerateStub(JSContext
*cx
, JSObject
*obj
)
3077 JS_PUBLIC_API(JSBool
)
3078 JS_ResolveStub(JSContext
*cx
, JSObject
*obj
, jsid id
)
3083 JS_PUBLIC_API(JSBool
)
3084 JS_ConvertStub(JSContext
*cx
, JSObject
*obj
, JSType type
, jsval
*vp
)
3086 JS_ASSERT(type
!= JSTYPE_OBJECT
&& type
!= JSTYPE_FUNCTION
);
3088 return DefaultValue(cx
, RootedVarObject(cx
, obj
), type
, vp
);
3091 JS_PUBLIC_API(JSObject
*)
3092 JS_InitClass(JSContext
*cx
, JSObject
*obj
, JSObject
*parent_proto
,
3093 JSClass
*clasp
, JSNative constructor
, unsigned nargs
,
3094 JSPropertySpec
*ps
, JSFunctionSpec
*fs
,
3095 JSPropertySpec
*static_ps
, JSFunctionSpec
*static_fs
)
3099 assertSameCompartment(cx
, obj
, parent_proto
);
3100 RootObject
objRoot(cx
, &obj
);
3101 return js_InitClass(cx
, objRoot
, parent_proto
, Valueify(clasp
), constructor
,
3102 nargs
, ps
, fs
, static_ps
, static_fs
);
3105 JS_PUBLIC_API(JSBool
)
3106 JS_LinkConstructorAndPrototype(JSContext
*cx
, JSObject
*ctor
, JSObject
*proto
)
3108 return LinkConstructorAndPrototype(cx
, ctor
, proto
);
3111 JS_PUBLIC_API(JSClass
*)
3112 JS_GetClass(JSObject
*obj
)
3114 return obj
->getJSClass();
3117 JS_PUBLIC_API(JSBool
)
3118 JS_InstanceOf(JSContext
*cx
, JSObject
*obj
, JSClass
*clasp
, jsval
*argv
)
3124 assertSameCompartment(cx
, obj
);
3125 assertSameCompartment(cx
, JSValueArray(argv
- 2, 2));
3128 if (!obj
|| obj
->getJSClass() != clasp
) {
3130 ReportIncompatibleMethod(cx
, CallReceiverFromArgv(argv
), Valueify(clasp
));
3136 JS_PUBLIC_API(JSBool
)
3137 JS_HasInstance(JSContext
*cx
, JSObject
*obj
, jsval v
, JSBool
*bp
)
3140 assertSameCompartment(cx
, obj
, v
);
3141 return HasInstance(cx
, obj
, &v
, bp
);
3144 JS_PUBLIC_API(void *)
3145 JS_GetPrivate(JSObject
*obj
)
3147 /* This function can be called by a finalizer. */
3148 return obj
->getPrivate();
3152 JS_SetPrivate(JSObject
*obj
, void *data
)
3154 /* This function can be called by a finalizer. */
3155 obj
->setPrivate(data
);
3158 JS_PUBLIC_API(void *)
3159 JS_GetInstancePrivate(JSContext
*cx
, JSObject
*obj
, JSClass
*clasp
, jsval
*argv
)
3161 if (!JS_InstanceOf(cx
, obj
, clasp
, argv
))
3163 return obj
->getPrivate();
3166 JS_PUBLIC_API(JSObject
*)
3167 JS_GetPrototype(JSObject
*obj
)
3169 return obj
->getProto();
3172 JS_PUBLIC_API(JSBool
)
3173 JS_SetPrototype(JSContext
*cx
, JSObject
*obj
, JSObject
*proto
)
3177 assertSameCompartment(cx
, obj
, proto
);
3178 return SetProto(cx
, RootedVarObject(cx
, obj
), RootedVarObject(cx
, proto
), JS_FALSE
);
3181 JS_PUBLIC_API(JSObject
*)
3182 JS_GetParent(JSObject
*obj
)
3184 JS_ASSERT(!obj
->isScope());
3185 return obj
->getParent();
3188 JS_PUBLIC_API(JSBool
)
3189 JS_SetParent(JSContext
*cx
, JSObject
*obj
, JSObject
*parent
)
3193 JS_ASSERT(!obj
->isScope());
3194 JS_ASSERT(parent
|| !obj
->getParent());
3195 assertSameCompartment(cx
, obj
, parent
);
3196 return JSObject::setParent(cx
, RootedVarObject(cx
, obj
), RootedVarObject(cx
, parent
));
3199 JS_PUBLIC_API(JSObject
*)
3200 JS_GetConstructor(JSContext
*cx
, JSObject
*proto
)
3206 assertSameCompartment(cx
, proto
);
3208 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
);
3210 if (!proto
->getProperty(cx
, cx
->runtime
->atomState
.constructorAtom
, &cval
))
3213 if (!IsFunctionObject(cval
)) {
3214 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_NO_CONSTRUCTOR
,
3215 proto
->getClass()->name
);
3218 return &cval
.toObject();
3221 JS_PUBLIC_API(JSBool
)
3222 JS_GetObjectId(JSContext
*cx
, JSObject
*obj
, jsid
*idp
)
3225 assertSameCompartment(cx
, obj
);
3226 *idp
= OBJECT_TO_JSID(obj
);
3230 JS_PUBLIC_API(JSObject
*)
3231 JS_NewGlobalObject(JSContext
*cx
, JSClass
*clasp
)
3233 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
3237 return GlobalObject::create(cx
, Valueify(clasp
));
3240 class AutoHoldCompartment
{
3242 explicit AutoHoldCompartment(JSCompartment
*compartment JS_GUARD_OBJECT_NOTIFIER_PARAM
)
3243 : holdp(&compartment
->hold
)
3245 JS_GUARD_OBJECT_NOTIFIER_INIT
;
3249 ~AutoHoldCompartment() {
3254 JS_DECL_USE_GUARD_OBJECT_NOTIFIER
3257 JS_PUBLIC_API(JSObject
*)
3258 JS_NewCompartmentAndGlobalObject(JSContext
*cx
, JSClass
*clasp
, JSPrincipals
*principals
)
3262 JSCompartment
*compartment
= NewCompartment(cx
, principals
);
3266 AutoHoldCompartment
hold(compartment
);
3268 JSCompartment
*saved
= cx
->compartment
;
3269 cx
->setCompartment(compartment
);
3270 JSObject
*obj
= JS_NewGlobalObject(cx
, clasp
);
3271 cx
->setCompartment(saved
);
3276 JS_PUBLIC_API(JSObject
*)
3277 JS_NewObject(JSContext
*cx
, JSClass
*jsclasp
, JSObject
*proto
, JSObject
*parent
)
3279 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
3282 assertSameCompartment(cx
, proto
, parent
);
3284 Class
*clasp
= Valueify(jsclasp
);
3286 clasp
= &ObjectClass
; /* default class is Object */
3288 JS_ASSERT(clasp
!= &FunctionClass
);
3289 JS_ASSERT(!(clasp
->flags
& JSCLASS_IS_GLOBAL
));
3291 if (proto
&& !proto
->setNewTypeUnknown(cx
))
3294 JSObject
*obj
= NewObjectWithClassProto(cx
, clasp
, proto
, parent
);
3296 if (clasp
->ext
.equality
)
3297 MarkTypeObjectFlags(cx
, obj
, OBJECT_FLAG_SPECIAL_EQUALITY
);
3298 MarkTypeObjectUnknownProperties(cx
, obj
->type());
3301 JS_ASSERT_IF(obj
, obj
->getParent());
3305 JS_PUBLIC_API(JSObject
*)
3306 JS_NewObjectWithGivenProto(JSContext
*cx
, JSClass
*jsclasp
, JSObject
*proto
, JSObject
*parent
)
3308 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
3311 assertSameCompartment(cx
, proto
, parent
);
3313 Class
*clasp
= Valueify(jsclasp
);
3315 clasp
= &ObjectClass
; /* default class is Object */
3317 JS_ASSERT(clasp
!= &FunctionClass
);
3318 JS_ASSERT(!(clasp
->flags
& JSCLASS_IS_GLOBAL
));
3320 JSObject
*obj
= NewObjectWithGivenProto(cx
, clasp
, proto
, parent
);
3322 MarkTypeObjectUnknownProperties(cx
, obj
->type());
3326 JS_PUBLIC_API(JSObject
*)
3327 JS_NewObjectForConstructor(JSContext
*cx
, JSClass
*clasp
, const jsval
*vp
)
3331 assertSameCompartment(cx
, *vp
);
3333 return js_CreateThis(cx
, Valueify(clasp
), JSVAL_TO_OBJECT(*vp
));
3336 JS_PUBLIC_API(JSBool
)
3337 JS_IsExtensible(JSObject
*obj
)
3339 return obj
->isExtensible();
3342 JS_PUBLIC_API(JSBool
)
3343 JS_IsNative(JSObject
*obj
)
3345 return obj
->isNative();
3348 JS_PUBLIC_API(JSRuntime
*)
3349 JS_GetObjectRuntime(JSObject
*obj
)
3351 return obj
->compartment()->rt
;
3354 JS_PUBLIC_API(JSBool
)
3355 JS_FreezeObject(JSContext
*cx
, JSObject
*obj
)
3359 assertSameCompartment(cx
, obj
);
3361 return obj
->freeze(cx
);
3364 JS_PUBLIC_API(JSBool
)
3365 JS_DeepFreezeObject(JSContext
*cx
, JSObject
*obj
)
3369 assertSameCompartment(cx
, obj
);
3371 /* Assume that non-extensible objects are already deep-frozen, to avoid divergence. */
3372 if (!obj
->isExtensible())
3375 if (!obj
->freeze(cx
))
3378 /* Walk slots in obj and if any value is a non-null object, seal it. */
3379 for (uint32_t i
= 0, n
= obj
->slotSpan(); i
< n
; ++i
) {
3380 const Value
&v
= obj
->getSlot(i
);
3381 if (v
.isPrimitive())
3383 if (!JS_DeepFreezeObject(cx
, &v
.toObject()))
3390 JS_PUBLIC_API(JSObject
*)
3391 JS_ConstructObject(JSContext
*cx
, JSClass
*jsclasp
, JSObject
*parent
)
3393 return JS_ConstructObjectWithArguments(cx
, jsclasp
, parent
, 0, NULL
);
3396 JS_PUBLIC_API(JSObject
*)
3397 JS_ConstructObjectWithArguments(JSContext
*cx
, JSClass
*jsclasp
, JSObject
*parent
,
3398 unsigned argc
, jsval
*argv
)
3402 assertSameCompartment(cx
, parent
, JSValueArray(argv
, argc
));
3404 AutoArrayRooter
argtvr(cx
, argc
, argv
);
3406 Class
*clasp
= Valueify(jsclasp
);
3408 clasp
= &ObjectClass
; /* default class is Object */
3410 JSProtoKey protoKey
= GetClassProtoKey(clasp
);
3412 /* Protect constructor in case a crazy getter for .prototype uproots it. */
3413 RootedVarValue
value(cx
);
3414 if (!js_FindClassObject(cx
, parent
, protoKey
, value
.address(), clasp
))
3418 if (!InvokeConstructor(cx
, value
, argc
, argv
, &rval
))
3422 * If the instance's class differs from what was requested, throw a type
3425 if (!rval
.isObject() || rval
.toObject().getClass() != clasp
) {
3426 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
,
3427 JSMSG_WRONG_CONSTRUCTOR
, clasp
->name
);
3430 return &rval
.toObject();
3434 LookupPropertyById(JSContext
*cx
, JSObject
*obj
, jsid id
, unsigned flags
,
3435 JSObject
**objp
, JSProperty
**propp
)
3439 assertSameCompartment(cx
, obj
, id
);
3441 JSAutoResolveFlags
rf(cx
, flags
);
3442 return obj
->lookupGeneric(cx
, id
, objp
, propp
);
3445 #define AUTO_NAMELEN(s,n) (((n) == (size_t)-1) ? js_strlen(s) : (n))
3448 LookupResult(JSContext
*cx
, JSObject
*obj
, JSObject
*obj2
, jsid id
,
3449 JSProperty
*prop
, Value
*vp
)
3452 /* XXX bad API: no way to tell "not defined" from "void value" */
3457 if (obj2
->isNative()) {
3458 Shape
*shape
= (Shape
*) prop
;
3460 /* Peek at the native property's slot value, without doing a Get. */
3461 if (shape
->hasSlot()) {
3462 *vp
= obj2
->nativeGetSlot(shape
->slot());
3466 if (obj2
->isDenseArray())
3467 return js_GetDenseArrayElementValue(cx
, obj2
, id
, vp
);
3468 if (obj2
->isProxy()) {
3469 AutoPropertyDescriptorRooter
desc(cx
);
3470 if (!Proxy::getPropertyDescriptor(cx
, obj2
, id
, false, &desc
))
3472 if (!(desc
.attrs
& JSPROP_SHARED
)) {
3479 /* XXX bad API: no way to return "defined but value unknown" */
3480 vp
->setBoolean(true);
3484 JS_PUBLIC_API(JSBool
)
3485 JS_LookupPropertyById(JSContext
*cx
, JSObject
*obj
, jsid id
, jsval
*vp
)
3489 return LookupPropertyById(cx
, obj
, id
, JSRESOLVE_QUALIFIED
, &obj2
, &prop
) &&
3490 LookupResult(cx
, obj
, obj2
, id
, prop
, vp
);
3493 JS_PUBLIC_API(JSBool
)
3494 JS_LookupElement(JSContext
*cx
, JSObject
*obj
, uint32_t index
, jsval
*vp
)
3498 if (!IndexToId(cx
, index
, &id
))
3500 return JS_LookupPropertyById(cx
, obj
, id
, vp
);
3503 JS_PUBLIC_API(JSBool
)
3504 JS_LookupProperty(JSContext
*cx
, JSObject
*obj
, const char *name
, jsval
*vp
)
3506 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
));
3507 return atom
&& JS_LookupPropertyById(cx
, obj
, AtomToId(atom
), vp
);
3510 JS_PUBLIC_API(JSBool
)
3511 JS_LookupUCProperty(JSContext
*cx
, JSObject
*obj
, const jschar
*name
, size_t namelen
, jsval
*vp
)
3513 JSAtom
*atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
));
3514 return atom
&& JS_LookupPropertyById(cx
, obj
, AtomToId(atom
), vp
);
3517 JS_PUBLIC_API(JSBool
)
3518 JS_LookupPropertyWithFlagsById(JSContext
*cx
, JSObject
*obj
, jsid id
, unsigned flags
,
3519 JSObject
**objp
, jsval
*vp
)
3526 assertSameCompartment(cx
, obj
, id
);
3527 ok
= obj
->isNative()
3528 ? LookupPropertyWithFlags(cx
, obj
, id
, flags
, objp
, &prop
)
3529 : obj
->lookupGeneric(cx
, id
, objp
, &prop
);
3530 return ok
&& LookupResult(cx
, obj
, *objp
, id
, prop
, vp
);
3533 JS_PUBLIC_API(JSBool
)
3534 JS_LookupPropertyWithFlags(JSContext
*cx
, JSObject
*obj
, const char *name
, unsigned flags
, jsval
*vp
)
3537 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
));
3538 return atom
&& JS_LookupPropertyWithFlagsById(cx
, obj
, AtomToId(atom
), flags
, &obj2
, vp
);
3541 JS_PUBLIC_API(JSBool
)
3542 JS_HasPropertyById(JSContext
*cx
, JSObject
*obj
, jsid id
, JSBool
*foundp
)
3546 JSBool ok
= LookupPropertyById(cx
, obj
, id
, JSRESOLVE_QUALIFIED
| JSRESOLVE_DETECTING
,
3548 *foundp
= (prop
!= NULL
);
3552 JS_PUBLIC_API(JSBool
)
3553 JS_HasElement(JSContext
*cx
, JSObject
*obj
, uint32_t index
, JSBool
*foundp
)
3558 if (!IndexToId(cx
, index
, &id
))
3560 return JS_HasPropertyById(cx
, obj
, id
, foundp
);
3563 JS_PUBLIC_API(JSBool
)
3564 JS_HasProperty(JSContext
*cx
, JSObject
*obj
, const char *name
, JSBool
*foundp
)
3566 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
));
3567 return atom
&& JS_HasPropertyById(cx
, obj
, AtomToId(atom
), foundp
);
3570 JS_PUBLIC_API(JSBool
)
3571 JS_HasUCProperty(JSContext
*cx
, JSObject
*obj
, const jschar
*name
, size_t namelen
, JSBool
*foundp
)
3573 JSAtom
*atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
));
3574 return atom
&& JS_HasPropertyById(cx
, obj
, AtomToId(atom
), foundp
);
3577 JS_PUBLIC_API(JSBool
)
3578 JS_AlreadyHasOwnPropertyById(JSContext
*cx
, JSObject
*obj
, jsid id
, JSBool
*foundp
)
3582 assertSameCompartment(cx
, obj
, id
);
3584 if (!obj
->isNative()) {
3588 if (!LookupPropertyById(cx
, obj
, id
, JSRESOLVE_QUALIFIED
| JSRESOLVE_DETECTING
,
3592 *foundp
= (obj
== obj2
);
3596 *foundp
= obj
->nativeContains(cx
, id
);
3600 JS_PUBLIC_API(JSBool
)
3601 JS_AlreadyHasOwnElement(JSContext
*cx
, JSObject
*obj
, uint32_t index
, JSBool
*foundp
)
3606 if (!IndexToId(cx
, index
, &id
))
3608 return JS_AlreadyHasOwnPropertyById(cx
, obj
, id
, foundp
);
3611 JS_PUBLIC_API(JSBool
)
3612 JS_AlreadyHasOwnProperty(JSContext
*cx
, JSObject
*obj
, const char *name
, JSBool
*foundp
)
3614 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
));
3615 return atom
&& JS_AlreadyHasOwnPropertyById(cx
, obj
, AtomToId(atom
), foundp
);
3618 JS_PUBLIC_API(JSBool
)
3619 JS_AlreadyHasOwnUCProperty(JSContext
*cx
, JSObject
*obj
, const jschar
*name
, size_t namelen
,
3622 JSAtom
*atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
));
3623 return atom
&& JS_AlreadyHasOwnPropertyById(cx
, obj
, AtomToId(atom
), foundp
);
3627 DefinePropertyById(JSContext
*cx
, HandleObject obj
, HandleId id
, HandleValue value
,
3628 PropertyOp getter
, StrictPropertyOp setter
, unsigned attrs
,
3629 unsigned flags
, int tinyid
)
3632 * JSPROP_READONLY has no meaning when accessors are involved. Ideally we'd
3633 * throw if this happens, but we've accepted it for long enough that it's
3634 * not worth trying to make callers change their ways. Just flip it off on
3635 * its way through the API layer so that we can enforce this internally.
3637 if (attrs
& (JSPROP_GETTER
| JSPROP_SETTER
))
3638 attrs
&= ~JSPROP_READONLY
;
3641 * When we use DefineProperty, we need full scriptable Function objects rather
3642 * than JSNatives. However, we might be pulling this property descriptor off
3643 * of something with JSNative property descriptors. If we are, wrap them in
3644 * JS Function objects.
3646 if (attrs
& JSPROP_NATIVE_ACCESSORS
) {
3647 JS_ASSERT(!(attrs
& (JSPROP_GETTER
| JSPROP_SETTER
)));
3648 attrs
&= ~JSPROP_NATIVE_ACCESSORS
;
3650 JSObject
*getobj
= JS_NewFunction(cx
, (Native
) getter
, 0, 0, &obj
->global(), NULL
);
3653 getter
= JS_DATA_TO_FUNC_PTR(PropertyOp
, getobj
);
3654 attrs
|= JSPROP_GETTER
;
3657 RootObject
getRoot(cx
, (JSObject
**) &getter
);
3658 JSObject
*setobj
= JS_NewFunction(cx
, (Native
) setter
, 1, 0, &obj
->global(), NULL
);
3661 setter
= JS_DATA_TO_FUNC_PTR(StrictPropertyOp
, setobj
);
3662 attrs
|= JSPROP_SETTER
;
3669 assertSameCompartment(cx
, obj
, id
, value
,
3670 (attrs
& JSPROP_GETTER
)
3671 ? JS_FUNC_TO_DATA_PTR(JSObject
*, getter
)
3673 (attrs
& JSPROP_SETTER
)
3674 ? JS_FUNC_TO_DATA_PTR(JSObject
*, setter
)
3677 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
| JSRESOLVE_DECLARING
);
3678 if (flags
!= 0 && obj
->isNative()) {
3679 return !!DefineNativeProperty(cx
, obj
, id
, value
, getter
, setter
,
3680 attrs
, flags
, tinyid
);
3682 return obj
->defineGeneric(cx
, id
, value
, getter
, setter
, attrs
);
3685 JS_PUBLIC_API(JSBool
)
3686 JS_DefinePropertyById(JSContext
*cx
, JSObject
*obj_
, jsid id_
, jsval value_
,
3687 JSPropertyOp getter
, JSStrictPropertyOp setter
, unsigned attrs
)
3689 RootedVarObject
obj(cx
, obj_
);
3690 RootedVarId
id(cx
, id_
);
3691 RootedVarValue
value(cx
, value_
);
3692 return DefinePropertyById(cx
, obj
, id
, value
, getter
, setter
, attrs
, 0, 0);
3695 JS_PUBLIC_API(JSBool
)
3696 JS_DefineElement(JSContext
*cx
, JSObject
*obj_
, uint32_t index
, jsval value_
,
3697 JSPropertyOp getter
, JSStrictPropertyOp setter
, unsigned attrs
)
3699 RootedVarObject
obj(cx
, obj_
);
3700 RootedVarValue
value(cx
, value_
);
3701 RootGetterSetter
gsRoot(cx
, attrs
, &getter
, &setter
);
3705 if (!IndexToId(cx
, index
, id
.address()))
3707 return DefinePropertyById(cx
, obj
, id
, value
, getter
, setter
, attrs
, 0, 0);
3711 DefineProperty(JSContext
*cx
, JSObject
*obj_
, const char *name
, const Value
&value_
,
3712 PropertyOp getter
, StrictPropertyOp setter
, unsigned attrs
,
3713 unsigned flags
, int tinyid
)
3715 RootedVarObject
obj(cx
, obj_
);
3716 RootedVarValue
value(cx
, value_
);
3717 RootGetterSetter
gsRoot(cx
, attrs
, &getter
, &setter
);
3720 if (attrs
& JSPROP_INDEX
) {
3721 id
= INT_TO_JSID(intptr_t(name
));
3722 attrs
&= ~JSPROP_INDEX
;
3724 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
));
3727 id
= AtomToId(atom
);
3730 return DefinePropertyById(cx
, obj
, id
, value
, getter
, setter
, attrs
, flags
, tinyid
);
3733 JS_PUBLIC_API(JSBool
)
3734 JS_DefineProperty(JSContext
*cx
, JSObject
*obj
, const char *name
, jsval value
,
3735 PropertyOp getter
, JSStrictPropertyOp setter
, unsigned attrs
)
3737 return DefineProperty(cx
, obj
, name
, value
, getter
, setter
, attrs
, 0, 0);
3740 JS_PUBLIC_API(JSBool
)
3741 JS_DefinePropertyWithTinyId(JSContext
*cx
, JSObject
*obj
, const char *name
, int8_t tinyid
,
3742 jsval value
, PropertyOp getter
, JSStrictPropertyOp setter
, unsigned attrs
)
3744 return DefineProperty(cx
, obj
, name
, value
, getter
, setter
, attrs
, Shape::HAS_SHORTID
, tinyid
);
3748 DefineUCProperty(JSContext
*cx
, JSObject
*obj_
, const jschar
*name
, size_t namelen
,
3749 const Value
&value_
, PropertyOp getter
, StrictPropertyOp setter
, unsigned attrs
,
3750 unsigned flags
, int tinyid
)
3752 RootedVarObject
obj(cx
, obj_
);
3753 RootedVarValue
value(cx
, value_
);
3754 RootGetterSetter
gsRoot(cx
, attrs
, &getter
, &setter
);
3755 JSAtom
*atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
));
3758 RootedVarId
id(cx
, AtomToId(atom
));
3759 return DefinePropertyById(cx
, obj
, id
, value
, getter
, setter
, attrs
, flags
, tinyid
);
3762 JS_PUBLIC_API(JSBool
)
3763 JS_DefineUCProperty(JSContext
*cx
, JSObject
*obj
, const jschar
*name
, size_t namelen
,
3764 jsval value
, JSPropertyOp getter
, JSStrictPropertyOp setter
, unsigned attrs
)
3766 return DefineUCProperty(cx
, obj
, name
, namelen
, value
, getter
, setter
, attrs
, 0, 0);
3769 JS_PUBLIC_API(JSBool
)
3770 JS_DefineUCPropertyWithTinyId(JSContext
*cx
, JSObject
*obj
, const jschar
*name
, size_t namelen
,
3771 int8_t tinyid
, jsval value
,
3772 JSPropertyOp getter
, JSStrictPropertyOp setter
, unsigned attrs
)
3774 return DefineUCProperty(cx
, obj
, name
, namelen
, value
, getter
, setter
, attrs
,
3775 Shape::HAS_SHORTID
, tinyid
);
3778 JS_PUBLIC_API(JSBool
)
3779 JS_DefineOwnProperty(JSContext
*cx
, JSObject
*obj
, jsid id
, jsval descriptor
, JSBool
*bp
)
3783 assertSameCompartment(cx
, obj
, id
, descriptor
);
3784 return js_DefineOwnProperty(cx
, RootedVarObject(cx
, obj
), RootedVarId(cx
, id
), descriptor
, bp
);
3787 JS_PUBLIC_API(JSObject
*)
3788 JS_DefineObject(JSContext
*cx
, JSObject
*obj
, const char *name
, JSClass
*jsclasp
,
3789 JSObject
*proto
, unsigned attrs
)
3793 assertSameCompartment(cx
, obj
, proto
);
3795 Class
*clasp
= Valueify(jsclasp
);
3797 clasp
= &ObjectClass
; /* default class is Object */
3799 RootObject
root(cx
, &obj
);
3800 RootedVarObject
nobj(cx
);
3802 nobj
= NewObjectWithClassProto(cx
, clasp
, proto
, obj
);
3806 if (!DefineProperty(cx
, obj
, name
, ObjectValue(*nobj
), NULL
, NULL
, attrs
, 0, 0))
3812 JS_PUBLIC_API(JSBool
)
3813 JS_DefineConstDoubles(JSContext
*cx
, JSObject
*obj_
, JSConstDoubleSpec
*cds
)
3815 RootedVarObject
obj(cx
, obj_
);
3822 for (ok
= JS_TRUE
; cds
->name
; cds
++) {
3823 Value value
= DoubleValue(cds
->dval
);
3826 attrs
= JSPROP_READONLY
| JSPROP_PERMANENT
;
3827 ok
= DefineProperty(cx
, obj
, cds
->name
, value
, NULL
, NULL
, attrs
, 0, 0);
3834 JS_PUBLIC_API(JSBool
)
3835 JS_DefineProperties(JSContext
*cx
, JSObject
*obj
, JSPropertySpec
*ps
)
3838 RootObject
root(cx
, &obj
);
3840 for (ok
= true; ps
->name
; ps
++) {
3841 ok
= DefineProperty(cx
, obj
, ps
->name
, UndefinedValue(), ps
->getter
, ps
->setter
,
3842 ps
->flags
, Shape::HAS_SHORTID
, ps
->tinyid
);
3850 GetPropertyDescriptorById(JSContext
*cx
, JSObject
*obj
, jsid id
, unsigned flags
,
3851 JSBool own
, PropertyDescriptor
*desc
)
3856 if (!LookupPropertyById(cx
, obj
, id
, flags
, &obj2
, &prop
))
3859 if (!prop
|| (own
&& obj
!= obj2
)) {
3862 desc
->getter
= NULL
;
3863 desc
->setter
= NULL
;
3864 desc
->value
.setUndefined();
3869 if (obj2
->isNative()) {
3870 Shape
*shape
= (Shape
*) prop
;
3871 desc
->attrs
= shape
->attributes();
3872 desc
->getter
= shape
->getter();
3873 desc
->setter
= shape
->setter();
3874 if (shape
->hasSlot())
3875 desc
->value
= obj2
->nativeGetSlot(shape
->slot());
3877 desc
->value
.setUndefined();
3879 if (obj2
->isProxy()) {
3880 JSAutoResolveFlags
rf(cx
, flags
);
3882 ? Proxy::getOwnPropertyDescriptor(cx
, obj2
, id
, false, desc
)
3883 : Proxy::getPropertyDescriptor(cx
, obj2
, id
, false, desc
);
3885 if (!obj2
->getGenericAttributes(cx
, id
, &desc
->attrs
))
3887 desc
->getter
= NULL
;
3888 desc
->setter
= NULL
;
3889 desc
->value
.setUndefined();
3894 JS_PUBLIC_API(JSBool
)
3895 JS_GetPropertyDescriptorById(JSContext
*cx
, JSObject
*obj
, jsid id
, unsigned flags
,
3896 JSPropertyDescriptor
*desc
)
3898 return GetPropertyDescriptorById(cx
, obj
, id
, flags
, JS_FALSE
, desc
);
3901 JS_PUBLIC_API(JSBool
)
3902 JS_GetPropertyAttrsGetterAndSetterById(JSContext
*cx
, JSObject
*obj
, jsid id
,
3903 unsigned *attrsp
, JSBool
*foundp
,
3904 JSPropertyOp
*getterp
, JSStrictPropertyOp
*setterp
)
3906 PropertyDescriptor desc
;
3907 if (!GetPropertyDescriptorById(cx
, obj
, id
, JSRESOLVE_QUALIFIED
, JS_FALSE
, &desc
))
3910 *attrsp
= desc
.attrs
;
3911 *foundp
= (desc
.obj
!= NULL
);
3913 *getterp
= desc
.getter
;
3915 *setterp
= desc
.setter
;
3919 JS_PUBLIC_API(JSBool
)
3920 JS_GetPropertyAttributes(JSContext
*cx
, JSObject
*obj
, const char *name
,
3921 unsigned *attrsp
, JSBool
*foundp
)
3923 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
));
3924 return atom
&& JS_GetPropertyAttrsGetterAndSetterById(cx
, obj
, AtomToId(atom
),
3925 attrsp
, foundp
, NULL
, NULL
);
3928 JS_PUBLIC_API(JSBool
)
3929 JS_GetUCPropertyAttributes(JSContext
*cx
, JSObject
*obj
, const jschar
*name
, size_t namelen
,
3930 unsigned *attrsp
, JSBool
*foundp
)
3932 JSAtom
*atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
));
3933 return atom
&& JS_GetPropertyAttrsGetterAndSetterById(cx
, obj
, AtomToId(atom
),
3934 attrsp
, foundp
, NULL
, NULL
);
3937 JS_PUBLIC_API(JSBool
)
3938 JS_GetPropertyAttrsGetterAndSetter(JSContext
*cx
, JSObject
*obj
, const char *name
,
3939 unsigned *attrsp
, JSBool
*foundp
,
3940 JSPropertyOp
*getterp
, JSStrictPropertyOp
*setterp
)
3942 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
));
3943 return atom
&& JS_GetPropertyAttrsGetterAndSetterById(cx
, obj
, AtomToId(atom
),
3944 attrsp
, foundp
, getterp
, setterp
);
3947 JS_PUBLIC_API(JSBool
)
3948 JS_GetUCPropertyAttrsGetterAndSetter(JSContext
*cx
, JSObject
*obj
,
3949 const jschar
*name
, size_t namelen
,
3950 unsigned *attrsp
, JSBool
*foundp
,
3951 JSPropertyOp
*getterp
, JSStrictPropertyOp
*setterp
)
3953 JSAtom
*atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
));
3954 return atom
&& JS_GetPropertyAttrsGetterAndSetterById(cx
, obj
, AtomToId(atom
),
3955 attrsp
, foundp
, getterp
, setterp
);
3958 JS_PUBLIC_API(JSBool
)
3959 JS_GetOwnPropertyDescriptor(JSContext
*cx
, JSObject
*obj
, jsid id
, jsval
*vp
)
3963 return GetOwnPropertyDescriptor(cx
, RootedVarObject(cx
, obj
), RootedVarId(cx
, id
), vp
);
3967 SetPropertyAttributesById(JSContext
*cx
, JSObject
*obj
, jsid id
, unsigned attrs
, JSBool
*foundp
)
3972 if (!LookupPropertyById(cx
, obj
, id
, JSRESOLVE_QUALIFIED
, &obj2
, &prop
))
3974 if (!prop
|| obj
!= obj2
) {
3978 Shape
*shape
= (Shape
*) prop
;
3979 JSBool ok
= obj
->isNative()
3980 ? obj
->changePropertyAttributes(cx
, shape
, attrs
)
3981 : obj
->setGenericAttributes(cx
, id
, &attrs
);
3987 JS_PUBLIC_API(JSBool
)
3988 JS_SetPropertyAttributes(JSContext
*cx
, JSObject
*obj
, const char *name
,
3989 unsigned attrs
, JSBool
*foundp
)
3991 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
));
3992 return atom
&& SetPropertyAttributesById(cx
, obj
, AtomToId(atom
), attrs
, foundp
);
3995 JS_PUBLIC_API(JSBool
)
3996 JS_SetUCPropertyAttributes(JSContext
*cx
, JSObject
*obj
, const jschar
*name
, size_t namelen
,
3997 unsigned attrs
, JSBool
*foundp
)
3999 JSAtom
*atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
));
4000 return atom
&& SetPropertyAttributesById(cx
, obj
, AtomToId(atom
), attrs
, foundp
);
4003 JS_PUBLIC_API(JSBool
)
4004 JS_GetPropertyById(JSContext
*cx
, JSObject
*obj
, jsid id
, jsval
*vp
)
4006 return JS_ForwardGetPropertyTo(cx
, obj
, id
, obj
, vp
);
4009 JS_PUBLIC_API(JSBool
)
4010 JS_ForwardGetPropertyTo(JSContext
*cx
, JSObject
*obj
, jsid id
, JSObject
*onBehalfOf
, jsval
*vp
)
4014 assertSameCompartment(cx
, obj
, id
);
4015 assertSameCompartment(cx
, onBehalfOf
);
4016 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
);
4017 return obj
->getGeneric(cx
, onBehalfOf
, id
, vp
);
4020 JS_PUBLIC_API(JSBool
)
4021 JS_GetPropertyByIdDefault(JSContext
*cx
, JSObject
*obj
, jsid id
, jsval def
, jsval
*vp
)
4023 return GetPropertyDefault(cx
, RootedVarObject(cx
, obj
), RootedVarId(cx
, id
), def
, vp
);
4026 JS_PUBLIC_API(JSBool
)
4027 JS_GetElement(JSContext
*cx
, JSObject
*obj
, uint32_t index
, jsval
*vp
)
4029 return JS_ForwardGetElementTo(cx
, obj
, index
, obj
, vp
);
4032 JS_PUBLIC_API(JSBool
)
4033 JS_ForwardGetElementTo(JSContext
*cx
, JSObject
*obj
, uint32_t index
, JSObject
*onBehalfOf
, jsval
*vp
)
4037 assertSameCompartment(cx
, obj
);
4038 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
);
4039 return obj
->getElement(cx
, onBehalfOf
, index
, vp
);
4042 JS_PUBLIC_API(JSBool
)
4043 JS_GetElementIfPresent(JSContext
*cx
, JSObject
*obj
, uint32_t index
, JSObject
*onBehalfOf
, jsval
*vp
, JSBool
* present
)
4047 assertSameCompartment(cx
, obj
);
4048 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
);
4050 if (!obj
->getElementIfPresent(cx
, onBehalfOf
, index
, vp
, &isPresent
))
4052 *present
= isPresent
;
4056 JS_PUBLIC_API(JSBool
)
4057 JS_GetProperty(JSContext
*cx
, JSObject
*obj_
, const char *name
, jsval
*vp
)
4059 RootedVarObject
obj(cx
, obj_
);
4060 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
));
4061 return atom
&& JS_GetPropertyById(cx
, obj
, AtomToId(atom
), vp
);
4064 JS_PUBLIC_API(JSBool
)
4065 JS_GetPropertyDefault(JSContext
*cx
, JSObject
*obj_
, const char *name
, jsval def
, jsval
*vp
)
4067 RootedVarObject
obj(cx
, obj_
);
4068 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
));
4069 return atom
&& JS_GetPropertyByIdDefault(cx
, obj
, AtomToId(atom
), def
, vp
);
4072 JS_PUBLIC_API(JSBool
)
4073 JS_GetUCProperty(JSContext
*cx
, JSObject
*obj_
, const jschar
*name
, size_t namelen
, jsval
*vp
)
4075 RootedVarObject
obj(cx
, obj_
);
4076 JSAtom
*atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
));
4077 return atom
&& JS_GetPropertyById(cx
, obj
, AtomToId(atom
), vp
);
4080 JS_PUBLIC_API(JSBool
)
4081 JS_GetMethodById(JSContext
*cx
, JSObject
*obj
, jsid id
, JSObject
**objp
, jsval
*vp
)
4085 assertSameCompartment(cx
, obj
, id
);
4086 if (!js_GetMethod(cx
, RootedVarObject(cx
, obj
), id
, 0, vp
))
4093 JS_PUBLIC_API(JSBool
)
4094 JS_GetMethod(JSContext
*cx
, JSObject
*obj
, const char *name
, JSObject
**objp
, jsval
*vp
)
4096 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
));
4097 return atom
&& JS_GetMethodById(cx
, obj
, AtomToId(atom
), objp
, vp
);
4100 JS_PUBLIC_API(JSBool
)
4101 JS_SetPropertyById(JSContext
*cx
, JSObject
*obj
, jsid id
, jsval
*vp
)
4105 assertSameCompartment(cx
, obj
, id
);
4106 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
| JSRESOLVE_ASSIGNING
);
4107 return obj
->setGeneric(cx
, id
, vp
, false);
4110 JS_PUBLIC_API(JSBool
)
4111 JS_SetElement(JSContext
*cx
, JSObject
*obj_
, uint32_t index
, jsval
*vp
)
4115 assertSameCompartment(cx
, obj_
, *vp
);
4116 RootedVarObject
obj(cx
, obj_
);
4117 RootValue
vpRoot(cx
, vp
);
4118 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
| JSRESOLVE_ASSIGNING
);
4119 return obj
->setElement(cx
, index
, vp
, false);
4122 JS_PUBLIC_API(JSBool
)
4123 JS_SetProperty(JSContext
*cx
, JSObject
*obj_
, const char *name
, jsval
*vp
)
4125 RootedVarObject
obj(cx
, obj_
);
4126 RootValue
vpRoot(cx
, vp
);
4127 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
));
4128 return atom
&& JS_SetPropertyById(cx
, obj
, AtomToId(atom
), vp
);
4131 JS_PUBLIC_API(JSBool
)
4132 JS_SetUCProperty(JSContext
*cx
, JSObject
*obj
, const jschar
*name
, size_t namelen
, jsval
*vp
)
4134 JSAtom
*atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
));
4135 return atom
&& JS_SetPropertyById(cx
, obj
, AtomToId(atom
), vp
);
4138 JS_PUBLIC_API(JSBool
)
4139 JS_DeletePropertyById2(JSContext
*cx
, JSObject
*obj
, jsid id
, jsval
*rval
)
4143 assertSameCompartment(cx
, obj
, id
);
4144 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
);
4146 if (JSID_IS_SPECIAL(id
))
4147 return obj
->deleteSpecial(cx
, JSID_TO_SPECIALID(id
), rval
, false);
4149 return obj
->deleteByValue(cx
, IdToValue(id
), rval
, false);
4152 JS_PUBLIC_API(JSBool
)
4153 JS_DeleteElement2(JSContext
*cx
, JSObject
*obj
, uint32_t index
, jsval
*rval
)
4157 assertSameCompartment(cx
, obj
);
4158 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
);
4159 return obj
->deleteElement(cx
, index
, rval
, false);
4162 JS_PUBLIC_API(JSBool
)
4163 JS_DeleteProperty2(JSContext
*cx
, JSObject
*obj
, const char *name
, jsval
*rval
)
4166 assertSameCompartment(cx
, obj
);
4167 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
);
4169 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
));
4173 return obj
->deleteByValue(cx
, StringValue(atom
), rval
, false);
4176 JS_PUBLIC_API(JSBool
)
4177 JS_DeleteUCProperty2(JSContext
*cx
, JSObject
*obj
, const jschar
*name
, size_t namelen
, jsval
*rval
)
4180 assertSameCompartment(cx
, obj
);
4181 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
);
4183 JSAtom
*atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
));
4187 return obj
->deleteByValue(cx
, StringValue(atom
), rval
, false);
4190 JS_PUBLIC_API(JSBool
)
4191 JS_DeletePropertyById(JSContext
*cx
, JSObject
*obj
, jsid id
)
4194 return JS_DeletePropertyById2(cx
, obj
, id
, &junk
);
4197 JS_PUBLIC_API(JSBool
)
4198 JS_DeleteElement(JSContext
*cx
, JSObject
*obj
, uint32_t index
)
4201 return JS_DeleteElement2(cx
, obj
, index
, &junk
);
4204 JS_PUBLIC_API(JSBool
)
4205 JS_DeleteProperty(JSContext
*cx
, JSObject
*obj
, const char *name
)
4208 return JS_DeleteProperty2(cx
, obj
, name
, &junk
);
4212 JS_ClearScope(JSContext
*cx
, JSObject
*obj
)
4216 assertSameCompartment(cx
, obj
);
4218 ClearOp clearOp
= obj
->getOps()->clear
;
4222 if (obj
->isNative())
4223 js_ClearNative(cx
, obj
);
4225 /* Clear cached class objects on the global object. */
4226 if (obj
->isGlobal())
4227 obj
->asGlobal().clear(cx
);
4232 JS_PUBLIC_API(JSIdArray
*)
4233 JS_Enumerate(JSContext
*cx
, JSObject
*obj
)
4237 assertSameCompartment(cx
, obj
);
4239 AutoIdVector
props(cx
);
4241 if (!GetPropertyNames(cx
, obj
, JSITER_OWNONLY
, &props
) || !VectorToIdArray(cx
, props
, &ida
))
4247 * XXX reverse iterator for properties, unreverse and meld with jsinterp.c's
4248 * prop_iterator_class somehow...
4249 * + preserve the obj->enumerate API while optimizing the native object case
4250 * + native case here uses a Shape *, but that iterates in reverse!
4251 * + so we make non-native match, by reverse-iterating after JS_Enumerating
4253 const uint32_t JSSLOT_ITER_INDEX
= 0;
4256 prop_iter_finalize(FreeOp
*fop
, JSObject
*obj
)
4258 void *pdata
= obj
->getPrivate();
4262 if (obj
->getSlot(JSSLOT_ITER_INDEX
).toInt32() >= 0) {
4263 /* Non-native case: destroy the ida enumerated when obj was created. */
4264 JSIdArray
*ida
= (JSIdArray
*) pdata
;
4265 DestroyIdArray(fop
, ida
);
4270 prop_iter_trace(JSTracer
*trc
, JSObject
*obj
)
4272 void *pdata
= obj
->getPrivate();
4276 if (obj
->getSlot(JSSLOT_ITER_INDEX
).toInt32() < 0) {
4278 * Native case: just mark the next property to visit. We don't need a
4279 * barrier here because the pointer is updated via setPrivate, which
4280 * always takes a barrier.
4282 Shape
*tmp
= (Shape
*)pdata
;
4283 MarkShapeUnbarriered(trc
, &tmp
, "prop iter shape");
4284 obj
->setPrivateUnbarriered(tmp
);
4286 /* Non-native case: mark each id in the JSIdArray private. */
4287 JSIdArray
*ida
= (JSIdArray
*) pdata
;
4288 MarkIdRange(trc
, ida
->length
, ida
->vector
, "prop iter");
4292 static Class prop_iter_class
= {
4294 JSCLASS_HAS_PRIVATE
| JSCLASS_IMPLEMENTS_BARRIERS
| JSCLASS_HAS_RESERVED_SLOTS(1),
4295 JS_PropertyStub
, /* addProperty */
4296 JS_PropertyStub
, /* delProperty */
4297 JS_PropertyStub
, /* getProperty */
4298 JS_StrictPropertyStub
, /* setProperty */
4303 NULL
, /* checkAccess */
4305 NULL
, /* construct */
4306 NULL
, /* hasInstance */
4310 JS_PUBLIC_API(JSObject
*)
4311 JS_NewPropertyIterator(JSContext
*cx
, JSObject
*obj
)
4320 assertSameCompartment(cx
, obj
);
4321 iterobj
= NewObjectWithClassProto(cx
, &prop_iter_class
, NULL
, obj
);
4325 if (obj
->isNative()) {
4326 /* Native case: start with the last property in obj. */
4327 pdata
= (void *)obj
->lastProperty();
4331 * Non-native case: enumerate a JSIdArray and keep it via private.
4333 * Note: we have to make sure that we root obj around the call to
4334 * JS_Enumerate to protect against multiple allocations under it.
4336 ida
= JS_Enumerate(cx
, obj
);
4340 index
= ida
->length
;
4343 /* iterobj cannot escape to other threads here. */
4344 iterobj
->setPrivate(pdata
);
4345 iterobj
->setSlot(JSSLOT_ITER_INDEX
, Int32Value(index
));
4349 JS_PUBLIC_API(JSBool
)
4350 JS_NextProperty(JSContext
*cx
, JSObject
*iterobj
, jsid
*idp
)
4358 assertSameCompartment(cx
, iterobj
);
4359 i
= iterobj
->getSlot(JSSLOT_ITER_INDEX
).toInt32();
4361 /* Native case: private data is a property tree node pointer. */
4362 JS_ASSERT(iterobj
->getParent()->isNative());
4363 shape
= (Shape
*) iterobj
->getPrivate();
4365 while (shape
->previous() && !shape
->enumerable())
4366 shape
= shape
->previous();
4368 if (!shape
->previous()) {
4369 JS_ASSERT(shape
->isEmptyShape());
4372 iterobj
->setPrivate(const_cast<Shape
*>(shape
->previous().get()));
4373 *idp
= shape
->propid();
4376 /* Non-native case: use the ida enumerated when iterobj was created. */
4377 ida
= (JSIdArray
*) iterobj
->getPrivate();
4378 JS_ASSERT(i
<= ida
->length
);
4379 STATIC_ASSUME(i
<= ida
->length
);
4383 *idp
= ida
->vector
[--i
];
4384 iterobj
->setSlot(JSSLOT_ITER_INDEX
, Int32Value(i
));
4390 JS_PUBLIC_API(JSObject
*)
4391 JS_NewElementIterator(JSContext
*cx
, JSObject
*obj
)
4395 assertSameCompartment(cx
, obj
);
4396 return ElementIteratorObject::create(cx
, RootedVarObject(cx
, obj
));
4399 JS_PUBLIC_API(JSObject
*)
4400 JS_ElementIteratorStub(JSContext
*cx
, JSObject
*obj
, JSBool keysonly
)
4402 JS_ASSERT(!keysonly
);
4403 return JS_NewElementIterator(cx
, obj
);
4406 JS_PUBLIC_API(jsval
)
4407 JS_GetReservedSlot(JSObject
*obj
, uint32_t index
)
4409 return obj
->getReservedSlot(index
);
4413 JS_SetReservedSlot(JSObject
*obj
, uint32_t index
, jsval v
)
4415 obj
->setReservedSlot(index
, v
);
4418 JS_PUBLIC_API(JSObject
*)
4419 JS_NewArrayObject(JSContext
*cx
, int length
, jsval
*vector
)
4421 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
4425 assertSameCompartment(cx
, JSValueArray(vector
, vector
? (uint32_t)length
: 0));
4426 return NewDenseCopiedArray(cx
, (uint32_t)length
, vector
);
4429 JS_PUBLIC_API(JSBool
)
4430 JS_IsArrayObject(JSContext
*cx
, JSObject
*obj
)
4432 assertSameCompartment(cx
, obj
);
4433 return ObjectClassIs(*obj
, ESClass_Array
, cx
);
4436 JS_PUBLIC_API(JSBool
)
4437 JS_GetArrayLength(JSContext
*cx
, JSObject
*obj
, uint32_t *lengthp
)
4441 assertSameCompartment(cx
, obj
);
4442 return js_GetLengthProperty(cx
, obj
, lengthp
);
4445 JS_PUBLIC_API(JSBool
)
4446 JS_SetArrayLength(JSContext
*cx
, JSObject
*obj
, uint32_t length
)
4450 assertSameCompartment(cx
, obj
);
4451 return js_SetLengthProperty(cx
, obj
, length
);
4454 JS_PUBLIC_API(JSBool
)
4455 JS_CheckAccess(JSContext
*cx
, JSObject
*obj
, jsid id
, JSAccessMode mode
,
4456 jsval
*vp
, unsigned *attrsp
)
4460 assertSameCompartment(cx
, obj
, id
);
4461 return CheckAccess(cx
, obj
, id
, mode
, vp
, attrsp
);
4465 JS_HoldPrincipals(JSPrincipals
*principals
)
4467 JS_ATOMIC_INCREMENT(&principals
->refcount
);
4471 JS_DropPrincipals(JSRuntime
*rt
, JSPrincipals
*principals
)
4473 int rc
= JS_ATOMIC_DECREMENT(&principals
->refcount
);
4475 rt
->destroyPrincipals(principals
);
4479 JS_SetSecurityCallbacks(JSRuntime
*rt
, const JSSecurityCallbacks
*scb
)
4481 JS_ASSERT(scb
!= &NullSecurityCallbacks
);
4482 rt
->securityCallbacks
= scb
? scb
: &NullSecurityCallbacks
;
4485 JS_PUBLIC_API(const JSSecurityCallbacks
*)
4486 JS_GetSecurityCallbacks(JSRuntime
*rt
)
4488 return (rt
->securityCallbacks
!= &NullSecurityCallbacks
) ? rt
->securityCallbacks
: NULL
;
4492 JS_SetTrustedPrincipals(JSRuntime
*rt
, JSPrincipals
*prin
)
4494 rt
->setTrustedPrincipals(prin
);
4497 extern JS_PUBLIC_API(void)
4498 JS_InitDestroyPrincipalsCallback(JSRuntime
*rt
, JSDestroyPrincipalsOp destroyPrincipals
)
4500 JS_ASSERT(destroyPrincipals
);
4501 JS_ASSERT(!rt
->destroyPrincipals
);
4502 rt
->destroyPrincipals
= destroyPrincipals
;
4505 JS_PUBLIC_API(JSFunction
*)
4506 JS_NewFunction(JSContext
*cx
, JSNative native
, unsigned nargs
, unsigned flags
,
4507 JSObject
*parent
, const char *name
)
4509 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
4514 assertSameCompartment(cx
, parent
);
4519 atom
= js_Atomize(cx
, name
, strlen(name
));
4524 RootObject
parentRoot(cx
, &parent
);
4525 return js_NewFunction(cx
, NULL
, native
, nargs
, flags
, parentRoot
, atom
);
4528 JS_PUBLIC_API(JSFunction
*)
4529 JS_NewFunctionById(JSContext
*cx
, JSNative native
, unsigned nargs
, unsigned flags
, JSObject
*parent
,
4532 JS_ASSERT(JSID_IS_STRING(id
));
4533 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
4536 assertSameCompartment(cx
, parent
);
4538 RootObject
parentRoot(cx
, &parent
);
4539 return js_NewFunction(cx
, NULL
, native
, nargs
, flags
, parentRoot
, JSID_TO_ATOM(id
));
4542 JS_PUBLIC_API(JSObject
*)
4543 JS_CloneFunctionObject(JSContext
*cx
, JSObject
*funobj
, JSObject
*parent_
)
4547 assertSameCompartment(cx
, parent_
); // XXX no funobj for now
4549 RootedVarObject
parent(cx
, parent_
);
4553 parent
= cx
->fp()->scopeChain();
4555 parent
= cx
->globalObject
;
4559 if (!funobj
->isFunction()) {
4561 * We cannot clone this object, so fail (we used to return funobj, bad
4562 * idea, but we changed incompatibly to teach any abusers a lesson!).
4564 Value v
= ObjectValue(*funobj
);
4565 js_ReportIsNotFunction(cx
, &v
, 0);
4569 RootedVarFunction
fun(cx
, funobj
->toFunction());
4570 if (fun
->isInterpreted() && fun
->script()->compileAndGo
) {
4571 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
,
4572 JSMSG_BAD_CLONE_FUNOBJ_SCOPE
);
4577 return CloneFunctionObject(cx
, fun
, parent
, fun
->getAllocKind());
4580 JS_PUBLIC_API(JSObject
*)
4581 JS_GetFunctionObject(JSFunction
*fun
)
4586 JS_PUBLIC_API(JSString
*)
4587 JS_GetFunctionId(JSFunction
*fun
)
4592 JS_PUBLIC_API(unsigned)
4593 JS_GetFunctionFlags(JSFunction
*fun
)
4598 JS_PUBLIC_API(uint16_t)
4599 JS_GetFunctionArity(JSFunction
*fun
)
4604 JS_PUBLIC_API(JSBool
)
4605 JS_ObjectIsFunction(JSContext
*cx
, JSObject
*obj
)
4607 return obj
->isFunction();
4610 JS_PUBLIC_API(JSBool
)
4611 JS_ObjectIsCallable(JSContext
*cx
, JSObject
*obj
)
4613 return obj
->isCallable();
4616 JS_PUBLIC_API(JSBool
)
4617 JS_IsNativeFunction(JSObject
*funobj
, JSNative call
)
4619 if (!funobj
->isFunction())
4621 JSFunction
*fun
= funobj
->toFunction();
4622 return fun
->isNative() && fun
->native() == call
;
4625 JS_PUBLIC_API(JSObject
*)
4626 JS_BindCallable(JSContext
*cx
, JSObject
*callable
, JSObject
*newThis
)
4628 RootedVarObject
target(cx
, callable
);
4629 RootedVarValue
thisArg(cx
, ObjectValue(*newThis
));
4630 return js_fun_bind(cx
, target
, thisArg
, NULL
, 0);
4634 js_generic_native_method_dispatcher(JSContext
*cx
, unsigned argc
, Value
*vp
)
4636 JSFunctionSpec
*fs
= (JSFunctionSpec
*)
4637 vp
->toObject().toFunction()->getExtendedSlot(0).toPrivate();
4638 JS_ASSERT((fs
->flags
& JSFUN_GENERIC_NATIVE
) != 0);
4641 js_ReportMissingArg(cx
, *vp
, 0);
4646 * Copy all actual (argc) arguments down over our |this| parameter, vp[1],
4647 * which is almost always the class constructor object, e.g. Array. Then
4648 * call the corresponding prototype native method with our first argument
4651 memmove(vp
+ 1, vp
+ 2, argc
* sizeof(jsval
));
4653 /* Clear the last parameter in case too few arguments were passed. */
4654 vp
[2 + --argc
].setUndefined();
4656 return fs
->call(cx
, argc
, vp
);
4659 JS_PUBLIC_API(JSBool
)
4660 JS_DefineFunctions(JSContext
*cx
, JSObject
*obj
, JSFunctionSpec
*fs
)
4662 RootObject
objRoot(cx
, &obj
);
4664 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
4666 RootedVarObject
ctor(cx
);
4671 assertSameCompartment(cx
, obj
);
4672 for (; fs
->name
; fs
++) {
4675 JSAtom
*atom
= js_Atomize(cx
, fs
->name
, strlen(fs
->name
));
4680 * Define a generic arity N+1 static method for the arity N prototype
4681 * method if flags contains JSFUN_GENERIC_NATIVE.
4683 if (flags
& JSFUN_GENERIC_NATIVE
) {
4684 RootAtom
root(cx
, &atom
);
4687 ctor
= JS_GetConstructor(cx
, obj
);
4692 flags
&= ~JSFUN_GENERIC_NATIVE
;
4693 fun
= js_DefineFunction(cx
, ctor
, AtomToId(atom
),
4694 js_generic_native_method_dispatcher
,
4697 JSFunction::ExtendedFinalizeKind
);
4702 * As jsapi.h notes, fs must point to storage that lives as long
4703 * as fun->object lives.
4705 fun
->setExtendedSlot(0, PrivateValue(fs
));
4708 fun
= js_DefineFunction(cx
, objRoot
,
4709 AtomToId(atom
), fs
->call
, fs
->nargs
, flags
);
4716 JS_PUBLIC_API(JSFunction
*)
4717 JS_DefineFunction(JSContext
*cx
, JSObject
*obj
, const char *name
, JSNative call
,
4718 unsigned nargs
, unsigned attrs
)
4720 RootObject
objRoot(cx
, &obj
);
4722 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
4725 assertSameCompartment(cx
, obj
);
4726 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
));
4729 return js_DefineFunction(cx
, objRoot
, AtomToId(atom
), call
, nargs
, attrs
);
4732 JS_PUBLIC_API(JSFunction
*)
4733 JS_DefineUCFunction(JSContext
*cx
, JSObject
*obj
,
4734 const jschar
*name
, size_t namelen
, JSNative call
,
4735 unsigned nargs
, unsigned attrs
)
4737 RootObject
objRoot(cx
, &obj
);
4739 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
4742 assertSameCompartment(cx
, obj
);
4743 JSAtom
*atom
= js_AtomizeChars(cx
, name
, AUTO_NAMELEN(name
, namelen
));
4746 return js_DefineFunction(cx
, objRoot
, AtomToId(atom
), call
, nargs
, attrs
);
4749 extern JS_PUBLIC_API(JSFunction
*)
4750 JS_DefineFunctionById(JSContext
*cx
, JSObject
*obj
, jsid id
, JSNative call
,
4751 unsigned nargs
, unsigned attrs
)
4753 RootObject
objRoot(cx
, &obj
);
4755 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
4758 assertSameCompartment(cx
, obj
);
4759 return js_DefineFunction(cx
, objRoot
, id
, call
, nargs
, attrs
);
4762 struct AutoLastFrameCheck
{
4763 AutoLastFrameCheck(JSContext
*cx JS_GUARD_OBJECT_NOTIFIER_PARAM
)
4766 JS_GUARD_OBJECT_NOTIFIER_INIT
;
4769 ~AutoLastFrameCheck() {
4770 if (cx
->isExceptionPending() &&
4771 !JS_IsRunning(cx
) &&
4772 !cx
->hasRunOption(JSOPTION_DONT_REPORT_UNCAUGHT
)) {
4773 js_ReportUncaughtException(cx
);
4779 JS_DECL_USE_GUARD_OBJECT_NOTIFIER
4782 inline static uint32_t
4783 JS_OPTIONS_TO_TCFLAGS(JSContext
*cx
)
4785 return (cx
->hasRunOption(JSOPTION_COMPILE_N_GO
) ? TCF_COMPILE_N_GO
: 0) |
4786 (cx
->hasRunOption(JSOPTION_NO_SCRIPT_RVAL
) ? TCF_NO_SCRIPT_RVAL
: 0);
4790 CompileUCScriptForPrincipalsCommon(JSContext
*cx
, JSObject
*obj
,
4791 JSPrincipals
*principals
, JSPrincipals
*originPrincipals
,
4792 const jschar
*chars
, size_t length
,
4793 const char *filename
, unsigned lineno
, JSVersion version
)
4795 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
4798 assertSameCompartment(cx
, obj
, principals
);
4799 AutoLastFrameCheck
lfc(cx
);
4801 uint32_t tcflags
= JS_OPTIONS_TO_TCFLAGS(cx
) | TCF_NEED_SCRIPT_GLOBAL
;
4802 return frontend::CompileScript(cx
, obj
, NULL
, principals
, originPrincipals
, tcflags
,
4803 chars
, length
, filename
, lineno
, version
);
4806 extern JS_PUBLIC_API(JSScript
*)
4807 JS_CompileUCScriptForPrincipalsVersion(JSContext
*cx
, JSObject
*obj
,
4808 JSPrincipals
*principals
,
4809 const jschar
*chars
, size_t length
,
4810 const char *filename
, unsigned lineno
,
4813 AutoVersionAPI
avi(cx
, version
);
4814 return CompileUCScriptForPrincipalsCommon(cx
, obj
, principals
, NULL
, chars
, length
,
4815 filename
, lineno
, avi
.version());
4818 extern JS_PUBLIC_API(JSScript
*)
4819 JS_CompileUCScriptForPrincipalsVersionOrigin(JSContext
*cx
, JSObject
*obj
,
4820 JSPrincipals
*principals
,
4821 JSPrincipals
*originPrincipals
,
4822 const jschar
*chars
, size_t length
,
4823 const char *filename
, unsigned lineno
,
4826 AutoVersionAPI
avi(cx
, version
);
4827 return CompileUCScriptForPrincipalsCommon(cx
, obj
, principals
, originPrincipals
,
4828 chars
, length
, filename
, lineno
, avi
.version());
4831 JS_PUBLIC_API(JSScript
*)
4832 JS_CompileUCScriptForPrincipals(JSContext
*cx
, JSObject
*obj
, JSPrincipals
*principals
,
4833 const jschar
*chars
, size_t length
,
4834 const char *filename
, unsigned lineno
)
4836 return CompileUCScriptForPrincipalsCommon(cx
, obj
, principals
, NULL
, chars
, length
,
4837 filename
, lineno
, cx
->findVersion());
4840 JS_PUBLIC_API(JSScript
*)
4841 JS_CompileUCScript(JSContext
*cx
, JSObject
*obj
, const jschar
*chars
, size_t length
,
4842 const char *filename
, unsigned lineno
)
4844 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
4845 return JS_CompileUCScriptForPrincipals(cx
, obj
, NULL
, chars
, length
, filename
, lineno
);
4848 JS_PUBLIC_API(JSScript
*)
4849 JS_CompileScriptForPrincipalsVersion(JSContext
*cx
, JSObject
*obj
,
4850 JSPrincipals
*principals
,
4851 const char *bytes
, size_t length
,
4852 const char *filename
, unsigned lineno
,
4855 AutoVersionAPI
ava(cx
, version
);
4856 return JS_CompileScriptForPrincipals(cx
, obj
, principals
, bytes
, length
, filename
, lineno
);
4859 JS_PUBLIC_API(JSScript
*)
4860 JS_CompileScriptForPrincipals(JSContext
*cx
, JSObject
*obj
,
4861 JSPrincipals
*principals
,
4862 const char *bytes
, size_t length
,
4863 const char *filename
, unsigned lineno
)
4865 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
4869 jschar
*chars
= InflateString(cx
, bytes
, &length
);
4873 JS_CompileUCScriptForPrincipals(cx
, obj
, principals
, chars
, length
, filename
, lineno
);
4878 JS_PUBLIC_API(JSScript
*)
4879 JS_CompileScript(JSContext
*cx
, JSObject
*obj
, const char *bytes
, size_t length
,
4880 const char *filename
, unsigned lineno
)
4882 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
4883 return JS_CompileScriptForPrincipals(cx
, obj
, NULL
, bytes
, length
, filename
, lineno
);
4886 JS_PUBLIC_API(JSBool
)
4887 JS_BufferIsCompilableUnit(JSContext
*cx
, JSBool bytes_are_utf8
, JSObject
*obj
, const char *bytes
, size_t length
)
4891 JSExceptionState
*exnState
;
4892 JSErrorReporter older
;
4896 assertSameCompartment(cx
, obj
);
4898 chars
= InflateString(cx
, bytes
, &length
, CESU8Encoding
);
4900 chars
= InflateString(cx
, bytes
, &length
);
4905 * Return true on any out-of-memory error, so our caller doesn't try to
4906 * collect more buffered source.
4909 exnState
= JS_SaveExceptionState(cx
);
4912 if (parser
.init(chars
, length
, NULL
, 1, cx
->findVersion())) {
4913 older
= JS_SetErrorReporter(cx
, NULL
);
4914 if (!parser
.parse(obj
) &&
4915 parser
.tokenStream
.isUnexpectedEOF()) {
4917 * We ran into an error. If it was because we ran out of
4918 * source, we return false so our caller knows to try to
4919 * collect more buffered source.
4923 JS_SetErrorReporter(cx
, older
);
4927 JS_RestoreExceptionState(cx
, exnState
);
4931 /* Use the fastest available getc. */
4932 #if defined(HAVE_GETC_UNLOCKED)
4933 # define fast_getc getc_unlocked
4934 #elif defined(HAVE__GETC_NOLOCK)
4935 # define fast_getc _getc_nolock
4937 # define fast_getc getc
4941 CompileUTF8FileHelper(JSContext
*cx
, JSObject
*obj
, JSPrincipals
*principals
,
4942 const char* filename
, FILE *fp
)
4945 int ok
= fstat(fileno(fp
), &st
);
4950 size_t len
= st
.st_size
;
4954 /* Read in the whole file, then compile it. */
4957 len
= 8; /* start with a small buffer, expand as necessary */
4960 bool hitEOF
= false;
4963 char* tmpbuf
= (char *) cx
->realloc_(buf
, len
* sizeof(char));
4980 buf
= (char *) cx
->malloc_(len
* sizeof(char));
4985 // The |i < len| is necessary for files that lie about their length,
4986 // e.g. /dev/zero and /dev/random. See bug 669434.
4987 while (i
< len
&& (c
= fast_getc(fp
)) != EOF
)
4991 JS_ASSERT(i
<= len
);
4993 size_t decodelen
= len
;
4994 jschar
*decodebuf
= (jschar
*)cx
->malloc_(decodelen
* sizeof(jschar
));
4995 if (JS_DecodeUTF8(cx
, buf
, len
, decodebuf
, &decodelen
)) {
4996 uint32_t tcflags
= JS_OPTIONS_TO_TCFLAGS(cx
) | TCF_NEED_SCRIPT_GLOBAL
;
4997 script
= frontend::CompileScript(cx
, obj
, NULL
, principals
, NULL
,
4998 tcflags
, decodebuf
, decodelen
,
4999 filename
, 1, cx
->findVersion());
5004 cx
->free_(decodebuf
);
5008 JS_PUBLIC_API(JSScript
*)
5009 JS_CompileUTF8File(JSContext
*cx
, JSObject
*obj
, const char *filename
)
5011 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
5014 assertSameCompartment(cx
, obj
);
5015 AutoLastFrameCheck
lfc(cx
);
5018 if (!filename
|| strcmp(filename
, "-") == 0) {
5021 fp
= fopen(filename
, "r");
5023 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_CANT_OPEN
,
5024 filename
, "No such file or directory");
5029 JSScript
*script
= CompileUTF8FileHelper(cx
, obj
, NULL
, filename
, fp
);
5035 JS_PUBLIC_API(JSScript
*)
5036 JS_CompileUTF8FileHandleForPrincipals(JSContext
*cx
, JSObject
*obj
, const char *filename
,
5037 FILE *file
, JSPrincipals
*principals
)
5039 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
5042 assertSameCompartment(cx
, obj
, principals
);
5043 AutoLastFrameCheck
lfc(cx
);
5045 return CompileUTF8FileHelper(cx
, obj
, principals
, filename
, file
);
5048 JS_PUBLIC_API(JSScript
*)
5049 JS_CompileUTF8FileHandleForPrincipalsVersion(JSContext
*cx
, JSObject
*obj
, const char *filename
,
5050 FILE *file
, JSPrincipals
*principals
, JSVersion version
)
5052 AutoVersionAPI
ava(cx
, version
);
5053 return JS_CompileUTF8FileHandleForPrincipals(cx
, obj
, filename
, file
, principals
);
5056 JS_PUBLIC_API(JSScript
*)
5057 JS_CompileUTF8FileHandle(JSContext
*cx
, JSObject
*obj
, const char *filename
, FILE *file
)
5059 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
5060 return JS_CompileUTF8FileHandleForPrincipals(cx
, obj
, filename
, file
, NULL
);
5063 JS_PUBLIC_API(JSObject
*)
5064 JS_GetGlobalFromScript(JSScript
*script
)
5066 JS_ASSERT(!script
->isCachedEval
);
5067 JS_ASSERT(script
->globalObject
);
5069 return script
->globalObject
;
5073 CompileUCFunctionForPrincipalsCommon(JSContext
*cx
, JSObject
*obj
,
5074 JSPrincipals
*principals
, const char *name
,
5075 unsigned nargs
, const char **argnames
,
5076 const jschar
*chars
, size_t length
,
5077 const char *filename
, unsigned lineno
, JSVersion version
)
5079 RootObject
objRoot(cx
, &obj
);
5081 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
5084 assertSameCompartment(cx
, obj
, principals
);
5085 AutoLastFrameCheck
lfc(cx
);
5087 RootedVarAtom
funAtom(cx
);
5089 funAtom
= js_Atomize(cx
, name
, strlen(name
));
5094 Bindings
bindings(cx
);
5095 for (unsigned i
= 0; i
< nargs
; i
++) {
5097 RootedVarAtom
argAtom(cx
, js_Atomize(cx
, argnames
[i
], strlen(argnames
[i
])));
5098 if (!argAtom
|| !bindings
.addArgument(cx
, argAtom
, &dummy
))
5102 JSFunction
*fun
= js_NewFunction(cx
, NULL
, NULL
, 0, JSFUN_INTERPRETED
, objRoot
, funAtom
);
5106 if (!frontend::CompileFunctionBody(cx
, fun
, principals
, NULL
, &bindings
,
5107 chars
, length
, filename
, lineno
, version
))
5112 if (obj
&& funAtom
&&
5113 !obj
->defineGeneric(cx
, AtomToId(funAtom
), ObjectValue(*fun
), NULL
, NULL
,
5122 JS_PUBLIC_API(JSFunction
*)
5123 JS_CompileUCFunctionForPrincipalsVersion(JSContext
*cx
, JSObject
*obj
,
5124 JSPrincipals
*principals
, const char *name
,
5125 unsigned nargs
, const char **argnames
,
5126 const jschar
*chars
, size_t length
,
5127 const char *filename
, unsigned lineno
,
5130 AutoVersionAPI
avi(cx
, version
);
5131 return CompileUCFunctionForPrincipalsCommon(cx
, obj
, principals
, name
, nargs
, argnames
, chars
,
5132 length
, filename
, lineno
, avi
.version());
5135 JS_PUBLIC_API(JSFunction
*)
5136 JS_CompileUCFunctionForPrincipals(JSContext
*cx
, JSObject
*obj
,
5137 JSPrincipals
*principals
, const char *name
,
5138 unsigned nargs
, const char **argnames
,
5139 const jschar
*chars
, size_t length
,
5140 const char *filename
, unsigned lineno
)
5142 return CompileUCFunctionForPrincipalsCommon(cx
, obj
, principals
, name
, nargs
, argnames
, chars
,
5143 length
, filename
, lineno
, cx
->findVersion());
5146 JS_PUBLIC_API(JSFunction
*)
5147 JS_CompileUCFunction(JSContext
*cx
, JSObject
*obj
, const char *name
,
5148 unsigned nargs
, const char **argnames
,
5149 const jschar
*chars
, size_t length
,
5150 const char *filename
, unsigned lineno
)
5152 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
5153 return JS_CompileUCFunctionForPrincipals(cx
, obj
, NULL
, name
, nargs
, argnames
,
5154 chars
, length
, filename
, lineno
);
5157 JS_PUBLIC_API(JSFunction
*)
5158 JS_CompileFunctionForPrincipals(JSContext
*cx
, JSObject
*obj
,
5159 JSPrincipals
*principals
, const char *name
,
5160 unsigned nargs
, const char **argnames
,
5161 const char *bytes
, size_t length
,
5162 const char *filename
, unsigned lineno
)
5164 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
5165 jschar
*chars
= InflateString(cx
, bytes
, &length
);
5168 JSFunction
*fun
= JS_CompileUCFunctionForPrincipals(cx
, obj
, principals
, name
,
5169 nargs
, argnames
, chars
, length
,
5175 JS_PUBLIC_API(JSFunction
*)
5176 JS_CompileFunction(JSContext
*cx
, JSObject
*obj
, const char *name
,
5177 unsigned nargs
, const char **argnames
,
5178 const char *bytes
, size_t length
,
5179 const char *filename
, unsigned lineno
)
5181 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
5182 return JS_CompileFunctionForPrincipals(cx
, obj
, NULL
, name
, nargs
, argnames
, bytes
, length
,
5186 JS_PUBLIC_API(JSString
*)
5187 JS_DecompileScript(JSContext
*cx
, JSScript
*script
, const char *name
, unsigned indent
)
5189 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
5196 if (cx
->compartment
!= script
->compartment())
5197 CompartmentChecker::fail(cx
->compartment
, script
->compartment());
5199 jp
= js_NewPrinter(cx
, name
, NULL
,
5200 indent
& ~JS_DONT_PRETTY_PRINT
,
5201 !(indent
& JS_DONT_PRETTY_PRINT
),
5205 if (js_DecompileScript(jp
, script
))
5206 str
= js_GetPrinterOutput(jp
);
5209 js_DestroyPrinter(jp
);
5213 JS_PUBLIC_API(JSString
*)
5214 JS_DecompileFunction(JSContext
*cx
, JSFunction
*fun
, unsigned indent
)
5216 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
5219 assertSameCompartment(cx
, fun
);
5220 return js_DecompileToString(cx
, "JS_DecompileFunction", fun
,
5221 indent
& ~JS_DONT_PRETTY_PRINT
,
5222 !(indent
& JS_DONT_PRETTY_PRINT
),
5223 false, false, js_DecompileFunction
);
5226 JS_PUBLIC_API(JSString
*)
5227 JS_DecompileFunctionBody(JSContext
*cx
, JSFunction
*fun
, unsigned indent
)
5229 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
5232 assertSameCompartment(cx
, fun
);
5233 return js_DecompileToString(cx
, "JS_DecompileFunctionBody", fun
,
5234 indent
& ~JS_DONT_PRETTY_PRINT
,
5235 !(indent
& JS_DONT_PRETTY_PRINT
),
5236 false, false, js_DecompileFunctionBody
);
5239 JS_NEVER_INLINE
JS_PUBLIC_API(JSBool
)
5240 JS_ExecuteScript(JSContext
*cx
, JSObject
*obj
, JSScript
*scriptArg
, jsval
*rval
)
5242 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
5245 assertSameCompartment(cx
, obj
);
5246 if (cx
->compartment
!= obj
->compartment())
5247 *(volatile int *) 0 = 0xf0;
5248 AutoLastFrameCheck
lfc(cx
);
5250 JS::Anchor
<JSScript
*> script
;
5253 * Mozilla caches pre-compiled scripts (e.g., in the XUL prototype cache)
5254 * and runs them against multiple globals. With a compartment per global,
5255 * this requires cloning the pre-compiled script into each new global.
5256 * Since each script gets run once, there is no point in trying to cache
5257 * this clone. Ideally, this would be handled at some pinch point in
5258 * mozilla, but there doesn't seem to be one, so we handle it here.
5260 if (scriptArg
->compartment() != obj
->compartment()) {
5261 script
= CloneScript(cx
, scriptArg
);
5268 return Execute(cx
, script
.get(), *obj
, rval
);
5271 JS_PUBLIC_API(JSBool
)
5272 JS_ExecuteScriptVersion(JSContext
*cx
, JSObject
*obj
, JSScript
*script
, jsval
*rval
,
5275 AutoVersionAPI
ava(cx
, version
);
5276 return JS_ExecuteScript(cx
, obj
, script
, rval
);
5280 EvaluateUCScriptForPrincipalsCommon(JSContext
*cx
, JSObject
*obj_
,
5281 JSPrincipals
*principals
, JSPrincipals
*originPrincipals
,
5282 const jschar
*chars
, unsigned length
,
5283 const char *filename
, unsigned lineno
,
5284 jsval
*rval
, JSVersion compileVersion
)
5286 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
5288 RootedVarObject
obj(cx
, obj_
);
5290 uint32_t flags
= TCF_COMPILE_N_GO
| TCF_NEED_SCRIPT_GLOBAL
;
5292 flags
|= TCF_NO_SCRIPT_RVAL
;
5295 AutoLastFrameCheck
lfc(cx
);
5296 JSScript
*script
= frontend::CompileScript(cx
, obj
, NULL
, principals
, originPrincipals
,
5297 flags
, chars
, length
, filename
, lineno
,
5302 JS_ASSERT(script
->getVersion() == compileVersion
);
5304 return Execute(cx
, script
, *obj
, rval
);
5307 JS_PUBLIC_API(JSBool
)
5308 JS_EvaluateUCScriptForPrincipals(JSContext
*cx
, JSObject
*obj
,
5309 JSPrincipals
*principals
,
5310 const jschar
*chars
, unsigned length
,
5311 const char *filename
, unsigned lineno
,
5314 return EvaluateUCScriptForPrincipalsCommon(cx
, obj
, principals
, NULL
, chars
, length
,
5315 filename
, lineno
, rval
, cx
->findVersion());
5318 JS_PUBLIC_API(JSBool
)
5319 JS_EvaluateUCScriptForPrincipalsVersion(JSContext
*cx
, JSObject
*obj
,
5320 JSPrincipals
*principals
,
5321 const jschar
*chars
, unsigned length
,
5322 const char *filename
, unsigned lineno
,
5323 jsval
*rval
, JSVersion version
)
5325 AutoVersionAPI
avi(cx
, version
);
5326 return EvaluateUCScriptForPrincipalsCommon(cx
, obj
, principals
, NULL
, chars
, length
,
5327 filename
, lineno
, rval
, avi
.version());
5330 extern JS_PUBLIC_API(JSBool
)
5331 JS_EvaluateUCScriptForPrincipalsVersionOrigin(JSContext
*cx
, JSObject
*obj
,
5332 JSPrincipals
*principals
,
5333 JSPrincipals
*originPrincipals
,
5334 const jschar
*chars
, unsigned length
,
5335 const char *filename
, unsigned lineno
,
5336 jsval
*rval
, JSVersion version
)
5338 AutoVersionAPI
avi(cx
, version
);
5339 return EvaluateUCScriptForPrincipalsCommon(cx
, obj
, principals
, originPrincipals
,
5340 chars
, length
, filename
, lineno
, rval
,
5344 JS_PUBLIC_API(JSBool
)
5345 JS_EvaluateUCScript(JSContext
*cx
, JSObject
*obj
, const jschar
*chars
, unsigned length
,
5346 const char *filename
, unsigned lineno
, jsval
*rval
)
5348 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
5349 return JS_EvaluateUCScriptForPrincipals(cx
, obj
, NULL
, chars
, length
, filename
, lineno
, rval
);
5352 /* Ancient unsigned nbytes is part of API/ABI, so use size_t length local. */
5353 JS_PUBLIC_API(JSBool
)
5354 JS_EvaluateScriptForPrincipals(JSContext
*cx
, JSObject
*obj
, JSPrincipals
*principals
,
5355 const char *bytes
, unsigned nbytes
,
5356 const char *filename
, unsigned lineno
, jsval
*rval
)
5358 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
5359 size_t length
= nbytes
;
5360 jschar
*chars
= InflateString(cx
, bytes
, &length
);
5363 JSBool ok
= JS_EvaluateUCScriptForPrincipals(cx
, obj
, principals
, chars
, length
,
5364 filename
, lineno
, rval
);
5369 JS_PUBLIC_API(JSBool
)
5370 JS_EvaluateScriptForPrincipalsVersion(JSContext
*cx
, JSObject
*obj
, JSPrincipals
*principals
,
5371 const char *bytes
, unsigned nbytes
,
5372 const char *filename
, unsigned lineno
, jsval
*rval
, JSVersion version
)
5374 AutoVersionAPI
avi(cx
, version
);
5375 return JS_EvaluateScriptForPrincipals(cx
, obj
, principals
, bytes
, nbytes
, filename
, lineno
,
5379 JS_PUBLIC_API(JSBool
)
5380 JS_EvaluateScript(JSContext
*cx
, JSObject
*obj
, const char *bytes
, unsigned nbytes
,
5381 const char *filename
, unsigned lineno
, jsval
*rval
)
5383 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
5384 return JS_EvaluateScriptForPrincipals(cx
, obj
, NULL
, bytes
, nbytes
, filename
, lineno
, rval
);
5387 JS_PUBLIC_API(JSBool
)
5388 JS_CallFunction(JSContext
*cx
, JSObject
*obj
, JSFunction
*fun
, unsigned argc
, jsval
*argv
,
5391 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
5394 assertSameCompartment(cx
, obj
, fun
, JSValueArray(argv
, argc
));
5395 AutoLastFrameCheck
lfc(cx
);
5397 return Invoke(cx
, ObjectOrNullValue(obj
), ObjectValue(*fun
), argc
, argv
, rval
);
5400 JS_PUBLIC_API(JSBool
)
5401 JS_CallFunctionName(JSContext
*cx
, JSObject
*obj_
, const char *name
, unsigned argc
, jsval
*argv
,
5404 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
5407 assertSameCompartment(cx
, obj_
, JSValueArray(argv
, argc
));
5408 AutoLastFrameCheck
lfc(cx
);
5410 RootedVarObject
obj(cx
, obj_
);
5413 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
));
5415 js_GetMethod(cx
, obj
, AtomToId(atom
), 0, &v
) &&
5416 Invoke(cx
, ObjectOrNullValue(obj
), v
, argc
, argv
, rval
);
5419 JS_PUBLIC_API(JSBool
)
5420 JS_CallFunctionValue(JSContext
*cx
, JSObject
*obj
, jsval fval
, unsigned argc
, jsval
*argv
,
5423 JS_THREADSAFE_ASSERT(cx
->compartment
!= cx
->runtime
->atomsCompartment
);
5426 assertSameCompartment(cx
, obj
, fval
, JSValueArray(argv
, argc
));
5427 AutoLastFrameCheck
lfc(cx
);
5429 return Invoke(cx
, ObjectOrNullValue(obj
), fval
, argc
, argv
, rval
);
5435 Call(JSContext
*cx
, jsval thisv
, jsval fval
, unsigned argc
, jsval
*argv
, jsval
*rval
)
5439 assertSameCompartment(cx
, thisv
, fval
, JSValueArray(argv
, argc
));
5440 AutoLastFrameCheck
lfc(cx
);
5442 return Invoke(cx
, thisv
, fval
, argc
, argv
, rval
);
5447 JS_PUBLIC_API(JSObject
*)
5448 JS_New(JSContext
*cx
, JSObject
*ctor
, unsigned argc
, jsval
*argv
)
5452 assertSameCompartment(cx
, ctor
, JSValueArray(argv
, argc
));
5453 AutoLastFrameCheck
lfc(cx
);
5455 // This is not a simple variation of JS_CallFunctionValue because JSOP_NEW
5456 // is not a simple variation of JSOP_CALL. We have to determine what class
5457 // of object to create, create it, and clamp the return value to an object,
5458 // among other details. InvokeConstructor does the hard work.
5459 InvokeArgsGuard args
;
5460 if (!cx
->stack
.pushInvokeArgs(cx
, argc
, &args
))
5463 args
.calleev().setObject(*ctor
);
5464 args
.thisv().setNull();
5465 PodCopy(args
.array(), argv
, argc
);
5467 if (!InvokeConstructor(cx
, args
))
5470 if (!args
.rval().isObject()) {
5472 * Although constructors may return primitives (via proxies), this
5473 * API is asking for an object, so we report an error.
5475 JSAutoByteString bytes
;
5476 if (js_ValueToPrintable(cx
, args
.rval(), &bytes
)) {
5477 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_BAD_NEW_RESULT
,
5483 return &args
.rval().toObject();
5486 JS_PUBLIC_API(JSOperationCallback
)
5487 JS_SetOperationCallback(JSContext
*cx
, JSOperationCallback callback
)
5489 JSOperationCallback old
= cx
->operationCallback
;
5490 cx
->operationCallback
= callback
;
5494 JS_PUBLIC_API(JSOperationCallback
)
5495 JS_GetOperationCallback(JSContext
*cx
)
5497 return cx
->operationCallback
;
5501 JS_TriggerOperationCallback(JSRuntime
*rt
)
5503 rt
->triggerOperationCallback();
5506 JS_PUBLIC_API(JSBool
)
5507 JS_IsRunning(JSContext
*cx
)
5509 StackFrame
*fp
= cx
->maybefp();
5510 while (fp
&& fp
->isDummyFrame())
5515 JS_PUBLIC_API(JSBool
)
5516 JS_SaveFrameChain(JSContext
*cx
)
5520 return cx
->stack
.saveFrameChain();
5524 JS_RestoreFrameChain(JSContext
*cx
)
5528 cx
->stack
.restoreFrameChain();
5531 #ifdef MOZ_TRACE_JSCALLS
5533 JS_SetFunctionCallback(JSContext
*cx
, JSFunctionCallback fcb
)
5535 cx
->functionCallback
= fcb
;
5538 JS_PUBLIC_API(JSFunctionCallback
)
5539 JS_GetFunctionCallback(JSContext
*cx
)
5541 return cx
->functionCallback
;
5545 /************************************************************************/
5546 JS_PUBLIC_API(JSString
*)
5547 JS_NewStringCopyN(JSContext
*cx
, const char *s
, size_t n
)
5551 return js_NewStringCopyN(cx
, s
, n
);
5554 JS_PUBLIC_API(JSString
*)
5555 JS_NewStringCopyZ(JSContext
*cx
, const char *s
)
5564 return cx
->runtime
->emptyString
;
5566 js
= InflateString(cx
, s
, &n
);
5569 str
= js_NewString(cx
, js
, n
);
5575 JS_PUBLIC_API(JSBool
)
5576 JS_StringHasBeenInterned(JSContext
*cx
, JSString
*str
)
5584 return AtomIsInterned(cx
, &str
->asAtom());
5588 INTERNED_STRING_TO_JSID(JSContext
*cx
, JSString
*str
)
5591 JS_ASSERT(((size_t)str
& JSID_TYPE_MASK
) == 0);
5592 JS_ASSERT_IF(cx
, JS_StringHasBeenInterned(cx
, str
));
5593 return AtomToId(&str
->asAtom());
5596 JS_PUBLIC_API(JSString
*)
5597 JS_InternJSString(JSContext
*cx
, JSString
*str
)
5601 JSAtom
*atom
= js_AtomizeString(cx
, str
, InternAtom
);
5602 JS_ASSERT_IF(atom
, JS_StringHasBeenInterned(cx
, atom
));
5606 JS_PUBLIC_API(JSString
*)
5607 JS_InternString(JSContext
*cx
, const char *s
)
5611 JSAtom
*atom
= js_Atomize(cx
, s
, strlen(s
), InternAtom
);
5612 JS_ASSERT_IF(atom
, JS_StringHasBeenInterned(cx
, atom
));
5616 JS_PUBLIC_API(JSString
*)
5617 JS_NewUCString(JSContext
*cx
, jschar
*chars
, size_t length
)
5621 return js_NewString(cx
, chars
, length
);
5624 JS_PUBLIC_API(JSString
*)
5625 JS_NewUCStringCopyN(JSContext
*cx
, const jschar
*s
, size_t n
)
5629 return js_NewStringCopyN(cx
, s
, n
);
5632 JS_PUBLIC_API(JSString
*)
5633 JS_NewUCStringCopyZ(JSContext
*cx
, const jschar
*s
)
5638 return cx
->runtime
->emptyString
;
5639 return js_NewStringCopyZ(cx
, s
);
5642 JS_PUBLIC_API(JSString
*)
5643 JS_InternUCStringN(JSContext
*cx
, const jschar
*s
, size_t length
)
5647 JSAtom
*atom
= js_AtomizeChars(cx
, s
, length
, InternAtom
);
5648 JS_ASSERT_IF(atom
, JS_StringHasBeenInterned(cx
, atom
));
5652 JS_PUBLIC_API(JSString
*)
5653 JS_InternUCString(JSContext
*cx
, const jschar
*s
)
5655 return JS_InternUCStringN(cx
, s
, js_strlen(s
));
5658 JS_PUBLIC_API(size_t)
5659 JS_GetStringLength(JSString
*str
)
5661 return str
->length();
5664 JS_PUBLIC_API(const jschar
*)
5665 JS_GetStringCharsZ(JSContext
*cx
, JSString
*str
)
5667 AssertNoGCOrFlatString(cx
, str
);
5669 assertSameCompartment(cx
, str
);
5670 return str
->getCharsZ(cx
);
5673 JS_PUBLIC_API(const jschar
*)
5674 JS_GetStringCharsZAndLength(JSContext
*cx
, JSString
*str
, size_t *plength
)
5676 AssertNoGCOrFlatString(cx
, str
);
5678 assertSameCompartment(cx
, str
);
5679 *plength
= str
->length();
5680 return str
->getCharsZ(cx
);
5683 JS_PUBLIC_API(const jschar
*)
5684 JS_GetStringCharsAndLength(JSContext
*cx
, JSString
*str
, size_t *plength
)
5686 AssertNoGCOrFlatString(cx
, str
);
5688 assertSameCompartment(cx
, str
);
5689 *plength
= str
->length();
5690 return str
->getChars(cx
);
5693 JS_PUBLIC_API(const jschar
*)
5694 JS_GetInternedStringChars(JSString
*str
)
5696 return str
->asAtom().chars();
5699 JS_PUBLIC_API(const jschar
*)
5700 JS_GetInternedStringCharsAndLength(JSString
*str
, size_t *plength
)
5702 JSAtom
&atom
= str
->asAtom();
5703 *plength
= atom
.length();
5704 return atom
.chars();
5707 extern JS_PUBLIC_API(JSFlatString
*)
5708 JS_FlattenString(JSContext
*cx
, JSString
*str
)
5712 assertSameCompartment(cx
, str
);
5713 return str
->getCharsZ(cx
) ? (JSFlatString
*)str
: NULL
;
5716 extern JS_PUBLIC_API(const jschar
*)
5717 JS_GetFlatStringChars(JSFlatString
*str
)
5719 return str
->chars();
5722 JS_PUBLIC_API(JSBool
)
5723 JS_CompareStrings(JSContext
*cx
, JSString
*str1
, JSString
*str2
, int32_t *result
)
5728 return CompareStrings(cx
, str1
, str2
, result
);
5731 JS_PUBLIC_API(JSBool
)
5732 JS_StringEqualsAscii(JSContext
*cx
, JSString
*str
, const char *asciiBytes
, JSBool
*match
)
5737 JSLinearString
*linearStr
= str
->ensureLinear(cx
);
5740 *match
= StringEqualsAscii(linearStr
, asciiBytes
);
5744 JS_PUBLIC_API(JSBool
)
5745 JS_FlatStringEqualsAscii(JSFlatString
*str
, const char *asciiBytes
)
5747 return StringEqualsAscii(str
, asciiBytes
);
5750 JS_PUBLIC_API(size_t)
5751 JS_PutEscapedFlatString(char *buffer
, size_t size
, JSFlatString
*str
, char quote
)
5753 return PutEscapedString(buffer
, size
, str
, quote
);
5756 JS_PUBLIC_API(size_t)
5757 JS_PutEscapedString(JSContext
*cx
, char *buffer
, size_t size
, JSString
*str
, char quote
)
5760 JSLinearString
*linearStr
= str
->ensureLinear(cx
);
5763 return PutEscapedString(buffer
, size
, linearStr
, quote
);
5766 JS_PUBLIC_API(JSBool
)
5767 JS_FileEscapedString(FILE *fp
, JSString
*str
, char quote
)
5769 JSLinearString
*linearStr
= str
->ensureLinear(NULL
);
5770 return linearStr
&& FileEscapedString(fp
, linearStr
, quote
);
5773 JS_PUBLIC_API(JSString
*)
5774 JS_NewGrowableString(JSContext
*cx
, jschar
*chars
, size_t length
)
5778 return js_NewString(cx
, chars
, length
);
5781 JS_PUBLIC_API(JSString
*)
5782 JS_NewDependentString(JSContext
*cx
, JSString
*str
, size_t start
, size_t length
)
5786 return js_NewDependentString(cx
, str
, start
, length
);
5789 JS_PUBLIC_API(JSString
*)
5790 JS_ConcatStrings(JSContext
*cx
, JSString
*left
, JSString
*right
)
5794 return js_ConcatStrings(cx
, RootedVarString(cx
, left
), RootedVarString(cx
, right
));
5797 JS_PUBLIC_API(const jschar
*)
5798 JS_UndependString(JSContext
*cx
, JSString
*str
)
5802 return str
->getCharsZ(cx
);
5805 JS_PUBLIC_API(JSBool
)
5806 JS_MakeStringImmutable(JSContext
*cx
, JSString
*str
)
5810 return !!str
->ensureFixed(cx
);
5813 JS_PUBLIC_API(JSBool
)
5814 JS_EncodeCharacters(JSContext
*cx
, const jschar
*src
, size_t srclen
, char *dst
, size_t *dstlenp
)
5821 n
= GetDeflatedStringLength(cx
, src
, srclen
);
5822 if (n
== (size_t)-1) {
5830 return DeflateStringToBuffer(cx
, src
, srclen
, dst
, dstlenp
);
5833 JS_PUBLIC_API(JSBool
)
5834 JS_DecodeBytes(JSContext
*cx
, const char *src
, size_t srclen
, jschar
*dst
, size_t *dstlenp
)
5838 return InflateStringToBuffer(cx
, src
, srclen
, dst
, dstlenp
);
5841 JS_PUBLIC_API(JSBool
)
5842 JS_DecodeUTF8(JSContext
*cx
, const char *src
, size_t srclen
, jschar
*dst
,
5847 return InflateUTF8StringToBuffer(cx
, src
, srclen
, dst
, dstlenp
);
5850 JS_PUBLIC_API(char *)
5851 JS_EncodeString(JSContext
*cx
, JSString
*str
)
5856 const jschar
*chars
= str
->getChars(cx
);
5859 return DeflateString(cx
, chars
, str
->length());
5862 JS_PUBLIC_API(size_t)
5863 JS_GetStringEncodingLength(JSContext
*cx
, JSString
*str
)
5865 /* jsd calls us with a NULL cx. Ugh. */
5871 const jschar
*chars
= str
->getChars(cx
);
5874 return GetDeflatedStringLength(cx
, chars
, str
->length());
5877 JS_PUBLIC_API(size_t)
5878 JS_EncodeStringToBuffer(JSString
*str
, char *buffer
, size_t length
)
5881 * FIXME bug 612141 - fix DeflateStringToBuffer interface so the result
5882 * would allow to distinguish between insufficient buffer and encoding
5885 size_t writtenLength
= length
;
5886 const jschar
*chars
= str
->getChars(NULL
);
5889 if (DeflateStringToBuffer(NULL
, chars
, str
->length(), buffer
, &writtenLength
)) {
5890 JS_ASSERT(writtenLength
<= length
);
5891 return writtenLength
;
5893 JS_ASSERT(writtenLength
<= length
);
5894 size_t necessaryLength
= GetDeflatedStringLength(NULL
, chars
, str
->length());
5895 if (necessaryLength
== size_t(-1))
5897 if (writtenLength
!= length
) {
5898 /* Make sure that the buffer contains only valid UTF-8 sequences. */
5899 JS_ASSERT(js_CStringsAreUTF8
);
5900 PodZero(buffer
+ writtenLength
, length
- writtenLength
);
5902 return necessaryLength
;
5905 JS_PUBLIC_API(JSBool
)
5906 JS_Stringify(JSContext
*cx
, jsval
*vp
, JSObject
*replacer
, jsval space
,
5907 JSONWriteCallback callback
, void *data
)
5911 assertSameCompartment(cx
, replacer
, space
);
5912 StringBuffer
sb(cx
);
5913 if (!js_Stringify(cx
, vp
, replacer
, space
, sb
))
5916 JSAtom
*nullAtom
= cx
->runtime
->atomState
.nullAtom
;
5917 return callback(nullAtom
->chars(), nullAtom
->length(), data
);
5919 return callback(sb
.begin(), sb
.length(), data
);
5922 JS_PUBLIC_API(JSBool
)
5923 JS_ParseJSON(JSContext
*cx
, const jschar
*chars
, uint32_t len
, jsval
*vp
)
5928 return ParseJSONWithReviver(cx
, chars
, len
, NullValue(), vp
);
5931 JS_PUBLIC_API(JSBool
)
5932 JS_ParseJSONWithReviver(JSContext
*cx
, const jschar
*chars
, uint32_t len
, jsval reviver
, jsval
*vp
)
5937 return ParseJSONWithReviver(cx
, chars
, len
, reviver
, vp
);
5940 JS_PUBLIC_API(JSBool
)
5941 JS_ReadStructuredClone(JSContext
*cx
, const uint64_t *buf
, size_t nbytes
,
5942 uint32_t version
, jsval
*vp
,
5943 const JSStructuredCloneCallbacks
*optionalCallbacks
,
5949 if (version
> JS_STRUCTURED_CLONE_VERSION
) {
5950 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_BAD_CLONE_VERSION
);
5953 const JSStructuredCloneCallbacks
*callbacks
=
5956 cx
->runtime
->structuredCloneCallbacks
;
5957 return ReadStructuredClone(cx
, buf
, nbytes
, vp
, callbacks
, closure
);
5960 JS_PUBLIC_API(JSBool
)
5961 JS_WriteStructuredClone(JSContext
*cx
, jsval v
, uint64_t **bufp
, size_t *nbytesp
,
5962 const JSStructuredCloneCallbacks
*optionalCallbacks
,
5967 assertSameCompartment(cx
, v
);
5969 const JSStructuredCloneCallbacks
*callbacks
=
5972 cx
->runtime
->structuredCloneCallbacks
;
5973 return WriteStructuredClone(cx
, v
, (uint64_t **) bufp
, nbytesp
, callbacks
, closure
);
5976 JS_PUBLIC_API(JSBool
)
5977 JS_StructuredClone(JSContext
*cx
, jsval v
, jsval
*vp
,
5978 const JSStructuredCloneCallbacks
*optionalCallbacks
,
5983 assertSameCompartment(cx
, v
);
5985 const JSStructuredCloneCallbacks
*callbacks
=
5988 cx
->runtime
->structuredCloneCallbacks
;
5989 JSAutoStructuredCloneBuffer buf
;
5990 return buf
.write(cx
, v
, callbacks
, closure
) &&
5991 buf
.read(cx
, vp
, callbacks
, closure
);
5995 JSAutoStructuredCloneBuffer::clear()
5998 Foreground::free_(data_
);
6006 JSAutoStructuredCloneBuffer::adopt(uint64_t *data
, size_t nbytes
, uint32_t version
)
6015 JSAutoStructuredCloneBuffer::copy(const uint64_t *srcData
, size_t nbytes
, uint32_t version
)
6017 uint64_t *newData
= static_cast<uint64_t *>(OffTheBooks::malloc_(nbytes
));
6021 js_memcpy(newData
, srcData
, nbytes
);
6030 JSAutoStructuredCloneBuffer::steal(uint64_t **datap
, size_t *nbytesp
, uint32_t *versionp
)
6035 *versionp
= version_
;
6043 JSAutoStructuredCloneBuffer::read(JSContext
*cx
, jsval
*vp
,
6044 const JSStructuredCloneCallbacks
*optionalCallbacks
,
6045 void *closure
) const
6049 return !!JS_ReadStructuredClone(cx
, data_
, nbytes_
, version_
, vp
,
6050 optionalCallbacks
, closure
);
6054 JSAutoStructuredCloneBuffer::write(JSContext
*cx
, jsval v
,
6055 const JSStructuredCloneCallbacks
*optionalCallbacks
,
6059 bool ok
= !!JS_WriteStructuredClone(cx
, v
, &data_
, &nbytes_
,
6060 optionalCallbacks
, closure
);
6064 version_
= JS_STRUCTURED_CLONE_VERSION
;
6070 JSAutoStructuredCloneBuffer::swap(JSAutoStructuredCloneBuffer
&other
)
6072 uint64_t *data
= other
.data_
;
6073 size_t nbytes
= other
.nbytes_
;
6074 uint32_t version
= other
.version_
;
6076 other
.data_
= this->data_
;
6077 other
.nbytes_
= this->nbytes_
;
6078 other
.version_
= this->version_
;
6081 this->nbytes_
= nbytes
;
6082 this->version_
= version
;
6086 JS_SetStructuredCloneCallbacks(JSRuntime
*rt
, const JSStructuredCloneCallbacks
*callbacks
)
6088 rt
->structuredCloneCallbacks
= callbacks
;
6091 JS_PUBLIC_API(JSBool
)
6092 JS_ReadUint32Pair(JSStructuredCloneReader
*r
, uint32_t *p1
, uint32_t *p2
)
6094 return r
->input().readPair((uint32_t *) p1
, (uint32_t *) p2
);
6097 JS_PUBLIC_API(JSBool
)
6098 JS_ReadBytes(JSStructuredCloneReader
*r
, void *p
, size_t len
)
6100 return r
->input().readBytes(p
, len
);
6103 JS_PUBLIC_API(JSBool
)
6104 JS_WriteUint32Pair(JSStructuredCloneWriter
*w
, uint32_t tag
, uint32_t data
)
6106 return w
->output().writePair(tag
, data
);
6109 JS_PUBLIC_API(JSBool
)
6110 JS_WriteBytes(JSStructuredCloneWriter
*w
, const void *p
, size_t len
)
6112 return w
->output().writeBytes(p
, len
);
6116 * The following determines whether C Strings are to be treated as UTF-8
6117 * or ISO-8859-1. For correct operation, it must be set prior to the
6118 * first call to JS_NewRuntime.
6120 #ifndef JS_C_STRINGS_ARE_UTF8
6121 JSBool js_CStringsAreUTF8
= JS_FALSE
;
6124 JS_PUBLIC_API(JSBool
)
6125 JS_CStringsAreUTF8()
6127 return js_CStringsAreUTF8
;
6131 JS_SetCStringsAreUTF8()
6133 JS_ASSERT(!js_NewRuntimeWasCalled
);
6135 #ifndef JS_C_STRINGS_ARE_UTF8
6136 js_CStringsAreUTF8
= JS_TRUE
;
6140 /************************************************************************/
6143 JS_ReportError(JSContext
*cx
, const char *format
, ...)
6148 va_start(ap
, format
);
6149 js_ReportErrorVA(cx
, JSREPORT_ERROR
, format
, ap
);
6154 JS_ReportErrorNumber(JSContext
*cx
, JSErrorCallback errorCallback
,
6155 void *userRef
, const unsigned errorNumber
, ...)
6160 va_start(ap
, errorNumber
);
6161 js_ReportErrorNumberVA(cx
, JSREPORT_ERROR
, errorCallback
, userRef
,
6162 errorNumber
, JS_TRUE
, ap
);
6167 JS_ReportErrorNumberUC(JSContext
*cx
, JSErrorCallback errorCallback
,
6168 void *userRef
, const unsigned errorNumber
, ...)
6173 va_start(ap
, errorNumber
);
6174 js_ReportErrorNumberVA(cx
, JSREPORT_ERROR
, errorCallback
, userRef
,
6175 errorNumber
, JS_FALSE
, ap
);
6179 JS_PUBLIC_API(JSBool
)
6180 JS_ReportWarning(JSContext
*cx
, const char *format
, ...)
6186 va_start(ap
, format
);
6187 ok
= js_ReportErrorVA(cx
, JSREPORT_WARNING
, format
, ap
);
6192 JS_PUBLIC_API(JSBool
)
6193 JS_ReportErrorFlagsAndNumber(JSContext
*cx
, unsigned flags
,
6194 JSErrorCallback errorCallback
, void *userRef
,
6195 const unsigned errorNumber
, ...)
6201 va_start(ap
, errorNumber
);
6202 ok
= js_ReportErrorNumberVA(cx
, flags
, errorCallback
, userRef
,
6203 errorNumber
, JS_TRUE
, ap
);
6208 JS_PUBLIC_API(JSBool
)
6209 JS_ReportErrorFlagsAndNumberUC(JSContext
*cx
, unsigned flags
,
6210 JSErrorCallback errorCallback
, void *userRef
,
6211 const unsigned errorNumber
, ...)
6217 va_start(ap
, errorNumber
);
6218 ok
= js_ReportErrorNumberVA(cx
, flags
, errorCallback
, userRef
,
6219 errorNumber
, JS_FALSE
, ap
);
6225 JS_ReportOutOfMemory(JSContext
*cx
)
6227 js_ReportOutOfMemory(cx
);
6231 JS_ReportAllocationOverflow(JSContext
*cx
)
6233 js_ReportAllocationOverflow(cx
);
6236 JS_PUBLIC_API(JSErrorReporter
)
6237 JS_GetErrorReporter(JSContext
*cx
)
6239 return cx
->errorReporter
;
6242 JS_PUBLIC_API(JSErrorReporter
)
6243 JS_SetErrorReporter(JSContext
*cx
, JSErrorReporter er
)
6245 JSErrorReporter older
;
6247 older
= cx
->errorReporter
;
6248 cx
->errorReporter
= er
;
6252 /************************************************************************/
6257 JS_PUBLIC_API(JSObject
*)
6258 JS_NewDateObject(JSContext
*cx
, int year
, int mon
, int mday
, int hour
, int min
, int sec
)
6262 return js_NewDateObject(cx
, year
, mon
, mday
, hour
, min
, sec
);
6265 JS_PUBLIC_API(JSObject
*)
6266 JS_NewDateObjectMsec(JSContext
*cx
, double msec
)
6270 return js_NewDateObjectMsec(cx
, msec
);
6273 JS_PUBLIC_API(JSBool
)
6274 JS_ObjectIsDate(JSContext
*cx
, JSObject
*obj
)
6278 return obj
->isDate();
6281 /************************************************************************/
6284 * Regular Expressions.
6286 JS_PUBLIC_API(JSObject
*)
6287 JS_NewRegExpObject(JSContext
*cx
, JSObject
*obj
, char *bytes
, size_t length
, unsigned flags
)
6291 jschar
*chars
= InflateString(cx
, bytes
, &length
);
6295 RegExpStatics
*res
= obj
->asGlobal().getRegExpStatics();
6296 RegExpObject
*reobj
= RegExpObject::create(cx
, res
, chars
, length
, RegExpFlag(flags
), NULL
);
6301 JS_PUBLIC_API(JSObject
*)
6302 JS_NewUCRegExpObject(JSContext
*cx
, JSObject
*obj
, jschar
*chars
, size_t length
, unsigned flags
)
6306 RegExpStatics
*res
= obj
->asGlobal().getRegExpStatics();
6307 return RegExpObject::create(cx
, res
, chars
, length
, RegExpFlag(flags
), NULL
);
6311 JS_SetRegExpInput(JSContext
*cx
, JSObject
*obj
, JSString
*input
, JSBool multiline
)
6315 assertSameCompartment(cx
, input
);
6317 obj
->asGlobal().getRegExpStatics()->reset(cx
, input
, !!multiline
);
6321 JS_ClearRegExpStatics(JSContext
*cx
, JSObject
*obj
)
6327 obj
->asGlobal().getRegExpStatics()->clear();
6330 JS_PUBLIC_API(JSBool
)
6331 JS_ExecuteRegExp(JSContext
*cx
, JSObject
*obj
, JSObject
*reobj
, jschar
*chars
, size_t length
,
6332 size_t *indexp
, JSBool test
, jsval
*rval
)
6337 RegExpStatics
*res
= obj
->asGlobal().getRegExpStatics();
6338 return ExecuteRegExp(cx
, res
, reobj
->asRegExp(), NULL
, chars
, length
,
6339 indexp
, test
? RegExpTest
: RegExpExec
, rval
);
6342 JS_PUBLIC_API(JSObject
*)
6343 JS_NewRegExpObjectNoStatics(JSContext
*cx
, char *bytes
, size_t length
, unsigned flags
)
6347 jschar
*chars
= InflateString(cx
, bytes
, &length
);
6350 RegExpObject
*reobj
= RegExpObject::createNoStatics(cx
, chars
, length
, RegExpFlag(flags
), NULL
);
6355 JS_PUBLIC_API(JSObject
*)
6356 JS_NewUCRegExpObjectNoStatics(JSContext
*cx
, jschar
*chars
, size_t length
, unsigned flags
)
6360 return RegExpObject::createNoStatics(cx
, chars
, length
, RegExpFlag(flags
), NULL
);
6363 JS_PUBLIC_API(JSBool
)
6364 JS_ExecuteRegExpNoStatics(JSContext
*cx
, JSObject
*obj
, jschar
*chars
, size_t length
,
6365 size_t *indexp
, JSBool test
, jsval
*rval
)
6370 return ExecuteRegExp(cx
, NULL
, obj
->asRegExp(), NULL
, chars
, length
, indexp
,
6371 test
? RegExpTest
: RegExpExec
, rval
);
6374 JS_PUBLIC_API(JSBool
)
6375 JS_ObjectIsRegExp(JSContext
*cx
, JSObject
*obj
)
6379 return obj
->isRegExp();
6382 JS_PUBLIC_API(unsigned)
6383 JS_GetRegExpFlags(JSContext
*cx
, JSObject
*obj
)
6388 return obj
->asRegExp().getFlags();
6391 JS_PUBLIC_API(JSString
*)
6392 JS_GetRegExpSource(JSContext
*cx
, JSObject
*obj
)
6397 return obj
->asRegExp().getSource();
6400 /************************************************************************/
6403 JS_SetLocaleCallbacks(JSContext
*cx
, JSLocaleCallbacks
*callbacks
)
6406 cx
->localeCallbacks
= callbacks
;
6409 JS_PUBLIC_API(JSLocaleCallbacks
*)
6410 JS_GetLocaleCallbacks(JSContext
*cx
)
6412 /* This function can be called by a finalizer. */
6413 return cx
->localeCallbacks
;
6416 /************************************************************************/
6418 JS_PUBLIC_API(JSBool
)
6419 JS_IsExceptionPending(JSContext
*cx
)
6421 /* This function can be called by a finalizer. */
6422 return (JSBool
) cx
->isExceptionPending();
6425 JS_PUBLIC_API(JSBool
)
6426 JS_GetPendingException(JSContext
*cx
, jsval
*vp
)
6430 if (!cx
->isExceptionPending())
6432 *vp
= cx
->getPendingException();
6433 assertSameCompartment(cx
, *vp
);
6438 JS_SetPendingException(JSContext
*cx
, jsval v
)
6442 assertSameCompartment(cx
, v
);
6443 cx
->setPendingException(v
);
6447 JS_ClearPendingException(JSContext
*cx
)
6450 cx
->clearPendingException();
6453 JS_PUBLIC_API(JSBool
)
6454 JS_ReportPendingException(JSContext
*cx
)
6459 return js_ReportUncaughtException(cx
);
6462 struct JSExceptionState
{
6467 JS_PUBLIC_API(JSExceptionState
*)
6468 JS_SaveExceptionState(JSContext
*cx
)
6470 JSExceptionState
*state
;
6474 state
= (JSExceptionState
*) cx
->malloc_(sizeof(JSExceptionState
));
6476 state
->throwing
= JS_GetPendingException(cx
, &state
->exception
);
6477 if (state
->throwing
&& JSVAL_IS_GCTHING(state
->exception
))
6478 js_AddRoot(cx
, &state
->exception
, "JSExceptionState.exception");
6484 JS_RestoreExceptionState(JSContext
*cx
, JSExceptionState
*state
)
6489 if (state
->throwing
)
6490 JS_SetPendingException(cx
, state
->exception
);
6492 JS_ClearPendingException(cx
);
6493 JS_DropExceptionState(cx
, state
);
6498 JS_DropExceptionState(JSContext
*cx
, JSExceptionState
*state
)
6503 if (state
->throwing
&& JSVAL_IS_GCTHING(state
->exception
)) {
6504 assertSameCompartment(cx
, state
->exception
);
6505 JS_RemoveValueRoot(cx
, &state
->exception
);
6511 JS_PUBLIC_API(JSErrorReport
*)
6512 JS_ErrorFromException(JSContext
*cx
, jsval v
)
6516 assertSameCompartment(cx
, v
);
6517 return js_ErrorFromException(cx
, v
);
6520 JS_PUBLIC_API(JSBool
)
6521 JS_ThrowReportedError(JSContext
*cx
, const char *message
,
6522 JSErrorReport
*reportp
)
6525 return JS_IsRunning(cx
) &&
6526 js_ErrorToException(cx
, message
, reportp
, NULL
, NULL
);
6529 JS_PUBLIC_API(JSBool
)
6530 JS_ThrowStopIteration(JSContext
*cx
)
6533 return js_ThrowStopIteration(cx
);
6536 JS_PUBLIC_API(intptr_t)
6537 JS_GetCurrentThread()
6539 #ifdef JS_THREADSAFE
6540 return reinterpret_cast<intptr_t>(PR_GetCurrentThread());
6546 extern JS_PUBLIC_API(void)
6547 JS_ClearRuntimeThread(JSRuntime
*rt
)
6550 #ifdef JS_THREADSAFE
6551 rt
->clearOwnerThread();
6555 extern JS_PUBLIC_API(void)
6556 JS_SetRuntimeThread(JSRuntime
*rt
)
6559 #ifdef JS_THREADSAFE
6560 rt
->setOwnerThread();
6564 extern JS_NEVER_INLINE
JS_PUBLIC_API(void)
6565 JS_AbortIfWrongThread(JSRuntime
*rt
)
6567 #ifdef JS_THREADSAFE
6568 if (!rt
->onOwnerThread())
6569 MOZ_Assert("rt->onOwnerThread()", __FILE__
, __LINE__
);
6575 JS_SetGCZeal(JSContext
*cx
, uint8_t zeal
, uint32_t frequency
)
6577 const char *env
= getenv("JS_GC_ZEAL");
6579 if (0 == strcmp(env
, "help")) {
6580 printf("Format: JS_GC_ZEAL=N[,F]\n"
6581 "N indicates \"zealousness\":\n"
6582 " 0: no additional GCs\n"
6583 " 1: additional GCs at common danger points\n"
6584 " 2: GC every F allocations (default: 100)\n"
6585 " 3: GC when the window paints (browser only)\n"
6586 " 4: Verify write barriers between instructions\n"
6587 " 5: Verify write barriers between paints\n");
6589 const char *p
= strchr(env
, ',');
6591 frequency
= p
? atoi(p
+ 1) : JS_DEFAULT_ZEAL_FREQ
;
6594 bool schedule
= zeal
>= js::gc::ZealAllocValue
;
6595 cx
->runtime
->gcZeal_
= zeal
;
6596 cx
->runtime
->gcZealFrequency
= frequency
;
6597 cx
->runtime
->gcNextScheduled
= schedule
? frequency
: 0;
6601 JS_ScheduleGC(JSContext
*cx
, uint32_t count
)
6603 cx
->runtime
->gcNextScheduled
= count
;
6607 /************************************************************************/
6609 #if !defined(STATIC_EXPORTABLE_JS_API) && !defined(STATIC_JS_API) && defined(XP_WIN)
6614 * Initialization routine for the JS DLL.
6616 BOOL WINAPI
DllMain (HINSTANCE hDLL
, DWORD dwReason
, LPVOID lpReserved
)
6623 JS_PUBLIC_API(JSBool
)
6624 JS_IndexToId(JSContext
*cx
, uint32_t index
, jsid
*id
)
6626 return IndexToId(cx
, index
, id
);
6629 JS_PUBLIC_API(JSBool
)
6630 JS_IsIdentifier(JSContext
*cx
, JSString
*str
, JSBool
*isIdentifier
)
6632 assertSameCompartment(cx
, str
);
6634 JSLinearString
* linearStr
= str
->ensureLinear(cx
);
6638 *isIdentifier
= js::IsIdentifier(linearStr
);
6642 JS_PUBLIC_API(JSBool
)
6643 JS_DescribeScriptedCaller(JSContext
*cx
, JSScript
**script
, unsigned *lineno
)
6650 ScriptFrameIter
i(cx
);
6655 *script
= i
.script();
6657 *lineno
= js::PCToLineNumber(i
.script(), i
.pc());
6661 #ifdef JS_THREADSAFE
6663 CallOnce(void *func
)
6665 JSInitCallback init
= JS_DATA_TO_FUNC_PTR(JSInitCallback
, func
);
6666 return init() ? PR_SUCCESS
: PR_FAILURE
;
6670 JS_PUBLIC_API(JSBool
)
6671 JS_CallOnce(JSCallOnceType
*once
, JSInitCallback func
)
6673 #ifdef JS_THREADSAFE
6674 return PR_CallOnceWithArg(once
, CallOnce
, JS_FUNC_TO_DATA_PTR(void *, func
)) == PR_SUCCESS
;
6687 AutoGCRooter::AutoGCRooter(JSContext
*cx
, ptrdiff_t tag
)
6688 : down(cx
->runtime
->autoGCRooters
), tag(tag
), stackTop(&cx
->runtime
->autoGCRooters
)
6690 JS_ASSERT(this != *stackTop
);
6694 AutoEnumStateRooter::~AutoEnumStateRooter()
6696 if (!stateValue
.isNull())
6697 MOZ_ALWAYS_TRUE(obj
->enumerate(context
, JSENUMERATE_DESTROY
, &stateValue
, 0));
6702 AssertArgumentsAreSane(JSContext
*cx
, const JS::Value
&v
)
6706 assertSameCompartment(cx
, v
);
6712 JS_PUBLIC_API(void *)
6713 JS_EncodeScript(JSContext
*cx
, JSScript
*script
, uint32_t *lengthp
)
6715 XDREncoder
encoder(cx
);
6716 if (!encoder
.codeScript(&script
))
6718 return encoder
.forgetData(lengthp
);
6721 JS_PUBLIC_API(void *)
6722 JS_EncodeInterpretedFunction(JSContext
*cx
, JSObject
*funobj
, uint32_t *lengthp
)
6724 XDREncoder
encoder(cx
);
6725 if (!encoder
.codeFunction(&funobj
))
6727 return encoder
.forgetData(lengthp
);
6730 JS_PUBLIC_API(JSScript
*)
6731 JS_DecodeScript(JSContext
*cx
, const void *data
, uint32_t length
,
6732 JSPrincipals
*principals
, JSPrincipals
*originPrincipals
)
6734 XDRDecoder
decoder(cx
, data
, length
, principals
, originPrincipals
);
6736 if (!decoder
.codeScript(&script
))
6741 JS_PUBLIC_API(JSObject
*)
6742 JS_DecodeInterpretedFunction(JSContext
*cx
, const void *data
, uint32_t length
,
6743 JSPrincipals
*principals
, JSPrincipals
*originPrincipals
)
6745 XDRDecoder
decoder(cx
, data
, length
, principals
, originPrincipals
);
6747 if (!decoder
.codeFunction(&funobj
))
6752 JS_PUBLIC_API(JSObject
*)
6753 JS_GetScriptedGlobal(JSContext
*cx
)
6755 ScriptFrameIter
i(cx
);
6757 return JS_GetGlobalForScopeChain(cx
);
6759 return JS_GetGlobalForFrame(Jsvalify(i
.fp()));