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