js/src/jsfriendapi.h

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

michael@0 1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
michael@0 2 * vim: set ts=8 sts=4 et sw=4 tw=99:
michael@0 3 * This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 #ifndef jsfriendapi_h
michael@0 8 #define jsfriendapi_h
michael@0 9
michael@0 10 #include "mozilla/Casting.h"
michael@0 11 #include "mozilla/MemoryReporting.h"
michael@0 12 #include "mozilla/TypedEnum.h"
michael@0 13
michael@0 14 #include "jsbytecode.h"
michael@0 15 #include "jspubtd.h"
michael@0 16
michael@0 17 #include "js/CallArgs.h"
michael@0 18 #include "js/CallNonGenericMethod.h"
michael@0 19 #include "js/Class.h"
michael@0 20
michael@0 21 /*
michael@0 22 * This macro checks if the stack pointer has exceeded a given limit. If
michael@0 23 * |tolerance| is non-zero, it returns true only if the stack pointer has
michael@0 24 * exceeded the limit by more than |tolerance| bytes.
michael@0 25 */
michael@0 26 #if JS_STACK_GROWTH_DIRECTION > 0
michael@0 27 # define JS_CHECK_STACK_SIZE_WITH_TOLERANCE(limit, sp, tolerance) \
michael@0 28 ((uintptr_t)(sp) < (limit)+(tolerance))
michael@0 29 #else
michael@0 30 # define JS_CHECK_STACK_SIZE_WITH_TOLERANCE(limit, sp, tolerance) \
michael@0 31 ((uintptr_t)(sp) > (limit)-(tolerance))
michael@0 32 #endif
michael@0 33
michael@0 34 #define JS_CHECK_STACK_SIZE(limit, lval) JS_CHECK_STACK_SIZE_WITH_TOLERANCE(limit, lval, 0)
michael@0 35
michael@0 36 class JSAtom;
michael@0 37 struct JSErrorFormatString;
michael@0 38 class JSLinearString;
michael@0 39 struct JSJitInfo;
michael@0 40 class JSErrorReport;
michael@0 41
michael@0 42 namespace JS {
michael@0 43 template <class T>
michael@0 44 class Heap;
michael@0 45 } /* namespace JS */
michael@0 46
michael@0 47 namespace js {
michael@0 48 class JS_FRIEND_API(BaseProxyHandler);
michael@0 49 } /* namespace js */
michael@0 50
michael@0 51 extern JS_FRIEND_API(void)
michael@0 52 JS_SetGrayGCRootsTracer(JSRuntime *rt, JSTraceDataOp traceOp, void *data);
michael@0 53
michael@0 54 extern JS_FRIEND_API(JSString *)
michael@0 55 JS_GetAnonymousString(JSRuntime *rt);
michael@0 56
michael@0 57 extern JS_FRIEND_API(void)
michael@0 58 JS_SetIsWorkerRuntime(JSRuntime *rt);
michael@0 59
michael@0 60 extern JS_FRIEND_API(JSObject *)
michael@0 61 JS_FindCompilationScope(JSContext *cx, JS::HandleObject obj);
michael@0 62
michael@0 63 extern JS_FRIEND_API(JSFunction *)
michael@0 64 JS_GetObjectFunction(JSObject *obj);
michael@0 65
michael@0 66 extern JS_FRIEND_API(bool)
michael@0 67 JS_SplicePrototype(JSContext *cx, JS::HandleObject obj, JS::HandleObject proto);
michael@0 68
michael@0 69 extern JS_FRIEND_API(JSObject *)
michael@0 70 JS_NewObjectWithUniqueType(JSContext *cx, const JSClass *clasp, JS::HandleObject proto,
michael@0 71 JS::HandleObject parent);
michael@0 72
michael@0 73 extern JS_FRIEND_API(uint32_t)
michael@0 74 JS_ObjectCountDynamicSlots(JS::HandleObject obj);
michael@0 75
michael@0 76 extern JS_FRIEND_API(size_t)
michael@0 77 JS_SetProtoCalled(JSContext *cx);
michael@0 78
michael@0 79 extern JS_FRIEND_API(size_t)
michael@0 80 JS_GetCustomIteratorCount(JSContext *cx);
michael@0 81
michael@0 82 extern JS_FRIEND_API(bool)
michael@0 83 JS_NondeterministicGetWeakMapKeys(JSContext *cx, JS::HandleObject obj, JS::MutableHandleObject ret);
michael@0 84
michael@0 85 /*
michael@0 86 * Determine whether the given object is backed by a DeadObjectProxy.
michael@0 87 *
michael@0 88 * Such objects hold no other objects (they have no outgoing reference edges)
michael@0 89 * and will throw if you touch them (e.g. by reading/writing a property).
michael@0 90 */
michael@0 91 extern JS_FRIEND_API(bool)
michael@0 92 JS_IsDeadWrapper(JSObject *obj);
michael@0 93
michael@0 94 /*
michael@0 95 * Used by the cycle collector to trace through the shape and all
michael@0 96 * shapes it reaches, marking all non-shape children found in the
michael@0 97 * process. Uses bounded stack space.
michael@0 98 */
michael@0 99 extern JS_FRIEND_API(void)
michael@0 100 JS_TraceShapeCycleCollectorChildren(JSTracer *trc, void *shape);
michael@0 101
michael@0 102 enum {
michael@0 103 JS_TELEMETRY_GC_REASON,
michael@0 104 JS_TELEMETRY_GC_IS_COMPARTMENTAL,
michael@0 105 JS_TELEMETRY_GC_MS,
michael@0 106 JS_TELEMETRY_GC_MAX_PAUSE_MS,
michael@0 107 JS_TELEMETRY_GC_MARK_MS,
michael@0 108 JS_TELEMETRY_GC_SWEEP_MS,
michael@0 109 JS_TELEMETRY_GC_MARK_ROOTS_MS,
michael@0 110 JS_TELEMETRY_GC_MARK_GRAY_MS,
michael@0 111 JS_TELEMETRY_GC_SLICE_MS,
michael@0 112 JS_TELEMETRY_GC_MMU_50,
michael@0 113 JS_TELEMETRY_GC_RESET,
michael@0 114 JS_TELEMETRY_GC_INCREMENTAL_DISABLED,
michael@0 115 JS_TELEMETRY_GC_NON_INCREMENTAL,
michael@0 116 JS_TELEMETRY_GC_SCC_SWEEP_TOTAL_MS,
michael@0 117 JS_TELEMETRY_GC_SCC_SWEEP_MAX_PAUSE_MS
michael@0 118 };
michael@0 119
michael@0 120 typedef void
michael@0 121 (* JSAccumulateTelemetryDataCallback)(int id, uint32_t sample);
michael@0 122
michael@0 123 extern JS_FRIEND_API(void)
michael@0 124 JS_SetAccumulateTelemetryCallback(JSRuntime *rt, JSAccumulateTelemetryDataCallback callback);
michael@0 125
michael@0 126 extern JS_FRIEND_API(JSPrincipals *)
michael@0 127 JS_GetCompartmentPrincipals(JSCompartment *compartment);
michael@0 128
michael@0 129 extern JS_FRIEND_API(void)
michael@0 130 JS_SetCompartmentPrincipals(JSCompartment *compartment, JSPrincipals *principals);
michael@0 131
michael@0 132 /* Safe to call with input obj == nullptr. Returns non-nullptr iff obj != nullptr. */
michael@0 133 extern JS_FRIEND_API(JSObject *)
michael@0 134 JS_ObjectToInnerObject(JSContext *cx, JS::HandleObject obj);
michael@0 135
michael@0 136 /* Requires obj != nullptr. */
michael@0 137 extern JS_FRIEND_API(JSObject *)
michael@0 138 JS_ObjectToOuterObject(JSContext *cx, JS::HandleObject obj);
michael@0 139
michael@0 140 extern JS_FRIEND_API(JSObject *)
michael@0 141 JS_CloneObject(JSContext *cx, JS::HandleObject obj, JS::HandleObject proto,
michael@0 142 JS::HandleObject parent);
michael@0 143
michael@0 144 extern JS_FRIEND_API(JSString *)
michael@0 145 JS_BasicObjectToString(JSContext *cx, JS::HandleObject obj);
michael@0 146
michael@0 147 extern JS_FRIEND_API(bool)
michael@0 148 js_GetterOnlyPropertyStub(JSContext *cx, JS::HandleObject obj, JS::HandleId id, bool strict,
michael@0 149 JS::MutableHandleValue vp);
michael@0 150
michael@0 151 JS_FRIEND_API(void)
michael@0 152 js_ReportOverRecursed(JSContext *maybecx);
michael@0 153
michael@0 154 JS_FRIEND_API(bool)
michael@0 155 js_ObjectClassIs(JSContext *cx, JS::HandleObject obj, js::ESClassValue classValue);
michael@0 156
michael@0 157 JS_FRIEND_API(const char *)
michael@0 158 js_ObjectClassName(JSContext *cx, JS::HandleObject obj);
michael@0 159
michael@0 160 namespace js {
michael@0 161
michael@0 162 JS_FRIEND_API(bool)
michael@0 163 AddRawValueRoot(JSContext *cx, JS::Value *vp, const char *name);
michael@0 164
michael@0 165 JS_FRIEND_API(void)
michael@0 166 RemoveRawValueRoot(JSContext *cx, JS::Value *vp);
michael@0 167
michael@0 168 } /* namespace js */
michael@0 169
michael@0 170 #ifdef JS_DEBUG
michael@0 171
michael@0 172 /*
michael@0 173 * Routines to print out values during debugging. These are FRIEND_API to help
michael@0 174 * the debugger find them and to support temporarily hacking js_Dump* calls
michael@0 175 * into other code.
michael@0 176 */
michael@0 177
michael@0 178 extern JS_FRIEND_API(void)
michael@0 179 js_DumpString(JSString *str);
michael@0 180
michael@0 181 extern JS_FRIEND_API(void)
michael@0 182 js_DumpAtom(JSAtom *atom);
michael@0 183
michael@0 184 extern JS_FRIEND_API(void)
michael@0 185 js_DumpObject(JSObject *obj);
michael@0 186
michael@0 187 extern JS_FRIEND_API(void)
michael@0 188 js_DumpChars(const jschar *s, size_t n);
michael@0 189 #endif
michael@0 190
michael@0 191 /*
michael@0 192 * Copies all own properties from |obj| to |target|. |obj| must be a "native"
michael@0 193 * object (that is to say, normal-ish - not an Array or a Proxy).
michael@0 194 *
michael@0 195 * This function immediately enters a compartment, and does not impose any
michael@0 196 * restrictions on the compartment of |cx|.
michael@0 197 */
michael@0 198 extern JS_FRIEND_API(bool)
michael@0 199 JS_CopyPropertiesFrom(JSContext *cx, JS::HandleObject target, JS::HandleObject obj);
michael@0 200
michael@0 201 /*
michael@0 202 * Single-property version of the above. This function asserts that an |own|
michael@0 203 * property of the given name exists on |obj|.
michael@0 204 *
michael@0 205 * On entry, |cx| must be same-compartment with |obj|.
michael@0 206 */
michael@0 207 extern JS_FRIEND_API(bool)
michael@0 208 JS_CopyPropertyFrom(JSContext *cx, JS::HandleId id, JS::HandleObject target,
michael@0 209 JS::HandleObject obj);
michael@0 210
michael@0 211 extern JS_FRIEND_API(bool)
michael@0 212 JS_WrapPropertyDescriptor(JSContext *cx, JS::MutableHandle<JSPropertyDescriptor> desc);
michael@0 213
michael@0 214 extern JS_FRIEND_API(bool)
michael@0 215 JS_WrapAutoIdVector(JSContext *cx, JS::AutoIdVector &props);
michael@0 216
michael@0 217 extern JS_FRIEND_API(bool)
michael@0 218 JS_EnumerateState(JSContext *cx, JS::HandleObject obj, JSIterateOp enum_op,
michael@0 219 JS::MutableHandleValue statep, JS::MutableHandleId idp);
michael@0 220
michael@0 221 struct JSFunctionSpecWithHelp {
michael@0 222 const char *name;
michael@0 223 JSNative call;
michael@0 224 uint16_t nargs;
michael@0 225 uint16_t flags;
michael@0 226 const char *usage;
michael@0 227 const char *help;
michael@0 228 };
michael@0 229
michael@0 230 #define JS_FN_HELP(name,call,nargs,flags,usage,help) \
michael@0 231 {name, call, nargs, (flags) | JSPROP_ENUMERATE | JSFUN_STUB_GSOPS, usage, help}
michael@0 232 #define JS_FS_HELP_END \
michael@0 233 {nullptr, nullptr, 0, 0, nullptr, nullptr}
michael@0 234
michael@0 235 extern JS_FRIEND_API(bool)
michael@0 236 JS_DefineFunctionsWithHelp(JSContext *cx, JS::HandleObject obj, const JSFunctionSpecWithHelp *fs);
michael@0 237
michael@0 238 namespace js {
michael@0 239
michael@0 240 /*
michael@0 241 * Helper Macros for creating JSClasses that function as proxies.
michael@0 242 *
michael@0 243 * NB: The macro invocation must be surrounded by braces, so as to
michael@0 244 * allow for potention JSClass extensions.
michael@0 245 */
michael@0 246 #define PROXY_MAKE_EXT(outerObject, innerObject, iteratorObject, \
michael@0 247 isWrappedNative) \
michael@0 248 { \
michael@0 249 outerObject, \
michael@0 250 innerObject, \
michael@0 251 iteratorObject, \
michael@0 252 isWrappedNative, \
michael@0 253 js::proxy_WeakmapKeyDelegate \
michael@0 254 }
michael@0 255
michael@0 256 #define PROXY_CLASS_WITH_EXT(name, extraSlots, flags, callOp, constructOp, ext) \
michael@0 257 { \
michael@0 258 name, \
michael@0 259 js::Class::NON_NATIVE | \
michael@0 260 JSCLASS_IS_PROXY | \
michael@0 261 JSCLASS_IMPLEMENTS_BARRIERS | \
michael@0 262 JSCLASS_HAS_RESERVED_SLOTS(js::PROXY_MINIMUM_SLOTS + (extraSlots)) | \
michael@0 263 flags, \
michael@0 264 JS_PropertyStub, /* addProperty */ \
michael@0 265 JS_DeletePropertyStub, /* delProperty */ \
michael@0 266 JS_PropertyStub, /* getProperty */ \
michael@0 267 JS_StrictPropertyStub, /* setProperty */ \
michael@0 268 JS_EnumerateStub, \
michael@0 269 JS_ResolveStub, \
michael@0 270 js::proxy_Convert, \
michael@0 271 js::proxy_Finalize, /* finalize */ \
michael@0 272 callOp, /* call */ \
michael@0 273 js::proxy_HasInstance, /* hasInstance */ \
michael@0 274 constructOp, /* construct */ \
michael@0 275 js::proxy_Trace, /* trace */ \
michael@0 276 JS_NULL_CLASS_SPEC, \
michael@0 277 ext, \
michael@0 278 { \
michael@0 279 js::proxy_LookupGeneric, \
michael@0 280 js::proxy_LookupProperty, \
michael@0 281 js::proxy_LookupElement, \
michael@0 282 js::proxy_DefineGeneric, \
michael@0 283 js::proxy_DefineProperty, \
michael@0 284 js::proxy_DefineElement, \
michael@0 285 js::proxy_GetGeneric, \
michael@0 286 js::proxy_GetProperty, \
michael@0 287 js::proxy_GetElement, \
michael@0 288 js::proxy_SetGeneric, \
michael@0 289 js::proxy_SetProperty, \
michael@0 290 js::proxy_SetElement, \
michael@0 291 js::proxy_GetGenericAttributes, \
michael@0 292 js::proxy_SetGenericAttributes, \
michael@0 293 js::proxy_DeleteProperty, \
michael@0 294 js::proxy_DeleteElement, \
michael@0 295 js::proxy_Watch, js::proxy_Unwatch, \
michael@0 296 js::proxy_Slice, \
michael@0 297 nullptr, /* enumerate */ \
michael@0 298 nullptr, /* thisObject */ \
michael@0 299 } \
michael@0 300 }
michael@0 301
michael@0 302 #define PROXY_CLASS_DEF(name, extraSlots, flags, callOp, constructOp) \
michael@0 303 PROXY_CLASS_WITH_EXT(name, extraSlots, flags, callOp, constructOp, \
michael@0 304 PROXY_MAKE_EXT( \
michael@0 305 nullptr, /* outerObject */ \
michael@0 306 nullptr, /* innerObject */ \
michael@0 307 nullptr, /* iteratorObject */ \
michael@0 308 false /* isWrappedNative */ \
michael@0 309 ))
michael@0 310
michael@0 311 /*
michael@0 312 * Proxy stubs, similar to JS_*Stub, for embedder proxy class definitions.
michael@0 313 *
michael@0 314 * NB: Should not be called directly.
michael@0 315 */
michael@0 316
michael@0 317 extern JS_FRIEND_API(bool)
michael@0 318 proxy_LookupGeneric(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::MutableHandleObject objp,
michael@0 319 JS::MutableHandle<Shape*> propp);
michael@0 320 extern JS_FRIEND_API(bool)
michael@0 321 proxy_LookupProperty(JSContext *cx, JS::HandleObject obj, JS::Handle<PropertyName*> name,
michael@0 322 JS::MutableHandleObject objp, JS::MutableHandle<Shape*> propp);
michael@0 323 extern JS_FRIEND_API(bool)
michael@0 324 proxy_LookupElement(JSContext *cx, JS::HandleObject obj, uint32_t index, JS::MutableHandleObject objp,
michael@0 325 JS::MutableHandle<Shape*> propp);
michael@0 326 extern JS_FRIEND_API(bool)
michael@0 327 proxy_DefineGeneric(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::HandleValue value,
michael@0 328 JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs);
michael@0 329 extern JS_FRIEND_API(bool)
michael@0 330 proxy_DefineProperty(JSContext *cx, JS::HandleObject obj, JS::Handle<PropertyName*> name,
michael@0 331 JS::HandleValue value, JSPropertyOp getter, JSStrictPropertyOp setter,
michael@0 332 unsigned attrs);
michael@0 333 extern JS_FRIEND_API(bool)
michael@0 334 proxy_DefineElement(JSContext *cx, JS::HandleObject obj, uint32_t index, JS::HandleValue value,
michael@0 335 JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs);
michael@0 336 extern JS_FRIEND_API(bool)
michael@0 337 proxy_GetGeneric(JSContext *cx, JS::HandleObject obj, JS::HandleObject receiver, JS::HandleId id,
michael@0 338 JS::MutableHandleValue vp);
michael@0 339 extern JS_FRIEND_API(bool)
michael@0 340 proxy_GetProperty(JSContext *cx, JS::HandleObject obj, JS::HandleObject receiver,
michael@0 341 JS::Handle<PropertyName*> name, JS::MutableHandleValue vp);
michael@0 342 extern JS_FRIEND_API(bool)
michael@0 343 proxy_GetElement(JSContext *cx, JS::HandleObject obj, JS::HandleObject receiver, uint32_t index,
michael@0 344 JS::MutableHandleValue vp);
michael@0 345 extern JS_FRIEND_API(bool)
michael@0 346 proxy_SetGeneric(JSContext *cx, JS::HandleObject obj, JS::HandleId id,
michael@0 347 JS::MutableHandleValue bp, bool strict);
michael@0 348 extern JS_FRIEND_API(bool)
michael@0 349 proxy_SetProperty(JSContext *cx, JS::HandleObject obj, JS::Handle<PropertyName*> name,
michael@0 350 JS::MutableHandleValue bp, bool strict);
michael@0 351 extern JS_FRIEND_API(bool)
michael@0 352 proxy_SetElement(JSContext *cx, JS::HandleObject obj, uint32_t index, JS::MutableHandleValue vp,
michael@0 353 bool strict);
michael@0 354 extern JS_FRIEND_API(bool)
michael@0 355 proxy_GetGenericAttributes(JSContext *cx, JS::HandleObject obj, JS::HandleId id, unsigned *attrsp);
michael@0 356 extern JS_FRIEND_API(bool)
michael@0 357 proxy_SetGenericAttributes(JSContext *cx, JS::HandleObject obj, JS::HandleId id, unsigned *attrsp);
michael@0 358 extern JS_FRIEND_API(bool)
michael@0 359 proxy_DeleteProperty(JSContext *cx, JS::HandleObject obj, JS::Handle<PropertyName*> name,
michael@0 360 bool *succeeded);
michael@0 361 extern JS_FRIEND_API(bool)
michael@0 362 proxy_DeleteElement(JSContext *cx, JS::HandleObject obj, uint32_t index, bool *succeeded);
michael@0 363
michael@0 364 extern JS_FRIEND_API(void)
michael@0 365 proxy_Trace(JSTracer *trc, JSObject *obj);
michael@0 366 extern JS_FRIEND_API(JSObject *)
michael@0 367 proxy_WeakmapKeyDelegate(JSObject *obj);
michael@0 368 extern JS_FRIEND_API(bool)
michael@0 369 proxy_Convert(JSContext *cx, JS::HandleObject proxy, JSType hint, JS::MutableHandleValue vp);
michael@0 370 extern JS_FRIEND_API(void)
michael@0 371 proxy_Finalize(FreeOp *fop, JSObject *obj);
michael@0 372 extern JS_FRIEND_API(bool)
michael@0 373 proxy_HasInstance(JSContext *cx, JS::HandleObject proxy, JS::MutableHandleValue v, bool *bp);
michael@0 374 extern JS_FRIEND_API(bool)
michael@0 375 proxy_Call(JSContext *cx, unsigned argc, JS::Value *vp);
michael@0 376 extern JS_FRIEND_API(bool)
michael@0 377 proxy_Construct(JSContext *cx, unsigned argc, JS::Value *vp);
michael@0 378 extern JS_FRIEND_API(JSObject *)
michael@0 379 proxy_innerObject(JSContext *cx, JS::HandleObject obj);
michael@0 380 extern JS_FRIEND_API(bool)
michael@0 381 proxy_Watch(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::HandleObject callable);
michael@0 382 extern JS_FRIEND_API(bool)
michael@0 383 proxy_Unwatch(JSContext *cx, JS::HandleObject obj, JS::HandleId id);
michael@0 384 extern JS_FRIEND_API(bool)
michael@0 385 proxy_Slice(JSContext *cx, JS::HandleObject proxy, uint32_t begin, uint32_t end,
michael@0 386 JS::HandleObject result);
michael@0 387
michael@0 388 /*
michael@0 389 * A class of objects that return source code on demand.
michael@0 390 *
michael@0 391 * When code is compiled with setSourceIsLazy(true), SpiderMonkey doesn't
michael@0 392 * retain the source code (and doesn't do lazy bytecode generation). If we ever
michael@0 393 * need the source code, say, in response to a call to Function.prototype.
michael@0 394 * toSource or Debugger.Source.prototype.text, then we call the 'load' member
michael@0 395 * function of the instance of this class that has hopefully been registered
michael@0 396 * with the runtime, passing the code's URL, and hope that it will be able to
michael@0 397 * find the source.
michael@0 398 */
michael@0 399 class SourceHook {
michael@0 400 public:
michael@0 401 virtual ~SourceHook() { }
michael@0 402
michael@0 403 /*
michael@0 404 * Set |*src| and |*length| to refer to the source code for |filename|.
michael@0 405 * On success, the caller owns the buffer to which |*src| points, and
michael@0 406 * should use JS_free to free it.
michael@0 407 */
michael@0 408 virtual bool load(JSContext *cx, const char *filename, jschar **src, size_t *length) = 0;
michael@0 409 };
michael@0 410
michael@0 411 /*
michael@0 412 * Have |rt| use |hook| to retrieve lazily-retrieved source code. See the
michael@0 413 * comments for SourceHook. The runtime takes ownership of the hook, and
michael@0 414 * will delete it when the runtime itself is deleted, or when a new hook is
michael@0 415 * set.
michael@0 416 */
michael@0 417 extern JS_FRIEND_API(void)
michael@0 418 SetSourceHook(JSRuntime *rt, SourceHook *hook);
michael@0 419
michael@0 420 /* Remove |rt|'s source hook, and return it. The caller now owns the hook. */
michael@0 421 extern JS_FRIEND_API(SourceHook *)
michael@0 422 ForgetSourceHook(JSRuntime *rt);
michael@0 423
michael@0 424 extern JS_FRIEND_API(JS::Zone *)
michael@0 425 GetCompartmentZone(JSCompartment *comp);
michael@0 426
michael@0 427 typedef bool
michael@0 428 (* PreserveWrapperCallback)(JSContext *cx, JSObject *obj);
michael@0 429
michael@0 430 typedef enum {
michael@0 431 CollectNurseryBeforeDump,
michael@0 432 IgnoreNurseryObjects
michael@0 433 } DumpHeapNurseryBehaviour;
michael@0 434
michael@0 435 /*
michael@0 436 * Dump the complete object graph of heap-allocated things.
michael@0 437 * fp is the file for the dump output.
michael@0 438 */
michael@0 439 extern JS_FRIEND_API(void)
michael@0 440 DumpHeapComplete(JSRuntime *rt, FILE *fp, DumpHeapNurseryBehaviour nurseryBehaviour);
michael@0 441
michael@0 442 #ifdef JS_OLD_GETTER_SETTER_METHODS
michael@0 443 JS_FRIEND_API(bool) obj_defineGetter(JSContext *cx, unsigned argc, JS::Value *vp);
michael@0 444 JS_FRIEND_API(bool) obj_defineSetter(JSContext *cx, unsigned argc, JS::Value *vp);
michael@0 445 #endif
michael@0 446
michael@0 447 extern JS_FRIEND_API(bool)
michael@0 448 IsSystemCompartment(JSCompartment *comp);
michael@0 449
michael@0 450 extern JS_FRIEND_API(bool)
michael@0 451 IsSystemZone(JS::Zone *zone);
michael@0 452
michael@0 453 extern JS_FRIEND_API(bool)
michael@0 454 IsAtomsCompartment(JSCompartment *comp);
michael@0 455
michael@0 456 /*
michael@0 457 * Check whether it is OK to assign an undeclared variable with the name
michael@0 458 * |propname| at the current location in script. It is not an error if there is
michael@0 459 * no current script location, or if that location is not an assignment to an
michael@0 460 * undeclared variable. Reports an error if one needs to be reported (and,
michael@0 461 * particularly, always reports when it returns false).
michael@0 462 */
michael@0 463 extern JS_FRIEND_API(bool)
michael@0 464 ReportIfUndeclaredVarAssignment(JSContext *cx, JS::HandleString propname);
michael@0 465
michael@0 466 /*
michael@0 467 * Returns whether we're in a non-strict property set (in that we're in a
michael@0 468 * non-strict script and the bytecode we're on is a property set). The return
michael@0 469 * value does NOT indicate any sort of exception was thrown: it's just a
michael@0 470 * boolean.
michael@0 471 */
michael@0 472 extern JS_FRIEND_API(bool)
michael@0 473 IsInNonStrictPropertySet(JSContext *cx);
michael@0 474
michael@0 475 struct WeakMapTracer;
michael@0 476
michael@0 477 /*
michael@0 478 * Weak map tracer callback, called once for every binding of every
michael@0 479 * weak map that was live at the time of the last garbage collection.
michael@0 480 *
michael@0 481 * m will be nullptr if the weak map is not contained in a JS Object.
michael@0 482 */
michael@0 483 typedef void
michael@0 484 (* WeakMapTraceCallback)(WeakMapTracer *trc, JSObject *m,
michael@0 485 void *k, JSGCTraceKind kkind,
michael@0 486 void *v, JSGCTraceKind vkind);
michael@0 487
michael@0 488 struct WeakMapTracer {
michael@0 489 JSRuntime *runtime;
michael@0 490 WeakMapTraceCallback callback;
michael@0 491
michael@0 492 WeakMapTracer(JSRuntime *rt, WeakMapTraceCallback cb)
michael@0 493 : runtime(rt), callback(cb) {}
michael@0 494 };
michael@0 495
michael@0 496 extern JS_FRIEND_API(void)
michael@0 497 TraceWeakMaps(WeakMapTracer *trc);
michael@0 498
michael@0 499 extern JS_FRIEND_API(bool)
michael@0 500 AreGCGrayBitsValid(JSRuntime *rt);
michael@0 501
michael@0 502 extern JS_FRIEND_API(bool)
michael@0 503 ZoneGlobalsAreAllGray(JS::Zone *zone);
michael@0 504
michael@0 505 typedef void
michael@0 506 (*GCThingCallback)(void *closure, void *gcthing);
michael@0 507
michael@0 508 extern JS_FRIEND_API(void)
michael@0 509 VisitGrayWrapperTargets(JS::Zone *zone, GCThingCallback callback, void *closure);
michael@0 510
michael@0 511 extern JS_FRIEND_API(JSObject *)
michael@0 512 GetWeakmapKeyDelegate(JSObject *key);
michael@0 513
michael@0 514 JS_FRIEND_API(JSGCTraceKind)
michael@0 515 GCThingTraceKind(void *thing);
michael@0 516
michael@0 517 /*
michael@0 518 * Invoke cellCallback on every gray JS_OBJECT in the given zone.
michael@0 519 */
michael@0 520 extern JS_FRIEND_API(void)
michael@0 521 IterateGrayObjects(JS::Zone *zone, GCThingCallback cellCallback, void *data);
michael@0 522
michael@0 523 #ifdef JS_HAS_CTYPES
michael@0 524 extern JS_FRIEND_API(size_t)
michael@0 525 SizeOfDataIfCDataObject(mozilla::MallocSizeOf mallocSizeOf, JSObject *obj);
michael@0 526 #endif
michael@0 527
michael@0 528 extern JS_FRIEND_API(JSCompartment *)
michael@0 529 GetAnyCompartmentInZone(JS::Zone *zone);
michael@0 530
michael@0 531 /*
michael@0 532 * Shadow declarations of JS internal structures, for access by inline access
michael@0 533 * functions below. Do not use these structures in any other way. When adding
michael@0 534 * new fields for access by inline methods, make sure to add static asserts to
michael@0 535 * the original header file to ensure that offsets are consistent.
michael@0 536 */
michael@0 537 namespace shadow {
michael@0 538
michael@0 539 struct TypeObject {
michael@0 540 const Class *clasp;
michael@0 541 JSObject *proto;
michael@0 542 };
michael@0 543
michael@0 544 struct BaseShape {
michael@0 545 const js::Class *clasp_;
michael@0 546 JSObject *parent;
michael@0 547 JSObject *_1;
michael@0 548 JSCompartment *compartment;
michael@0 549 };
michael@0 550
michael@0 551 class Shape {
michael@0 552 public:
michael@0 553 shadow::BaseShape *base;
michael@0 554 jsid _1;
michael@0 555 uint32_t slotInfo;
michael@0 556
michael@0 557 static const uint32_t FIXED_SLOTS_SHIFT = 27;
michael@0 558 };
michael@0 559
michael@0 560 struct Object {
michael@0 561 shadow::Shape *shape;
michael@0 562 shadow::TypeObject *type;
michael@0 563 JS::Value *slots;
michael@0 564 JS::Value *_1;
michael@0 565
michael@0 566 size_t numFixedSlots() const { return shape->slotInfo >> Shape::FIXED_SLOTS_SHIFT; }
michael@0 567 JS::Value *fixedSlots() const {
michael@0 568 return (JS::Value *)(uintptr_t(this) + sizeof(shadow::Object));
michael@0 569 }
michael@0 570
michael@0 571 JS::Value &slotRef(size_t slot) const {
michael@0 572 size_t nfixed = numFixedSlots();
michael@0 573 if (slot < nfixed)
michael@0 574 return fixedSlots()[slot];
michael@0 575 return slots[slot - nfixed];
michael@0 576 }
michael@0 577
michael@0 578 // Reserved slots with index < MAX_FIXED_SLOTS are guaranteed to
michael@0 579 // be fixed slots.
michael@0 580 static const uint32_t MAX_FIXED_SLOTS = 16;
michael@0 581 };
michael@0 582
michael@0 583 struct Function {
michael@0 584 Object base;
michael@0 585 uint16_t nargs;
michael@0 586 uint16_t flags;
michael@0 587 /* Used only for natives */
michael@0 588 JSNative native;
michael@0 589 const JSJitInfo *jitinfo;
michael@0 590 void *_1;
michael@0 591 };
michael@0 592
michael@0 593 struct Atom {
michael@0 594 static const size_t LENGTH_SHIFT = 4;
michael@0 595 size_t lengthAndFlags;
michael@0 596 const jschar *chars;
michael@0 597 };
michael@0 598
michael@0 599 } /* namespace shadow */
michael@0 600
michael@0 601 // This is equal to |&JSObject::class_|. Use it in places where you don't want
michael@0 602 // to #include jsobj.h.
michael@0 603 extern JS_FRIEND_DATA(const js::Class* const) ObjectClassPtr;
michael@0 604
michael@0 605 inline const js::Class *
michael@0 606 GetObjectClass(JSObject *obj)
michael@0 607 {
michael@0 608 return reinterpret_cast<const shadow::Object*>(obj)->type->clasp;
michael@0 609 }
michael@0 610
michael@0 611 inline const JSClass *
michael@0 612 GetObjectJSClass(JSObject *obj)
michael@0 613 {
michael@0 614 return js::Jsvalify(GetObjectClass(obj));
michael@0 615 }
michael@0 616
michael@0 617 inline bool
michael@0 618 IsInnerObject(JSObject *obj) {
michael@0 619 return !!GetObjectClass(obj)->ext.outerObject;
michael@0 620 }
michael@0 621
michael@0 622 inline bool
michael@0 623 IsOuterObject(JSObject *obj) {
michael@0 624 return !!GetObjectClass(obj)->ext.innerObject;
michael@0 625 }
michael@0 626
michael@0 627 JS_FRIEND_API(bool)
michael@0 628 IsFunctionObject(JSObject *obj);
michael@0 629
michael@0 630 JS_FRIEND_API(bool)
michael@0 631 IsScopeObject(JSObject *obj);
michael@0 632
michael@0 633 JS_FRIEND_API(bool)
michael@0 634 IsCallObject(JSObject *obj);
michael@0 635
michael@0 636 inline JSObject *
michael@0 637 GetObjectParent(JSObject *obj)
michael@0 638 {
michael@0 639 JS_ASSERT(!IsScopeObject(obj));
michael@0 640 return reinterpret_cast<shadow::Object*>(obj)->shape->base->parent;
michael@0 641 }
michael@0 642
michael@0 643 static MOZ_ALWAYS_INLINE JSCompartment *
michael@0 644 GetObjectCompartment(JSObject *obj)
michael@0 645 {
michael@0 646 return reinterpret_cast<shadow::Object*>(obj)->shape->base->compartment;
michael@0 647 }
michael@0 648
michael@0 649 JS_FRIEND_API(JSObject *)
michael@0 650 GetObjectParentMaybeScope(JSObject *obj);
michael@0 651
michael@0 652 JS_FRIEND_API(JSObject *)
michael@0 653 GetGlobalForObjectCrossCompartment(JSObject *obj);
michael@0 654
michael@0 655 // Sidestep the activeContext checking implicitly performed in
michael@0 656 // JS_SetPendingException.
michael@0 657 JS_FRIEND_API(void)
michael@0 658 SetPendingExceptionCrossContext(JSContext *cx, JS::HandleValue v);
michael@0 659
michael@0 660 JS_FRIEND_API(void)
michael@0 661 AssertSameCompartment(JSContext *cx, JSObject *obj);
michael@0 662
michael@0 663 #ifdef JS_DEBUG
michael@0 664 JS_FRIEND_API(void)
michael@0 665 AssertSameCompartment(JSObject *objA, JSObject *objB);
michael@0 666 #else
michael@0 667 inline void AssertSameCompartment(JSObject *objA, JSObject *objB) {}
michael@0 668 #endif
michael@0 669
michael@0 670 // For legacy consumers only. This whole concept is going away soon.
michael@0 671 JS_FRIEND_API(JSObject *)
michael@0 672 DefaultObjectForContextOrNull(JSContext *cx);
michael@0 673
michael@0 674 JS_FRIEND_API(void)
michael@0 675 SetDefaultObjectForContext(JSContext *cx, JSObject *obj);
michael@0 676
michael@0 677 JS_FRIEND_API(void)
michael@0 678 NotifyAnimationActivity(JSObject *obj);
michael@0 679
michael@0 680 /*
michael@0 681 * Return the outermost enclosing function (script) of the scripted caller.
michael@0 682 * This function returns nullptr in several cases:
michael@0 683 * - no script is running on the context
michael@0 684 * - the caller is in global or eval code
michael@0 685 * In particular, this function will "stop" its outermost search at eval() and
michael@0 686 * thus it will really return the outermost enclosing function *since the
michael@0 687 * innermost eval*.
michael@0 688 */
michael@0 689 JS_FRIEND_API(JSScript *)
michael@0 690 GetOutermostEnclosingFunctionOfScriptedCaller(JSContext *cx);
michael@0 691
michael@0 692 JS_FRIEND_API(JSFunction *)
michael@0 693 DefineFunctionWithReserved(JSContext *cx, JSObject *obj, const char *name, JSNative call,
michael@0 694 unsigned nargs, unsigned attrs);
michael@0 695
michael@0 696 JS_FRIEND_API(JSFunction *)
michael@0 697 NewFunctionWithReserved(JSContext *cx, JSNative call, unsigned nargs, unsigned flags,
michael@0 698 JSObject *parent, const char *name);
michael@0 699
michael@0 700 JS_FRIEND_API(JSFunction *)
michael@0 701 NewFunctionByIdWithReserved(JSContext *cx, JSNative native, unsigned nargs, unsigned flags,
michael@0 702 JSObject *parent, jsid id);
michael@0 703
michael@0 704 JS_FRIEND_API(JSObject *)
michael@0 705 InitClassWithReserved(JSContext *cx, JSObject *obj, JSObject *parent_proto,
michael@0 706 const JSClass *clasp, JSNative constructor, unsigned nargs,
michael@0 707 const JSPropertySpec *ps, const JSFunctionSpec *fs,
michael@0 708 const JSPropertySpec *static_ps, const JSFunctionSpec *static_fs);
michael@0 709
michael@0 710 JS_FRIEND_API(const JS::Value &)
michael@0 711 GetFunctionNativeReserved(JSObject *fun, size_t which);
michael@0 712
michael@0 713 JS_FRIEND_API(void)
michael@0 714 SetFunctionNativeReserved(JSObject *fun, size_t which, const JS::Value &val);
michael@0 715
michael@0 716 JS_FRIEND_API(bool)
michael@0 717 GetObjectProto(JSContext *cx, JS::HandleObject obj, JS::MutableHandleObject proto);
michael@0 718
michael@0 719 JS_FRIEND_API(bool)
michael@0 720 GetOriginalEval(JSContext *cx, JS::HandleObject scope,
michael@0 721 JS::MutableHandleObject eval);
michael@0 722
michael@0 723 inline void *
michael@0 724 GetObjectPrivate(JSObject *obj)
michael@0 725 {
michael@0 726 const shadow::Object *nobj = reinterpret_cast<const shadow::Object*>(obj);
michael@0 727 void **addr = reinterpret_cast<void**>(&nobj->fixedSlots()[nobj->numFixedSlots()]);
michael@0 728 return *addr;
michael@0 729 }
michael@0 730
michael@0 731 /*
michael@0 732 * Get a slot that is both reserved for object's clasp *and* is fixed (fits
michael@0 733 * within the maximum capacity for the object's fixed slots).
michael@0 734 */
michael@0 735 inline const JS::Value &
michael@0 736 GetReservedSlot(JSObject *obj, size_t slot)
michael@0 737 {
michael@0 738 JS_ASSERT(slot < JSCLASS_RESERVED_SLOTS(GetObjectClass(obj)));
michael@0 739 return reinterpret_cast<const shadow::Object *>(obj)->slotRef(slot);
michael@0 740 }
michael@0 741
michael@0 742 JS_FRIEND_API(void)
michael@0 743 SetReservedSlotWithBarrier(JSObject *obj, size_t slot, const JS::Value &value);
michael@0 744
michael@0 745 inline void
michael@0 746 SetReservedSlot(JSObject *obj, size_t slot, const JS::Value &value)
michael@0 747 {
michael@0 748 JS_ASSERT(slot < JSCLASS_RESERVED_SLOTS(GetObjectClass(obj)));
michael@0 749 shadow::Object *sobj = reinterpret_cast<shadow::Object *>(obj);
michael@0 750 if (sobj->slotRef(slot).isMarkable()
michael@0 751 #ifdef JSGC_GENERATIONAL
michael@0 752 || value.isMarkable()
michael@0 753 #endif
michael@0 754 )
michael@0 755 {
michael@0 756 SetReservedSlotWithBarrier(obj, slot, value);
michael@0 757 } else {
michael@0 758 sobj->slotRef(slot) = value;
michael@0 759 }
michael@0 760 }
michael@0 761
michael@0 762 JS_FRIEND_API(uint32_t)
michael@0 763 GetObjectSlotSpan(JSObject *obj);
michael@0 764
michael@0 765 inline const JS::Value &
michael@0 766 GetObjectSlot(JSObject *obj, size_t slot)
michael@0 767 {
michael@0 768 JS_ASSERT(slot < GetObjectSlotSpan(obj));
michael@0 769 return reinterpret_cast<const shadow::Object *>(obj)->slotRef(slot);
michael@0 770 }
michael@0 771
michael@0 772 inline const jschar *
michael@0 773 GetAtomChars(JSAtom *atom)
michael@0 774 {
michael@0 775 return reinterpret_cast<shadow::Atom *>(atom)->chars;
michael@0 776 }
michael@0 777
michael@0 778 inline size_t
michael@0 779 GetAtomLength(JSAtom *atom)
michael@0 780 {
michael@0 781 using shadow::Atom;
michael@0 782 return reinterpret_cast<Atom*>(atom)->lengthAndFlags >> Atom::LENGTH_SHIFT;
michael@0 783 }
michael@0 784
michael@0 785 inline JSLinearString *
michael@0 786 AtomToLinearString(JSAtom *atom)
michael@0 787 {
michael@0 788 return reinterpret_cast<JSLinearString *>(atom);
michael@0 789 }
michael@0 790
michael@0 791 JS_FRIEND_API(bool)
michael@0 792 GetPropertyNames(JSContext *cx, JSObject *obj, unsigned flags, JS::AutoIdVector *props);
michael@0 793
michael@0 794 JS_FRIEND_API(bool)
michael@0 795 AppendUnique(JSContext *cx, JS::AutoIdVector &base, JS::AutoIdVector &others);
michael@0 796
michael@0 797 JS_FRIEND_API(bool)
michael@0 798 GetGeneric(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, JS::Value *vp);
michael@0 799
michael@0 800 JS_FRIEND_API(bool)
michael@0 801 StringIsArrayIndex(JSLinearString *str, uint32_t *indexp);
michael@0 802
michael@0 803 JS_FRIEND_API(void)
michael@0 804 SetPreserveWrapperCallback(JSRuntime *rt, PreserveWrapperCallback callback);
michael@0 805
michael@0 806 JS_FRIEND_API(bool)
michael@0 807 IsObjectInContextCompartment(JSObject *obj, const JSContext *cx);
michael@0 808
michael@0 809 /*
michael@0 810 * NB: these flag bits are encoded into the bytecode stream in the immediate
michael@0 811 * operand of JSOP_ITER, so don't change them without advancing vm/Xdr.h's
michael@0 812 * XDR_BYTECODE_VERSION.
michael@0 813 */
michael@0 814 #define JSITER_ENUMERATE 0x1 /* for-in compatible hidden default iterator */
michael@0 815 #define JSITER_FOREACH 0x2 /* return [key, value] pair rather than key */
michael@0 816 #define JSITER_KEYVALUE 0x4 /* destructuring for-in wants [key, value] */
michael@0 817 #define JSITER_OWNONLY 0x8 /* iterate over obj's own properties only */
michael@0 818 #define JSITER_HIDDEN 0x10 /* also enumerate non-enumerable properties */
michael@0 819
michael@0 820 JS_FRIEND_API(bool)
michael@0 821 RunningWithTrustedPrincipals(JSContext *cx);
michael@0 822
michael@0 823 inline uintptr_t
michael@0 824 GetNativeStackLimit(JSContext *cx)
michael@0 825 {
michael@0 826 StackKind kind = RunningWithTrustedPrincipals(cx) ? StackForTrustedScript
michael@0 827 : StackForUntrustedScript;
michael@0 828 PerThreadDataFriendFields *mainThread =
michael@0 829 PerThreadDataFriendFields::getMainThread(GetRuntime(cx));
michael@0 830 return mainThread->nativeStackLimit[kind];
michael@0 831 }
michael@0 832
michael@0 833 /*
michael@0 834 * These macros report a stack overflow and run |onerror| if we are close to
michael@0 835 * using up the C stack. The JS_CHECK_CHROME_RECURSION variant gives us a little
michael@0 836 * extra space so that we can ensure that crucial code is able to run.
michael@0 837 */
michael@0 838
michael@0 839 #define JS_CHECK_RECURSION(cx, onerror) \
michael@0 840 JS_BEGIN_MACRO \
michael@0 841 int stackDummy_; \
michael@0 842 if (!JS_CHECK_STACK_SIZE(js::GetNativeStackLimit(cx), &stackDummy_)) { \
michael@0 843 js_ReportOverRecursed(cx); \
michael@0 844 onerror; \
michael@0 845 } \
michael@0 846 JS_END_MACRO
michael@0 847
michael@0 848 #define JS_CHECK_RECURSION_DONT_REPORT(cx, onerror) \
michael@0 849 JS_BEGIN_MACRO \
michael@0 850 int stackDummy_; \
michael@0 851 if (!JS_CHECK_STACK_SIZE(js::GetNativeStackLimit(cx), &stackDummy_)) { \
michael@0 852 onerror; \
michael@0 853 } \
michael@0 854 JS_END_MACRO
michael@0 855
michael@0 856 #define JS_CHECK_RECURSION_WITH_SP_DONT_REPORT(cx, sp, onerror) \
michael@0 857 JS_BEGIN_MACRO \
michael@0 858 if (!JS_CHECK_STACK_SIZE(js::GetNativeStackLimit(cx), sp)) { \
michael@0 859 onerror; \
michael@0 860 } \
michael@0 861 JS_END_MACRO
michael@0 862
michael@0 863 #define JS_CHECK_RECURSION_WITH_SP(cx, sp, onerror) \
michael@0 864 JS_BEGIN_MACRO \
michael@0 865 if (!JS_CHECK_STACK_SIZE(js::GetNativeStackLimit(cx), sp)) { \
michael@0 866 js_ReportOverRecursed(cx); \
michael@0 867 onerror; \
michael@0 868 } \
michael@0 869 JS_END_MACRO
michael@0 870
michael@0 871 #define JS_CHECK_CHROME_RECURSION(cx, onerror) \
michael@0 872 JS_BEGIN_MACRO \
michael@0 873 int stackDummy_; \
michael@0 874 if (!JS_CHECK_STACK_SIZE_WITH_TOLERANCE(js::GetNativeStackLimit(cx), \
michael@0 875 &stackDummy_, \
michael@0 876 1024 * sizeof(size_t))) \
michael@0 877 { \
michael@0 878 js_ReportOverRecursed(cx); \
michael@0 879 onerror; \
michael@0 880 } \
michael@0 881 JS_END_MACRO
michael@0 882
michael@0 883 JS_FRIEND_API(void)
michael@0 884 StartPCCountProfiling(JSContext *cx);
michael@0 885
michael@0 886 JS_FRIEND_API(void)
michael@0 887 StopPCCountProfiling(JSContext *cx);
michael@0 888
michael@0 889 JS_FRIEND_API(void)
michael@0 890 PurgePCCounts(JSContext *cx);
michael@0 891
michael@0 892 JS_FRIEND_API(size_t)
michael@0 893 GetPCCountScriptCount(JSContext *cx);
michael@0 894
michael@0 895 JS_FRIEND_API(JSString *)
michael@0 896 GetPCCountScriptSummary(JSContext *cx, size_t script);
michael@0 897
michael@0 898 JS_FRIEND_API(JSString *)
michael@0 899 GetPCCountScriptContents(JSContext *cx, size_t script);
michael@0 900
michael@0 901 #ifdef JS_THREADSAFE
michael@0 902 JS_FRIEND_API(bool)
michael@0 903 ContextHasOutstandingRequests(const JSContext *cx);
michael@0 904 #endif
michael@0 905
michael@0 906 typedef void
michael@0 907 (* ActivityCallback)(void *arg, bool active);
michael@0 908
michael@0 909 /*
michael@0 910 * Sets a callback that is run whenever the runtime goes idle - the
michael@0 911 * last active request ceases - and begins activity - when it was
michael@0 912 * idle and a request begins.
michael@0 913 */
michael@0 914 JS_FRIEND_API(void)
michael@0 915 SetActivityCallback(JSRuntime *rt, ActivityCallback cb, void *arg);
michael@0 916
michael@0 917 extern JS_FRIEND_API(const JSStructuredCloneCallbacks *)
michael@0 918 GetContextStructuredCloneCallbacks(JSContext *cx);
michael@0 919
michael@0 920 extern JS_FRIEND_API(bool)
michael@0 921 IsContextRunningJS(JSContext *cx);
michael@0 922
michael@0 923 typedef bool
michael@0 924 (* DOMInstanceClassMatchesProto)(JSObject *protoObject, uint32_t protoID, uint32_t depth);
michael@0 925 struct JSDOMCallbacks {
michael@0 926 DOMInstanceClassMatchesProto instanceClassMatchesProto;
michael@0 927 };
michael@0 928 typedef struct JSDOMCallbacks DOMCallbacks;
michael@0 929
michael@0 930 extern JS_FRIEND_API(void)
michael@0 931 SetDOMCallbacks(JSRuntime *rt, const DOMCallbacks *callbacks);
michael@0 932
michael@0 933 extern JS_FRIEND_API(const DOMCallbacks *)
michael@0 934 GetDOMCallbacks(JSRuntime *rt);
michael@0 935
michael@0 936 extern JS_FRIEND_API(JSObject *)
michael@0 937 GetTestingFunctions(JSContext *cx);
michael@0 938
michael@0 939 /*
michael@0 940 * Helper to convert FreeOp to JSFreeOp when the definition of FreeOp is not
michael@0 941 * available and the compiler does not know that FreeOp inherits from
michael@0 942 * JSFreeOp.
michael@0 943 */
michael@0 944 inline JSFreeOp *
michael@0 945 CastToJSFreeOp(FreeOp *fop)
michael@0 946 {
michael@0 947 return reinterpret_cast<JSFreeOp *>(fop);
michael@0 948 }
michael@0 949
michael@0 950 /* Implemented in jsexn.cpp. */
michael@0 951
michael@0 952 /*
michael@0 953 * Get an error type name from a JSExnType constant.
michael@0 954 * Returns nullptr for invalid arguments and JSEXN_INTERNALERR
michael@0 955 */
michael@0 956 extern JS_FRIEND_API(const jschar*)
michael@0 957 GetErrorTypeName(JSRuntime* rt, int16_t exnType);
michael@0 958
michael@0 959 #ifdef JS_DEBUG
michael@0 960 extern JS_FRIEND_API(unsigned)
michael@0 961 GetEnterCompartmentDepth(JSContext* cx);
michael@0 962 #endif
michael@0 963
michael@0 964 /* Implemented in jswrapper.cpp. */
michael@0 965 typedef enum NukeReferencesToWindow {
michael@0 966 NukeWindowReferences,
michael@0 967 DontNukeWindowReferences
michael@0 968 } NukeReferencesToWindow;
michael@0 969
michael@0 970 /*
michael@0 971 * These filters are designed to be ephemeral stack classes, and thus don't
michael@0 972 * do any rooting or holding of their members.
michael@0 973 */
michael@0 974 struct CompartmentFilter {
michael@0 975 virtual bool match(JSCompartment *c) const = 0;
michael@0 976 };
michael@0 977
michael@0 978 struct AllCompartments : public CompartmentFilter {
michael@0 979 virtual bool match(JSCompartment *c) const { return true; }
michael@0 980 };
michael@0 981
michael@0 982 struct ContentCompartmentsOnly : public CompartmentFilter {
michael@0 983 virtual bool match(JSCompartment *c) const {
michael@0 984 return !IsSystemCompartment(c);
michael@0 985 }
michael@0 986 };
michael@0 987
michael@0 988 struct ChromeCompartmentsOnly : public CompartmentFilter {
michael@0 989 virtual bool match(JSCompartment *c) const {
michael@0 990 return IsSystemCompartment(c);
michael@0 991 }
michael@0 992 };
michael@0 993
michael@0 994 struct SingleCompartment : public CompartmentFilter {
michael@0 995 JSCompartment *ours;
michael@0 996 SingleCompartment(JSCompartment *c) : ours(c) {}
michael@0 997 virtual bool match(JSCompartment *c) const { return c == ours; }
michael@0 998 };
michael@0 999
michael@0 1000 struct CompartmentsWithPrincipals : public CompartmentFilter {
michael@0 1001 JSPrincipals *principals;
michael@0 1002 CompartmentsWithPrincipals(JSPrincipals *p) : principals(p) {}
michael@0 1003 virtual bool match(JSCompartment *c) const {
michael@0 1004 return JS_GetCompartmentPrincipals(c) == principals;
michael@0 1005 }
michael@0 1006 };
michael@0 1007
michael@0 1008 extern JS_FRIEND_API(bool)
michael@0 1009 NukeCrossCompartmentWrappers(JSContext* cx,
michael@0 1010 const CompartmentFilter& sourceFilter,
michael@0 1011 const CompartmentFilter& targetFilter,
michael@0 1012 NukeReferencesToWindow nukeReferencesToWindow);
michael@0 1013
michael@0 1014 /* Specify information about DOMProxy proxies in the DOM, for use by ICs. */
michael@0 1015
michael@0 1016 /*
michael@0 1017 * The DOMProxyShadowsCheck function will be called to check if the property for
michael@0 1018 * id should be gotten from the prototype, or if there is an own property that
michael@0 1019 * shadows it.
michael@0 1020 * If DoesntShadow is returned then the slot at listBaseExpandoSlot should
michael@0 1021 * either be undefined or point to an expando object that would contain the own
michael@0 1022 * property.
michael@0 1023 * If DoesntShadowUnique is returned then the slot at listBaseExpandoSlot should
michael@0 1024 * contain a private pointer to a ExpandoAndGeneration, which contains a
michael@0 1025 * JS::Value that should either be undefined or point to an expando object, and
michael@0 1026 * a uint32 value. If that value changes then the IC for getting a property will
michael@0 1027 * be invalidated.
michael@0 1028 */
michael@0 1029
michael@0 1030 struct ExpandoAndGeneration {
michael@0 1031 ExpandoAndGeneration()
michael@0 1032 : expando(JS::UndefinedValue()),
michael@0 1033 generation(0)
michael@0 1034 {}
michael@0 1035
michael@0 1036 void Unlink()
michael@0 1037 {
michael@0 1038 ++generation;
michael@0 1039 expando.setUndefined();
michael@0 1040 }
michael@0 1041
michael@0 1042 static size_t offsetOfExpando()
michael@0 1043 {
michael@0 1044 return offsetof(ExpandoAndGeneration, expando);
michael@0 1045 }
michael@0 1046
michael@0 1047 static size_t offsetOfGeneration()
michael@0 1048 {
michael@0 1049 return offsetof(ExpandoAndGeneration, generation);
michael@0 1050 }
michael@0 1051
michael@0 1052 JS::Heap<JS::Value> expando;
michael@0 1053 uint32_t generation;
michael@0 1054 };
michael@0 1055
michael@0 1056 typedef enum DOMProxyShadowsResult {
michael@0 1057 ShadowCheckFailed,
michael@0 1058 Shadows,
michael@0 1059 DoesntShadow,
michael@0 1060 DoesntShadowUnique
michael@0 1061 } DOMProxyShadowsResult;
michael@0 1062 typedef DOMProxyShadowsResult
michael@0 1063 (* DOMProxyShadowsCheck)(JSContext* cx, JS::HandleObject object, JS::HandleId id);
michael@0 1064 JS_FRIEND_API(void)
michael@0 1065 SetDOMProxyInformation(const void *domProxyHandlerFamily, uint32_t domProxyExpandoSlot,
michael@0 1066 DOMProxyShadowsCheck domProxyShadowsCheck);
michael@0 1067
michael@0 1068 const void *GetDOMProxyHandlerFamily();
michael@0 1069 uint32_t GetDOMProxyExpandoSlot();
michael@0 1070 DOMProxyShadowsCheck GetDOMProxyShadowsCheck();
michael@0 1071
michael@0 1072 } /* namespace js */
michael@0 1073
michael@0 1074 /* Implemented in jsdate.cpp. */
michael@0 1075
michael@0 1076 /*
michael@0 1077 * Detect whether the internal date value is NaN. (Because failure is
michael@0 1078 * out-of-band for js_DateGet*)
michael@0 1079 */
michael@0 1080 extern JS_FRIEND_API(bool)
michael@0 1081 js_DateIsValid(JSObject* obj);
michael@0 1082
michael@0 1083 extern JS_FRIEND_API(double)
michael@0 1084 js_DateGetMsecSinceEpoch(JSObject *obj);
michael@0 1085
michael@0 1086 /* Implemented in jscntxt.cpp. */
michael@0 1087
michael@0 1088 /*
michael@0 1089 * Report an exception, which is currently realized as a printf-style format
michael@0 1090 * string and its arguments.
michael@0 1091 */
michael@0 1092 typedef enum JSErrNum {
michael@0 1093 #define MSG_DEF(name, number, count, exception, format) \
michael@0 1094 name = number,
michael@0 1095 #include "js.msg"
michael@0 1096 #undef MSG_DEF
michael@0 1097 JSErr_Limit
michael@0 1098 } JSErrNum;
michael@0 1099
michael@0 1100 extern JS_FRIEND_API(const JSErrorFormatString *)
michael@0 1101 js_GetErrorMessage(void *userRef, const char *locale, const unsigned errorNumber);
michael@0 1102
michael@0 1103 namespace js {
michael@0 1104
michael@0 1105 // Creates a string of the form |ErrorType: ErrorMessage| for a JSErrorReport,
michael@0 1106 // which generally matches the toString() behavior of an ErrorObject.
michael@0 1107 extern JS_FRIEND_API(JSString *)
michael@0 1108 ErrorReportToString(JSContext *cx, JSErrorReport *reportp);
michael@0 1109
michael@0 1110 } /* namespace js */
michael@0 1111
michael@0 1112
michael@0 1113 /* Implemented in jsclone.cpp. */
michael@0 1114
michael@0 1115 extern JS_FRIEND_API(uint64_t)
michael@0 1116 js_GetSCOffset(JSStructuredCloneWriter* writer);
michael@0 1117
michael@0 1118 /* Typed Array functions, implemented in jstypedarray.cpp */
michael@0 1119
michael@0 1120 namespace js {
michael@0 1121 namespace ArrayBufferView {
michael@0 1122
michael@0 1123 enum ViewType {
michael@0 1124 TYPE_INT8 = 0,
michael@0 1125 TYPE_UINT8,
michael@0 1126 TYPE_INT16,
michael@0 1127 TYPE_UINT16,
michael@0 1128 TYPE_INT32,
michael@0 1129 TYPE_UINT32,
michael@0 1130 TYPE_FLOAT32,
michael@0 1131 TYPE_FLOAT64,
michael@0 1132
michael@0 1133 /*
michael@0 1134 * Special type that is a uint8_t, but assignments are clamped to [0, 256).
michael@0 1135 * Treat the raw data type as a uint8_t.
michael@0 1136 */
michael@0 1137 TYPE_UINT8_CLAMPED,
michael@0 1138
michael@0 1139 /*
michael@0 1140 * Type returned for a DataView. Note that there is no single element type
michael@0 1141 * in this case.
michael@0 1142 */
michael@0 1143 TYPE_DATAVIEW,
michael@0 1144
michael@0 1145 TYPE_MAX
michael@0 1146 };
michael@0 1147
michael@0 1148 } /* namespace ArrayBufferView */
michael@0 1149
michael@0 1150 } /* namespace js */
michael@0 1151
michael@0 1152 typedef js::ArrayBufferView::ViewType JSArrayBufferViewType;
michael@0 1153
michael@0 1154 /*
michael@0 1155 * Create a new typed array with nelements elements.
michael@0 1156 *
michael@0 1157 * These functions (except the WithBuffer variants) fill in the array with zeros.
michael@0 1158 */
michael@0 1159
michael@0 1160 extern JS_FRIEND_API(JSObject *)
michael@0 1161 JS_NewInt8Array(JSContext *cx, uint32_t nelements);
michael@0 1162 extern JS_FRIEND_API(JSObject *)
michael@0 1163 JS_NewUint8Array(JSContext *cx, uint32_t nelements);
michael@0 1164 extern JS_FRIEND_API(JSObject *)
michael@0 1165 JS_NewUint8ClampedArray(JSContext *cx, uint32_t nelements);
michael@0 1166
michael@0 1167 extern JS_FRIEND_API(JSObject *)
michael@0 1168 JS_NewInt16Array(JSContext *cx, uint32_t nelements);
michael@0 1169 extern JS_FRIEND_API(JSObject *)
michael@0 1170 JS_NewUint16Array(JSContext *cx, uint32_t nelements);
michael@0 1171 extern JS_FRIEND_API(JSObject *)
michael@0 1172 JS_NewInt32Array(JSContext *cx, uint32_t nelements);
michael@0 1173 extern JS_FRIEND_API(JSObject *)
michael@0 1174 JS_NewUint32Array(JSContext *cx, uint32_t nelements);
michael@0 1175 extern JS_FRIEND_API(JSObject *)
michael@0 1176 JS_NewFloat32Array(JSContext *cx, uint32_t nelements);
michael@0 1177 extern JS_FRIEND_API(JSObject *)
michael@0 1178 JS_NewFloat64Array(JSContext *cx, uint32_t nelements);
michael@0 1179
michael@0 1180 /*
michael@0 1181 * Create a new typed array and copy in values from the given object. The
michael@0 1182 * object is used as if it were an array; that is, the new array (if
michael@0 1183 * successfully created) will have length given by array.length, and its
michael@0 1184 * elements will be those specified by array[0], array[1], and so on, after
michael@0 1185 * conversion to the typed array element type.
michael@0 1186 */
michael@0 1187
michael@0 1188 extern JS_FRIEND_API(JSObject *)
michael@0 1189 JS_NewInt8ArrayFromArray(JSContext *cx, JS::HandleObject array);
michael@0 1190 extern JS_FRIEND_API(JSObject *)
michael@0 1191 JS_NewUint8ArrayFromArray(JSContext *cx, JS::HandleObject array);
michael@0 1192 extern JS_FRIEND_API(JSObject *)
michael@0 1193 JS_NewUint8ClampedArrayFromArray(JSContext *cx, JS::HandleObject array);
michael@0 1194 extern JS_FRIEND_API(JSObject *)
michael@0 1195 JS_NewInt16ArrayFromArray(JSContext *cx, JS::HandleObject array);
michael@0 1196 extern JS_FRIEND_API(JSObject *)
michael@0 1197 JS_NewUint16ArrayFromArray(JSContext *cx, JS::HandleObject array);
michael@0 1198 extern JS_FRIEND_API(JSObject *)
michael@0 1199 JS_NewInt32ArrayFromArray(JSContext *cx, JS::HandleObject array);
michael@0 1200 extern JS_FRIEND_API(JSObject *)
michael@0 1201 JS_NewUint32ArrayFromArray(JSContext *cx, JS::HandleObject array);
michael@0 1202 extern JS_FRIEND_API(JSObject *)
michael@0 1203 JS_NewFloat32ArrayFromArray(JSContext *cx, JS::HandleObject array);
michael@0 1204 extern JS_FRIEND_API(JSObject *)
michael@0 1205 JS_NewFloat64ArrayFromArray(JSContext *cx, JS::HandleObject array);
michael@0 1206
michael@0 1207 /*
michael@0 1208 * Create a new typed array using the given ArrayBuffer for storage. The
michael@0 1209 * length value is optional; if -1 is passed, enough elements to use up the
michael@0 1210 * remainder of the byte array is used as the default value.
michael@0 1211 */
michael@0 1212
michael@0 1213 extern JS_FRIEND_API(JSObject *)
michael@0 1214 JS_NewInt8ArrayWithBuffer(JSContext *cx, JS::HandleObject arrayBuffer,
michael@0 1215 uint32_t byteOffset, int32_t length);
michael@0 1216 extern JS_FRIEND_API(JSObject *)
michael@0 1217 JS_NewUint8ArrayWithBuffer(JSContext *cx, JS::HandleObject arrayBuffer,
michael@0 1218 uint32_t byteOffset, int32_t length);
michael@0 1219 extern JS_FRIEND_API(JSObject *)
michael@0 1220 JS_NewUint8ClampedArrayWithBuffer(JSContext *cx, JS::HandleObject arrayBuffer,
michael@0 1221 uint32_t byteOffset, int32_t length);
michael@0 1222 extern JS_FRIEND_API(JSObject *)
michael@0 1223 JS_NewInt16ArrayWithBuffer(JSContext *cx, JS::HandleObject arrayBuffer,
michael@0 1224 uint32_t byteOffset, int32_t length);
michael@0 1225 extern JS_FRIEND_API(JSObject *)
michael@0 1226 JS_NewUint16ArrayWithBuffer(JSContext *cx, JS::HandleObject arrayBuffer,
michael@0 1227 uint32_t byteOffset, int32_t length);
michael@0 1228 extern JS_FRIEND_API(JSObject *)
michael@0 1229 JS_NewInt32ArrayWithBuffer(JSContext *cx, JS::HandleObject arrayBuffer,
michael@0 1230 uint32_t byteOffset, int32_t length);
michael@0 1231 extern JS_FRIEND_API(JSObject *)
michael@0 1232 JS_NewUint32ArrayWithBuffer(JSContext *cx, JS::HandleObject arrayBuffer,
michael@0 1233 uint32_t byteOffset, int32_t length);
michael@0 1234 extern JS_FRIEND_API(JSObject *)
michael@0 1235 JS_NewFloat32ArrayWithBuffer(JSContext *cx, JS::HandleObject arrayBuffer,
michael@0 1236 uint32_t byteOffset, int32_t length);
michael@0 1237 extern JS_FRIEND_API(JSObject *)
michael@0 1238 JS_NewFloat64ArrayWithBuffer(JSContext *cx, JS::HandleObject arrayBuffer,
michael@0 1239 uint32_t byteOffset, int32_t length);
michael@0 1240
michael@0 1241 /*
michael@0 1242 * Create a new ArrayBuffer with the given byte length.
michael@0 1243 */
michael@0 1244 extern JS_FRIEND_API(JSObject *)
michael@0 1245 JS_NewArrayBuffer(JSContext *cx, uint32_t nbytes);
michael@0 1246
michael@0 1247 /*
michael@0 1248 * Check whether obj supports JS_GetTypedArray* APIs. Note that this may return
michael@0 1249 * false if a security wrapper is encountered that denies the unwrapping. If
michael@0 1250 * this test or one of the JS_Is*Array tests succeeds, then it is safe to call
michael@0 1251 * the various accessor JSAPI calls defined below.
michael@0 1252 */
michael@0 1253 extern JS_FRIEND_API(bool)
michael@0 1254 JS_IsTypedArrayObject(JSObject *obj);
michael@0 1255
michael@0 1256 /*
michael@0 1257 * Check whether obj supports JS_GetArrayBufferView* APIs. Note that this may
michael@0 1258 * return false if a security wrapper is encountered that denies the
michael@0 1259 * unwrapping. If this test or one of the more specific tests succeeds, then it
michael@0 1260 * is safe to call the various ArrayBufferView accessor JSAPI calls defined
michael@0 1261 * below.
michael@0 1262 */
michael@0 1263 extern JS_FRIEND_API(bool)
michael@0 1264 JS_IsArrayBufferViewObject(JSObject *obj);
michael@0 1265
michael@0 1266 /*
michael@0 1267 * Test for specific typed array types (ArrayBufferView subtypes)
michael@0 1268 */
michael@0 1269
michael@0 1270 extern JS_FRIEND_API(bool)
michael@0 1271 JS_IsInt8Array(JSObject *obj);
michael@0 1272 extern JS_FRIEND_API(bool)
michael@0 1273 JS_IsUint8Array(JSObject *obj);
michael@0 1274 extern JS_FRIEND_API(bool)
michael@0 1275 JS_IsUint8ClampedArray(JSObject *obj);
michael@0 1276 extern JS_FRIEND_API(bool)
michael@0 1277 JS_IsInt16Array(JSObject *obj);
michael@0 1278 extern JS_FRIEND_API(bool)
michael@0 1279 JS_IsUint16Array(JSObject *obj);
michael@0 1280 extern JS_FRIEND_API(bool)
michael@0 1281 JS_IsInt32Array(JSObject *obj);
michael@0 1282 extern JS_FRIEND_API(bool)
michael@0 1283 JS_IsUint32Array(JSObject *obj);
michael@0 1284 extern JS_FRIEND_API(bool)
michael@0 1285 JS_IsFloat32Array(JSObject *obj);
michael@0 1286 extern JS_FRIEND_API(bool)
michael@0 1287 JS_IsFloat64Array(JSObject *obj);
michael@0 1288
michael@0 1289 /*
michael@0 1290 * Test for specific typed array types (ArrayBufferView subtypes) and return
michael@0 1291 * the unwrapped object if so, else nullptr. Never throws.
michael@0 1292 */
michael@0 1293
michael@0 1294 namespace js {
michael@0 1295
michael@0 1296 extern JS_FRIEND_API(JSObject *)
michael@0 1297 UnwrapInt8Array(JSObject *obj);
michael@0 1298 extern JS_FRIEND_API(JSObject *)
michael@0 1299 UnwrapUint8Array(JSObject *obj);
michael@0 1300 extern JS_FRIEND_API(JSObject *)
michael@0 1301 UnwrapUint8ClampedArray(JSObject *obj);
michael@0 1302 extern JS_FRIEND_API(JSObject *)
michael@0 1303 UnwrapInt16Array(JSObject *obj);
michael@0 1304 extern JS_FRIEND_API(JSObject *)
michael@0 1305 UnwrapUint16Array(JSObject *obj);
michael@0 1306 extern JS_FRIEND_API(JSObject *)
michael@0 1307 UnwrapInt32Array(JSObject *obj);
michael@0 1308 extern JS_FRIEND_API(JSObject *)
michael@0 1309 UnwrapUint32Array(JSObject *obj);
michael@0 1310 extern JS_FRIEND_API(JSObject *)
michael@0 1311 UnwrapFloat32Array(JSObject *obj);
michael@0 1312 extern JS_FRIEND_API(JSObject *)
michael@0 1313 UnwrapFloat64Array(JSObject *obj);
michael@0 1314
michael@0 1315 extern JS_FRIEND_API(JSObject *)
michael@0 1316 UnwrapArrayBuffer(JSObject *obj);
michael@0 1317
michael@0 1318 extern JS_FRIEND_API(JSObject *)
michael@0 1319 UnwrapArrayBufferView(JSObject *obj);
michael@0 1320
michael@0 1321 namespace detail {
michael@0 1322
michael@0 1323 extern JS_FRIEND_DATA(const Class* const) Int8ArrayClassPtr;
michael@0 1324 extern JS_FRIEND_DATA(const Class* const) Uint8ArrayClassPtr;
michael@0 1325 extern JS_FRIEND_DATA(const Class* const) Uint8ClampedArrayClassPtr;
michael@0 1326 extern JS_FRIEND_DATA(const Class* const) Int16ArrayClassPtr;
michael@0 1327 extern JS_FRIEND_DATA(const Class* const) Uint16ArrayClassPtr;
michael@0 1328 extern JS_FRIEND_DATA(const Class* const) Int32ArrayClassPtr;
michael@0 1329 extern JS_FRIEND_DATA(const Class* const) Uint32ArrayClassPtr;
michael@0 1330 extern JS_FRIEND_DATA(const Class* const) Float32ArrayClassPtr;
michael@0 1331 extern JS_FRIEND_DATA(const Class* const) Float64ArrayClassPtr;
michael@0 1332
michael@0 1333 const size_t TypedArrayLengthSlot = 4;
michael@0 1334
michael@0 1335 } // namespace detail
michael@0 1336
michael@0 1337 /*
michael@0 1338 * Test for specific typed array types (ArrayBufferView subtypes) and return
michael@0 1339 * the unwrapped object if so, else nullptr. Never throws.
michael@0 1340 */
michael@0 1341
michael@0 1342 #define JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Type, type) \
michael@0 1343 inline void \
michael@0 1344 Get ## Type ## ArrayLengthAndData(JSObject *obj, uint32_t *length, type **data) \
michael@0 1345 { \
michael@0 1346 JS_ASSERT(GetObjectClass(obj) == detail::Type ## ArrayClassPtr); \
michael@0 1347 const JS::Value &slot = GetReservedSlot(obj, detail::TypedArrayLengthSlot); \
michael@0 1348 *length = mozilla::SafeCast<uint32_t>(slot.toInt32()); \
michael@0 1349 *data = static_cast<type*>(GetObjectPrivate(obj)); \
michael@0 1350 }
michael@0 1351
michael@0 1352 JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Int8, int8_t)
michael@0 1353 JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Uint8, uint8_t)
michael@0 1354 JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Uint8Clamped, uint8_t)
michael@0 1355 JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Int16, int16_t)
michael@0 1356 JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Uint16, uint16_t)
michael@0 1357 JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Int32, int32_t)
michael@0 1358 JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Uint32, uint32_t)
michael@0 1359 JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Float32, float)
michael@0 1360 JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Float64, double)
michael@0 1361
michael@0 1362 #undef JS_DEFINE_DATA_AND_LENGTH_ACCESSOR
michael@0 1363
michael@0 1364 // This one isn't inlined because it's rather tricky (by dint of having to deal
michael@0 1365 // with a dozen-plus classes and varying slot layouts.
michael@0 1366 extern JS_FRIEND_API(void)
michael@0 1367 GetArrayBufferViewLengthAndData(JSObject *obj, uint32_t *length, uint8_t **data);
michael@0 1368
michael@0 1369 // This one isn't inlined because there are a bunch of different ArrayBuffer
michael@0 1370 // classes that would have to be individually handled here.
michael@0 1371 extern JS_FRIEND_API(void)
michael@0 1372 GetArrayBufferLengthAndData(JSObject *obj, uint32_t *length, uint8_t **data);
michael@0 1373
michael@0 1374 } // namespace js
michael@0 1375
michael@0 1376 /*
michael@0 1377 * Unwrap Typed arrays all at once. Return nullptr without throwing if the
michael@0 1378 * object cannot be viewed as the correct typed array, or the typed array
michael@0 1379 * object on success, filling both outparameters.
michael@0 1380 */
michael@0 1381 extern JS_FRIEND_API(JSObject *)
michael@0 1382 JS_GetObjectAsInt8Array(JSObject *obj, uint32_t *length, int8_t **data);
michael@0 1383 extern JS_FRIEND_API(JSObject *)
michael@0 1384 JS_GetObjectAsUint8Array(JSObject *obj, uint32_t *length, uint8_t **data);
michael@0 1385 extern JS_FRIEND_API(JSObject *)
michael@0 1386 JS_GetObjectAsUint8ClampedArray(JSObject *obj, uint32_t *length, uint8_t **data);
michael@0 1387 extern JS_FRIEND_API(JSObject *)
michael@0 1388 JS_GetObjectAsInt16Array(JSObject *obj, uint32_t *length, int16_t **data);
michael@0 1389 extern JS_FRIEND_API(JSObject *)
michael@0 1390 JS_GetObjectAsUint16Array(JSObject *obj, uint32_t *length, uint16_t **data);
michael@0 1391 extern JS_FRIEND_API(JSObject *)
michael@0 1392 JS_GetObjectAsInt32Array(JSObject *obj, uint32_t *length, int32_t **data);
michael@0 1393 extern JS_FRIEND_API(JSObject *)
michael@0 1394 JS_GetObjectAsUint32Array(JSObject *obj, uint32_t *length, uint32_t **data);
michael@0 1395 extern JS_FRIEND_API(JSObject *)
michael@0 1396 JS_GetObjectAsFloat32Array(JSObject *obj, uint32_t *length, float **data);
michael@0 1397 extern JS_FRIEND_API(JSObject *)
michael@0 1398 JS_GetObjectAsFloat64Array(JSObject *obj, uint32_t *length, double **data);
michael@0 1399 extern JS_FRIEND_API(JSObject *)
michael@0 1400 JS_GetObjectAsArrayBufferView(JSObject *obj, uint32_t *length, uint8_t **data);
michael@0 1401 extern JS_FRIEND_API(JSObject *)
michael@0 1402 JS_GetObjectAsArrayBuffer(JSObject *obj, uint32_t *length, uint8_t **data);
michael@0 1403
michael@0 1404 /*
michael@0 1405 * Get the type of elements in a typed array, or TYPE_DATAVIEW if a DataView.
michael@0 1406 *
michael@0 1407 * |obj| must have passed a JS_IsArrayBufferView/JS_Is*Array test, or somehow
michael@0 1408 * be known that it would pass such a test: it is an ArrayBufferView or a
michael@0 1409 * wrapper of an ArrayBufferView, and the unwrapping will succeed.
michael@0 1410 */
michael@0 1411 extern JS_FRIEND_API(JSArrayBufferViewType)
michael@0 1412 JS_GetArrayBufferViewType(JSObject *obj);
michael@0 1413
michael@0 1414 /*
michael@0 1415 * Check whether obj supports the JS_GetArrayBuffer* APIs. Note that this may
michael@0 1416 * return false if a security wrapper is encountered that denies the
michael@0 1417 * unwrapping. If this test succeeds, then it is safe to call the various
michael@0 1418 * accessor JSAPI calls defined below.
michael@0 1419 */
michael@0 1420 extern JS_FRIEND_API(bool)
michael@0 1421 JS_IsArrayBufferObject(JSObject *obj);
michael@0 1422
michael@0 1423 /*
michael@0 1424 * Return the available byte length of an array buffer.
michael@0 1425 *
michael@0 1426 * |obj| must have passed a JS_IsArrayBufferObject test, or somehow be known
michael@0 1427 * that it would pass such a test: it is an ArrayBuffer or a wrapper of an
michael@0 1428 * ArrayBuffer, and the unwrapping will succeed.
michael@0 1429 */
michael@0 1430 extern JS_FRIEND_API(uint32_t)
michael@0 1431 JS_GetArrayBufferByteLength(JSObject *obj);
michael@0 1432
michael@0 1433 /*
michael@0 1434 * Check whether the obj is ArrayBufferObject and memory mapped. Note that this
michael@0 1435 * may return false if a security wrapper is encountered that denies the
michael@0 1436 * unwrapping.
michael@0 1437 */
michael@0 1438 extern JS_FRIEND_API(bool)
michael@0 1439 JS_IsMappedArrayBufferObject(JSObject *obj);
michael@0 1440
michael@0 1441 /*
michael@0 1442 * Return the number of elements in a typed array.
michael@0 1443 *
michael@0 1444 * |obj| must have passed a JS_IsTypedArrayObject/JS_Is*Array test, or somehow
michael@0 1445 * be known that it would pass such a test: it is a typed array or a wrapper of
michael@0 1446 * a typed array, and the unwrapping will succeed.
michael@0 1447 */
michael@0 1448 extern JS_FRIEND_API(uint32_t)
michael@0 1449 JS_GetTypedArrayLength(JSObject *obj);
michael@0 1450
michael@0 1451 /*
michael@0 1452 * Return the byte offset from the start of an array buffer to the start of a
michael@0 1453 * typed array view.
michael@0 1454 *
michael@0 1455 * |obj| must have passed a JS_IsTypedArrayObject/JS_Is*Array test, or somehow
michael@0 1456 * be known that it would pass such a test: it is a typed array or a wrapper of
michael@0 1457 * a typed array, and the unwrapping will succeed.
michael@0 1458 */
michael@0 1459 extern JS_FRIEND_API(uint32_t)
michael@0 1460 JS_GetTypedArrayByteOffset(JSObject *obj);
michael@0 1461
michael@0 1462 /*
michael@0 1463 * Return the byte length of a typed array.
michael@0 1464 *
michael@0 1465 * |obj| must have passed a JS_IsTypedArrayObject/JS_Is*Array test, or somehow
michael@0 1466 * be known that it would pass such a test: it is a typed array or a wrapper of
michael@0 1467 * a typed array, and the unwrapping will succeed.
michael@0 1468 */
michael@0 1469 extern JS_FRIEND_API(uint32_t)
michael@0 1470 JS_GetTypedArrayByteLength(JSObject *obj);
michael@0 1471
michael@0 1472 /*
michael@0 1473 * Check whether obj supports JS_ArrayBufferView* APIs. Note that this may
michael@0 1474 * return false if a security wrapper is encountered that denies the
michael@0 1475 * unwrapping.
michael@0 1476 */
michael@0 1477 extern JS_FRIEND_API(bool)
michael@0 1478 JS_IsArrayBufferViewObject(JSObject *obj);
michael@0 1479
michael@0 1480 /*
michael@0 1481 * More generic name for JS_GetTypedArrayByteLength to cover DataViews as well
michael@0 1482 */
michael@0 1483 extern JS_FRIEND_API(uint32_t)
michael@0 1484 JS_GetArrayBufferViewByteLength(JSObject *obj);
michael@0 1485
michael@0 1486 /*
michael@0 1487 * Return a pointer to the start of the data referenced by a typed array. The
michael@0 1488 * data is still owned by the typed array, and should not be modified on
michael@0 1489 * another thread. Furthermore, the pointer can become invalid on GC (if the
michael@0 1490 * data is small and fits inside the array's GC header), so callers must take
michael@0 1491 * care not to hold on across anything that could GC.
michael@0 1492 *
michael@0 1493 * |obj| must have passed a JS_Is*Array test, or somehow be known that it would
michael@0 1494 * pass such a test: it is a typed array or a wrapper of a typed array, and the
michael@0 1495 * unwrapping will succeed.
michael@0 1496 */
michael@0 1497
michael@0 1498 extern JS_FRIEND_API(uint8_t *)
michael@0 1499 JS_GetArrayBufferData(JSObject *obj);
michael@0 1500 extern JS_FRIEND_API(int8_t *)
michael@0 1501 JS_GetInt8ArrayData(JSObject *obj);
michael@0 1502 extern JS_FRIEND_API(uint8_t *)
michael@0 1503 JS_GetUint8ArrayData(JSObject *obj);
michael@0 1504 extern JS_FRIEND_API(uint8_t *)
michael@0 1505 JS_GetUint8ClampedArrayData(JSObject *obj);
michael@0 1506 extern JS_FRIEND_API(int16_t *)
michael@0 1507 JS_GetInt16ArrayData(JSObject *obj);
michael@0 1508 extern JS_FRIEND_API(uint16_t *)
michael@0 1509 JS_GetUint16ArrayData(JSObject *obj);
michael@0 1510 extern JS_FRIEND_API(int32_t *)
michael@0 1511 JS_GetInt32ArrayData(JSObject *obj);
michael@0 1512 extern JS_FRIEND_API(uint32_t *)
michael@0 1513 JS_GetUint32ArrayData(JSObject *obj);
michael@0 1514 extern JS_FRIEND_API(float *)
michael@0 1515 JS_GetFloat32ArrayData(JSObject *obj);
michael@0 1516 extern JS_FRIEND_API(double *)
michael@0 1517 JS_GetFloat64ArrayData(JSObject *obj);
michael@0 1518
michael@0 1519 /*
michael@0 1520 * Stable versions of the above functions where the buffer remains valid as long
michael@0 1521 * as the object is live.
michael@0 1522 */
michael@0 1523 extern JS_FRIEND_API(uint8_t *)
michael@0 1524 JS_GetStableArrayBufferData(JSContext *cx, JS::HandleObject obj);
michael@0 1525
michael@0 1526 /*
michael@0 1527 * Same as above, but for any kind of ArrayBufferView. Prefer the type-specific
michael@0 1528 * versions when possible.
michael@0 1529 */
michael@0 1530 extern JS_FRIEND_API(void *)
michael@0 1531 JS_GetArrayBufferViewData(JSObject *obj);
michael@0 1532
michael@0 1533 /*
michael@0 1534 * Return the ArrayBuffer underlying an ArrayBufferView. If the buffer has been
michael@0 1535 * neutered, this will still return the neutered buffer. |obj| must be an
michael@0 1536 * object that would return true for JS_IsArrayBufferViewObject().
michael@0 1537 */
michael@0 1538 extern JS_FRIEND_API(JSObject *)
michael@0 1539 JS_GetArrayBufferViewBuffer(JSContext *cx, JSObject *obj);
michael@0 1540
michael@0 1541 typedef enum {
michael@0 1542 ChangeData,
michael@0 1543 KeepData
michael@0 1544 } NeuterDataDisposition;
michael@0 1545
michael@0 1546 /*
michael@0 1547 * Set an ArrayBuffer's length to 0 and neuter all of its views.
michael@0 1548 *
michael@0 1549 * The |changeData| argument is a hint to inform internal behavior with respect
michael@0 1550 * to the internal pointer to the ArrayBuffer's data after being neutered.
michael@0 1551 * There is no guarantee it will be respected. But if it is respected, the
michael@0 1552 * ArrayBuffer's internal data pointer will, or will not, have changed
michael@0 1553 * accordingly.
michael@0 1554 */
michael@0 1555 extern JS_FRIEND_API(bool)
michael@0 1556 JS_NeuterArrayBuffer(JSContext *cx, JS::HandleObject obj,
michael@0 1557 NeuterDataDisposition changeData);
michael@0 1558
michael@0 1559 /*
michael@0 1560 * Check whether obj supports JS_GetDataView* APIs.
michael@0 1561 */
michael@0 1562 JS_FRIEND_API(bool)
michael@0 1563 JS_IsDataViewObject(JSObject *obj);
michael@0 1564
michael@0 1565 /*
michael@0 1566 * Return the byte offset of a data view into its array buffer. |obj| must be a
michael@0 1567 * DataView.
michael@0 1568 *
michael@0 1569 * |obj| must have passed a JS_IsDataViewObject test, or somehow be known that
michael@0 1570 * it would pass such a test: it is a data view or a wrapper of a data view,
michael@0 1571 * and the unwrapping will succeed.
michael@0 1572 */
michael@0 1573 JS_FRIEND_API(uint32_t)
michael@0 1574 JS_GetDataViewByteOffset(JSObject *obj);
michael@0 1575
michael@0 1576 /*
michael@0 1577 * Return the byte length of a data view.
michael@0 1578 *
michael@0 1579 * |obj| must have passed a JS_IsDataViewObject test, or somehow be known that
michael@0 1580 * it would pass such a test: it is a data view or a wrapper of a data view,
michael@0 1581 * and the unwrapping will succeed. If cx is nullptr, then DEBUG builds may be
michael@0 1582 * unable to assert when unwrapping should be disallowed.
michael@0 1583 */
michael@0 1584 JS_FRIEND_API(uint32_t)
michael@0 1585 JS_GetDataViewByteLength(JSObject *obj);
michael@0 1586
michael@0 1587 /*
michael@0 1588 * Return a pointer to the beginning of the data referenced by a DataView.
michael@0 1589 *
michael@0 1590 * |obj| must have passed a JS_IsDataViewObject test, or somehow be known that
michael@0 1591 * it would pass such a test: it is a data view or a wrapper of a data view,
michael@0 1592 * and the unwrapping will succeed. If cx is nullptr, then DEBUG builds may be
michael@0 1593 * unable to assert when unwrapping should be disallowed.
michael@0 1594 */
michael@0 1595 JS_FRIEND_API(void *)
michael@0 1596 JS_GetDataViewData(JSObject *obj);
michael@0 1597
michael@0 1598 namespace js {
michael@0 1599
michael@0 1600 /*
michael@0 1601 * Add a watchpoint -- in the Object.prototype.watch sense -- to |obj| for the
michael@0 1602 * property |id|, using the callable object |callable| as the function to be
michael@0 1603 * called for notifications.
michael@0 1604 *
michael@0 1605 * This is an internal function exposed -- temporarily -- only so that DOM
michael@0 1606 * proxies can be watchable. Don't use it! We'll soon kill off the
michael@0 1607 * Object.prototype.{,un}watch functions, at which point this will go too.
michael@0 1608 */
michael@0 1609 extern JS_FRIEND_API(bool)
michael@0 1610 WatchGuts(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::HandleObject callable);
michael@0 1611
michael@0 1612 /*
michael@0 1613 * Remove a watchpoint -- in the Object.prototype.watch sense -- from |obj| for
michael@0 1614 * the property |id|.
michael@0 1615 *
michael@0 1616 * This is an internal function exposed -- temporarily -- only so that DOM
michael@0 1617 * proxies can be watchable. Don't use it! We'll soon kill off the
michael@0 1618 * Object.prototype.{,un}watch functions, at which point this will go too.
michael@0 1619 */
michael@0 1620 extern JS_FRIEND_API(bool)
michael@0 1621 UnwatchGuts(JSContext *cx, JS::HandleObject obj, JS::HandleId id);
michael@0 1622
michael@0 1623 } // namespace js
michael@0 1624
michael@0 1625 /*
michael@0 1626 * A class, expected to be passed by value, which represents the CallArgs for a
michael@0 1627 * JSJitGetterOp.
michael@0 1628 */
michael@0 1629 class JSJitGetterCallArgs : protected JS::MutableHandleValue
michael@0 1630 {
michael@0 1631 public:
michael@0 1632 explicit JSJitGetterCallArgs(const JS::CallArgs& args)
michael@0 1633 : JS::MutableHandleValue(args.rval())
michael@0 1634 {}
michael@0 1635
michael@0 1636 explicit JSJitGetterCallArgs(JS::RootedValue* rooted)
michael@0 1637 : JS::MutableHandleValue(rooted)
michael@0 1638 {}
michael@0 1639
michael@0 1640 JS::MutableHandleValue rval() {
michael@0 1641 return *this;
michael@0 1642 }
michael@0 1643 };
michael@0 1644
michael@0 1645 /*
michael@0 1646 * A class, expected to be passed by value, which represents the CallArgs for a
michael@0 1647 * JSJitSetterOp.
michael@0 1648 */
michael@0 1649 class JSJitSetterCallArgs : protected JS::MutableHandleValue
michael@0 1650 {
michael@0 1651 public:
michael@0 1652 explicit JSJitSetterCallArgs(const JS::CallArgs& args)
michael@0 1653 : JS::MutableHandleValue(args[0])
michael@0 1654 {}
michael@0 1655
michael@0 1656 JS::MutableHandleValue operator[](unsigned i) {
michael@0 1657 MOZ_ASSERT(i == 0);
michael@0 1658 return *this;
michael@0 1659 }
michael@0 1660
michael@0 1661 unsigned length() const { return 1; }
michael@0 1662
michael@0 1663 // Add get() or maybe hasDefined() as needed
michael@0 1664 };
michael@0 1665
michael@0 1666 struct JSJitMethodCallArgsTraits;
michael@0 1667
michael@0 1668 /*
michael@0 1669 * A class, expected to be passed by reference, which represents the CallArgs
michael@0 1670 * for a JSJitMethodOp.
michael@0 1671 */
michael@0 1672 class JSJitMethodCallArgs : protected JS::detail::CallArgsBase<JS::detail::NoUsedRval>
michael@0 1673 {
michael@0 1674 private:
michael@0 1675 typedef JS::detail::CallArgsBase<JS::detail::NoUsedRval> Base;
michael@0 1676 friend struct JSJitMethodCallArgsTraits;
michael@0 1677
michael@0 1678 public:
michael@0 1679 explicit JSJitMethodCallArgs(const JS::CallArgs& args) {
michael@0 1680 argv_ = args.array();
michael@0 1681 argc_ = args.length();
michael@0 1682 }
michael@0 1683
michael@0 1684 JS::MutableHandleValue rval() const {
michael@0 1685 return Base::rval();
michael@0 1686 }
michael@0 1687
michael@0 1688 unsigned length() const { return Base::length(); }
michael@0 1689
michael@0 1690 JS::MutableHandleValue operator[](unsigned i) const {
michael@0 1691 return Base::operator[](i);
michael@0 1692 }
michael@0 1693
michael@0 1694 bool hasDefined(unsigned i) const {
michael@0 1695 return Base::hasDefined(i);
michael@0 1696 }
michael@0 1697
michael@0 1698 JSObject &callee() const {
michael@0 1699 // We can't use Base::callee() because that will try to poke at
michael@0 1700 // this->usedRval_, which we don't have.
michael@0 1701 return argv_[-2].toObject();
michael@0 1702 }
michael@0 1703
michael@0 1704 // Add get() as needed
michael@0 1705 };
michael@0 1706
michael@0 1707 struct JSJitMethodCallArgsTraits
michael@0 1708 {
michael@0 1709 static const size_t offsetOfArgv = offsetof(JSJitMethodCallArgs, argv_);
michael@0 1710 static const size_t offsetOfArgc = offsetof(JSJitMethodCallArgs, argc_);
michael@0 1711 };
michael@0 1712
michael@0 1713 /*
michael@0 1714 * This struct contains metadata passed from the DOM to the JS Engine for JIT
michael@0 1715 * optimizations on DOM property accessors. Eventually, this should be made
michael@0 1716 * available to general JSAPI users, but we are not currently ready to do so.
michael@0 1717 */
michael@0 1718 typedef bool
michael@0 1719 (* JSJitGetterOp)(JSContext *cx, JS::HandleObject thisObj,
michael@0 1720 void *specializedThis, JSJitGetterCallArgs args);
michael@0 1721 typedef bool
michael@0 1722 (* JSJitSetterOp)(JSContext *cx, JS::HandleObject thisObj,
michael@0 1723 void *specializedThis, JSJitSetterCallArgs args);
michael@0 1724 typedef bool
michael@0 1725 (* JSJitMethodOp)(JSContext *cx, JS::HandleObject thisObj,
michael@0 1726 void *specializedThis, const JSJitMethodCallArgs& args);
michael@0 1727
michael@0 1728 struct JSJitInfo {
michael@0 1729 enum OpType {
michael@0 1730 Getter,
michael@0 1731 Setter,
michael@0 1732 Method,
michael@0 1733 ParallelNative,
michael@0 1734 StaticMethod,
michael@0 1735 // Must be last
michael@0 1736 OpTypeCount
michael@0 1737 };
michael@0 1738
michael@0 1739 enum ArgType {
michael@0 1740 // Basic types
michael@0 1741 String = (1 << 0),
michael@0 1742 Integer = (1 << 1), // Only 32-bit or less
michael@0 1743 Double = (1 << 2), // Maybe we want to add Float sometime too
michael@0 1744 Boolean = (1 << 3),
michael@0 1745 Object = (1 << 4),
michael@0 1746 Null = (1 << 5),
michael@0 1747
michael@0 1748 // And derived types
michael@0 1749 Numeric = Integer | Double,
michael@0 1750 // Should "Primitive" use the WebIDL definition, which
michael@0 1751 // excludes string and null, or the typical JS one that includes them?
michael@0 1752 Primitive = Numeric | Boolean | Null | String,
michael@0 1753 ObjectOrNull = Object | Null,
michael@0 1754 Any = ObjectOrNull | Primitive,
michael@0 1755
michael@0 1756 // Our sentinel value.
michael@0 1757 ArgTypeListEnd = (1 << 31)
michael@0 1758 };
michael@0 1759
michael@0 1760 static_assert(Any & String, "Any must include String.");
michael@0 1761 static_assert(Any & Integer, "Any must include Integer.");
michael@0 1762 static_assert(Any & Double, "Any must include Double.");
michael@0 1763 static_assert(Any & Boolean, "Any must include Boolean.");
michael@0 1764 static_assert(Any & Object, "Any must include Object.");
michael@0 1765 static_assert(Any & Null, "Any must include Null.");
michael@0 1766
michael@0 1767 enum AliasSet {
michael@0 1768 // An enum that describes what this getter/setter/method aliases. This
michael@0 1769 // determines what things can be hoisted past this call, and if this
michael@0 1770 // call is movable what it can be hoisted past.
michael@0 1771
michael@0 1772 // Alias nothing: a constant value, getting it can't affect any other
michael@0 1773 // values, nothing can affect it.
michael@0 1774 AliasNone,
michael@0 1775
michael@0 1776 // Alias things that can modify the DOM but nothing else. Doing the
michael@0 1777 // call can't affect the behavior of any other function.
michael@0 1778 AliasDOMSets,
michael@0 1779
michael@0 1780 // Alias the world. Calling this can change arbitrary values anywhere
michael@0 1781 // in the system. Most things fall in this bucket.
michael@0 1782 AliasEverything,
michael@0 1783
michael@0 1784 // Must be last.
michael@0 1785 AliasSetCount
michael@0 1786 };
michael@0 1787
michael@0 1788 bool hasParallelNative() const
michael@0 1789 {
michael@0 1790 return type() == ParallelNative;
michael@0 1791 }
michael@0 1792
michael@0 1793 bool needsOuterizedThisObject() const
michael@0 1794 {
michael@0 1795 return type() != Getter && type() != Setter;
michael@0 1796 }
michael@0 1797
michael@0 1798 bool isTypedMethodJitInfo() const
michael@0 1799 {
michael@0 1800 return isTypedMethod;
michael@0 1801 }
michael@0 1802
michael@0 1803 OpType type() const
michael@0 1804 {
michael@0 1805 return OpType(type_);
michael@0 1806 }
michael@0 1807
michael@0 1808 AliasSet aliasSet() const
michael@0 1809 {
michael@0 1810 return AliasSet(aliasSet_);
michael@0 1811 }
michael@0 1812
michael@0 1813 JSValueType returnType() const
michael@0 1814 {
michael@0 1815 return JSValueType(returnType_);
michael@0 1816 }
michael@0 1817
michael@0 1818 union {
michael@0 1819 JSJitGetterOp getter;
michael@0 1820 JSJitSetterOp setter;
michael@0 1821 JSJitMethodOp method;
michael@0 1822 /* An alternative native that's safe to call in parallel mode. */
michael@0 1823 JSParallelNative parallelNative;
michael@0 1824 /* A DOM static method, used for Promise wrappers */
michael@0 1825 JSNative staticMethod;
michael@0 1826 };
michael@0 1827
michael@0 1828 uint16_t protoID;
michael@0 1829 uint16_t depth;
michael@0 1830
michael@0 1831 // These fields are carefully packed to take up 4 bytes. If you need more
michael@0 1832 // bits for whatever reason, please see if you can steal bits from existing
michael@0 1833 // fields before adding more members to this structure.
michael@0 1834
michael@0 1835 #define JITINFO_OP_TYPE_BITS 4
michael@0 1836 #define JITINFO_ALIAS_SET_BITS 4
michael@0 1837 #define JITINFO_RETURN_TYPE_BITS 8
michael@0 1838
michael@0 1839 // The OpType that says what sort of function we are.
michael@0 1840 uint32_t type_ : JITINFO_OP_TYPE_BITS;
michael@0 1841
michael@0 1842 // The alias set for this op. This is a _minimal_ alias set; in
michael@0 1843 // particular for a method it does not include whatever argument
michael@0 1844 // conversions might do. That's covered by argTypes and runtime
michael@0 1845 // analysis of the actual argument types being passed in.
michael@0 1846 uint32_t aliasSet_ : JITINFO_ALIAS_SET_BITS;
michael@0 1847
michael@0 1848 // The return type tag. Might be JSVAL_TYPE_UNKNOWN.
michael@0 1849 uint32_t returnType_ : JITINFO_RETURN_TYPE_BITS;
michael@0 1850
michael@0 1851 static_assert(OpTypeCount <= (1 << JITINFO_OP_TYPE_BITS),
michael@0 1852 "Not enough space for OpType");
michael@0 1853 static_assert(AliasSetCount <= (1 << JITINFO_ALIAS_SET_BITS),
michael@0 1854 "Not enough space for AliasSet");
michael@0 1855 static_assert((sizeof(JSValueType) * 8) <= JITINFO_RETURN_TYPE_BITS,
michael@0 1856 "Not enough space for JSValueType");
michael@0 1857
michael@0 1858 #undef JITINFO_RETURN_TYPE_BITS
michael@0 1859 #undef JITINFO_ALIAS_SET_BITS
michael@0 1860 #undef JITINFO_OP_TYPE_BITS
michael@0 1861
michael@0 1862 uint32_t isInfallible : 1; /* Is op fallible? False in setters. */
michael@0 1863 uint32_t isMovable : 1; /* Is op movable? To be movable the op must
michael@0 1864 not AliasEverything, but even that might
michael@0 1865 not be enough (e.g. in cases when it can
michael@0 1866 throw). */
michael@0 1867 // XXXbz should we have a JSValueType for the type of the member?
michael@0 1868 uint32_t isInSlot : 1; /* True if this is a getter that can get a member
michael@0 1869 from a slot of the "this" object directly. */
michael@0 1870 uint32_t isTypedMethod : 1; /* True if this is an instance of
michael@0 1871 JSTypedMethodJitInfo. */
michael@0 1872 uint32_t slotIndex : 12; /* If isInSlot is true, the index of the slot to
michael@0 1873 get the value from. Otherwise 0. */
michael@0 1874 };
michael@0 1875
michael@0 1876 static_assert(sizeof(JSJitInfo) == (sizeof(void*) + 2 * sizeof(uint32_t)),
michael@0 1877 "There are several thousand instances of JSJitInfo stored in "
michael@0 1878 "a binary. Please don't increase its space requirements without "
michael@0 1879 "verifying that there is no other way forward (better packing, "
michael@0 1880 "smaller datatypes for fields, subclassing, etc.).");
michael@0 1881
michael@0 1882 struct JSTypedMethodJitInfo
michael@0 1883 {
michael@0 1884 // We use C-style inheritance here, rather than C++ style inheritance
michael@0 1885 // because not all compilers support brace-initialization for non-aggregate
michael@0 1886 // classes. Using C++ style inheritance and constructors instead of
michael@0 1887 // brace-initialization would also force the creation of static
michael@0 1888 // constructors (on some compilers) when JSJitInfo and JSTypedMethodJitInfo
michael@0 1889 // structures are declared. Since there can be several thousand of these
michael@0 1890 // structures present and we want to have roughly equivalent performance
michael@0 1891 // across a range of compilers, we do things manually.
michael@0 1892 JSJitInfo base;
michael@0 1893
michael@0 1894 const JSJitInfo::ArgType* const argTypes; /* For a method, a list of sets of
michael@0 1895 types that the function
michael@0 1896 expects. This can be used,
michael@0 1897 for example, to figure out
michael@0 1898 when argument coercions can
michael@0 1899 have side-effects. */
michael@0 1900 };
michael@0 1901
michael@0 1902 namespace JS {
michael@0 1903 namespace detail {
michael@0 1904
michael@0 1905 /* NEVER DEFINED, DON'T USE. For use by JS_CAST_PARALLEL_NATIVE_TO only. */
michael@0 1906 inline int CheckIsParallelNative(JSParallelNative parallelNative);
michael@0 1907
michael@0 1908 } // namespace detail
michael@0 1909 } // namespace JS
michael@0 1910
michael@0 1911 #define JS_CAST_PARALLEL_NATIVE_TO(v, To) \
michael@0 1912 (static_cast<void>(sizeof(JS::detail::CheckIsParallelNative(v))), \
michael@0 1913 reinterpret_cast<To>(v))
michael@0 1914
michael@0 1915 /*
michael@0 1916 * You may ask yourself: why do we define a wrapper around a wrapper here?
michael@0 1917 * The answer is that some compilers don't understand initializing a union
michael@0 1918 * as we do below with a construct like:
michael@0 1919 *
michael@0 1920 * reinterpret_cast<JSJitGetterOp>(JSParallelNativeThreadSafeWrapper<op>)
michael@0 1921 *
michael@0 1922 * (We need the reinterpret_cast because we must initialize the union with
michael@0 1923 * a datum of the type of the union's first member.)
michael@0 1924 *
michael@0 1925 * Presumably this has something to do with template instantiation.
michael@0 1926 * Initializing with a normal function pointer seems to work fine. Hence
michael@0 1927 * the ugliness that you see before you.
michael@0 1928 */
michael@0 1929 #define JS_JITINFO_NATIVE_PARALLEL(infoName, parallelOp) \
michael@0 1930 const JSJitInfo infoName = \
michael@0 1931 {{JS_CAST_PARALLEL_NATIVE_TO(parallelOp, JSJitGetterOp)},0,0,JSJitInfo::ParallelNative,JSJitInfo::AliasEverything,JSVAL_TYPE_MISSING,false,false,false,false,0}
michael@0 1932
michael@0 1933 #define JS_JITINFO_NATIVE_PARALLEL_THREADSAFE(infoName, wrapperName, serialOp) \
michael@0 1934 bool wrapperName##_ParallelNativeThreadSafeWrapper(js::ForkJoinContext *cx, unsigned argc, \
michael@0 1935 JS::Value *vp) \
michael@0 1936 { \
michael@0 1937 return JSParallelNativeThreadSafeWrapper<serialOp>(cx, argc, vp); \
michael@0 1938 } \
michael@0 1939 JS_JITINFO_NATIVE_PARALLEL(infoName, wrapperName##_ParallelNativeThreadSafeWrapper)
michael@0 1940
michael@0 1941 static MOZ_ALWAYS_INLINE const JSJitInfo *
michael@0 1942 FUNCTION_VALUE_TO_JITINFO(const JS::Value& v)
michael@0 1943 {
michael@0 1944 JS_ASSERT(js::GetObjectClass(&v.toObject()) == js::FunctionClassPtr);
michael@0 1945 return reinterpret_cast<js::shadow::Function *>(&v.toObject())->jitinfo;
michael@0 1946 }
michael@0 1947
michael@0 1948 /* Statically asserted in jsfun.h. */
michael@0 1949 static const unsigned JS_FUNCTION_INTERPRETED_BIT = 0x1;
michael@0 1950
michael@0 1951 static MOZ_ALWAYS_INLINE void
michael@0 1952 SET_JITINFO(JSFunction * func, const JSJitInfo *info)
michael@0 1953 {
michael@0 1954 js::shadow::Function *fun = reinterpret_cast<js::shadow::Function *>(func);
michael@0 1955 JS_ASSERT(!(fun->flags & JS_FUNCTION_INTERPRETED_BIT));
michael@0 1956 fun->jitinfo = info;
michael@0 1957 }
michael@0 1958
michael@0 1959 /*
michael@0 1960 * Engine-internal extensions of jsid. This code is here only until we
michael@0 1961 * eliminate Gecko's dependencies on it!
michael@0 1962 */
michael@0 1963
michael@0 1964 static MOZ_ALWAYS_INLINE jsid
michael@0 1965 JSID_FROM_BITS(size_t bits)
michael@0 1966 {
michael@0 1967 jsid id;
michael@0 1968 JSID_BITS(id) = bits;
michael@0 1969 return id;
michael@0 1970 }
michael@0 1971
michael@0 1972 namespace js {
michael@0 1973 namespace detail {
michael@0 1974 bool IdMatchesAtom(jsid id, JSAtom *atom);
michael@0 1975 }
michael@0 1976 }
michael@0 1977
michael@0 1978 /*
michael@0 1979 * Must not be used on atoms that are representable as integer jsids.
michael@0 1980 * Prefer NameToId or AtomToId over this function:
michael@0 1981 *
michael@0 1982 * A PropertyName is an atom that does not contain an integer in the range
michael@0 1983 * [0, UINT32_MAX]. However, jsid can only hold an integer in the range
michael@0 1984 * [0, JSID_INT_MAX] (where JSID_INT_MAX == 2^31-1). Thus, for the range of
michael@0 1985 * integers (JSID_INT_MAX, UINT32_MAX], to represent as a jsid 'id', it must be
michael@0 1986 * the case JSID_IS_ATOM(id) and !JSID_TO_ATOM(id)->isPropertyName(). In most
michael@0 1987 * cases when creating a jsid, code does not have to care about this corner
michael@0 1988 * case because:
michael@0 1989 *
michael@0 1990 * - When given an arbitrary JSAtom*, AtomToId must be used, which checks for
michael@0 1991 * integer atoms representable as integer jsids, and does this conversion.
michael@0 1992 *
michael@0 1993 * - When given a PropertyName*, NameToId can be used which which does not need
michael@0 1994 * to do any dynamic checks.
michael@0 1995 *
michael@0 1996 * Thus, it is only the rare third case which needs this function, which
michael@0 1997 * handles any JSAtom* that is known not to be representable with an int jsid.
michael@0 1998 */
michael@0 1999 static MOZ_ALWAYS_INLINE jsid
michael@0 2000 NON_INTEGER_ATOM_TO_JSID(JSAtom *atom)
michael@0 2001 {
michael@0 2002 JS_ASSERT(((size_t)atom & 0x7) == 0);
michael@0 2003 jsid id = JSID_FROM_BITS((size_t)atom);
michael@0 2004 JS_ASSERT(js::detail::IdMatchesAtom(id, atom));
michael@0 2005 return id;
michael@0 2006 }
michael@0 2007
michael@0 2008 /* All strings stored in jsids are atomized, but are not necessarily property names. */
michael@0 2009 static MOZ_ALWAYS_INLINE bool
michael@0 2010 JSID_IS_ATOM(jsid id)
michael@0 2011 {
michael@0 2012 return JSID_IS_STRING(id);
michael@0 2013 }
michael@0 2014
michael@0 2015 static MOZ_ALWAYS_INLINE bool
michael@0 2016 JSID_IS_ATOM(jsid id, JSAtom *atom)
michael@0 2017 {
michael@0 2018 return id == JSID_FROM_BITS((size_t)atom);
michael@0 2019 }
michael@0 2020
michael@0 2021 static MOZ_ALWAYS_INLINE JSAtom *
michael@0 2022 JSID_TO_ATOM(jsid id)
michael@0 2023 {
michael@0 2024 return (JSAtom *)JSID_TO_STRING(id);
michael@0 2025 }
michael@0 2026
michael@0 2027 JS_STATIC_ASSERT(sizeof(jsid) == sizeof(void*));
michael@0 2028
michael@0 2029 namespace js {
michael@0 2030
michael@0 2031 static MOZ_ALWAYS_INLINE JS::Value
michael@0 2032 IdToValue(jsid id)
michael@0 2033 {
michael@0 2034 if (JSID_IS_STRING(id))
michael@0 2035 return JS::StringValue(JSID_TO_STRING(id));
michael@0 2036 if (MOZ_LIKELY(JSID_IS_INT(id)))
michael@0 2037 return JS::Int32Value(JSID_TO_INT(id));
michael@0 2038 if (MOZ_LIKELY(JSID_IS_OBJECT(id)))
michael@0 2039 return JS::ObjectValue(*JSID_TO_OBJECT(id));
michael@0 2040 JS_ASSERT(JSID_IS_VOID(id));
michael@0 2041 return JS::UndefinedValue();
michael@0 2042 }
michael@0 2043
michael@0 2044 extern JS_FRIEND_API(bool)
michael@0 2045 IsTypedArrayThisCheck(JS::IsAcceptableThis test);
michael@0 2046
michael@0 2047 /*
michael@0 2048 * If the embedder has registered a default JSContext callback, returns the
michael@0 2049 * result of the callback. Otherwise, asserts that |rt| has exactly one
michael@0 2050 * JSContext associated with it, and returns that context.
michael@0 2051 */
michael@0 2052 extern JS_FRIEND_API(JSContext *)
michael@0 2053 DefaultJSContext(JSRuntime *rt);
michael@0 2054
michael@0 2055 typedef JSContext*
michael@0 2056 (* DefaultJSContextCallback)(JSRuntime *rt);
michael@0 2057
michael@0 2058 JS_FRIEND_API(void)
michael@0 2059 SetDefaultJSContextCallback(JSRuntime *rt, DefaultJSContextCallback cb);
michael@0 2060
michael@0 2061 /*
michael@0 2062 * To help embedders enforce their invariants, we allow them to specify in
michael@0 2063 * advance which JSContext should be passed to JSAPI calls. If this is set
michael@0 2064 * to a non-null value, the assertSameCompartment machinery does double-
michael@0 2065 * duty (in debug builds) to verify that it matches the cx being used.
michael@0 2066 */
michael@0 2067 #ifdef DEBUG
michael@0 2068 JS_FRIEND_API(void)
michael@0 2069 Debug_SetActiveJSContext(JSRuntime *rt, JSContext *cx);
michael@0 2070 #else
michael@0 2071 inline void
michael@0 2072 Debug_SetActiveJSContext(JSRuntime *rt, JSContext *cx) {};
michael@0 2073 #endif
michael@0 2074
michael@0 2075
michael@0 2076 enum CTypesActivityType {
michael@0 2077 CTYPES_CALL_BEGIN,
michael@0 2078 CTYPES_CALL_END,
michael@0 2079 CTYPES_CALLBACK_BEGIN,
michael@0 2080 CTYPES_CALLBACK_END
michael@0 2081 };
michael@0 2082
michael@0 2083 typedef void
michael@0 2084 (* CTypesActivityCallback)(JSContext *cx, CTypesActivityType type);
michael@0 2085
michael@0 2086 /*
michael@0 2087 * Sets a callback that is run whenever js-ctypes is about to be used when
michael@0 2088 * calling into C.
michael@0 2089 */
michael@0 2090 JS_FRIEND_API(void)
michael@0 2091 SetCTypesActivityCallback(JSRuntime *rt, CTypesActivityCallback cb);
michael@0 2092
michael@0 2093 class JS_FRIEND_API(AutoCTypesActivityCallback) {
michael@0 2094 private:
michael@0 2095 JSContext *cx;
michael@0 2096 CTypesActivityCallback callback;
michael@0 2097 CTypesActivityType endType;
michael@0 2098 MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
michael@0 2099
michael@0 2100 public:
michael@0 2101 AutoCTypesActivityCallback(JSContext *cx, CTypesActivityType beginType,
michael@0 2102 CTypesActivityType endType
michael@0 2103 MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
michael@0 2104 ~AutoCTypesActivityCallback() {
michael@0 2105 DoEndCallback();
michael@0 2106 }
michael@0 2107 void DoEndCallback() {
michael@0 2108 if (callback) {
michael@0 2109 callback(cx, endType);
michael@0 2110 callback = nullptr;
michael@0 2111 }
michael@0 2112 }
michael@0 2113 };
michael@0 2114
michael@0 2115 typedef bool
michael@0 2116 (* ObjectMetadataCallback)(JSContext *cx, JSObject **pmetadata);
michael@0 2117
michael@0 2118 /*
michael@0 2119 * Specify a callback to invoke when creating each JS object in the current
michael@0 2120 * compartment, which may return a metadata object to associate with the
michael@0 2121 * object. Objects with different metadata have different shape hierarchies,
michael@0 2122 * so for efficiency, objects should generally try to share metadata objects.
michael@0 2123 */
michael@0 2124 JS_FRIEND_API(void)
michael@0 2125 SetObjectMetadataCallback(JSContext *cx, ObjectMetadataCallback callback);
michael@0 2126
michael@0 2127 /* Manipulate the metadata associated with an object. */
michael@0 2128
michael@0 2129 JS_FRIEND_API(bool)
michael@0 2130 SetObjectMetadata(JSContext *cx, JS::HandleObject obj, JS::HandleObject metadata);
michael@0 2131
michael@0 2132 JS_FRIEND_API(JSObject *)
michael@0 2133 GetObjectMetadata(JSObject *obj);
michael@0 2134
michael@0 2135 JS_FRIEND_API(void)
michael@0 2136 UnsafeDefineElement(JSContext *cx, JS::HandleObject obj, uint32_t index, JS::HandleValue value);
michael@0 2137
michael@0 2138 JS_FRIEND_API(bool)
michael@0 2139 SliceSlowly(JSContext* cx, JS::HandleObject obj, JS::HandleObject receiver,
michael@0 2140 uint32_t begin, uint32_t end, JS::HandleObject result);
michael@0 2141
michael@0 2142 /* ES5 8.12.8. */
michael@0 2143 extern JS_FRIEND_API(bool)
michael@0 2144 DefaultValue(JSContext *cx, JS::HandleObject obj, JSType hint, JS::MutableHandleValue vp);
michael@0 2145
michael@0 2146 /*
michael@0 2147 * Helper function. To approximate a call to the [[DefineOwnProperty]] internal
michael@0 2148 * method described in ES5, first call this, then call JS_DefinePropertyById.
michael@0 2149 *
michael@0 2150 * JS_DefinePropertyById by itself does not enforce the invariants on
michael@0 2151 * non-configurable properties when obj->isNative(). This function performs the
michael@0 2152 * relevant checks (specified in ES5 8.12.9 [[DefineOwnProperty]] steps 1-11),
michael@0 2153 * but only if obj is native.
michael@0 2154 *
michael@0 2155 * The reason for the messiness here is that ES5 uses [[DefineOwnProperty]] as
michael@0 2156 * a sort of extension point, but there is no hook in js::Class,
michael@0 2157 * js::ProxyHandler, or the JSAPI with precisely the right semantics for it.
michael@0 2158 */
michael@0 2159 extern JS_FRIEND_API(bool)
michael@0 2160 CheckDefineProperty(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::HandleValue value,
michael@0 2161 JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs);
michael@0 2162
michael@0 2163 /*
michael@0 2164 * Helper function for HTMLDocument and HTMLFormElement.
michael@0 2165 *
michael@0 2166 * These are the only two interfaces that have [OverrideBuiltins], a named
michael@0 2167 * getter, and no named setter. They're implemented as proxies with a custom
michael@0 2168 * getOwnPropertyDescriptor() method. Unfortunately, overriding
michael@0 2169 * getOwnPropertyDescriptor() automatically affects the behavior of set(),
michael@0 2170 * which normally is just common sense but is *not* desired for these two
michael@0 2171 * interfaces.
michael@0 2172 *
michael@0 2173 * The fix is for these two interfaces to override set() to ignore the
michael@0 2174 * getOwnPropertyDescriptor() override.
michael@0 2175 *
michael@0 2176 * SetPropertyIgnoringNamedGetter is exposed to make it easier to override
michael@0 2177 * set() in this way. It carries out all the steps of BaseProxyHandler::set()
michael@0 2178 * except the initial getOwnPropertyDescriptor()/getPropertyDescriptor() calls.
michael@0 2179 * The caller must supply those results as the 'desc' and 'descIsOwn'
michael@0 2180 * parameters.
michael@0 2181 *
michael@0 2182 * Implemented in jsproxy.cpp.
michael@0 2183 */
michael@0 2184 JS_FRIEND_API(bool)
michael@0 2185 SetPropertyIgnoringNamedGetter(JSContext *cx, BaseProxyHandler *handler,
michael@0 2186 JS::HandleObject proxy, JS::HandleObject receiver,
michael@0 2187 JS::HandleId id, JS::MutableHandle<JSPropertyDescriptor> desc,
michael@0 2188 bool descIsOwn, bool strict, JS::MutableHandleValue vp);
michael@0 2189
michael@0 2190 } /* namespace js */
michael@0 2191
michael@0 2192 extern JS_FRIEND_API(bool)
michael@0 2193 js_DefineOwnProperty(JSContext *cx, JSObject *objArg, jsid idArg,
michael@0 2194 JS::Handle<JSPropertyDescriptor> descriptor, bool *bp);
michael@0 2195
michael@0 2196 extern JS_FRIEND_API(bool)
michael@0 2197 js_ReportIsNotFunction(JSContext *cx, JS::HandleValue v);
michael@0 2198
michael@0 2199 #ifdef JSGC_GENERATIONAL
michael@0 2200 extern JS_FRIEND_API(void)
michael@0 2201 JS_StoreObjectPostBarrierCallback(JSContext* cx,
michael@0 2202 void (*callback)(JSTracer *trc, JSObject *key, void *data),
michael@0 2203 JSObject *key, void *data);
michael@0 2204
michael@0 2205 extern JS_FRIEND_API(void)
michael@0 2206 JS_StoreStringPostBarrierCallback(JSContext* cx,
michael@0 2207 void (*callback)(JSTracer *trc, JSString *key, void *data),
michael@0 2208 JSString *key, void *data);
michael@0 2209 #else
michael@0 2210 inline void
michael@0 2211 JS_StoreObjectPostBarrierCallback(JSContext* cx,
michael@0 2212 void (*callback)(JSTracer *trc, JSObject *key, void *data),
michael@0 2213 JSObject *key, void *data) {}
michael@0 2214
michael@0 2215 inline void
michael@0 2216 JS_StoreStringPostBarrierCallback(JSContext* cx,
michael@0 2217 void (*callback)(JSTracer *trc, JSString *key, void *data),
michael@0 2218 JSString *key, void *data) {}
michael@0 2219 #endif /* JSGC_GENERATIONAL */
michael@0 2220
michael@0 2221 #endif /* jsfriendapi_h */

mercurial