gecko/js/src/jsfriendapi.h

1503 lines
48 KiB
C++

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef jsfriendapi_h___
#define jsfriendapi_h___
#include "jsclass.h"
#include "jspubtd.h"
#include "jsprvtd.h"
#include "mozilla/GuardObjects.h"
JS_BEGIN_EXTERN_C
extern JS_FRIEND_API(void)
JS_SetGrayGCRootsTracer(JSRuntime *rt, JSTraceDataOp traceOp, void *data);
extern JS_FRIEND_API(JSString *)
JS_GetAnonymousString(JSRuntime *rt);
extern JS_FRIEND_API(JSObject *)
JS_FindCompilationScope(JSContext *cx, JSRawObject obj);
extern JS_FRIEND_API(JSFunction *)
JS_GetObjectFunction(JSRawObject obj);
extern JS_FRIEND_API(JSObject *)
JS_GetGlobalForFrame(JSStackFrame *fp);
extern JS_FRIEND_API(JSBool)
JS_SplicePrototype(JSContext *cx, JSObject *obj, JSObject *proto);
extern JS_FRIEND_API(JSObject *)
JS_NewObjectWithUniqueType(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent);
extern JS_FRIEND_API(uint32_t)
JS_ObjectCountDynamicSlots(JSHandleObject obj);
extern JS_FRIEND_API(void)
JS_ShrinkGCBuffers(JSRuntime *rt);
extern JS_FRIEND_API(size_t)
JS_GetE4XObjectsCreated(JSContext *cx);
extern JS_FRIEND_API(size_t)
JS_SetProtoCalled(JSContext *cx);
extern JS_FRIEND_API(size_t)
JS_GetCustomIteratorCount(JSContext *cx);
extern JS_FRIEND_API(JSBool)
JS_NondeterministicGetWeakMapKeys(JSContext *cx, JSObject *obj, JSObject **ret);
/*
* Determine whether the given object is backed by a DeadObjectProxy.
*
* Such objects hold no other objects (they have no outgoing reference edges)
* and will throw if you touch them (e.g. by reading/writing a property).
*/
extern JS_FRIEND_API(JSBool)
JS_IsDeadWrapper(JSObject *obj);
/*
* Used by the cycle collector to trace through the shape and all
* shapes it reaches, marking all non-shape children found in the
* process. Uses bounded stack space.
*/
extern JS_FRIEND_API(void)
JS_TraceShapeCycleCollectorChildren(JSTracer *trc, void *shape);
enum {
JS_TELEMETRY_GC_REASON,
JS_TELEMETRY_GC_IS_COMPARTMENTAL,
JS_TELEMETRY_GC_MS,
JS_TELEMETRY_GC_MAX_PAUSE_MS,
JS_TELEMETRY_GC_MARK_MS,
JS_TELEMETRY_GC_SWEEP_MS,
JS_TELEMETRY_GC_MARK_ROOTS_MS,
JS_TELEMETRY_GC_MARK_GRAY_MS,
JS_TELEMETRY_GC_SLICE_MS,
JS_TELEMETRY_GC_MMU_50,
JS_TELEMETRY_GC_RESET,
JS_TELEMETRY_GC_INCREMENTAL_DISABLED,
JS_TELEMETRY_GC_NON_INCREMENTAL,
JS_TELEMETRY_GC_SCC_SWEEP_TOTAL_MS,
JS_TELEMETRY_GC_SCC_SWEEP_MAX_PAUSE_MS
};
typedef void
(* JSAccumulateTelemetryDataCallback)(int id, uint32_t sample);
extern JS_FRIEND_API(void)
JS_SetAccumulateTelemetryCallback(JSRuntime *rt, JSAccumulateTelemetryDataCallback callback);
extern JS_FRIEND_API(JSPrincipals *)
JS_GetCompartmentPrincipals(JSCompartment *compartment);
extern JS_FRIEND_API(void)
JS_SetCompartmentPrincipals(JSCompartment *compartment, JSPrincipals *principals);
/* Safe to call with input obj == NULL. Returns non-NULL iff obj != NULL. */
extern JS_FRIEND_API(JSObject *)
JS_ObjectToInnerObject(JSContext *cx, JSObject *obj);
/* Requires obj != NULL. */
extern JS_FRIEND_API(JSObject *)
JS_ObjectToOuterObject(JSContext *cx, JSObject *obj);
extern JS_FRIEND_API(JSObject *)
JS_CloneObject(JSContext *cx, JSObject *obj, JSObject *proto, JSObject *parent);
extern JS_FRIEND_API(JSBool)
js_GetterOnlyPropertyStub(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict, JSMutableHandleValue vp);
JS_FRIEND_API(void)
js_ReportOverRecursed(JSContext *maybecx);
#ifdef DEBUG
/*
* Routines to print out values during debugging. These are FRIEND_API to help
* the debugger find them and to support temporarily hacking js_Dump* calls
* into other code.
*/
extern JS_FRIEND_API(void)
js_DumpString(JSString *str);
extern JS_FRIEND_API(void)
js_DumpAtom(JSAtom *atom);
extern JS_FRIEND_API(void)
js_DumpObject(JSObject *obj);
extern JS_FRIEND_API(void)
js_DumpChars(const jschar *s, size_t n);
#endif
#ifdef __cplusplus
extern JS_FRIEND_API(bool)
JS_CopyPropertiesFrom(JSContext *cx, JSObject *target, JSObject *obj);
extern JS_FRIEND_API(JSBool)
JS_WrapPropertyDescriptor(JSContext *cx, js::PropertyDescriptor *desc);
extern JS_FRIEND_API(JSBool)
JS_WrapAutoIdVector(JSContext *cx, JS::AutoIdVector &props);
extern JS_FRIEND_API(JSBool)
JS_EnumerateState(JSContext *cx, JSHandleObject obj, JSIterateOp enum_op,
js::MutableHandleValue statep, js::MutableHandleId idp);
struct JSFunctionSpecWithHelp {
const char *name;
JSNative call;
uint16_t nargs;
uint16_t flags;
const char *usage;
const char *help;
};
#define JS_FN_HELP(name,call,nargs,flags,usage,help) \
{name, call, nargs, (flags) | JSPROP_ENUMERATE | JSFUN_STUB_GSOPS, usage, help}
#define JS_FS_HELP_END \
{NULL, NULL, 0, 0, NULL, NULL}
extern JS_FRIEND_API(bool)
JS_DefineFunctionsWithHelp(JSContext *cx, JSObject *obj, const JSFunctionSpecWithHelp *fs);
#endif
JS_END_EXTERN_C
#ifdef __cplusplus
typedef bool (* JS_SourceHook)(JSContext *cx, JSScript *script, jschar **src, uint32_t *length);
extern JS_FRIEND_API(void)
JS_SetSourceHook(JSRuntime *rt, JS_SourceHook hook);
namespace js {
inline JSRuntime *
GetRuntime(const JSContext *cx)
{
return ContextFriendFields::get(cx)->runtime;
}
typedef bool
(* PreserveWrapperCallback)(JSContext *cx, JSObject *obj);
/*
* Dump the complete object graph of heap-allocated things.
* fp is the file for the dump output.
*/
extern JS_FRIEND_API(void)
DumpHeapComplete(JSRuntime *rt, FILE *fp);
class JS_FRIEND_API(AutoSwitchCompartment) {
private:
JSContext *cx;
JSCompartment *oldCompartment;
public:
AutoSwitchCompartment(JSContext *cx, JSCompartment *newCompartment
JS_GUARD_OBJECT_NOTIFIER_PARAM);
AutoSwitchCompartment(JSContext *cx, JSHandleObject target JS_GUARD_OBJECT_NOTIFIER_PARAM);
~AutoSwitchCompartment();
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
};
#ifdef OLD_GETTER_SETTER_METHODS
JS_FRIEND_API(JSBool) obj_defineGetter(JSContext *cx, unsigned argc, js::Value *vp);
JS_FRIEND_API(JSBool) obj_defineSetter(JSContext *cx, unsigned argc, js::Value *vp);
#endif
extern JS_FRIEND_API(bool)
IsSystemCompartment(const JSCompartment *compartment);
extern JS_FRIEND_API(bool)
IsAtomsCompartment(const JSCompartment *c);
/*
* Check whether it is OK to assign an undeclared property with name
* propname of the global object in the current script on cx. Reports
* an error if one needs to be reported (in particular in all cases
* when it returns false).
*/
extern JS_FRIEND_API(bool)
CheckUndeclaredVarAssignment(JSContext *cx, JSString *propname);
struct WeakMapTracer;
/*
* Weak map tracer callback, called once for every binding of every
* weak map that was live at the time of the last garbage collection.
*
* m will be NULL if the weak map is not contained in a JS Object.
*/
typedef void
(* WeakMapTraceCallback)(WeakMapTracer *trc, JSObject *m,
void *k, JSGCTraceKind kkind,
void *v, JSGCTraceKind vkind);
struct WeakMapTracer {
JSRuntime *runtime;
WeakMapTraceCallback callback;
WeakMapTracer(JSRuntime *rt, WeakMapTraceCallback cb)
: runtime(rt), callback(cb) {}
};
extern JS_FRIEND_API(void)
TraceWeakMaps(WeakMapTracer *trc);
extern JS_FRIEND_API(bool)
GCThingIsMarkedGray(void *thing);
typedef void
(GCThingCallback)(void *closure, void *gcthing);
extern JS_FRIEND_API(void)
VisitGrayWrapperTargets(JSCompartment *comp, GCThingCallback *callback, void *closure);
/*
* Shadow declarations of JS internal structures, for access by inline access
* functions below. Do not use these structures in any other way. When adding
* new fields for access by inline methods, make sure to add static asserts to
* the original header file to ensure that offsets are consistent.
*/
namespace shadow {
struct TypeObject {
JSObject *proto;
};
struct BaseShape {
js::Class *clasp;
JSObject *parent;
};
struct Shape {
BaseShape *base;
jsid _1;
uint32_t slotInfo;
static const uint32_t FIXED_SLOTS_SHIFT = 27;
};
struct Object {
Shape *shape;
TypeObject *type;
js::Value *slots;
js::Value *_1;
size_t numFixedSlots() const { return shape->slotInfo >> Shape::FIXED_SLOTS_SHIFT; }
Value *fixedSlots() const {
return (Value *)(uintptr_t(this) + sizeof(shadow::Object));
}
js::Value &slotRef(size_t slot) const {
size_t nfixed = numFixedSlots();
if (slot < nfixed)
return fixedSlots()[slot];
return slots[slot - nfixed];
}
};
struct Function {
Object base;
uint16_t nargs;
uint16_t flags;
/* Used only for natives */
Native native;
const JSJitInfo *jitinfo;
void *_1;
};
struct Atom {
size_t _;
const jschar *chars;
};
} /* namespace shadow */
extern JS_FRIEND_DATA(js::Class) AnyNameClass;
extern JS_FRIEND_DATA(js::Class) AttributeNameClass;
extern JS_FRIEND_DATA(js::Class) CallClass;
extern JS_FRIEND_DATA(js::Class) DeclEnvClass;
extern JS_FRIEND_DATA(js::Class) FunctionClass;
extern JS_FRIEND_DATA(js::Class) FunctionProxyClass;
extern JS_FRIEND_DATA(js::Class) NamespaceClass;
extern JS_FRIEND_DATA(js::Class) OuterWindowProxyClass;
extern JS_FRIEND_DATA(js::Class) ObjectProxyClass;
extern JS_FRIEND_DATA(js::Class) QNameClass;
extern JS_FRIEND_DATA(js::Class) XMLClass;
extern JS_FRIEND_DATA(js::Class) ObjectClass;
inline js::Class *
GetObjectClass(RawObject obj)
{
return reinterpret_cast<const shadow::Object*>(obj)->shape->base->clasp;
}
inline JSClass *
GetObjectJSClass(RawObject obj)
{
return js::Jsvalify(GetObjectClass(obj));
}
JS_FRIEND_API(bool)
IsScopeObject(RawObject obj);
inline JSObject *
GetObjectParent(RawObject obj)
{
JS_ASSERT(!IsScopeObject(obj));
return reinterpret_cast<shadow::Object*>(obj)->shape->base->parent;
}
JS_FRIEND_API(JSObject *)
GetObjectParentMaybeScope(RawObject obj);
JS_FRIEND_API(JSObject *)
GetGlobalForObjectCrossCompartment(RawObject obj);
JS_FRIEND_API(void)
NotifyAnimationActivity(RawObject obj);
JS_FRIEND_API(bool)
IsOriginalScriptFunction(JSFunction *fun);
JS_FRIEND_API(JSFunction *)
DefineFunctionWithReserved(JSContext *cx, JSObject *obj, const char *name, JSNative call,
unsigned nargs, unsigned attrs);
JS_FRIEND_API(JSFunction *)
NewFunctionWithReserved(JSContext *cx, JSNative call, unsigned nargs, unsigned flags,
JSObject *parent, const char *name);
JS_FRIEND_API(JSFunction *)
NewFunctionByIdWithReserved(JSContext *cx, JSNative native, unsigned nargs, unsigned flags,
JSObject *parent, jsid id);
JS_FRIEND_API(JSObject *)
InitClassWithReserved(JSContext *cx, JSObject *obj, JSObject *parent_proto,
JSClass *clasp, JSNative constructor, unsigned nargs,
JSPropertySpec *ps, JSFunctionSpec *fs,
JSPropertySpec *static_ps, JSFunctionSpec *static_fs);
JS_FRIEND_API(const Value &)
GetFunctionNativeReserved(RawObject fun, size_t which);
JS_FRIEND_API(void)
SetFunctionNativeReserved(RawObject fun, size_t which, const Value &val);
inline bool
GetObjectProto(JSContext *cx, JSObject *obj, JSObject **proto)
{
js::Class *clasp = GetObjectClass(obj);
if (clasp == &js::ObjectProxyClass ||
clasp == &js::OuterWindowProxyClass ||
clasp == &js::FunctionProxyClass)
{
return JS_GetPrototype(cx, obj, proto);
}
*proto = reinterpret_cast<const shadow::Object*>(obj)->type->proto;
return true;
}
inline void *
GetObjectPrivate(RawObject obj)
{
const shadow::Object *nobj = reinterpret_cast<const shadow::Object*>(obj);
void **addr = reinterpret_cast<void**>(&nobj->fixedSlots()[nobj->numFixedSlots()]);
return *addr;
}
/*
* Get a slot that is both reserved for object's clasp *and* is fixed (fits
* within the maximum capacity for the object's fixed slots).
*/
inline const Value &
GetReservedSlot(RawObject obj, size_t slot)
{
JS_ASSERT(slot < JSCLASS_RESERVED_SLOTS(GetObjectClass(obj)));
return reinterpret_cast<const shadow::Object *>(obj)->slotRef(slot);
}
JS_FRIEND_API(void)
SetReservedSlotWithBarrier(RawObject obj, size_t slot, const Value &value);
inline void
SetReservedSlot(RawObject obj, size_t slot, const Value &value)
{
JS_ASSERT(slot < JSCLASS_RESERVED_SLOTS(GetObjectClass(obj)));
shadow::Object *sobj = reinterpret_cast<shadow::Object *>(obj);
if (sobj->slotRef(slot).isMarkable())
SetReservedSlotWithBarrier(obj, slot, value);
else
sobj->slotRef(slot) = value;
}
JS_FRIEND_API(uint32_t)
GetObjectSlotSpan(RawObject obj);
inline const Value &
GetObjectSlot(RawObject obj, size_t slot)
{
JS_ASSERT(slot < GetObjectSlotSpan(obj));
return reinterpret_cast<const shadow::Object *>(obj)->slotRef(slot);
}
inline const jschar *
GetAtomChars(JSAtom *atom)
{
return reinterpret_cast<shadow::Atom *>(atom)->chars;
}
inline JSLinearString *
AtomToLinearString(JSAtom *atom)
{
return reinterpret_cast<JSLinearString *>(atom);
}
static inline js::PropertyOp
CastAsJSPropertyOp(RawObject object)
{
return JS_DATA_TO_FUNC_PTR(js::PropertyOp, object);
}
static inline js::StrictPropertyOp
CastAsJSStrictPropertyOp(RawObject object)
{
return JS_DATA_TO_FUNC_PTR(js::StrictPropertyOp, object);
}
JS_FRIEND_API(bool)
GetPropertyNames(JSContext *cx, RawObject obj, unsigned flags, js::AutoIdVector *props);
JS_FRIEND_API(bool)
GetGeneric(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp);
JS_FRIEND_API(bool)
StringIsArrayIndex(JSLinearString *str, uint32_t *indexp);
JS_FRIEND_API(void)
SetPreserveWrapperCallback(JSRuntime *rt, PreserveWrapperCallback callback);
JS_FRIEND_API(bool)
IsObjectInContextCompartment(RawObject obj, const JSContext *cx);
/*
* NB: these flag bits are encoded into the bytecode stream in the immediate
* operand of JSOP_ITER, so don't change them without advancing vm/Xdr.h's
* XDR_BYTECODE_VERSION.
*/
#define JSITER_ENUMERATE 0x1 /* for-in compatible hidden default iterator */
#define JSITER_FOREACH 0x2 /* return [key, value] pair rather than key */
#define JSITER_KEYVALUE 0x4 /* destructuring for-in wants [key, value] */
#define JSITER_OWNONLY 0x8 /* iterate over obj's own properties only */
#define JSITER_HIDDEN 0x10 /* also enumerate non-enumerable properties */
#define JSITER_FOR_OF 0x20 /* harmony for-of loop */
inline uintptr_t
GetNativeStackLimit(const JSRuntime *rt)
{
return RuntimeFriendFields::get(rt)->nativeStackLimit;
}
#define JS_CHECK_RECURSION(cx, onerror) \
JS_BEGIN_MACRO \
int stackDummy_; \
if (!JS_CHECK_STACK_SIZE(js::GetNativeStackLimit(js::GetRuntime(cx)), &stackDummy_)) { \
js_ReportOverRecursed(cx); \
onerror; \
} \
JS_END_MACRO
JS_FRIEND_API(void)
StartPCCountProfiling(JSContext *cx);
JS_FRIEND_API(void)
StopPCCountProfiling(JSContext *cx);
JS_FRIEND_API(void)
PurgePCCounts(JSContext *cx);
JS_FRIEND_API(size_t)
GetPCCountScriptCount(JSContext *cx);
JS_FRIEND_API(JSString *)
GetPCCountScriptSummary(JSContext *cx, size_t script);
JS_FRIEND_API(JSString *)
GetPCCountScriptContents(JSContext *cx, size_t script);
/*
* A call stack can be specified to the JS engine such that all JS entry/exits
* to functions push/pop an entry to/from the specified stack.
*
* For more detailed information, see vm/SPSProfiler.h
*/
class ProfileEntry
{
/*
* All fields are marked volatile to prevent the compiler from re-ordering
* instructions. Namely this sequence:
*
* entry[size] = ...;
* size++;
*
* If the size modification were somehow reordered before the stores, then
* if a sample were taken it would be examining bogus information.
*
* A ProfileEntry represents both a C++ profile entry and a JS one. Both use
* the string as a description, but JS uses the sp as NULL to indicate that
* it is a JS entry. The script_ is then only ever examined for a JS entry,
* and the idx is used by both, but with different meanings.
*/
const char * volatile string; // Descriptive string of this entry
void * volatile sp; // Relevant stack pointer for the entry
JSScript * volatile script_; // if js(), non-null script which is running
int32_t volatile idx; // if js(), idx of pc, otherwise line number
public:
/*
* All of these methods are marked with the 'volatile' keyword because SPS's
* representation of the stack is stored such that all ProfileEntry
* instances are volatile. These methods would not be available unless they
* were marked as volatile as well
*/
bool js() volatile {
JS_ASSERT_IF(sp == NULL, script_ != NULL);
return sp == NULL;
}
uint32_t line() volatile { JS_ASSERT(!js()); return idx; }
JSScript *script() volatile { JS_ASSERT(js()); return script_; }
void *stackAddress() volatile { return sp; }
const char *label() volatile { return string; }
void setLine(uint32_t line) volatile { JS_ASSERT(!js()); idx = line; }
void setLabel(const char *string) volatile { this->string = string; }
void setStackAddress(void *sp) volatile { this->sp = sp; }
void setScript(JSScript *script) volatile { script_ = script; }
/* we can't know the layout of JSScript, so look in vm/SPSProfiler.cpp */
JS_FRIEND_API(jsbytecode *) pc() volatile;
JS_FRIEND_API(void) setPC(jsbytecode *pc) volatile;
static size_t offsetOfString() { return offsetof(ProfileEntry, string); }
static size_t offsetOfStackAddress() { return offsetof(ProfileEntry, sp); }
static size_t offsetOfPCIdx() { return offsetof(ProfileEntry, idx); }
static size_t offsetOfScript() { return offsetof(ProfileEntry, script_); }
/*
* The index used in the entry can either be a line number or the offset of
* a pc into a script's code. To signify a NULL pc, use a -1 index. This is
* checked against in pc() and setPC() to set/get the right pc.
*/
static const int32_t NullPCIndex = -1;
};
JS_FRIEND_API(void)
SetRuntimeProfilingStack(JSRuntime *rt, ProfileEntry *stack, uint32_t *size,
uint32_t max);
JS_FRIEND_API(void)
EnableRuntimeProfilingStack(JSRuntime *rt, bool enabled);
JS_FRIEND_API(jsbytecode*)
ProfilingGetPC(JSRuntime *rt, JSScript *script, void *ip);
#ifdef JS_THREADSAFE
JS_FRIEND_API(void *)
GetOwnerThread(const JSContext *cx);
JS_FRIEND_API(bool)
ContextHasOutstandingRequests(const JSContext *cx);
#endif
JS_FRIEND_API(JSCompartment *)
GetContextCompartment(const JSContext *cx);
JS_FRIEND_API(bool)
HasUnrootedGlobal(const JSContext *cx);
typedef void
(* ActivityCallback)(void *arg, JSBool active);
/*
* Sets a callback that is run whenever the runtime goes idle - the
* last active request ceases - and begins activity - when it was
* idle and a request begins.
*/
JS_FRIEND_API(void)
SetActivityCallback(JSRuntime *rt, ActivityCallback cb, void *arg);
extern JS_FRIEND_API(const JSStructuredCloneCallbacks *)
GetContextStructuredCloneCallbacks(JSContext *cx);
extern JS_FRIEND_API(JSVersion)
VersionSetMoarXML(JSVersion version, bool enable);
extern JS_FRIEND_API(bool)
CanCallContextDebugHandler(JSContext *cx);
extern JS_FRIEND_API(JSTrapStatus)
CallContextDebugHandler(JSContext *cx, JSScript *script, jsbytecode *bc, Value *rval);
extern JS_FRIEND_API(bool)
IsContextRunningJS(JSContext *cx);
class SystemAllocPolicy;
typedef Vector<JSCompartment*, 0, SystemAllocPolicy> CompartmentVector;
extern JS_FRIEND_API(const CompartmentVector&)
GetRuntimeCompartments(JSRuntime *rt);
#define GCREASONS(D) \
/* Reasons internal to the JS engine */ \
D(API) \
D(MAYBEGC) \
D(LAST_CONTEXT) \
D(DESTROY_CONTEXT) \
D(LAST_DITCH) \
D(TOO_MUCH_MALLOC) \
D(ALLOC_TRIGGER) \
D(DEBUG_GC) \
D(DEBUG_MODE_GC) \
D(TRANSPLANT) \
D(RESET) \
\
/* Reasons from Firefox */ \
D(DOM_WINDOW_UTILS) \
D(COMPONENT_UTILS) \
D(MEM_PRESSURE) \
D(CC_WAITING) \
D(CC_FORCED) \
D(LOAD_END) \
D(POST_COMPARTMENT) \
D(PAGE_HIDE) \
D(NSJSCONTEXT_DESTROY) \
D(SET_NEW_DOCUMENT) \
D(SET_DOC_SHELL) \
D(DOM_UTILS) \
D(DOM_IPC) \
D(DOM_WORKER) \
D(INTER_SLICE_GC) \
D(REFRESH_FRAME) \
D(FULL_GC_TIMER) \
D(SHUTDOWN_CC)
namespace gcreason {
/* GCReasons will end up looking like JSGC_MAYBEGC */
enum Reason {
#define MAKE_REASON(name) name,
GCREASONS(MAKE_REASON)
#undef MAKE_REASON
NO_REASON,
NUM_REASONS,
/*
* For telemetry, we want to keep a fixed max bucket size over time so we
* don't have to switch histograms. 100 is conservative; as of this writing
* there are 26. But the cost of extra buckets seems to be low while the
* cost of switching histograms is high.
*/
NUM_TELEMETRY_REASONS = 100
};
} /* namespace gcreason */
extern JS_FRIEND_API(void)
PrepareCompartmentForGC(JSCompartment *comp);
extern JS_FRIEND_API(void)
PrepareForFullGC(JSRuntime *rt);
extern JS_FRIEND_API(void)
PrepareForIncrementalGC(JSRuntime *rt);
extern JS_FRIEND_API(bool)
IsGCScheduled(JSRuntime *rt);
extern JS_FRIEND_API(void)
SkipCompartmentForGC(JSCompartment *comp);
/*
* When triggering a GC using one of the functions below, it is first necessary
* to select the compartments to be collected. To do this, you can call
* PrepareCompartmentForGC on each compartment, or you can call PrepareForFullGC
* to select all compartments. Failing to select any compartment is an error.
*/
extern JS_FRIEND_API(void)
GCForReason(JSRuntime *rt, gcreason::Reason reason);
extern JS_FRIEND_API(void)
ShrinkingGC(JSRuntime *rt, gcreason::Reason reason);
extern JS_FRIEND_API(void)
IncrementalGC(JSRuntime *rt, gcreason::Reason reason, int64_t millis = 0);
extern JS_FRIEND_API(void)
FinishIncrementalGC(JSRuntime *rt, gcreason::Reason reason);
enum GCProgress {
/*
* During non-incremental GC, the GC is bracketed by JSGC_CYCLE_BEGIN/END
* callbacks. During an incremental GC, the sequence of callbacks is as
* follows:
* JSGC_CYCLE_BEGIN, JSGC_SLICE_END (first slice)
* JSGC_SLICE_BEGIN, JSGC_SLICE_END (second slice)
* ...
* JSGC_SLICE_BEGIN, JSGC_CYCLE_END (last slice)
*/
GC_CYCLE_BEGIN,
GC_SLICE_BEGIN,
GC_SLICE_END,
GC_CYCLE_END
};
struct JS_FRIEND_API(GCDescription) {
bool isCompartment;
GCDescription(bool isCompartment)
: isCompartment(isCompartment) {}
jschar *formatMessage(JSRuntime *rt) const;
jschar *formatJSON(JSRuntime *rt, uint64_t timestamp) const;
};
typedef void
(* GCSliceCallback)(JSRuntime *rt, GCProgress progress, const GCDescription &desc);
extern JS_FRIEND_API(GCSliceCallback)
SetGCSliceCallback(JSRuntime *rt, GCSliceCallback callback);
typedef void
(* AnalysisPurgeCallback)(JSRuntime *rt, JSFlatString *desc);
extern JS_FRIEND_API(AnalysisPurgeCallback)
SetAnalysisPurgeCallback(JSRuntime *rt, AnalysisPurgeCallback callback);
/* Was the most recent GC run incrementally? */
extern JS_FRIEND_API(bool)
WasIncrementalGC(JSRuntime *rt);
typedef JSBool
(* DOMInstanceClassMatchesProto)(JSHandleObject protoObject, uint32_t protoID,
uint32_t depth);
struct JSDOMCallbacks {
DOMInstanceClassMatchesProto instanceClassMatchesProto;
};
typedef struct JSDOMCallbacks DOMCallbacks;
extern JS_FRIEND_API(void)
SetDOMCallbacks(JSRuntime *rt, const DOMCallbacks *callbacks);
extern JS_FRIEND_API(const DOMCallbacks *)
GetDOMCallbacks(JSRuntime *rt);
/*
* Signals a good place to do an incremental slice, because the browser is
* drawing a frame.
*/
extern JS_FRIEND_API(void)
NotifyDidPaint(JSRuntime *rt);
extern JS_FRIEND_API(bool)
IsIncrementalGCEnabled(JSRuntime *rt);
JS_FRIEND_API(bool)
IsIncrementalGCInProgress(JSRuntime *rt);
extern JS_FRIEND_API(void)
DisableIncrementalGC(JSRuntime *rt);
extern JS_FRIEND_API(bool)
IsIncrementalBarrierNeeded(JSRuntime *rt);
extern JS_FRIEND_API(bool)
IsIncrementalBarrierNeeded(JSContext *cx);
extern JS_FRIEND_API(bool)
IsIncrementalBarrierNeededOnObject(RawObject obj);
extern JS_FRIEND_API(bool)
IsIncrementalBarrierNeededOnScript(JSScript *obj);
extern JS_FRIEND_API(void)
IncrementalReferenceBarrier(void *ptr);
extern JS_FRIEND_API(void)
IncrementalValueBarrier(const Value &v);
extern JS_FRIEND_API(void)
PokeGC(JSRuntime *rt);
class ObjectPtr
{
JSObject *value;
public:
ObjectPtr() : value(NULL) {}
ObjectPtr(JSObject *obj) : value(obj) {}
/* Always call finalize before the destructor. */
~ObjectPtr() { JS_ASSERT(!value); }
void finalize(JSRuntime *rt) {
if (IsIncrementalBarrierNeeded(rt))
IncrementalReferenceBarrier(value);
value = NULL;
}
void init(JSObject *obj) { value = obj; }
JSObject *get() const { return value; }
void writeBarrierPre(JSRuntime *rt) {
IncrementalReferenceBarrier(value);
}
ObjectPtr &operator=(JSObject *obj) {
IncrementalReferenceBarrier(value);
value = obj;
return *this;
}
JSObject &operator*() const { return *value; }
JSObject *operator->() const { return value; }
operator JSObject *() const { return value; }
};
extern JS_FRIEND_API(JSObject *)
GetTestingFunctions(JSContext *cx);
/*
* Helper to convert FreeOp to JSFreeOp when the definition of FreeOp is not
* available and the compiler does not know that FreeOp inherits from
* JSFreeOp.
*/
inline JSFreeOp *
CastToJSFreeOp(FreeOp *fop)
{
return reinterpret_cast<JSFreeOp *>(fop);
}
/* Implemented in jsexn.cpp. */
/*
* Get an error type name from a JSExnType constant.
* Returns NULL for invalid arguments and JSEXN_INTERNALERR
*/
extern JS_FRIEND_API(const jschar*)
GetErrorTypeName(JSContext* cx, int16_t exnType);
/* Implemented in jswrapper.cpp. */
typedef enum NukeReferencesToWindow {
NukeWindowReferences,
DontNukeWindowReferences
} NukeReferencesToWindow;
/*
* These filters are designed to be ephemeral stack classes, and thus don't
* do any rooting or holding of their members.
*/
struct CompartmentFilter {
virtual bool match(JSCompartment *c) const = 0;
};
struct AllCompartments : public CompartmentFilter {
virtual bool match(JSCompartment *c) const { return true; }
};
struct ContentCompartmentsOnly : public CompartmentFilter {
virtual bool match(JSCompartment *c) const {
return !IsSystemCompartment(c);
}
};
struct ChromeCompartmentsOnly : public CompartmentFilter {
virtual bool match(JSCompartment *c) const {
return IsSystemCompartment(c);
}
};
struct SingleCompartment : public CompartmentFilter {
JSCompartment *ours;
SingleCompartment(JSCompartment *c) : ours(c) {}
virtual bool match(JSCompartment *c) const { return c == ours; }
};
struct CompartmentsWithPrincipals : public CompartmentFilter {
JSPrincipals *principals;
CompartmentsWithPrincipals(JSPrincipals *p) : principals(p) {}
virtual bool match(JSCompartment *c) const {
return JS_GetCompartmentPrincipals(c) == principals;
}
};
extern JS_FRIEND_API(JSBool)
NukeCrossCompartmentWrappers(JSContext* cx,
const CompartmentFilter& sourceFilter,
const CompartmentFilter& targetFilter,
NukeReferencesToWindow nukeReferencesToWindow);
/* Specify information about ListBase proxies in the DOM, for use by ICs. */
JS_FRIEND_API(void)
SetListBaseInformation(void *listBaseHandlerFamily, uint32_t listBaseExpandoSlot);
void *GetListBaseHandlerFamily();
uint32_t GetListBaseExpandoSlot();
} /* namespace js */
#endif
/* Implemented in jsdate.cpp. */
/*
* Detect whether the internal date value is NaN. (Because failure is
* out-of-band for js_DateGet*)
*/
extern JS_FRIEND_API(JSBool)
js_DateIsValid(JSContext *cx, JSObject* obj);
extern JS_FRIEND_API(double)
js_DateGetMsecSinceEpoch(JSContext *cx, JSRawObject obj);
/* Implemented in jscntxt.cpp. */
/*
* Report an exception, which is currently realized as a printf-style format
* string and its arguments.
*/
typedef enum JSErrNum {
#define MSG_DEF(name, number, count, exception, format) \
name = number,
#include "js.msg"
#undef MSG_DEF
JSErr_Limit
} JSErrNum;
extern JS_FRIEND_API(const JSErrorFormatString *)
js_GetErrorMessage(void *userRef, const char *locale, const unsigned errorNumber);
/* Implemented in jsclone.cpp. */
extern JS_FRIEND_API(uint64_t)
js_GetSCOffset(JSStructuredCloneWriter* writer);
/* Typed Array functions, implemented in jstypedarray.cpp */
#ifdef __cplusplus
namespace js {
namespace ArrayBufferView {
enum ViewType {
TYPE_INT8 = 0,
TYPE_UINT8,
TYPE_INT16,
TYPE_UINT16,
TYPE_INT32,
TYPE_UINT32,
TYPE_FLOAT32,
TYPE_FLOAT64,
/*
* Special type that is a uint8_t, but assignments are clamped to [0, 256).
* Treat the raw data type as a uint8_t.
*/
TYPE_UINT8_CLAMPED,
TYPE_MAX
};
} /* namespace ArrayBufferView */
} /* namespace js */
typedef js::ArrayBufferView::ViewType JSArrayBufferViewType;
#else
typedef uint32_t JSArrayBufferViewType;
#endif /* __cplusplus */
/*
* Create a new typed array with nelements elements.
*
* These functions (except the WithBuffer variants) fill in the array with zeros.
*/
extern JS_FRIEND_API(JSObject *)
JS_NewInt8Array(JSContext *cx, uint32_t nelements);
extern JS_FRIEND_API(JSObject *)
JS_NewUint8Array(JSContext *cx, uint32_t nelements);
extern JS_FRIEND_API(JSObject *)
JS_NewUint8ClampedArray(JSContext *cx, uint32_t nelements);
extern JS_FRIEND_API(JSObject *)
JS_NewInt16Array(JSContext *cx, uint32_t nelements);
extern JS_FRIEND_API(JSObject *)
JS_NewUint16Array(JSContext *cx, uint32_t nelements);
extern JS_FRIEND_API(JSObject *)
JS_NewInt32Array(JSContext *cx, uint32_t nelements);
extern JS_FRIEND_API(JSObject *)
JS_NewUint32Array(JSContext *cx, uint32_t nelements);
extern JS_FRIEND_API(JSObject *)
JS_NewFloat32Array(JSContext *cx, uint32_t nelements);
extern JS_FRIEND_API(JSObject *)
JS_NewFloat64Array(JSContext *cx, uint32_t nelements);
/*
* Create a new typed array and copy in values from the given object. The
* object is used as if it were an array; that is, the new array (if
* successfully created) will have length given by array.length, and its
* elements will be those specified by array[0], array[1], and so on, after
* conversion to the typed array element type.
*/
extern JS_FRIEND_API(JSObject *)
JS_NewInt8ArrayFromArray(JSContext *cx, JSObject *array);
extern JS_FRIEND_API(JSObject *)
JS_NewUint8ArrayFromArray(JSContext *cx, JSObject *array);
extern JS_FRIEND_API(JSObject *)
JS_NewUint8ClampedArrayFromArray(JSContext *cx, JSObject *array);
extern JS_FRIEND_API(JSObject *)
JS_NewInt16ArrayFromArray(JSContext *cx, JSObject *array);
extern JS_FRIEND_API(JSObject *)
JS_NewUint16ArrayFromArray(JSContext *cx, JSObject *array);
extern JS_FRIEND_API(JSObject *)
JS_NewInt32ArrayFromArray(JSContext *cx, JSObject *array);
extern JS_FRIEND_API(JSObject *)
JS_NewUint32ArrayFromArray(JSContext *cx, JSObject *array);
extern JS_FRIEND_API(JSObject *)
JS_NewFloat32ArrayFromArray(JSContext *cx, JSObject *array);
extern JS_FRIEND_API(JSObject *)
JS_NewFloat64ArrayFromArray(JSContext *cx, JSObject *array);
/*
* Create a new typed array using the given ArrayBuffer for storage. byteOffset
* must not exceed (signed) INT32_MAX. The length value is optional; if -1 is
* passed, enough elements to use up the remainder of the byte array is used as
* the default value.
*/
extern JS_FRIEND_API(JSObject *)
JS_NewInt8ArrayWithBuffer(JSContext *cx, JSObject *arrayBuffer,
uint32_t byteOffset, int32_t length);
extern JS_FRIEND_API(JSObject *)
JS_NewUint8ArrayWithBuffer(JSContext *cx, JSObject *arrayBuffer,
uint32_t byteOffset, int32_t length);
extern JS_FRIEND_API(JSObject *)
JS_NewUint8ClampedArrayWithBuffer(JSContext *cx, JSObject *arrayBuffer,
uint32_t byteOffset, int32_t length);
extern JS_FRIEND_API(JSObject *)
JS_NewInt16ArrayWithBuffer(JSContext *cx, JSObject *arrayBuffer,
uint32_t byteOffset, int32_t length);
extern JS_FRIEND_API(JSObject *)
JS_NewUint16ArrayWithBuffer(JSContext *cx, JSObject *arrayBuffer,
uint32_t byteOffset, int32_t length);
extern JS_FRIEND_API(JSObject *)
JS_NewInt32ArrayWithBuffer(JSContext *cx, JSObject *arrayBuffer,
uint32_t byteOffset, int32_t length);
extern JS_FRIEND_API(JSObject *)
JS_NewUint32ArrayWithBuffer(JSContext *cx, JSObject *arrayBuffer,
uint32_t byteOffset, int32_t length);
extern JS_FRIEND_API(JSObject *)
JS_NewFloat32ArrayWithBuffer(JSContext *cx, JSObject *arrayBuffer,
uint32_t byteOffset, int32_t length);
extern JS_FRIEND_API(JSObject *)
JS_NewFloat64ArrayWithBuffer(JSContext *cx, JSObject *arrayBuffer,
uint32_t byteOffset, int32_t length);
/*
* Create a new ArrayBuffer with the given byte length.
*/
extern JS_FRIEND_API(JSObject *)
JS_NewArrayBuffer(JSContext *cx, uint32_t nbytes);
/*
* Check whether obj supports JS_GetTypedArray* APIs. Note that this may return
* false if a security wrapper is encountered that denies the unwrapping. If
* this test or one of the JS_Is*Array tests succeeds, then it is safe to call
* the various accessor JSAPI calls defined below.
*/
extern JS_FRIEND_API(JSBool)
JS_IsTypedArrayObject(JSObject *obj, JSContext *cx);
/*
* Check whether obj supports JS_GetArrayBufferView* APIs. Note that this may
* return false if a security wrapper is encountered that denies the
* unwrapping. If this test or one of the more specific tests succeeds, then it
* is safe to call the various ArrayBufferView accessor JSAPI calls defined
* below. cx MUST be non-NULL and valid.
*/
extern JS_FRIEND_API(JSBool)
JS_IsArrayBufferViewObject(JSObject *obj, JSContext *cx);
/*
* Test for specific typed array types (ArrayBufferView subtypes)
*/
extern JS_FRIEND_API(JSBool)
JS_IsInt8Array(JSObject *obj, JSContext *cx);
extern JS_FRIEND_API(JSBool)
JS_IsUint8Array(JSObject *obj, JSContext *cx);
extern JS_FRIEND_API(JSBool)
JS_IsUint8ClampedArray(JSObject *obj, JSContext *cx);
extern JS_FRIEND_API(JSBool)
JS_IsInt16Array(JSObject *obj, JSContext *cx);
extern JS_FRIEND_API(JSBool)
JS_IsUint16Array(JSObject *obj, JSContext *cx);
extern JS_FRIEND_API(JSBool)
JS_IsInt32Array(JSObject *obj, JSContext *cx);
extern JS_FRIEND_API(JSBool)
JS_IsUint32Array(JSObject *obj, JSContext *cx);
extern JS_FRIEND_API(JSBool)
JS_IsFloat32Array(JSObject *obj, JSContext *cx);
extern JS_FRIEND_API(JSBool)
JS_IsFloat64Array(JSObject *obj, JSContext *cx);
/*
* Unwrap Typed arrays all at once. Return NULL without throwing if the object
* cannot be viewed as the correct typed array, or the typed array object on
* success, filling both outparameters.
*/
extern JS_FRIEND_API(JSObject *)
JS_GetObjectAsInt8Array(JSContext *cx, JSObject *obj, uint32_t *length, int8_t **data);
extern JS_FRIEND_API(JSObject *)
JS_GetObjectAsUint8Array(JSContext *cx, JSObject *obj, uint32_t *length, uint8_t **data);
extern JS_FRIEND_API(JSObject *)
JS_GetObjectAsUint8ClampedArray(JSContext *cx, JSObject *obj, uint32_t *length, uint8_t **data);
extern JS_FRIEND_API(JSObject *)
JS_GetObjectAsInt16Array(JSContext *cx, JSObject *obj, uint32_t *length, int16_t **data);
extern JS_FRIEND_API(JSObject *)
JS_GetObjectAsUint16Array(JSContext *cx, JSObject *obj, uint32_t *length, uint16_t **data);
extern JS_FRIEND_API(JSObject *)
JS_GetObjectAsInt32Array(JSContext *cx, JSObject *obj, uint32_t *length, int32_t **data);
extern JS_FRIEND_API(JSObject *)
JS_GetObjectAsUint32Array(JSContext *cx, JSObject *obj, uint32_t *length, uint32_t **data);
extern JS_FRIEND_API(JSObject *)
JS_GetObjectAsFloat32Array(JSContext *cx, JSObject *obj, uint32_t *length, float **data);
extern JS_FRIEND_API(JSObject *)
JS_GetObjectAsFloat64Array(JSContext *cx, JSObject *obj, uint32_t *length, double **data);
extern JS_FRIEND_API(JSObject *)
JS_GetObjectAsArrayBufferView(JSContext *cx, JSObject *obj, uint32_t *length, uint8_t **data);
extern JS_FRIEND_API(JSObject *)
JS_GetObjectAsArrayBuffer(JSContext *cx, JSObject *obj, uint32_t *length, uint8_t **data);
/*
* Get the type of elements in a typed array.
*
* |obj| must have passed a JS_IsTypedArrayObject/JS_Is*Array test, or somehow
* be known that it would pass such a test: it is a typed array or a wrapper of
* a typed array, and the unwrapping will succeed. If cx is NULL, then DEBUG
* builds may be unable to assert when unwrapping should be disallowed.
*/
extern JS_FRIEND_API(JSArrayBufferViewType)
JS_GetTypedArrayType(JSObject *obj, JSContext *maybecx);
/*
* Check whether obj supports the JS_GetArrayBuffer* APIs. Note that this may
* return false if a security wrapper is encountered that denies the
* unwrapping. If this test succeeds, then it is safe to call the various
* accessor JSAPI calls defined below.
*/
extern JS_FRIEND_API(JSBool)
JS_IsArrayBufferObject(JSObject *obj, JSContext *maybecx);
/*
* Return the available byte length of an array buffer.
*
* |obj| must have passed a JS_IsArrayBufferObject test, or somehow be known
* that it would pass such a test: it is an ArrayBuffer or a wrapper of an
* ArrayBuffer, and the unwrapping will succeed. If cx is NULL, then DEBUG
* builds may be unable to assert when unwrapping should be disallowed.
*/
extern JS_FRIEND_API(uint32_t)
JS_GetArrayBufferByteLength(JSObject *obj, JSContext *maybecx);
/*
* Return a pointer to an array buffer's data. The buffer is still owned by the
* array buffer object, and should not be modified on another thread. The
* returned pointer is stable across GCs.
*
* |obj| must have passed a JS_IsArrayBufferObject test, or somehow be known
* that it would pass such a test: it is an ArrayBuffer or a wrapper of an
* ArrayBuffer, and the unwrapping will succeed. If cx is NULL, then DEBUG
* builds may be unable to assert when unwrapping should be disallowed.
*/
extern JS_FRIEND_API(uint8_t *)
JS_GetArrayBufferData(JSObject *obj, JSContext *maybecx);
/*
* Return the number of elements in a typed array.
*
* |obj| must have passed a JS_IsTypedArrayObject/JS_Is*Array test, or somehow
* be known that it would pass such a test: it is a typed array or a wrapper of
* a typed array, and the unwrapping will succeed. If cx is NULL, then DEBUG
* builds may be unable to assert when unwrapping should be disallowed.
*/
extern JS_FRIEND_API(uint32_t)
JS_GetTypedArrayLength(JSObject *obj, JSContext *cx);
/*
* Return the byte offset from the start of an array buffer to the start of a
* typed array view.
*
* |obj| must have passed a JS_IsTypedArrayObject/JS_Is*Array test, or somehow
* be known that it would pass such a test: it is a typed array or a wrapper of
* a typed array, and the unwrapping will succeed. If cx is NULL, then DEBUG
* builds may be unable to assert when unwrapping should be disallowed.
*/
extern JS_FRIEND_API(uint32_t)
JS_GetTypedArrayByteOffset(JSObject *obj, JSContext *cx);
/*
* Return the byte length of a typed array.
*
* |obj| must have passed a JS_IsTypedArrayObject/JS_Is*Array test, or somehow
* be known that it would pass such a test: it is a typed array or a wrapper of
* a typed array, and the unwrapping will succeed. If cx is NULL, then DEBUG
* builds may be unable to assert when unwrapping should be disallowed.
*/
extern JS_FRIEND_API(uint32_t)
JS_GetTypedArrayByteLength(JSObject *obj, JSContext *cx);
/*
* Check whether obj supports JS_ArrayBufferView* APIs. Note that this may
* return false if a security wrapper is encountered that denies the
* unwrapping.
*/
extern JS_FRIEND_API(JSBool)
JS_IsArrayBufferViewObject(JSObject *obj, JSContext *cx);
/*
* More generic name for JS_GetTypedArrayByteLength to cover DataViews as well
*/
extern JS_FRIEND_API(uint32_t)
JS_GetArrayBufferViewByteLength(JSObject *obj, JSContext *cx);
/*
* Return a pointer to the start of the data referenced by a typed array. The
* data is still owned by the typed array, and should not be modified on
* another thread.
*
* |obj| must have passed a JS_Is*Array test, or somehow be known that it would
* pass such a test: it is a typed array or a wrapper of a typed array, and the
* unwrapping will succeed. If cx is NULL, then DEBUG builds may be unable to
* assert when unwrapping should be disallowed.
*/
extern JS_FRIEND_API(int8_t *)
JS_GetInt8ArrayData(JSObject *obj, JSContext *maybecx);
extern JS_FRIEND_API(uint8_t *)
JS_GetUint8ArrayData(JSObject *obj, JSContext *maybecx);
extern JS_FRIEND_API(uint8_t *)
JS_GetUint8ClampedArrayData(JSObject *obj, JSContext *maybecx);
extern JS_FRIEND_API(int16_t *)
JS_GetInt16ArrayData(JSObject *obj, JSContext *maybecx);
extern JS_FRIEND_API(uint16_t *)
JS_GetUint16ArrayData(JSObject *obj, JSContext *maybecx);
extern JS_FRIEND_API(int32_t *)
JS_GetInt32ArrayData(JSObject *obj, JSContext *maybecx);
extern JS_FRIEND_API(uint32_t *)
JS_GetUint32ArrayData(JSObject *obj, JSContext *maybecx);
extern JS_FRIEND_API(float *)
JS_GetFloat32ArrayData(JSObject *obj, JSContext *maybecx);
extern JS_FRIEND_API(double *)
JS_GetFloat64ArrayData(JSObject *obj, JSContext *maybecx);
/*
* Same as above, but for any kind of ArrayBufferView. Prefer the type-specific
* versions when possible.
*/
extern JS_FRIEND_API(void *)
JS_GetArrayBufferViewData(JSObject *obj, JSContext *maybecx);
/*
* Check whether obj supports JS_GetDataView* APIs. Note that this may fail and
* throw an exception if a security wrapper is encountered that denies the
* operation.
*/
JS_FRIEND_API(JSBool)
JS_IsDataViewObject(JSContext *cx, JSObject *obj, JSBool *isDataView);
/*
* Return the byte offset of a data view into its array buffer. |obj| must be a
* DataView.
*
* |obj| must have passed a JS_IsDataViewObject test, or somehow be known that
* it would pass such a test: it is a data view or a wrapper of a data view,
* and the unwrapping will succeed. If cx is NULL, then DEBUG builds may be
* unable to assert when unwrapping should be disallowed.
*/
JS_FRIEND_API(uint32_t)
JS_GetDataViewByteOffset(JSObject *obj, JSContext *maybecx);
/*
* Return the byte length of a data view.
*
* |obj| must have passed a JS_IsDataViewObject test, or somehow be known that
* it would pass such a test: it is a data view or a wrapper of a data view,
* and the unwrapping will succeed. If cx is NULL, then DEBUG builds may be
* unable to assert when unwrapping should be disallowed.
*/
JS_FRIEND_API(uint32_t)
JS_GetDataViewByteLength(JSObject *obj, JSContext *maybecx);
/*
* Return a pointer to the beginning of the data referenced by a DataView.
*
* |obj| must have passed a JS_IsDataViewObject test, or somehow be known that
* it would pass such a test: it is a data view or a wrapper of a data view,
* and the unwrapping will succeed. If cx is NULL, then DEBUG builds may be
* unable to assert when unwrapping should be disallowed.
*/
JS_FRIEND_API(void *)
JS_GetDataViewData(JSObject *obj, JSContext *maybecx);
#ifdef __cplusplus
/*
* This struct contains metadata passed from the DOM to the JS Engine for JIT
* optimizations on DOM property accessors. Eventually, this should be made
* available to general JSAPI users, but we are not currently ready to do so.
*/
typedef bool
(* JSJitPropertyOp)(JSContext *cx, JSHandleObject thisObj,
void *specializedThis, JS::Value *vp);
typedef bool
(* JSJitMethodOp)(JSContext *cx, JSHandleObject thisObj,
void *specializedThis, unsigned argc, JS::Value *vp);
struct JSJitInfo {
JSJitPropertyOp op;
uint32_t protoID;
uint32_t depth;
bool isInfallible; /* Is op fallible? False in setters. */
bool isConstant; /* Getting a construction-time constant? */
};
static JS_ALWAYS_INLINE const JSJitInfo *
FUNCTION_VALUE_TO_JITINFO(const JS::Value& v)
{
JS_ASSERT(js::GetObjectClass(&v.toObject()) == &js::FunctionClass);
return reinterpret_cast<js::shadow::Function *>(&v.toObject())->jitinfo;
}
static JS_ALWAYS_INLINE void
SET_JITINFO(JSFunction * func, const JSJitInfo *info)
{
js::shadow::Function *fun = reinterpret_cast<js::shadow::Function *>(func);
/* JS_ASSERT(func->isNative()). 0x4000 is JSFUN_INTERPRETED */
JS_ASSERT(!(fun->flags & 0x4000));
fun->jitinfo = info;
}
#endif /* __cplusplus */
/*
* Engine-internal extensions of jsid. This code is here only until we
* eliminate Gecko's dependencies on it!
*/
static JS_ALWAYS_INLINE jsid
JSID_FROM_BITS(size_t bits)
{
jsid id;
JSID_BITS(id) = bits;
return id;
}
/*
* Must not be used on atoms that are representable as integer jsids.
* Prefer NameToId or AtomToId over this function:
*
* A PropertyName is an atom that does not contain an integer in the range
* [0, UINT32_MAX]. However, jsid can only hold an integer in the range
* [0, JSID_INT_MAX] (where JSID_INT_MAX == 2^31-1). Thus, for the range of
* integers (JSID_INT_MAX, UINT32_MAX], to represent as a jsid 'id', it must be
* the case JSID_IS_ATOM(id) and !JSID_TO_ATOM(id)->isPropertyName(). In most
* cases when creating a jsid, code does not have to care about this corner
* case because:
*
* - When given an arbitrary JSAtom*, AtomToId must be used, which checks for
* integer atoms representable as integer jsids, and does this conversion.
*
* - When given a PropertyName*, NameToId can be used which which does not need
* to do any dynamic checks.
*
* Thus, it is only the rare third case which needs this function, which
* handles any JSAtom* that is known not to be representable with an int jsid.
*/
static JS_ALWAYS_INLINE jsid
NON_INTEGER_ATOM_TO_JSID(JSAtom *atom)
{
JS_ASSERT(((size_t)atom & 0x7) == 0);
jsid id = JSID_FROM_BITS((size_t)atom);
JS_ASSERT(id == INTERNED_STRING_TO_JSID(NULL, (JSString*)atom));
return id;
}
/* All strings stored in jsids are atomized, but are not necessarily property names. */
static JS_ALWAYS_INLINE JSBool
JSID_IS_ATOM(jsid id)
{
return JSID_IS_STRING(id);
}
static JS_ALWAYS_INLINE JSBool
JSID_IS_ATOM(jsid id, JSAtom *atom)
{
return id == JSID_FROM_BITS((size_t)atom);
}
static JS_ALWAYS_INLINE JSAtom *
JSID_TO_ATOM(jsid id)
{
return (JSAtom *)JSID_TO_STRING(id);
}
JS_STATIC_ASSERT(sizeof(jsid) == JS_BYTES_PER_WORD);
#ifdef __cplusplus
namespace js {
static JS_ALWAYS_INLINE Value
IdToValue(jsid id)
{
if (JSID_IS_STRING(id))
return StringValue(JSID_TO_STRING(id));
if (JS_LIKELY(JSID_IS_INT(id)))
return Int32Value(JSID_TO_INT(id));
if (JS_LIKELY(JSID_IS_OBJECT(id)))
return ObjectValue(*JSID_TO_OBJECT(id));
JS_ASSERT(JSID_IS_DEFAULT_XML_NAMESPACE(id) || JSID_IS_VOID(id));
return UndefinedValue();
}
static JS_ALWAYS_INLINE jsval
IdToJsval(jsid id)
{
return IdToValue(id);
}
} /* namespace js */
#endif /* __cplusplus */
#endif /* jsfriendapi_h___ */