Line data Source code
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/. */
6 :
7 : #ifndef jsfriendapi_h
8 : #define jsfriendapi_h
9 :
10 : #include "mozilla/Atomics.h"
11 : #include "mozilla/Casting.h"
12 : #include "mozilla/Maybe.h"
13 : #include "mozilla/MemoryReporting.h"
14 : #include "mozilla/UniquePtr.h"
15 :
16 : #include "jsapi.h" // For JSAutoByteString. See bug 1033916.
17 : #include "jspubtd.h"
18 :
19 : #include "js/CallArgs.h"
20 : #include "js/CallNonGenericMethod.h"
21 : #include "js/Class.h"
22 : #include "js/HeapAPI.h"
23 : #include "js/TypeDecls.h"
24 : #include "js/Utility.h"
25 :
26 : #ifndef JS_STACK_GROWTH_DIRECTION
27 : # ifdef __hppa
28 : # define JS_STACK_GROWTH_DIRECTION (1)
29 : # else
30 : # define JS_STACK_GROWTH_DIRECTION (-1)
31 : # endif
32 : #endif
33 :
34 : #if JS_STACK_GROWTH_DIRECTION > 0
35 : # define JS_CHECK_STACK_SIZE(limit, sp) (MOZ_LIKELY((uintptr_t)(sp) < (limit)))
36 : #else
37 : # define JS_CHECK_STACK_SIZE(limit, sp) (MOZ_LIKELY((uintptr_t)(sp) > (limit)))
38 : #endif
39 :
40 : struct JSErrorFormatString;
41 : class JSLinearString;
42 : struct JSJitInfo;
43 : class JSErrorReport;
44 :
45 : namespace JS {
46 : template <class T>
47 : class Heap;
48 : } /* namespace JS */
49 :
50 : namespace js {
51 : class JS_FRIEND_API(BaseProxyHandler);
52 : class InterpreterFrame;
53 : } /* namespace js */
54 :
55 : extern JS_FRIEND_API(void)
56 : JS_SetGrayGCRootsTracer(JSContext* cx, JSTraceDataOp traceOp, void* data);
57 :
58 : extern JS_FRIEND_API(JSObject*)
59 : JS_FindCompilationScope(JSContext* cx, JS::HandleObject obj);
60 :
61 : extern JS_FRIEND_API(JSFunction*)
62 : JS_GetObjectFunction(JSObject* obj);
63 :
64 : extern JS_FRIEND_API(bool)
65 : JS_SplicePrototype(JSContext* cx, JS::HandleObject obj, JS::HandleObject proto);
66 :
67 : extern JS_FRIEND_API(JSObject*)
68 : JS_NewObjectWithUniqueType(JSContext* cx, const JSClass* clasp, JS::HandleObject proto);
69 :
70 : /**
71 : * Allocate an object in exactly the same way as JS_NewObjectWithGivenProto, but
72 : * without invoking the metadata callback on it. This allows creation of
73 : * internal bookkeeping objects that are guaranteed to not have metadata
74 : * attached to them.
75 : */
76 : extern JS_FRIEND_API(JSObject*)
77 : JS_NewObjectWithoutMetadata(JSContext* cx, const JSClass* clasp, JS::Handle<JSObject*> proto);
78 :
79 : extern JS_FRIEND_API(bool)
80 : JS_NondeterministicGetWeakMapKeys(JSContext* cx, JS::HandleObject obj, JS::MutableHandleObject ret);
81 :
82 : extern JS_FRIEND_API(bool)
83 : JS_NondeterministicGetWeakSetKeys(JSContext* cx, JS::HandleObject obj, JS::MutableHandleObject ret);
84 :
85 : // Raw JSScript* because this needs to be callable from a signal handler.
86 : extern JS_FRIEND_API(unsigned)
87 : JS_PCToLineNumber(JSScript* script, jsbytecode* pc, unsigned* columnp = nullptr);
88 :
89 : /**
90 : * Determine whether the given object is backed by a DeadObjectProxy.
91 : *
92 : * Such objects hold no other objects (they have no outgoing reference edges)
93 : * and will throw if you touch them (e.g. by reading/writing a property).
94 : */
95 : extern JS_FRIEND_API(bool)
96 : JS_IsDeadWrapper(JSObject* obj);
97 :
98 : /**
99 : * Creates a new dead wrapper object in the given scope. To be used when
100 : * attempting to wrap objects from scopes which are already dead.
101 : *
102 : * If origObject is passed, it must be an proxy object, and will be
103 : * used to determine the characteristics of the new dead wrapper.
104 : */
105 : extern JS_FRIEND_API(JSObject*)
106 : JS_NewDeadWrapper(JSContext* cx, JSObject* origObject = nullptr);
107 :
108 : /**
109 : * Determine whether the given object is a ScriptSourceObject.
110 : */
111 : extern JS_FRIEND_API(bool)
112 : JS_IsScriptSourceObject(JSObject* obj);
113 :
114 : /*
115 : * Used by the cycle collector to trace through a shape or object group and
116 : * all cycle-participating data it reaches, using bounded stack space.
117 : */
118 : extern JS_FRIEND_API(void)
119 : JS_TraceShapeCycleCollectorChildren(JS::CallbackTracer* trc, JS::GCCellPtr shape);
120 : extern JS_FRIEND_API(void)
121 : JS_TraceObjectGroupCycleCollectorChildren(JS::CallbackTracer* trc, JS::GCCellPtr group);
122 :
123 : /*
124 : * Telemetry reasons passed to the accumulate telemetry callback.
125 : *
126 : * It's OK for these enum values to change as they will be mapped to a fixed
127 : * member of the mozilla::Telemetry::HistogramID enum by the callback.
128 : */
129 : enum {
130 : JS_TELEMETRY_GC_REASON,
131 : JS_TELEMETRY_GC_IS_ZONE_GC,
132 : JS_TELEMETRY_GC_MS,
133 : JS_TELEMETRY_GC_BUDGET_MS,
134 : JS_TELEMETRY_GC_BUDGET_OVERRUN,
135 : JS_TELEMETRY_GC_ANIMATION_MS,
136 : JS_TELEMETRY_GC_MAX_PAUSE_MS_2,
137 : JS_TELEMETRY_GC_MARK_MS,
138 : JS_TELEMETRY_GC_SWEEP_MS,
139 : JS_TELEMETRY_GC_COMPACT_MS,
140 : JS_TELEMETRY_GC_MARK_ROOTS_MS,
141 : JS_TELEMETRY_GC_MARK_GRAY_MS,
142 : JS_TELEMETRY_GC_SLICE_MS,
143 : JS_TELEMETRY_GC_SLOW_PHASE,
144 : JS_TELEMETRY_GC_SLOW_TASK,
145 : JS_TELEMETRY_GC_MMU_50,
146 : JS_TELEMETRY_GC_RESET,
147 : JS_TELEMETRY_GC_RESET_REASON,
148 : JS_TELEMETRY_GC_INCREMENTAL_DISABLED,
149 : JS_TELEMETRY_GC_NON_INCREMENTAL,
150 : JS_TELEMETRY_GC_NON_INCREMENTAL_REASON,
151 : JS_TELEMETRY_GC_SCC_SWEEP_TOTAL_MS,
152 : JS_TELEMETRY_GC_SCC_SWEEP_MAX_PAUSE_MS,
153 : JS_TELEMETRY_GC_MINOR_REASON,
154 : JS_TELEMETRY_GC_MINOR_REASON_LONG,
155 : JS_TELEMETRY_GC_MINOR_US,
156 : JS_TELEMETRY_GC_NURSERY_BYTES,
157 : JS_TELEMETRY_GC_PRETENURE_COUNT,
158 : JS_TELEMETRY_PRIVILEGED_PARSER_COMPILE_LAZY_AFTER_MS,
159 : JS_TELEMETRY_WEB_PARSER_COMPILE_LAZY_AFTER_MS,
160 : JS_TELEMETRY_END
161 : };
162 :
163 : typedef void
164 : (*JSAccumulateTelemetryDataCallback)(int id, uint32_t sample, const char* key);
165 :
166 : extern JS_FRIEND_API(void)
167 : JS_SetAccumulateTelemetryCallback(JSContext* cx, JSAccumulateTelemetryDataCallback callback);
168 :
169 : /*
170 : * Use counter names passed to the accumulate use counter callback.
171 : *
172 : * It's OK to for these enum values to change as they will be mapped to a
173 : * fixed member of the mozilla::UseCounter enum by the callback.
174 : */
175 :
176 : enum class JSUseCounter {
177 : ASMJS,
178 : WASM
179 : };
180 :
181 : typedef void
182 : (*JSSetUseCounterCallback)(JSObject* obj, JSUseCounter counter);
183 :
184 : extern JS_FRIEND_API(void)
185 : JS_SetSetUseCounterCallback(JSContext* cx, JSSetUseCounterCallback callback);
186 :
187 : extern JS_FRIEND_API(JSPrincipals*)
188 : JS_GetCompartmentPrincipals(JS::Compartment* compartment);
189 :
190 : extern JS_FRIEND_API(JSPrincipals*)
191 : JS_GetScriptPrincipals(JSScript* script);
192 :
193 : namespace js {
194 : extern JS_FRIEND_API(JS::Realm*)
195 : GetScriptRealm(JSScript* script);
196 : } /* namespace js */
197 :
198 : extern JS_FRIEND_API(bool)
199 : JS_ScriptHasMutedErrors(JSScript* script);
200 :
201 : extern JS_FRIEND_API(JSObject*)
202 : JS_CloneObject(JSContext* cx, JS::HandleObject obj, JS::HandleObject proto);
203 :
204 : /**
205 : * Copy the own properties of src to dst in a fast way. src and dst must both
206 : * be native and must be in the compartment of cx. They must have the same
207 : * class, the same parent, and the same prototype. Class reserved slots will
208 : * NOT be copied.
209 : *
210 : * dst must not have any properties on it before this function is called.
211 : *
212 : * src must have been allocated via JS_NewObjectWithoutMetadata so that we can
213 : * be sure it has no metadata that needs copying to dst. This also means that
214 : * dst needs to have the compartment global as its parent. This function will
215 : * preserve the existing metadata on dst, if any.
216 : */
217 : extern JS_FRIEND_API(bool)
218 : JS_InitializePropertiesFromCompatibleNativeObject(JSContext* cx,
219 : JS::HandleObject dst,
220 : JS::HandleObject src);
221 :
222 : namespace js {
223 :
224 : JS_FRIEND_API(bool)
225 : GetBuiltinClass(JSContext* cx, JS::HandleObject obj, ESClass* cls);
226 :
227 : JS_FRIEND_API(const char*)
228 : ObjectClassName(JSContext* cx, JS::HandleObject obj);
229 :
230 : JS_FRIEND_API(void)
231 : ReportOverRecursed(JSContext* maybecx);
232 :
233 : JS_FRIEND_API(bool)
234 : AddRawValueRoot(JSContext* cx, JS::Value* vp, const char* name);
235 :
236 : JS_FRIEND_API(void)
237 : RemoveRawValueRoot(JSContext* cx, JS::Value* vp);
238 :
239 : JS_FRIEND_API(JSAtom*)
240 : GetPropertyNameFromPC(JSScript* script, jsbytecode* pc);
241 :
242 : #ifdef JS_DEBUG
243 :
244 : /*
245 : * Routines to print out values during debugging. These are FRIEND_API to help
246 : * the debugger find them and to support temporarily hacking js::Dump* calls
247 : * into other code. Note that there are overloads that do not require the FILE*
248 : * parameter, which will default to stderr.
249 : */
250 :
251 : extern JS_FRIEND_API(void)
252 : DumpString(JSString* str, FILE* fp);
253 :
254 : extern JS_FRIEND_API(void)
255 : DumpAtom(JSAtom* atom, FILE* fp);
256 :
257 : extern JS_FRIEND_API(void)
258 : DumpObject(JSObject* obj, FILE* fp);
259 :
260 : extern JS_FRIEND_API(void)
261 : DumpChars(const char16_t* s, size_t n, FILE* fp);
262 :
263 : extern JS_FRIEND_API(void)
264 : DumpValue(const JS::Value& val, FILE* fp);
265 :
266 : extern JS_FRIEND_API(void)
267 : DumpId(jsid id, FILE* fp);
268 :
269 : extern JS_FRIEND_API(void)
270 : DumpInterpreterFrame(JSContext* cx, FILE* fp, InterpreterFrame* start = nullptr);
271 :
272 : extern JS_FRIEND_API(bool)
273 : DumpPC(JSContext* cx, FILE* fp);
274 :
275 : extern JS_FRIEND_API(bool)
276 : DumpScript(JSContext* cx, JSScript* scriptArg, FILE* fp);
277 :
278 : // Versions for use directly in a debugger (default parameters are not handled
279 : // well in gdb; built-in handles like stderr are not handled well in lldb.)
280 : extern JS_FRIEND_API(void) DumpString(JSString* str);
281 : extern JS_FRIEND_API(void) DumpAtom(JSAtom* atom);
282 : extern JS_FRIEND_API(void) DumpObject(JSObject* obj);
283 : extern JS_FRIEND_API(void) DumpChars(const char16_t* s, size_t n);
284 : extern JS_FRIEND_API(void) DumpValue(const JS::Value& val);
285 : extern JS_FRIEND_API(void) DumpId(jsid id);
286 : extern JS_FRIEND_API(void) DumpInterpreterFrame(JSContext* cx, InterpreterFrame* start = nullptr);
287 : extern JS_FRIEND_API(bool) DumpPC(JSContext* cx);
288 : extern JS_FRIEND_API(bool) DumpScript(JSContext* cx, JSScript* scriptArg);
289 :
290 : #endif
291 :
292 : extern JS_FRIEND_API(void)
293 : DumpBacktrace(JSContext* cx, FILE* fp);
294 :
295 : extern JS_FRIEND_API(void)
296 : DumpBacktrace(JSContext* cx);
297 :
298 : } // namespace js
299 :
300 : namespace JS {
301 :
302 : /** Exposed for DumpJSStack */
303 : extern JS_FRIEND_API(JS::UniqueChars)
304 : FormatStackDump(JSContext* cx, JS::UniqueChars&& buf, bool showArgs, bool showLocals,
305 : bool showThisProps);
306 :
307 : /**
308 : * Set all of the uninitialized lexicals on an object to undefined. Return
309 : * true if any lexicals were initialized and false otherwise.
310 : * */
311 : extern JS_FRIEND_API(bool)
312 : ForceLexicalInitialization(JSContext *cx, HandleObject obj);
313 :
314 : /**
315 : * Whether we are poisoning unused/released data for error detection. Governed
316 : * by the JS_GC_POISONING #ifdef as well as the $JSGC_DISABLE_POISONING
317 : * environment variable.
318 : */
319 : extern JS_FRIEND_API(int)
320 : IsGCPoisoning();
321 :
322 : extern JS_FRIEND_API(JSPrincipals*)
323 : GetRealmPrincipals(JS::Realm* realm);
324 :
325 : extern JS_FRIEND_API(void)
326 : SetRealmPrincipals(JS::Realm* realm, JSPrincipals* principals);
327 :
328 : extern JS_FRIEND_API(bool)
329 : GetIsSecureContext(JS::Realm* realm);
330 :
331 : } // namespace JS
332 :
333 : /**
334 : * Copies all own properties from |obj| to |target|. |obj| must be a "native"
335 : * object (that is to say, normal-ish - not an Array or a Proxy).
336 : *
337 : * This function immediately enters a compartment, and does not impose any
338 : * restrictions on the compartment of |cx|.
339 : */
340 : extern JS_FRIEND_API(bool)
341 : JS_CopyPropertiesFrom(JSContext* cx, JS::HandleObject target, JS::HandleObject obj);
342 :
343 : /*
344 : * Single-property version of the above. This function asserts that an |own|
345 : * property of the given name exists on |obj|.
346 : *
347 : * On entry, |cx| must be same-compartment with |obj|.
348 : *
349 : * The copyBehavior argument controls what happens with
350 : * non-configurable properties.
351 : */
352 : typedef enum {
353 : MakeNonConfigurableIntoConfigurable,
354 : CopyNonConfigurableAsIs
355 : } PropertyCopyBehavior;
356 :
357 : extern JS_FRIEND_API(bool)
358 : JS_CopyPropertyFrom(JSContext* cx, JS::HandleId id, JS::HandleObject target,
359 : JS::HandleObject obj,
360 : PropertyCopyBehavior copyBehavior = CopyNonConfigurableAsIs);
361 :
362 : extern JS_FRIEND_API(bool)
363 : JS_WrapPropertyDescriptor(JSContext* cx, JS::MutableHandle<JS::PropertyDescriptor> desc);
364 :
365 : struct JSFunctionSpecWithHelp {
366 : const char* name;
367 : JSNative call;
368 : uint16_t nargs;
369 : uint16_t flags;
370 : const JSJitInfo* jitInfo;
371 : const char* usage;
372 : const char* help;
373 : };
374 :
375 : #define JS_FN_HELP(name,call,nargs,flags,usage,help) \
376 : {name, call, nargs, (flags) | JSPROP_ENUMERATE, nullptr, usage, help}
377 : #define JS_INLINABLE_FN_HELP(name,call,nargs,flags,native,usage,help) \
378 : {name, call, nargs, (flags) | JSPROP_ENUMERATE, &js::jit::JitInfo_##native,\
379 : usage, help}
380 : #define JS_FS_HELP_END \
381 : {nullptr, nullptr, 0, 0, nullptr, nullptr}
382 :
383 : extern JS_FRIEND_API(bool)
384 : JS_DefineFunctionsWithHelp(JSContext* cx, JS::HandleObject obj, const JSFunctionSpecWithHelp* fs);
385 :
386 : namespace js {
387 :
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() { }
402 :
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, char16_t** src, size_t* length) = 0;
409 : };
410 :
411 : /**
412 : * Have |cx| use |hook| to retrieve lazily-retrieved source code. See the
413 : * comments for SourceHook. The context takes ownership of the hook, and
414 : * will delete it when the context itself is deleted, or when a new hook is
415 : * set.
416 : */
417 : extern JS_FRIEND_API(void)
418 : SetSourceHook(JSContext* cx, mozilla::UniquePtr<SourceHook> hook);
419 :
420 : /** Remove |cx|'s source hook, and return it. The caller now owns the hook. */
421 : extern JS_FRIEND_API(mozilla::UniquePtr<SourceHook>)
422 : ForgetSourceHook(JSContext* cx);
423 :
424 : /**
425 : * Use the runtime's internal handling of job queues for Promise jobs.
426 : *
427 : * Most embeddings, notably web browsers, will have their own task scheduling
428 : * systems and need to integrate handling of Promise jobs into that, so they
429 : * will want to manage job queues themselves. For basic embeddings such as the
430 : * JS shell that don't have an event loop of their own, it's easier to have
431 : * SpiderMonkey handle job queues internally.
432 : *
433 : * Note that the embedding still has to trigger processing of job queues at
434 : * right time(s), such as after evaluation of a script has run to completion.
435 : */
436 : extern JS_FRIEND_API(bool)
437 : UseInternalJobQueues(JSContext* cx);
438 :
439 : /**
440 : * Enqueue |job| on the internal job queue.
441 : *
442 : * This is useful in tests for creating situations where a call occurs with no
443 : * other JavaScript on the stack.
444 : */
445 : extern JS_FRIEND_API(bool)
446 : EnqueueJob(JSContext* cx, JS::HandleObject job);
447 :
448 : /**
449 : * Instruct the runtime to stop draining the internal job queue.
450 : *
451 : * Useful if the embedding is in the process of quitting in reaction to a
452 : * builtin being called, or if it wants to resume executing jobs later on.
453 : */
454 : extern JS_FRIEND_API(void)
455 : StopDrainingJobQueue(JSContext* cx);
456 :
457 : extern JS_FRIEND_API(void)
458 : RunJobs(JSContext* cx);
459 :
460 : extern JS_FRIEND_API(JS::Zone*)
461 : GetRealmZone(JS::Realm* realm);
462 :
463 : typedef bool
464 : (* PreserveWrapperCallback)(JSContext* cx, JSObject* obj);
465 :
466 : typedef enum {
467 : CollectNurseryBeforeDump,
468 : IgnoreNurseryObjects
469 : } DumpHeapNurseryBehaviour;
470 :
471 : /**
472 : * Dump the complete object graph of heap-allocated things.
473 : * fp is the file for the dump output.
474 : */
475 : extern JS_FRIEND_API(void)
476 : DumpHeap(JSContext* cx, FILE* fp, DumpHeapNurseryBehaviour nurseryBehaviour);
477 :
478 : #ifdef JS_OLD_GETTER_SETTER_METHODS
479 : JS_FRIEND_API(bool) obj_defineGetter(JSContext* cx, unsigned argc, JS::Value* vp);
480 : JS_FRIEND_API(bool) obj_defineSetter(JSContext* cx, unsigned argc, JS::Value* vp);
481 : #endif
482 :
483 : extern JS_FRIEND_API(bool)
484 : IsSystemRealm(JS::Realm* realm);
485 :
486 : extern JS_FRIEND_API(bool)
487 : IsSystemCompartment(JS::Compartment* comp);
488 :
489 : extern JS_FRIEND_API(bool)
490 : IsSystemZone(JS::Zone* zone);
491 :
492 : extern JS_FRIEND_API(bool)
493 : IsAtomsZone(JS::Zone* zone);
494 :
495 : struct WeakMapTracer
496 : {
497 : JSRuntime* runtime;
498 :
499 0 : explicit WeakMapTracer(JSRuntime* rt) : runtime(rt) {}
500 :
501 : // Weak map tracer callback, called once for every binding of every
502 : // weak map that was live at the time of the last garbage collection.
503 : //
504 : // m will be nullptr if the weak map is not contained in a JS Object.
505 : //
506 : // The callback should not GC (and will assert in a debug build if it does so.)
507 : virtual void trace(JSObject* m, JS::GCCellPtr key, JS::GCCellPtr value) = 0;
508 : };
509 :
510 : extern JS_FRIEND_API(void)
511 : TraceWeakMaps(WeakMapTracer* trc);
512 :
513 : extern JS_FRIEND_API(bool)
514 : AreGCGrayBitsValid(JSRuntime* rt);
515 :
516 : extern JS_FRIEND_API(bool)
517 : ZoneGlobalsAreAllGray(JS::Zone* zone);
518 :
519 : extern JS_FRIEND_API(bool)
520 : IsObjectZoneSweepingOrCompacting(JSObject* obj);
521 :
522 : typedef void
523 : (*GCThingCallback)(void* closure, JS::GCCellPtr thing);
524 :
525 : extern JS_FRIEND_API(void)
526 : VisitGrayWrapperTargets(JS::Zone* zone, GCThingCallback callback, void* closure);
527 :
528 : extern JS_FRIEND_API(JSObject*)
529 : GetWeakmapKeyDelegate(JSObject* key);
530 :
531 : /**
532 : * Invoke cellCallback on every gray JSObject in the given zone.
533 : */
534 : extern JS_FRIEND_API(void)
535 : IterateGrayObjects(JS::Zone* zone, GCThingCallback cellCallback, void* data);
536 :
537 : /**
538 : * Invoke cellCallback on every gray JSObject in the given zone while cycle
539 : * collection is in progress.
540 : */
541 : extern JS_FRIEND_API(void)
542 : IterateGrayObjectsUnderCC(JS::Zone* zone, GCThingCallback cellCallback, void* data);
543 :
544 : #if defined(JS_GC_ZEAL) || defined(DEBUG)
545 : // Trace the heap and check there are no black to gray edges. These are
546 : // not allowed since the cycle collector could throw away the gray thing and
547 : // leave a dangling pointer.
548 : //
549 : // This doesn't trace weak maps as these are handled separately.
550 : extern JS_FRIEND_API(bool)
551 : CheckGrayMarkingState(JSRuntime* rt);
552 : #endif
553 :
554 : #ifdef JS_HAS_CTYPES
555 : extern JS_FRIEND_API(size_t)
556 : SizeOfDataIfCDataObject(mozilla::MallocSizeOf mallocSizeOf, JSObject* obj);
557 : #endif
558 :
559 : // Note: this returns nullptr iff |zone| is the atoms zone.
560 : extern JS_FRIEND_API(JS::Realm*)
561 : GetAnyRealmInZone(JS::Zone* zone);
562 :
563 : /*
564 : * Shadow declarations of JS internal structures, for access by inline access
565 : * functions below. Do not use these structures in any other way. When adding
566 : * new fields for access by inline methods, make sure to add static asserts to
567 : * the original header file to ensure that offsets are consistent.
568 : */
569 : namespace shadow {
570 :
571 : struct ObjectGroup {
572 : const Class* clasp;
573 : JSObject* proto;
574 : JS::Realm* realm;
575 : };
576 :
577 : struct BaseShape {
578 : const js::Class* clasp_;
579 : JSObject* parent;
580 : };
581 :
582 : class Shape {
583 : public:
584 : shadow::BaseShape* base;
585 : jsid _1;
586 : uint32_t immutableFlags;
587 :
588 : static const uint32_t FIXED_SLOTS_SHIFT = 24;
589 : static const uint32_t FIXED_SLOTS_MASK = 0x1f << FIXED_SLOTS_SHIFT;
590 : };
591 :
592 : /**
593 : * This layout is shared by all native objects. For non-native objects, the
594 : * group may always be accessed safely, and other members may be as well,
595 : * depending on the object's specific layout.
596 : */
597 : struct Object {
598 : shadow::ObjectGroup* group;
599 : shadow::Shape* shape;
600 : JS::Value* slots;
601 : void* _1;
602 :
603 : static const size_t MAX_FIXED_SLOTS = 16;
604 :
605 : size_t numFixedSlots() const {
606 0 : return (shape->immutableFlags & Shape::FIXED_SLOTS_MASK) >> Shape::FIXED_SLOTS_SHIFT;
607 : }
608 :
609 : JS::Value* fixedSlots() const {
610 0 : return (JS::Value*)(uintptr_t(this) + sizeof(shadow::Object));
611 : }
612 :
613 : JS::Value& slotRef(size_t slot) const {
614 0 : size_t nfixed = numFixedSlots();
615 0 : if (slot < nfixed)
616 0 : return fixedSlots()[slot];
617 0 : return slots[slot - nfixed];
618 : }
619 : };
620 :
621 : struct Function {
622 : Object base;
623 : uint16_t nargs;
624 : uint16_t flags;
625 : /* Used only for natives */
626 : JSNative native;
627 : const JSJitInfo* jitinfo;
628 : void* _1;
629 : };
630 :
631 : } /* namespace shadow */
632 :
633 : // This is equal to |&JSObject::class_|. Use it in places where you don't want
634 : // to #include vm/JSObject.h.
635 : extern JS_FRIEND_DATA(const js::Class* const) ObjectClassPtr;
636 :
637 : inline const js::Class*
638 : GetObjectClass(const JSObject* obj)
639 : {
640 0 : return reinterpret_cast<const shadow::Object*>(obj)->group->clasp;
641 : }
642 :
643 : inline const JSClass*
644 : GetObjectJSClass(JSObject* obj)
645 : {
646 : return js::Jsvalify(GetObjectClass(obj));
647 : }
648 :
649 : JS_FRIEND_API(const Class*)
650 : ProtoKeyToClass(JSProtoKey key);
651 :
652 : // Returns the key for the class inherited by a given standard class (that
653 : // is to say, the prototype of this standard class's prototype).
654 : //
655 : // You must be sure that this corresponds to a standard class with a cached
656 : // JSProtoKey before calling this function. In general |key| will match the
657 : // cached proto key, except in cases where multiple JSProtoKeys share a
658 : // JSClass.
659 : inline JSProtoKey
660 2 : InheritanceProtoKeyForStandardClass(JSProtoKey key)
661 : {
662 : // [Object] has nothing to inherit from.
663 0 : if (key == JSProto_Object)
664 : return JSProto_Null;
665 :
666 : // If we're ClassSpec defined return the proto key from that
667 0 : if (ProtoKeyToClass(key)->specDefined())
668 0 : return ProtoKeyToClass(key)->specInheritanceProtoKey();
669 :
670 : // Otherwise, we inherit [Object].
671 : return JSProto_Object;
672 : }
673 :
674 : JS_FRIEND_API(bool)
675 : IsFunctionObject(JSObject* obj);
676 :
677 : JS_FRIEND_API(bool)
678 : IsCrossCompartmentWrapper(const JSObject* obj);
679 :
680 : static MOZ_ALWAYS_INLINE JS::Compartment*
681 : GetObjectCompartment(JSObject* obj)
682 : {
683 0 : JS::Realm* realm = reinterpret_cast<shadow::Object*>(obj)->group->realm;
684 0 : return JS::GetCompartmentForRealm(realm);
685 : }
686 :
687 : // CrossCompartmentWrappers are shared by all realms within the compartment, so
688 : // getting a wrapper's realm usually doesn't make sense.
689 : static MOZ_ALWAYS_INLINE JS::Realm*
690 : GetNonCCWObjectRealm(JSObject* obj)
691 : {
692 : MOZ_ASSERT(!js::IsCrossCompartmentWrapper(obj));
693 : return reinterpret_cast<shadow::Object*>(obj)->group->realm;
694 : }
695 :
696 : JS_FRIEND_API(JSObject*)
697 : GetGlobalForObjectCrossCompartment(JSObject* obj);
698 :
699 : JS_FRIEND_API(JSObject*)
700 : GetPrototypeNoProxy(JSObject* obj);
701 :
702 : JS_FRIEND_API(void)
703 : AssertSameCompartment(JSContext* cx, JSObject* obj);
704 :
705 : JS_FRIEND_API(void)
706 : AssertSameCompartment(JSContext* cx, JS::HandleValue v);
707 :
708 : #ifdef JS_DEBUG
709 : JS_FRIEND_API(void)
710 : AssertSameCompartment(JSObject* objA, JSObject* objB);
711 : #else
712 : inline void AssertSameCompartment(JSObject* objA, JSObject* objB) {}
713 : #endif
714 :
715 : JS_FRIEND_API(void)
716 : NotifyAnimationActivity(JSObject* obj);
717 :
718 : JS_FRIEND_API(JSFunction*)
719 : DefineFunctionWithReserved(JSContext* cx, JSObject* obj, const char* name, JSNative call,
720 : unsigned nargs, unsigned attrs);
721 :
722 : JS_FRIEND_API(JSFunction*)
723 : NewFunctionWithReserved(JSContext* cx, JSNative call, unsigned nargs, unsigned flags,
724 : const char* name);
725 :
726 : JS_FRIEND_API(JSFunction*)
727 : NewFunctionByIdWithReserved(JSContext* cx, JSNative native, unsigned nargs, unsigned flags,
728 : jsid id);
729 :
730 : JS_FRIEND_API(const JS::Value&)
731 : GetFunctionNativeReserved(JSObject* fun, size_t which);
732 :
733 : JS_FRIEND_API(void)
734 : SetFunctionNativeReserved(JSObject* fun, size_t which, const JS::Value& val);
735 :
736 : JS_FRIEND_API(bool)
737 : FunctionHasNativeReserved(JSObject* fun);
738 :
739 : JS_FRIEND_API(bool)
740 : GetObjectProto(JSContext* cx, JS::HandleObject obj, JS::MutableHandleObject proto);
741 :
742 : extern JS_FRIEND_API(JSObject*)
743 : GetStaticPrototype(JSObject* obj);
744 :
745 : JS_FRIEND_API(bool)
746 : GetRealmOriginalEval(JSContext* cx, JS::MutableHandleObject eval);
747 :
748 : inline void*
749 : GetObjectPrivate(JSObject* obj)
750 : {
751 : MOZ_ASSERT(GetObjectClass(obj)->flags & JSCLASS_HAS_PRIVATE);
752 : const shadow::Object* nobj = reinterpret_cast<const shadow::Object*>(obj);
753 : void** addr = reinterpret_cast<void**>(&nobj->fixedSlots()[nobj->numFixedSlots()]);
754 : return *addr;
755 : }
756 :
757 : /**
758 : * Get the value stored in an object's reserved slot. This can be used with
759 : * both native objects and proxies, but if |obj| is known to be a proxy
760 : * GetProxyReservedSlot is a bit more efficient.
761 : */
762 : inline const JS::Value&
763 : GetReservedSlot(JSObject* obj, size_t slot)
764 0 : {
765 : MOZ_ASSERT(slot < JSCLASS_RESERVED_SLOTS(GetObjectClass(obj)));
766 0 : return reinterpret_cast<const shadow::Object*>(obj)->slotRef(slot);
767 0 : }
768 :
769 : JS_FRIEND_API(void)
770 : SetReservedSlotWithBarrier(JSObject* obj, size_t slot, const JS::Value& value);
771 :
772 : /**
773 : * Store a value in an object's reserved slot. This can be used with
774 : * both native objects and proxies, but if |obj| is known to be a proxy
775 : * SetProxyReservedSlot is a bit more efficient.
776 : */
777 : inline void
778 : SetReservedSlot(JSObject* obj, size_t slot, const JS::Value& value)
779 0 : {
780 : MOZ_ASSERT(slot < JSCLASS_RESERVED_SLOTS(GetObjectClass(obj)));
781 0 : shadow::Object* sobj = reinterpret_cast<shadow::Object*>(obj);
782 0 : if (sobj->slotRef(slot).isGCThing() || value.isGCThing())
783 0 : SetReservedSlotWithBarrier(obj, slot, value);
784 0 : else
785 : sobj->slotRef(slot) = value;
786 0 : }
787 0 :
788 : JS_FRIEND_API(uint32_t)
789 : GetObjectSlotSpan(JSObject* obj);
790 :
791 : inline const JS::Value&
792 : GetObjectSlot(JSObject* obj, size_t slot)
793 : {
794 : MOZ_ASSERT(slot < GetObjectSlotSpan(obj));
795 : return reinterpret_cast<const shadow::Object*>(obj)->slotRef(slot);
796 : }
797 :
798 : MOZ_ALWAYS_INLINE size_t
799 : GetAtomLength(JSAtom* atom)
800 : {
801 : return reinterpret_cast<JS::shadow::String*>(atom)->length;
802 : }
803 :
804 : static const uint32_t MaxStringLength = (1 << 28) - 1;
805 :
806 : MOZ_ALWAYS_INLINE size_t
807 : GetStringLength(JSString* s)
808 : {
809 : return reinterpret_cast<JS::shadow::String*>(s)->length;
810 0 : }
811 :
812 : MOZ_ALWAYS_INLINE size_t
813 : GetFlatStringLength(JSFlatString* s)
814 : {
815 : return reinterpret_cast<JS::shadow::String*>(s)->length;
816 : }
817 :
818 : MOZ_ALWAYS_INLINE size_t
819 : GetLinearStringLength(JSLinearString* s)
820 : {
821 : return reinterpret_cast<JS::shadow::String*>(s)->length;
822 0 : }
823 :
824 : MOZ_ALWAYS_INLINE bool
825 : LinearStringHasLatin1Chars(JSLinearString* s)
826 : {
827 : return reinterpret_cast<JS::shadow::String*>(s)->flags & JS::shadow::String::LATIN1_CHARS_BIT;
828 0 : }
829 :
830 : MOZ_ALWAYS_INLINE bool
831 : AtomHasLatin1Chars(JSAtom* atom)
832 : {
833 : return reinterpret_cast<JS::shadow::String*>(atom)->flags & JS::shadow::String::LATIN1_CHARS_BIT;
834 : }
835 :
836 : MOZ_ALWAYS_INLINE bool
837 : StringHasLatin1Chars(JSString* s)
838 : {
839 : return reinterpret_cast<JS::shadow::String*>(s)->flags & JS::shadow::String::LATIN1_CHARS_BIT;
840 : }
841 :
842 : MOZ_ALWAYS_INLINE const JS::Latin1Char*
843 : GetLatin1LinearStringChars(const JS::AutoRequireNoGC& nogc, JSLinearString* linear)
844 0 : {
845 : MOZ_ASSERT(LinearStringHasLatin1Chars(linear));
846 0 :
847 : using JS::shadow::String;
848 : String* s = reinterpret_cast<String*>(linear);
849 0 : if (s->flags & String::INLINE_CHARS_BIT)
850 0 : return s->inlineStorageLatin1;
851 0 : return s->nonInlineCharsLatin1;
852 0 : }
853 :
854 : MOZ_ALWAYS_INLINE const char16_t*
855 : GetTwoByteLinearStringChars(const JS::AutoRequireNoGC& nogc, JSLinearString* linear)
856 0 : {
857 : MOZ_ASSERT(!LinearStringHasLatin1Chars(linear));
858 0 :
859 : using JS::shadow::String;
860 : String* s = reinterpret_cast<String*>(linear);
861 0 : if (s->flags & String::INLINE_CHARS_BIT)
862 0 : return s->inlineStorageTwoByte;
863 0 : return s->nonInlineCharsTwoByte;
864 0 : }
865 :
866 : MOZ_ALWAYS_INLINE JSLinearString*
867 : AtomToLinearString(JSAtom* atom)
868 : {
869 : return reinterpret_cast<JSLinearString*>(atom);
870 : }
871 :
872 : MOZ_ALWAYS_INLINE JSFlatString*
873 : AtomToFlatString(JSAtom* atom)
874 : {
875 : return reinterpret_cast<JSFlatString*>(atom);
876 : }
877 :
878 : MOZ_ALWAYS_INLINE JSLinearString*
879 : FlatStringToLinearString(JSFlatString* s)
880 : {
881 : return reinterpret_cast<JSLinearString*>(s);
882 : }
883 :
884 : MOZ_ALWAYS_INLINE const JS::Latin1Char*
885 : GetLatin1AtomChars(const JS::AutoRequireNoGC& nogc, JSAtom* atom)
886 : {
887 : return GetLatin1LinearStringChars(nogc, AtomToLinearString(atom));
888 : }
889 :
890 : MOZ_ALWAYS_INLINE const char16_t*
891 : GetTwoByteAtomChars(const JS::AutoRequireNoGC& nogc, JSAtom* atom)
892 : {
893 : return GetTwoByteLinearStringChars(nogc, AtomToLinearString(atom));
894 : }
895 :
896 : MOZ_ALWAYS_INLINE bool
897 : IsExternalString(JSString* str, const JSStringFinalizer** fin, const char16_t** chars)
898 : {
899 : using JS::shadow::String;
900 : String* s = reinterpret_cast<String*>(str);
901 :
902 : if ((s->flags & String::TYPE_FLAGS_MASK) != String::EXTERNAL_FLAGS)
903 : return false;
904 :
905 : MOZ_ASSERT(JS_IsExternalString(str));
906 : *fin = s->externalFinalizer;
907 : *chars = s->nonInlineCharsTwoByte;
908 : return true;
909 : }
910 :
911 : JS_FRIEND_API(JSLinearString*)
912 : StringToLinearStringSlow(JSContext* cx, JSString* str);
913 :
914 : MOZ_ALWAYS_INLINE JSLinearString*
915 : StringToLinearString(JSContext* cx, JSString* str)
916 2 : {
917 : using JS::shadow::String;
918 : String* s = reinterpret_cast<String*>(str);
919 0 : if (MOZ_UNLIKELY(!(s->flags & String::LINEAR_BIT)))
920 0 : return StringToLinearStringSlow(cx, str);
921 0 : return reinterpret_cast<JSLinearString*>(str);
922 : }
923 :
924 : template<typename CharType>
925 : MOZ_ALWAYS_INLINE void
926 : CopyLinearStringChars(CharType* dest, JSLinearString* s, size_t len, size_t start = 0);
927 :
928 : MOZ_ALWAYS_INLINE void
929 : CopyLinearStringChars(char16_t* dest, JSLinearString* s, size_t len, size_t start = 0)
930 0 : {
931 : MOZ_ASSERT(start + len <= GetLinearStringLength(s));
932 0 : JS::AutoCheckCannotGC nogc;
933 0 : if (LinearStringHasLatin1Chars(s)) {
934 0 : const JS::Latin1Char* src = GetLatin1LinearStringChars(nogc, s);
935 0 : for (size_t i = 0; i < len; i++)
936 0 : dest[i] = src[start + i];
937 0 : } else {
938 : const char16_t* src = GetTwoByteLinearStringChars(nogc, s);
939 0 : mozilla::PodCopy(dest, src + start, len);
940 0 : }
941 : }
942 0 :
943 : MOZ_ALWAYS_INLINE void
944 : CopyLinearStringChars(char* dest, JSLinearString* s, size_t len, size_t start = 0)
945 : {
946 : MOZ_ASSERT(start + len <= GetLinearStringLength(s));
947 : JS::AutoCheckCannotGC nogc;
948 : if (LinearStringHasLatin1Chars(s)) {
949 : const JS::Latin1Char* src = GetLatin1LinearStringChars(nogc, s);
950 : for (size_t i = 0; i < len; i++)
951 : dest[i] = char(src[start + i]);
952 : } else {
953 : const char16_t* src = GetTwoByteLinearStringChars(nogc, s);
954 : for (size_t i = 0; i < len; i++)
955 : dest[i] = char(src[start + i]);
956 : }
957 : }
958 :
959 : template<typename CharType>
960 : inline bool
961 : CopyStringChars(JSContext* cx, CharType* dest, JSString* s, size_t len, size_t start = 0)
962 2 : {
963 : JSLinearString* linear = StringToLinearString(cx, s);
964 0 : if (!linear)
965 2 : return false;
966 :
967 : CopyLinearStringChars(dest, linear, len, start);
968 0 : return true;
969 0 : }
970 :
971 : inline void
972 : CopyFlatStringChars(char16_t* dest, JSFlatString* s, size_t len)
973 : {
974 : CopyLinearStringChars(dest, FlatStringToLinearString(s), len);
975 : }
976 :
977 : /**
978 : * Add some or all property keys of obj to the id vector *props.
979 : *
980 : * The flags parameter controls which property keys are added. Pass a
981 : * combination of the following bits:
982 : *
983 : * JSITER_OWNONLY - Don't also search the prototype chain; only consider
984 : * obj's own properties.
985 : *
986 : * JSITER_HIDDEN - Include nonenumerable properties.
987 : *
988 : * JSITER_SYMBOLS - Include property keys that are symbols. The default
989 : * behavior is to filter out symbols.
990 : *
991 : * JSITER_SYMBOLSONLY - Exclude non-symbol property keys.
992 : *
993 : * This is the closest C++ API we have to `Reflect.ownKeys(obj)`, or
994 : * equivalently, the ES6 [[OwnPropertyKeys]] internal method. Pass
995 : * `JSITER_OWNONLY | JSITER_HIDDEN | JSITER_SYMBOLS` as flags to get
996 : * results that match the output of Reflect.ownKeys.
997 : */
998 : JS_FRIEND_API(bool)
999 : GetPropertyKeys(JSContext* cx, JS::HandleObject obj, unsigned flags, JS::AutoIdVector* props);
1000 :
1001 : JS_FRIEND_API(bool)
1002 : AppendUnique(JSContext* cx, JS::AutoIdVector& base, JS::AutoIdVector& others);
1003 :
1004 : JS_FRIEND_API(bool)
1005 : StringIsArrayIndex(JSLinearString* str, uint32_t* indexp);
1006 :
1007 : JS_FRIEND_API(void)
1008 : SetPreserveWrapperCallback(JSContext* cx, PreserveWrapperCallback callback);
1009 :
1010 : JS_FRIEND_API(bool)
1011 : IsObjectInContextCompartment(JSObject* obj, const JSContext* cx);
1012 :
1013 : /*
1014 : * NB: keep these in sync with the copy in builtin/SelfHostingDefines.h.
1015 : */
1016 : /* 0x1 is no longer used */
1017 : /* 0x2 is no longer used */
1018 : /* 0x4 is no longer used */
1019 : #define JSITER_OWNONLY 0x8 /* iterate over obj's own properties only */
1020 : #define JSITER_HIDDEN 0x10 /* also enumerate non-enumerable properties */
1021 : #define JSITER_SYMBOLS 0x20 /* also include symbol property keys */
1022 : #define JSITER_SYMBOLSONLY 0x40 /* exclude string property keys */
1023 : #define JSITER_FORAWAITOF 0x80 /* for-await-of */
1024 :
1025 : JS_FRIEND_API(bool)
1026 : RunningWithTrustedPrincipals(JSContext* cx);
1027 :
1028 : MOZ_ALWAYS_INLINE uintptr_t
1029 : GetNativeStackLimit(JSContext* cx, JS::StackKind kind, int extraAllowance = 0)
1030 : {
1031 : uintptr_t limit = JS::RootingContext::get(cx)->nativeStackLimit[kind];
1032 0 : #if JS_STACK_GROWTH_DIRECTION > 0
1033 : limit += extraAllowance;
1034 : #else
1035 : limit -= extraAllowance;
1036 0 : #endif
1037 : return limit;
1038 : }
1039 :
1040 : MOZ_ALWAYS_INLINE uintptr_t
1041 : GetNativeStackLimit(JSContext* cx, int extraAllowance = 0)
1042 : {
1043 : JS::StackKind kind = RunningWithTrustedPrincipals(cx) ? JS::StackForTrustedScript
1044 2 : : JS::StackForUntrustedScript;
1045 2 : return GetNativeStackLimit(cx, kind, extraAllowance);
1046 2 : }
1047 :
1048 : /*
1049 : * These functions return |false| if we are close to using up the C++ stack.
1050 : * They also report an overrecursion error, except for the DontReport variants.
1051 : * The CheckSystemRecursionLimit variant gives us a little extra space so we
1052 : * can ensure that crucial code is able to run. CheckRecursionLimitConservative
1053 : * allows less space than any other check, including a safety buffer (as in, it
1054 : * uses the untrusted limit and subtracts a little more from it).
1055 : */
1056 :
1057 : MOZ_ALWAYS_INLINE bool
1058 : CheckRecursionLimit(JSContext* cx, uintptr_t limit)
1059 0 : {
1060 : int stackDummy;
1061 :
1062 : JS_STACK_OOM_POSSIBLY_FAIL_REPORT();
1063 2 :
1064 : if (!JS_CHECK_STACK_SIZE(limit, &stackDummy)) {
1065 0 : ReportOverRecursed(cx);
1066 0 : return false;
1067 0 : }
1068 : return true;
1069 : }
1070 :
1071 : MOZ_ALWAYS_INLINE bool
1072 : CheckRecursionLimitDontReport(uintptr_t limit)
1073 : {
1074 : int stackDummy;
1075 :
1076 : JS_STACK_OOM_POSSIBLY_FAIL();
1077 0 :
1078 : return JS_CHECK_STACK_SIZE(limit, &stackDummy);
1079 0 : }
1080 :
1081 : MOZ_ALWAYS_INLINE bool
1082 : CheckRecursionLimit(JSContext* cx)
1083 0 : {
1084 : JS_STACK_OOM_POSSIBLY_FAIL_REPORT();
1085 0 :
1086 : // GetNativeStackLimit(cx) is pretty slow because it has to do an uninlined
1087 : // call to RunningWithTrustedPrincipals to determine which stack limit to
1088 : // use. To work around this, check the untrusted limit first to avoid the
1089 : // overhead in most cases.
1090 : uintptr_t untrustedLimit = GetNativeStackLimit(cx, JS::StackForUntrustedScript);
1091 2 : if (MOZ_LIKELY(CheckRecursionLimitDontReport(untrustedLimit)))
1092 0 : return true;
1093 : return CheckRecursionLimit(cx, GetNativeStackLimit(cx));
1094 0 : }
1095 :
1096 : MOZ_ALWAYS_INLINE bool
1097 : CheckRecursionLimitDontReport(JSContext* cx)
1098 3590 : {
1099 : return CheckRecursionLimitDontReport(GetNativeStackLimit(cx));
1100 7180 : }
1101 :
1102 : MOZ_ALWAYS_INLINE bool
1103 : CheckRecursionLimitWithStackPointerDontReport(JSContext* cx, void* sp)
1104 58 : {
1105 : JS_STACK_OOM_POSSIBLY_FAIL();
1106 58 :
1107 : return JS_CHECK_STACK_SIZE(GetNativeStackLimit(cx), sp);
1108 58 : }
1109 :
1110 : MOZ_ALWAYS_INLINE bool
1111 : CheckRecursionLimitWithStackPointer(JSContext* cx, void* sp)
1112 442 : {
1113 : JS_STACK_OOM_POSSIBLY_FAIL_REPORT();
1114 442 :
1115 : if (!JS_CHECK_STACK_SIZE(GetNativeStackLimit(cx), sp)) {
1116 442 : ReportOverRecursed(cx);
1117 0 : return false;
1118 0 : }
1119 : return true;
1120 : }
1121 :
1122 : MOZ_ALWAYS_INLINE bool
1123 : CheckSystemRecursionLimit(JSContext* cx)
1124 : {
1125 : return CheckRecursionLimit(cx, GetNativeStackLimit(cx, JS::StackForSystemCode));
1126 45108 : }
1127 :
1128 : MOZ_ALWAYS_INLINE bool
1129 : CheckRecursionLimitConservative(JSContext* cx)
1130 : {
1131 : return CheckRecursionLimit(cx, GetNativeStackLimit(cx, JS::StackForUntrustedScript,
1132 : -1024 * int(sizeof(size_t))));
1133 : }
1134 :
1135 : MOZ_ALWAYS_INLINE bool
1136 : CheckRecursionLimitConservativeDontReport(JSContext* cx)
1137 : {
1138 : return CheckRecursionLimitDontReport(GetNativeStackLimit(cx, JS::StackForUntrustedScript,
1139 : -1024 * int(sizeof(size_t))));
1140 : }
1141 :
1142 : JS_FRIEND_API(void)
1143 : StartPCCountProfiling(JSContext* cx);
1144 :
1145 : JS_FRIEND_API(void)
1146 : StopPCCountProfiling(JSContext* cx);
1147 :
1148 : JS_FRIEND_API(void)
1149 : PurgePCCounts(JSContext* cx);
1150 :
1151 : JS_FRIEND_API(size_t)
1152 : GetPCCountScriptCount(JSContext* cx);
1153 :
1154 : JS_FRIEND_API(JSString*)
1155 : GetPCCountScriptSummary(JSContext* cx, size_t script);
1156 :
1157 : JS_FRIEND_API(JSString*)
1158 : GetPCCountScriptContents(JSContext* cx, size_t script);
1159 :
1160 : /**
1161 : * Generate lcov trace file content for the current compartment, and allocate a
1162 : * new buffer and return the content in it, the size of the newly allocated
1163 : * content within the buffer would be set to the length out-param.
1164 : *
1165 : * In case of out-of-memory, this function returns nullptr and does not set any
1166 : * value to the length out-param.
1167 : */
1168 : JS_FRIEND_API(char*)
1169 : GetCodeCoverageSummary(JSContext* cx, size_t* length);
1170 :
1171 : typedef void
1172 : (* ActivityCallback)(void* arg, bool active);
1173 :
1174 : /**
1175 : * Sets a callback that is run whenever the runtime goes idle - the
1176 : * last active request ceases - and begins activity - when it was
1177 : * idle and a request begins.
1178 : */
1179 : JS_FRIEND_API(void)
1180 : SetActivityCallback(JSContext* cx, ActivityCallback cb, void* arg);
1181 :
1182 : typedef bool
1183 : (* DOMInstanceClassHasProtoAtDepth)(const Class* instanceClass,
1184 : uint32_t protoID, uint32_t depth);
1185 : struct JSDOMCallbacks {
1186 : DOMInstanceClassHasProtoAtDepth instanceClassMatchesProto;
1187 : };
1188 : typedef struct JSDOMCallbacks DOMCallbacks;
1189 :
1190 : extern JS_FRIEND_API(void)
1191 : SetDOMCallbacks(JSContext* cx, const DOMCallbacks* callbacks);
1192 :
1193 : extern JS_FRIEND_API(const DOMCallbacks*)
1194 : GetDOMCallbacks(JSContext* cx);
1195 :
1196 : extern JS_FRIEND_API(JSObject*)
1197 : GetTestingFunctions(JSContext* cx);
1198 :
1199 : /**
1200 : * Helper to convert FreeOp to JSFreeOp when the definition of FreeOp is not
1201 : * available and the compiler does not know that FreeOp inherits from
1202 : * JSFreeOp.
1203 : */
1204 : inline JSFreeOp*
1205 : CastToJSFreeOp(FreeOp* fop)
1206 : {
1207 : return reinterpret_cast<JSFreeOp*>(fop);
1208 : }
1209 :
1210 : /* Implemented in jsexn.cpp. */
1211 :
1212 : /**
1213 : * Get an error type name from a JSExnType constant.
1214 : * Returns nullptr for invalid arguments and JSEXN_INTERNALERR
1215 : */
1216 : extern JS_FRIEND_API(JSFlatString*)
1217 : GetErrorTypeName(JSContext* cx, int16_t exnType);
1218 :
1219 : extern JS_FRIEND_API(RegExpShared*)
1220 : RegExpToSharedNonInline(JSContext* cx, JS::HandleObject regexp);
1221 :
1222 : /* Implemented in CrossCompartmentWrapper.cpp. */
1223 : typedef enum NukeReferencesToWindow {
1224 : NukeWindowReferences,
1225 : DontNukeWindowReferences
1226 : } NukeReferencesToWindow;
1227 :
1228 : typedef enum NukeReferencesFromTarget {
1229 : NukeAllReferences,
1230 : NukeIncomingReferences,
1231 : } NukeReferencesFromTarget;
1232 :
1233 : /*
1234 : * These filters are designed to be ephemeral stack classes, and thus don't
1235 : * do any rooting or holding of their members.
1236 : */
1237 : struct CompartmentFilter {
1238 : virtual bool match(JS::Compartment* c) const = 0;
1239 : };
1240 :
1241 : struct AllCompartments : public CompartmentFilter {
1242 : virtual bool match(JS::Compartment* c) const override { return true; }
1243 0 : };
1244 :
1245 : struct ContentCompartmentsOnly : public CompartmentFilter {
1246 : virtual bool match(JS::Compartment* c) const override {
1247 0 : return !IsSystemCompartment(c);
1248 0 : }
1249 : };
1250 :
1251 : struct ChromeCompartmentsOnly : public CompartmentFilter {
1252 : virtual bool match(JS::Compartment* c) const override {
1253 0 : return IsSystemCompartment(c);
1254 0 : }
1255 : };
1256 :
1257 : struct SingleCompartment : public CompartmentFilter {
1258 : JS::Compartment* ours;
1259 : explicit SingleCompartment(JS::Compartment* c) : ours(c) {}
1260 : virtual bool match(JS::Compartment* c) const override { return c == ours; }
1261 0 : };
1262 :
1263 : struct CompartmentsWithPrincipals : public CompartmentFilter {
1264 : JSPrincipals* principals;
1265 : explicit CompartmentsWithPrincipals(JSPrincipals* p) : principals(p) {}
1266 : virtual bool match(JS::Compartment* c) const override {
1267 0 : return JS_GetCompartmentPrincipals(c) == principals;
1268 0 : }
1269 : };
1270 :
1271 : extern JS_FRIEND_API(bool)
1272 : NukeCrossCompartmentWrappers(JSContext* cx,
1273 : const CompartmentFilter& sourceFilter,
1274 : JS::Compartment* target,
1275 : NukeReferencesToWindow nukeReferencesToWindow,
1276 : NukeReferencesFromTarget nukeReferencesFromTarget);
1277 :
1278 : /* Specify information about DOMProxy proxies in the DOM, for use by ICs. */
1279 :
1280 : /*
1281 : * The DOMProxyShadowsCheck function will be called to check if the property for
1282 : * id should be gotten from the prototype, or if there is an own property that
1283 : * shadows it.
1284 : * * If ShadowsViaDirectExpando is returned, then the slot at
1285 : * listBaseExpandoSlot contains an expando object which has the property in
1286 : * question.
1287 : * * If ShadowsViaIndirectExpando is returned, then the slot at
1288 : * listBaseExpandoSlot contains a private pointer to an ExpandoAndGeneration
1289 : * and the expando object in the ExpandoAndGeneration has the property in
1290 : * question.
1291 : * * If DoesntShadow is returned then the slot at listBaseExpandoSlot should
1292 : * either be undefined or point to an expando object that would contain the
1293 : * own property.
1294 : * * If DoesntShadowUnique is returned then the slot at listBaseExpandoSlot
1295 : * should contain a private pointer to a ExpandoAndGeneration, which contains
1296 : * a JS::Value that should either be undefined or point to an expando object,
1297 : * and a uint64 value. If that value changes then the IC for getting a
1298 : * property will be invalidated.
1299 : * * If Shadows is returned, that means the property is an own property of the
1300 : * proxy but doesn't live on the expando object.
1301 : */
1302 :
1303 : struct ExpandoAndGeneration {
1304 : ExpandoAndGeneration()
1305 : : expando(JS::UndefinedValue()),
1306 : generation(0)
1307 : {}
1308 :
1309 : void OwnerUnlinked()
1310 : {
1311 : ++generation;
1312 : }
1313 :
1314 : static size_t offsetOfExpando()
1315 : {
1316 : return offsetof(ExpandoAndGeneration, expando);
1317 : }
1318 :
1319 : static size_t offsetOfGeneration()
1320 : {
1321 : return offsetof(ExpandoAndGeneration, generation);
1322 : }
1323 :
1324 : JS::Heap<JS::Value> expando;
1325 : uint64_t generation;
1326 : };
1327 :
1328 : typedef enum DOMProxyShadowsResult {
1329 : ShadowCheckFailed,
1330 : Shadows,
1331 : DoesntShadow,
1332 : DoesntShadowUnique,
1333 : ShadowsViaDirectExpando,
1334 : ShadowsViaIndirectExpando
1335 : } DOMProxyShadowsResult;
1336 : typedef DOMProxyShadowsResult
1337 : (* DOMProxyShadowsCheck)(JSContext* cx, JS::HandleObject object, JS::HandleId id);
1338 : JS_FRIEND_API(void)
1339 : SetDOMProxyInformation(const void* domProxyHandlerFamily,
1340 : DOMProxyShadowsCheck domProxyShadowsCheck);
1341 :
1342 : const void* GetDOMProxyHandlerFamily();
1343 : DOMProxyShadowsCheck GetDOMProxyShadowsCheck();
1344 : inline bool DOMProxyIsShadowing(DOMProxyShadowsResult result) {
1345 : return result == Shadows ||
1346 48 : result == ShadowsViaDirectExpando ||
1347 48 : result == ShadowsViaIndirectExpando;
1348 : }
1349 :
1350 : // Callbacks and other information for use by the JITs when optimizing accesses
1351 : // on xray wrappers.
1352 : struct XrayJitInfo {
1353 : // Test whether a proxy handler is a cross compartment xray with no
1354 : // security checks.
1355 : bool (*isCrossCompartmentXray)(const BaseProxyHandler* handler);
1356 :
1357 : // Test whether xrays with a global object's compartment have expandos of
1358 : // their own, instead of sharing them with Xrays from other compartments.
1359 : bool (*globalHasExclusiveExpandos)(JSObject* obj);
1360 :
1361 : // Proxy reserved slot used by xrays in sandboxes to store their holder
1362 : // object.
1363 : size_t xrayHolderSlot;
1364 :
1365 : // Reserved slot used by xray holders to store the xray's expando object.
1366 : size_t holderExpandoSlot;
1367 :
1368 : // Reserved slot used by xray expandos to store a custom prototype.
1369 : size_t expandoProtoSlot;
1370 : };
1371 :
1372 : JS_FRIEND_API(void)
1373 : SetXrayJitInfo(XrayJitInfo* info);
1374 :
1375 : XrayJitInfo*
1376 : GetXrayJitInfo();
1377 :
1378 : /* Implemented in jsdate.cpp. */
1379 :
1380 : /** Detect whether the internal date value is NaN. */
1381 : extern JS_FRIEND_API(bool)
1382 : DateIsValid(JSContext* cx, JS::HandleObject obj, bool* isValid);
1383 :
1384 : extern JS_FRIEND_API(bool)
1385 : DateGetMsecSinceEpoch(JSContext* cx, JS::HandleObject obj, double* msecSinceEpoch);
1386 :
1387 : } /* namespace js */
1388 :
1389 : typedef enum JSErrNum {
1390 : #define MSG_DEF(name, count, exception, format) \
1391 : name,
1392 : #include "js.msg"
1393 : #undef MSG_DEF
1394 : JSErr_Limit
1395 : } JSErrNum;
1396 :
1397 : namespace js {
1398 :
1399 : /* Implemented in vm/JSContext.cpp. */
1400 :
1401 : extern JS_FRIEND_API(const JSErrorFormatString*)
1402 : GetErrorMessage(void* userRef, const unsigned errorNumber);
1403 :
1404 : // AutoStableStringChars is here so we can use it in ErrorReport. It
1405 : // should get moved out of here if we can manage it. See bug 1040316.
1406 :
1407 : /**
1408 : * This class provides safe access to a string's chars across a GC. Once
1409 : * we allocate strings and chars in the nursery (bug 903519), this class
1410 : * will have to make a copy of the string's chars if they are allocated
1411 : * in the nursery, so it's best to avoid using this class unless you really
1412 : * need it. It's usually more efficient to use the latin1Chars/twoByteChars
1413 : * JSString methods and often the code can be rewritten so that only indexes
1414 : * instead of char pointers are used in parts of the code that can GC.
1415 : */
1416 : class MOZ_STACK_CLASS JS_FRIEND_API(AutoStableStringChars)
1417 2 : {
1418 : /*
1419 : * When copying string char, use this many bytes of inline storage. This is
1420 : * chosen to allow the inline string types to be copied without allocating.
1421 : * This is asserted in AutoStableStringChars::allocOwnChars.
1422 : */
1423 : static const size_t InlineCapacity = 24;
1424 :
1425 : /* Ensure the string is kept alive while we're using its chars. */
1426 : JS::RootedString s_;
1427 : union {
1428 : const char16_t* twoByteChars_;
1429 : const JS::Latin1Char* latin1Chars_;
1430 : };
1431 : mozilla::Maybe<Vector<uint8_t, InlineCapacity>> ownChars_;
1432 : enum State { Uninitialized, Latin1, TwoByte };
1433 : State state_;
1434 :
1435 : public:
1436 : explicit AutoStableStringChars(JSContext* cx)
1437 : : s_(cx), state_(Uninitialized)
1438 2 : {}
1439 :
1440 : MOZ_MUST_USE
1441 : bool init(JSContext* cx, JSString* s);
1442 :
1443 : /* Like init(), but Latin1 chars are inflated to TwoByte. */
1444 : MOZ_MUST_USE
1445 : bool initTwoByte(JSContext* cx, JSString* s);
1446 :
1447 : bool isLatin1() const { return state_ == Latin1; }
1448 : bool isTwoByte() const { return state_ == TwoByte; }
1449 :
1450 : const JS::Latin1Char* latin1Chars() const {
1451 : MOZ_ASSERT(state_ == Latin1);
1452 : return latin1Chars_;
1453 : }
1454 : const char16_t* twoByteChars() const {
1455 : MOZ_ASSERT(state_ == TwoByte);
1456 2 : return twoByteChars_;
1457 : }
1458 :
1459 : mozilla::Range<const JS::Latin1Char> latin1Range() const {
1460 142 : MOZ_ASSERT(state_ == Latin1);
1461 142 : return mozilla::Range<const JS::Latin1Char>(latin1Chars_,
1462 142 : GetStringLength(s_));
1463 568 : }
1464 :
1465 : mozilla::Range<const char16_t> twoByteRange() const {
1466 94 : MOZ_ASSERT(state_ == TwoByte);
1467 94 : return mozilla::Range<const char16_t>(twoByteChars_,
1468 94 : GetStringLength(s_));
1469 376 : }
1470 :
1471 : /* If we own the chars, transfer ownership to the caller. */
1472 : bool maybeGiveOwnershipToCaller() {
1473 86 : MOZ_ASSERT(state_ != Uninitialized);
1474 86 : if (!ownChars_.isSome() || !ownChars_->extractRawBuffer())
1475 86 : return false;
1476 : state_ = Uninitialized;
1477 0 : ownChars_.reset();
1478 0 : return true;
1479 0 : }
1480 :
1481 : private:
1482 : AutoStableStringChars(const AutoStableStringChars& other) = delete;
1483 : void operator=(const AutoStableStringChars& other) = delete;
1484 :
1485 : bool baseIsInline(JS::Handle<JSLinearString*> linearString);
1486 : template <typename T> T* allocOwnChars(JSContext* cx, size_t count);
1487 : bool copyLatin1Chars(JSContext* cx, JS::Handle<JSLinearString*> linearString);
1488 : bool copyTwoByteChars(JSContext* cx, JS::Handle<JSLinearString*> linearString);
1489 : bool copyAndInflateLatin1Chars(JSContext*, JS::Handle<JSLinearString*> linearString);
1490 : };
1491 :
1492 : struct MOZ_STACK_CLASS JS_FRIEND_API(ErrorReport)
1493 : {
1494 : explicit ErrorReport(JSContext* cx);
1495 : ~ErrorReport();
1496 :
1497 : enum SniffingBehavior {
1498 : WithSideEffects,
1499 : NoSideEffects
1500 : };
1501 :
1502 : /**
1503 : * Generate a JSErrorReport from the provided thrown value.
1504 : *
1505 : * If the value is a (possibly wrapped) Error object, the JSErrorReport will
1506 : * be exactly initialized from the Error object's information, without
1507 : * observable side effects. (The Error object's JSErrorReport is reused, if
1508 : * it has one.)
1509 : *
1510 : * Otherwise various attempts are made to derive JSErrorReport information
1511 : * from |exn| and from the current execution state. This process is
1512 : * *definitely* inconsistent with any standard, and particulars of the
1513 : * behavior implemented here generally shouldn't be relied upon.
1514 : *
1515 : * If the value of |sniffingBehavior| is |WithSideEffects|, some of these
1516 : * attempts *may* invoke user-configurable behavior when |exn| is an object:
1517 : * converting |exn| to a string, detecting and getting properties on |exn|,
1518 : * accessing |exn|'s prototype chain, and others are possible. Users *must*
1519 : * tolerate |ErrorReport::init| potentially having arbitrary effects. Any
1520 : * exceptions thrown by these operations will be caught and silently
1521 : * ignored, and "default" values will be substituted into the JSErrorReport.
1522 : *
1523 : * But if the value of |sniffingBehavior| is |NoSideEffects|, these attempts
1524 : * *will not* invoke any observable side effects. The JSErrorReport will
1525 : * simply contain fewer, less precise details.
1526 : *
1527 : * Unlike some functions involved in error handling, this function adheres
1528 : * to the usual JSAPI return value error behavior.
1529 : */
1530 : bool init(JSContext* cx, JS::HandleValue exn,
1531 : SniffingBehavior sniffingBehavior);
1532 :
1533 : JSErrorReport* report()
1534 : {
1535 : return reportp;
1536 : }
1537 :
1538 : const JS::ConstUTF8CharsZ toStringResult()
1539 : {
1540 : return toStringResult_;
1541 : }
1542 :
1543 : private:
1544 : // More or less an equivalent of JS_ReportErrorNumber/js::ReportErrorNumberVA
1545 : // but fills in an ErrorReport instead of reporting it. Uses varargs to
1546 : // make it simpler to call js::ExpandErrorArgumentsVA.
1547 : //
1548 : // Returns false if we fail to actually populate the ErrorReport
1549 : // for some reason (probably out of memory).
1550 : bool populateUncaughtExceptionReportUTF8(JSContext* cx, ...);
1551 : bool populateUncaughtExceptionReportUTF8VA(JSContext* cx, va_list ap);
1552 :
1553 : // Reports exceptions from add-on scopes to telemetry.
1554 : void ReportAddonExceptionToTelemetry(JSContext* cx);
1555 :
1556 : // We may have a provided JSErrorReport, so need a way to represent that.
1557 : JSErrorReport* reportp;
1558 :
1559 : // Or we may need to synthesize a JSErrorReport one of our own.
1560 : JSErrorReport ownedReport;
1561 :
1562 : // And we have a string to maybe keep alive that has pointers into
1563 : // it from ownedReport.
1564 : JS::RootedString str;
1565 :
1566 : // And keep its chars alive too.
1567 : AutoStableStringChars strChars;
1568 :
1569 : // And we need to root our exception value.
1570 : JS::RootedObject exnObject;
1571 :
1572 : // And for our filename.
1573 : JSAutoByteString filename;
1574 :
1575 : // We may have a result of error.toString().
1576 : // FIXME: We should not call error.toString(), since it could have side
1577 : // effect (see bug 633623).
1578 : JS::ConstUTF8CharsZ toStringResult_;
1579 : JSAutoByteString toStringResultBytesStorage;
1580 : };
1581 :
1582 : /* Implemented in vm/StructuredClone.cpp. */
1583 : extern JS_FRIEND_API(uint64_t)
1584 : GetSCOffset(JSStructuredCloneWriter* writer);
1585 :
1586 : namespace Scalar {
1587 :
1588 : /**
1589 : * Scalar types that can appear in typed arrays and typed objects. The enum
1590 : * values must to be kept in sync with the JS_SCALARTYPEREPR_ constants, as
1591 : * well as the TypedArrayObject::classes and TypedArrayObject::protoClasses
1592 : * definitions.
1593 : */
1594 : enum Type {
1595 : Int8 = 0,
1596 : Uint8,
1597 : Int16,
1598 : Uint16,
1599 : Int32,
1600 : Uint32,
1601 : Float32,
1602 : Float64,
1603 :
1604 : /**
1605 : * Special type that is a uint8_t, but assignments are clamped to [0, 256).
1606 : * Treat the raw data type as a uint8_t.
1607 : */
1608 : Uint8Clamped,
1609 :
1610 : /**
1611 : * Types that don't have their own TypedArray equivalent, for now.
1612 : */
1613 : MaxTypedArrayViewType,
1614 :
1615 : Int64,
1616 : Float32x4,
1617 : Int8x16,
1618 : Int16x8,
1619 : Int32x4
1620 : };
1621 :
1622 : static inline size_t
1623 : byteSize(Type atype)
1624 2 : {
1625 : switch (atype) {
1626 2 : case Int8:
1627 : case Uint8:
1628 : case Uint8Clamped:
1629 : return 1;
1630 : case Int16:
1631 : case Uint16:
1632 : return 2;
1633 2 : case Int32:
1634 : case Uint32:
1635 : case Float32:
1636 : return 4;
1637 2 : case Int64:
1638 : case Float64:
1639 : return 8;
1640 2 : case Int8x16:
1641 : case Int16x8:
1642 : case Int32x4:
1643 : case Float32x4:
1644 : return 16;
1645 0 : default:
1646 : MOZ_CRASH("invalid scalar type");
1647 0 : }
1648 : }
1649 :
1650 : static inline bool
1651 : isSignedIntType(Type atype) {
1652 0 : switch (atype) {
1653 : case Int8:
1654 : case Int16:
1655 : case Int32:
1656 : case Int64:
1657 : case Int8x16:
1658 : case Int16x8:
1659 : case Int32x4:
1660 : return true;
1661 : case Uint8:
1662 : case Uint8Clamped:
1663 : case Uint16:
1664 : case Uint32:
1665 : case Float32:
1666 : case Float64:
1667 : case Float32x4:
1668 : return false;
1669 : default:
1670 : MOZ_CRASH("invalid scalar type");
1671 0 : }
1672 : }
1673 :
1674 : static inline bool
1675 : isSimdType(Type atype) {
1676 0 : switch (atype) {
1677 : case Int8:
1678 : case Uint8:
1679 : case Uint8Clamped:
1680 : case Int16:
1681 : case Uint16:
1682 : case Int32:
1683 : case Uint32:
1684 : case Int64:
1685 : case Float32:
1686 : case Float64:
1687 : return false;
1688 : case Int8x16:
1689 : case Int16x8:
1690 : case Int32x4:
1691 : case Float32x4:
1692 : return true;
1693 : case MaxTypedArrayViewType:
1694 : break;
1695 : }
1696 : MOZ_CRASH("invalid scalar type");
1697 0 : }
1698 :
1699 : static inline size_t
1700 : scalarByteSize(Type atype) {
1701 0 : switch (atype) {
1702 0 : case Int8x16:
1703 : return 1;
1704 : case Int16x8:
1705 : return 2;
1706 0 : case Int32x4:
1707 : case Float32x4:
1708 : return 4;
1709 0 : case Int8:
1710 : case Uint8:
1711 : case Uint8Clamped:
1712 : case Int16:
1713 : case Uint16:
1714 : case Int32:
1715 : case Uint32:
1716 : case Int64:
1717 : case Float32:
1718 : case Float64:
1719 : case MaxTypedArrayViewType:
1720 : break;
1721 : }
1722 : MOZ_CRASH("invalid simd type");
1723 0 : }
1724 :
1725 : } /* namespace Scalar */
1726 : } /* namespace js */
1727 :
1728 : /*
1729 : * Create a new typed array with nelements elements.
1730 : *
1731 : * These functions (except the WithBuffer variants) fill in the array with zeros.
1732 : */
1733 :
1734 : extern JS_FRIEND_API(JSObject*)
1735 : JS_NewInt8Array(JSContext* cx, uint32_t nelements);
1736 : extern JS_FRIEND_API(JSObject*)
1737 : JS_NewUint8Array(JSContext* cx, uint32_t nelements);
1738 : extern JS_FRIEND_API(JSObject*)
1739 : JS_NewUint8ClampedArray(JSContext* cx, uint32_t nelements);
1740 : extern JS_FRIEND_API(JSObject*)
1741 : JS_NewInt16Array(JSContext* cx, uint32_t nelements);
1742 : extern JS_FRIEND_API(JSObject*)
1743 : JS_NewUint16Array(JSContext* cx, uint32_t nelements);
1744 : extern JS_FRIEND_API(JSObject*)
1745 : JS_NewInt32Array(JSContext* cx, uint32_t nelements);
1746 : extern JS_FRIEND_API(JSObject*)
1747 : JS_NewUint32Array(JSContext* cx, uint32_t nelements);
1748 : extern JS_FRIEND_API(JSObject*)
1749 : JS_NewFloat32Array(JSContext* cx, uint32_t nelements);
1750 : extern JS_FRIEND_API(JSObject*)
1751 : JS_NewFloat64Array(JSContext* cx, uint32_t nelements);
1752 :
1753 : /*
1754 : * Create a new typed array and copy in values from the given object. The
1755 : * object is used as if it were an array; that is, the new array (if
1756 : * successfully created) will have length given by array.length, and its
1757 : * elements will be those specified by array[0], array[1], and so on, after
1758 : * conversion to the typed array element type.
1759 : */
1760 :
1761 : extern JS_FRIEND_API(JSObject*)
1762 : JS_NewInt8ArrayFromArray(JSContext* cx, JS::HandleObject array);
1763 : extern JS_FRIEND_API(JSObject*)
1764 : JS_NewUint8ArrayFromArray(JSContext* cx, JS::HandleObject array);
1765 : extern JS_FRIEND_API(JSObject*)
1766 : JS_NewUint8ClampedArrayFromArray(JSContext* cx, JS::HandleObject array);
1767 : extern JS_FRIEND_API(JSObject*)
1768 : JS_NewInt16ArrayFromArray(JSContext* cx, JS::HandleObject array);
1769 : extern JS_FRIEND_API(JSObject*)
1770 : JS_NewUint16ArrayFromArray(JSContext* cx, JS::HandleObject array);
1771 : extern JS_FRIEND_API(JSObject*)
1772 : JS_NewInt32ArrayFromArray(JSContext* cx, JS::HandleObject array);
1773 : extern JS_FRIEND_API(JSObject*)
1774 : JS_NewUint32ArrayFromArray(JSContext* cx, JS::HandleObject array);
1775 : extern JS_FRIEND_API(JSObject*)
1776 : JS_NewFloat32ArrayFromArray(JSContext* cx, JS::HandleObject array);
1777 : extern JS_FRIEND_API(JSObject*)
1778 : JS_NewFloat64ArrayFromArray(JSContext* cx, JS::HandleObject array);
1779 :
1780 : /*
1781 : * Create a new typed array using the given ArrayBuffer or
1782 : * SharedArrayBuffer for storage. The length value is optional; if -1
1783 : * is passed, enough elements to use up the remainder of the byte
1784 : * array is used as the default value.
1785 : */
1786 :
1787 : extern JS_FRIEND_API(JSObject*)
1788 : JS_NewInt8ArrayWithBuffer(JSContext* cx, JS::HandleObject arrayBuffer,
1789 : uint32_t byteOffset, int32_t length);
1790 : extern JS_FRIEND_API(JSObject*)
1791 : JS_NewUint8ArrayWithBuffer(JSContext* cx, JS::HandleObject arrayBuffer,
1792 : uint32_t byteOffset, int32_t length);
1793 : extern JS_FRIEND_API(JSObject*)
1794 : JS_NewUint8ClampedArrayWithBuffer(JSContext* cx, JS::HandleObject arrayBuffer,
1795 : uint32_t byteOffset, int32_t length);
1796 : extern JS_FRIEND_API(JSObject*)
1797 : JS_NewInt16ArrayWithBuffer(JSContext* cx, JS::HandleObject arrayBuffer,
1798 : uint32_t byteOffset, int32_t length);
1799 : extern JS_FRIEND_API(JSObject*)
1800 : JS_NewUint16ArrayWithBuffer(JSContext* cx, JS::HandleObject arrayBuffer,
1801 : uint32_t byteOffset, int32_t length);
1802 : extern JS_FRIEND_API(JSObject*)
1803 : JS_NewInt32ArrayWithBuffer(JSContext* cx, JS::HandleObject arrayBuffer,
1804 : uint32_t byteOffset, int32_t length);
1805 : extern JS_FRIEND_API(JSObject*)
1806 : JS_NewUint32ArrayWithBuffer(JSContext* cx, JS::HandleObject arrayBuffer,
1807 : uint32_t byteOffset, int32_t length);
1808 : extern JS_FRIEND_API(JSObject*)
1809 : JS_NewFloat32ArrayWithBuffer(JSContext* cx, JS::HandleObject arrayBuffer,
1810 : uint32_t byteOffset, int32_t length);
1811 : extern JS_FRIEND_API(JSObject*)
1812 : JS_NewFloat64ArrayWithBuffer(JSContext* cx, JS::HandleObject arrayBuffer,
1813 : uint32_t byteOffset, int32_t length);
1814 :
1815 : /**
1816 : * Create a new SharedArrayBuffer with the given byte length. This
1817 : * may only be called if
1818 : * JS::RealmCreationOptionsRef(cx).getSharedMemoryAndAtomicsEnabled() is
1819 : * true.
1820 : */
1821 : extern JS_FRIEND_API(JSObject*)
1822 : JS_NewSharedArrayBuffer(JSContext* cx, uint32_t nbytes);
1823 :
1824 : /**
1825 : * Create a new ArrayBuffer with the given byte length.
1826 : */
1827 : extern JS_FRIEND_API(JSObject*)
1828 : JS_NewArrayBuffer(JSContext* cx, uint32_t nbytes);
1829 :
1830 : /**
1831 : * Check whether obj supports JS_GetTypedArray* APIs. Note that this may return
1832 : * false if a security wrapper is encountered that denies the unwrapping. If
1833 : * this test or one of the JS_Is*Array tests succeeds, then it is safe to call
1834 : * the various accessor JSAPI calls defined below.
1835 : */
1836 : extern JS_FRIEND_API(bool)
1837 : JS_IsTypedArrayObject(JSObject* obj);
1838 :
1839 : /**
1840 : * Check whether obj supports JS_GetArrayBufferView* APIs. Note that this may
1841 : * return false if a security wrapper is encountered that denies the
1842 : * unwrapping. If this test or one of the more specific tests succeeds, then it
1843 : * is safe to call the various ArrayBufferView accessor JSAPI calls defined
1844 : * below.
1845 : */
1846 : extern JS_FRIEND_API(bool)
1847 : JS_IsArrayBufferViewObject(JSObject* obj);
1848 :
1849 : /*
1850 : * Test for specific typed array types (ArrayBufferView subtypes)
1851 : */
1852 :
1853 : extern JS_FRIEND_API(bool)
1854 : JS_IsInt8Array(JSObject* obj);
1855 : extern JS_FRIEND_API(bool)
1856 : JS_IsUint8Array(JSObject* obj);
1857 : extern JS_FRIEND_API(bool)
1858 : JS_IsUint8ClampedArray(JSObject* obj);
1859 : extern JS_FRIEND_API(bool)
1860 : JS_IsInt16Array(JSObject* obj);
1861 : extern JS_FRIEND_API(bool)
1862 : JS_IsUint16Array(JSObject* obj);
1863 : extern JS_FRIEND_API(bool)
1864 : JS_IsInt32Array(JSObject* obj);
1865 : extern JS_FRIEND_API(bool)
1866 : JS_IsUint32Array(JSObject* obj);
1867 : extern JS_FRIEND_API(bool)
1868 : JS_IsFloat32Array(JSObject* obj);
1869 : extern JS_FRIEND_API(bool)
1870 : JS_IsFloat64Array(JSObject* obj);
1871 :
1872 : /**
1873 : * Return the isShared flag of a typed array, which denotes whether
1874 : * the underlying buffer is a SharedArrayBuffer.
1875 : *
1876 : * |obj| must have passed a JS_IsTypedArrayObject/JS_Is*Array test, or somehow
1877 : * be known that it would pass such a test: it is a typed array or a wrapper of
1878 : * a typed array, and the unwrapping will succeed.
1879 : */
1880 : extern JS_FRIEND_API(bool)
1881 : JS_GetTypedArraySharedness(JSObject* obj);
1882 :
1883 : /*
1884 : * Test for specific typed array types (ArrayBufferView subtypes) and return
1885 : * the unwrapped object if so, else nullptr. Never throws.
1886 : */
1887 :
1888 : namespace js {
1889 :
1890 : extern JS_FRIEND_API(JSObject*)
1891 : UnwrapInt8Array(JSObject* obj);
1892 : extern JS_FRIEND_API(JSObject*)
1893 : UnwrapUint8Array(JSObject* obj);
1894 : extern JS_FRIEND_API(JSObject*)
1895 : UnwrapUint8ClampedArray(JSObject* obj);
1896 : extern JS_FRIEND_API(JSObject*)
1897 : UnwrapInt16Array(JSObject* obj);
1898 : extern JS_FRIEND_API(JSObject*)
1899 : UnwrapUint16Array(JSObject* obj);
1900 : extern JS_FRIEND_API(JSObject*)
1901 : UnwrapInt32Array(JSObject* obj);
1902 : extern JS_FRIEND_API(JSObject*)
1903 : UnwrapUint32Array(JSObject* obj);
1904 : extern JS_FRIEND_API(JSObject*)
1905 : UnwrapFloat32Array(JSObject* obj);
1906 : extern JS_FRIEND_API(JSObject*)
1907 : UnwrapFloat64Array(JSObject* obj);
1908 :
1909 : extern JS_FRIEND_API(JSObject*)
1910 : UnwrapArrayBuffer(JSObject* obj);
1911 :
1912 : extern JS_FRIEND_API(JSObject*)
1913 : UnwrapArrayBufferView(JSObject* obj);
1914 :
1915 : extern JS_FRIEND_API(JSObject*)
1916 : UnwrapSharedArrayBuffer(JSObject* obj);
1917 :
1918 : extern JS_FRIEND_API(JSObject*)
1919 : UnwrapReadableStream(JSObject* obj);
1920 :
1921 :
1922 : namespace detail {
1923 :
1924 : extern JS_FRIEND_DATA(const Class* const) Int8ArrayClassPtr;
1925 : extern JS_FRIEND_DATA(const Class* const) Uint8ArrayClassPtr;
1926 : extern JS_FRIEND_DATA(const Class* const) Uint8ClampedArrayClassPtr;
1927 : extern JS_FRIEND_DATA(const Class* const) Int16ArrayClassPtr;
1928 : extern JS_FRIEND_DATA(const Class* const) Uint16ArrayClassPtr;
1929 : extern JS_FRIEND_DATA(const Class* const) Int32ArrayClassPtr;
1930 : extern JS_FRIEND_DATA(const Class* const) Uint32ArrayClassPtr;
1931 : extern JS_FRIEND_DATA(const Class* const) Float32ArrayClassPtr;
1932 : extern JS_FRIEND_DATA(const Class* const) Float64ArrayClassPtr;
1933 :
1934 : const size_t TypedArrayLengthSlot = 1;
1935 :
1936 : } // namespace detail
1937 :
1938 : #define JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Type, type) \
1939 : inline void \
1940 : Get ## Type ## ArrayLengthAndData(JSObject* obj, uint32_t* length, bool* isSharedMemory, type** data) \
1941 : { \
1942 : MOZ_ASSERT(GetObjectClass(obj) == detail::Type ## ArrayClassPtr); \
1943 : const JS::Value& lenSlot = GetReservedSlot(obj, detail::TypedArrayLengthSlot); \
1944 : *length = mozilla::AssertedCast<uint32_t>(lenSlot.toInt32()); \
1945 : *isSharedMemory = JS_GetTypedArraySharedness(obj); \
1946 : *data = static_cast<type*>(GetObjectPrivate(obj)); \
1947 : }
1948 :
1949 : JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Int8, int8_t)
1950 : JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Uint8, uint8_t)
1951 : JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Uint8Clamped, uint8_t)
1952 : JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Int16, int16_t)
1953 : JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Uint16, uint16_t)
1954 : JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Int32, int32_t)
1955 : JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Uint32, uint32_t)
1956 : JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Float32, float)
1957 : JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Float64, double)
1958 :
1959 : #undef JS_DEFINE_DATA_AND_LENGTH_ACCESSOR
1960 :
1961 : // This one isn't inlined because it's rather tricky (by dint of having to deal
1962 : // with a dozen-plus classes and varying slot layouts.
1963 : extern JS_FRIEND_API(void)
1964 : GetArrayBufferViewLengthAndData(JSObject* obj, uint32_t* length, bool* isSharedMemory, uint8_t** data);
1965 :
1966 : // This one isn't inlined because there are a bunch of different ArrayBuffer
1967 : // classes that would have to be individually handled here.
1968 : //
1969 : // There is an isShared out argument for API consistency (eases use from DOM).
1970 : // It will always be set to false.
1971 : extern JS_FRIEND_API(void)
1972 : GetArrayBufferLengthAndData(JSObject* obj, uint32_t* length, bool* isSharedMemory, uint8_t** data);
1973 :
1974 : // Ditto for SharedArrayBuffer.
1975 : //
1976 : // There is an isShared out argument for API consistency (eases use from DOM).
1977 : // It will always be set to true.
1978 : extern JS_FRIEND_API(void)
1979 : GetSharedArrayBufferLengthAndData(JSObject* obj, uint32_t* length, bool* isSharedMemory, uint8_t** data);
1980 :
1981 : } // namespace js
1982 :
1983 : JS_FRIEND_API(uint8_t*)
1984 : JS_GetSharedArrayBufferData(JSObject* obj, bool* isSharedMemory, const JS::AutoRequireNoGC&);
1985 :
1986 : /*
1987 : * Unwrap Typed arrays all at once. Return nullptr without throwing if the
1988 : * object cannot be viewed as the correct typed array, or the typed array
1989 : * object on success, filling both outparameters.
1990 : */
1991 : extern JS_FRIEND_API(JSObject*)
1992 : JS_GetObjectAsInt8Array(JSObject* obj, uint32_t* length, bool* isSharedMemory, int8_t** data);
1993 : extern JS_FRIEND_API(JSObject*)
1994 : JS_GetObjectAsUint8Array(JSObject* obj, uint32_t* length, bool* isSharedMemory, uint8_t** data);
1995 : extern JS_FRIEND_API(JSObject*)
1996 : JS_GetObjectAsUint8ClampedArray(JSObject* obj, uint32_t* length, bool* isSharedMemory, uint8_t** data);
1997 : extern JS_FRIEND_API(JSObject*)
1998 : JS_GetObjectAsInt16Array(JSObject* obj, uint32_t* length, bool* isSharedMemory, int16_t** data);
1999 : extern JS_FRIEND_API(JSObject*)
2000 : JS_GetObjectAsUint16Array(JSObject* obj, uint32_t* length, bool* isSharedMemory, uint16_t** data);
2001 : extern JS_FRIEND_API(JSObject*)
2002 : JS_GetObjectAsInt32Array(JSObject* obj, uint32_t* length, bool* isSharedMemory, int32_t** data);
2003 : extern JS_FRIEND_API(JSObject*)
2004 : JS_GetObjectAsUint32Array(JSObject* obj, uint32_t* length, bool* isSharedMemory, uint32_t** data);
2005 : extern JS_FRIEND_API(JSObject*)
2006 : JS_GetObjectAsFloat32Array(JSObject* obj, uint32_t* length, bool* isSharedMemory, float** data);
2007 : extern JS_FRIEND_API(JSObject*)
2008 : JS_GetObjectAsFloat64Array(JSObject* obj, uint32_t* length, bool* isSharedMemory, double** data);
2009 : extern JS_FRIEND_API(JSObject*)
2010 : JS_GetObjectAsArrayBufferView(JSObject* obj, uint32_t* length, bool* isSharedMemory, uint8_t** data);
2011 :
2012 : /*
2013 : * Unwrap an ArrayBuffer, return nullptr if it's a different type.
2014 : */
2015 : extern JS_FRIEND_API(JSObject*)
2016 : JS_GetObjectAsArrayBuffer(JSObject* obj, uint32_t* length, uint8_t** data);
2017 :
2018 : /*
2019 : * Get the type of elements in a typed array, or MaxTypedArrayViewType if a DataView.
2020 : *
2021 : * |obj| must have passed a JS_IsArrayBufferView/JS_Is*Array test, or somehow
2022 : * be known that it would pass such a test: it is an ArrayBufferView or a
2023 : * wrapper of an ArrayBufferView, and the unwrapping will succeed.
2024 : */
2025 : extern JS_FRIEND_API(js::Scalar::Type)
2026 : JS_GetArrayBufferViewType(JSObject* obj);
2027 :
2028 : extern JS_FRIEND_API(js::Scalar::Type)
2029 : JS_GetSharedArrayBufferViewType(JSObject* obj);
2030 :
2031 : /*
2032 : * Check whether obj supports the JS_GetArrayBuffer* APIs. Note that this may
2033 : * return false if a security wrapper is encountered that denies the
2034 : * unwrapping. If this test succeeds, then it is safe to call the various
2035 : * accessor JSAPI calls defined below.
2036 : */
2037 : extern JS_FRIEND_API(bool)
2038 : JS_IsArrayBufferObject(JSObject* obj);
2039 :
2040 : extern JS_FRIEND_API(bool)
2041 : JS_IsSharedArrayBufferObject(JSObject* obj);
2042 :
2043 : /**
2044 : * Return the available byte length of an array buffer.
2045 : *
2046 : * |obj| must have passed a JS_IsArrayBufferObject test, or somehow be known
2047 : * that it would pass such a test: it is an ArrayBuffer or a wrapper of an
2048 : * ArrayBuffer, and the unwrapping will succeed.
2049 : */
2050 : extern JS_FRIEND_API(uint32_t)
2051 : JS_GetArrayBufferByteLength(JSObject* obj);
2052 :
2053 : extern JS_FRIEND_API(uint32_t)
2054 : JS_GetSharedArrayBufferByteLength(JSObject* obj);
2055 :
2056 : /**
2057 : * Return true if the arrayBuffer contains any data. This will return false for
2058 : * ArrayBuffer.prototype and detached ArrayBuffers.
2059 : *
2060 : * |obj| must have passed a JS_IsArrayBufferObject test, or somehow be known
2061 : * that it would pass such a test: it is an ArrayBuffer or a wrapper of an
2062 : * ArrayBuffer, and the unwrapping will succeed.
2063 : */
2064 : extern JS_FRIEND_API(bool)
2065 : JS_ArrayBufferHasData(JSObject* obj);
2066 :
2067 : /**
2068 : * Return a pointer to the start of the data referenced by a typed array. The
2069 : * data is still owned by the typed array, and should not be modified on
2070 : * another thread. Furthermore, the pointer can become invalid on GC (if the
2071 : * data is small and fits inside the array's GC header), so callers must take
2072 : * care not to hold on across anything that could GC.
2073 : *
2074 : * |obj| must have passed a JS_IsArrayBufferObject test, or somehow be known
2075 : * that it would pass such a test: it is an ArrayBuffer or a wrapper of an
2076 : * ArrayBuffer, and the unwrapping will succeed.
2077 : *
2078 : * |*isSharedMemory| will be set to false, the argument is present to simplify
2079 : * its use from code that also interacts with SharedArrayBuffer.
2080 : */
2081 : extern JS_FRIEND_API(uint8_t*)
2082 : JS_GetArrayBufferData(JSObject* obj, bool* isSharedMemory, const JS::AutoRequireNoGC&);
2083 :
2084 : /**
2085 : * Check whether the obj is ArrayBufferObject and memory mapped. Note that this
2086 : * may return false if a security wrapper is encountered that denies the
2087 : * unwrapping.
2088 : */
2089 : extern JS_FRIEND_API(bool)
2090 : JS_IsMappedArrayBufferObject(JSObject* obj);
2091 :
2092 : /**
2093 : * Return the number of elements in a typed array.
2094 : *
2095 : * |obj| must have passed a JS_IsTypedArrayObject/JS_Is*Array test, or somehow
2096 : * be known that it would pass such a test: it is a typed array or a wrapper of
2097 : * a typed array, and the unwrapping will succeed.
2098 : */
2099 : extern JS_FRIEND_API(uint32_t)
2100 : JS_GetTypedArrayLength(JSObject* obj);
2101 :
2102 : /**
2103 : * Return the byte offset from the start of an array buffer to the start of a
2104 : * typed array view.
2105 : *
2106 : * |obj| must have passed a JS_IsTypedArrayObject/JS_Is*Array test, or somehow
2107 : * be known that it would pass such a test: it is a typed array or a wrapper of
2108 : * a typed array, and the unwrapping will succeed.
2109 : */
2110 : extern JS_FRIEND_API(uint32_t)
2111 : JS_GetTypedArrayByteOffset(JSObject* obj);
2112 :
2113 : /**
2114 : * Return the byte length of a typed array.
2115 : *
2116 : * |obj| must have passed a JS_IsTypedArrayObject/JS_Is*Array test, or somehow
2117 : * be known that it would pass such a test: it is a typed array or a wrapper of
2118 : * a typed array, and the unwrapping will succeed.
2119 : */
2120 : extern JS_FRIEND_API(uint32_t)
2121 : JS_GetTypedArrayByteLength(JSObject* obj);
2122 :
2123 : /**
2124 : * Check whether obj supports JS_ArrayBufferView* APIs. Note that this may
2125 : * return false if a security wrapper is encountered that denies the
2126 : * unwrapping.
2127 : */
2128 : extern JS_FRIEND_API(bool)
2129 : JS_IsArrayBufferViewObject(JSObject* obj);
2130 :
2131 : /**
2132 : * More generic name for JS_GetTypedArrayByteLength to cover DataViews as well
2133 : */
2134 : extern JS_FRIEND_API(uint32_t)
2135 : JS_GetArrayBufferViewByteLength(JSObject* obj);
2136 :
2137 : /**
2138 : * More generic name for JS_GetTypedArrayByteOffset to cover DataViews as well
2139 : */
2140 : extern JS_FRIEND_API(uint32_t)
2141 : JS_GetArrayBufferViewByteOffset(JSObject* obj);
2142 :
2143 : /*
2144 : * Return a pointer to the start of the data referenced by a typed array. The
2145 : * data is still owned by the typed array, and should not be modified on
2146 : * another thread. Furthermore, the pointer can become invalid on GC (if the
2147 : * data is small and fits inside the array's GC header), so callers must take
2148 : * care not to hold on across anything that could GC.
2149 : *
2150 : * |obj| must have passed a JS_Is*Array test, or somehow be known that it would
2151 : * pass such a test: it is a typed array or a wrapper of a typed array, and the
2152 : * unwrapping will succeed.
2153 : *
2154 : * |*isSharedMemory| will be set to true if the typed array maps a
2155 : * SharedArrayBuffer, otherwise to false.
2156 : */
2157 :
2158 : extern JS_FRIEND_API(int8_t*)
2159 : JS_GetInt8ArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoRequireNoGC&);
2160 : extern JS_FRIEND_API(uint8_t*)
2161 : JS_GetUint8ArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoRequireNoGC&);
2162 : extern JS_FRIEND_API(uint8_t*)
2163 : JS_GetUint8ClampedArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoRequireNoGC&);
2164 : extern JS_FRIEND_API(int16_t*)
2165 : JS_GetInt16ArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoRequireNoGC&);
2166 : extern JS_FRIEND_API(uint16_t*)
2167 : JS_GetUint16ArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoRequireNoGC&);
2168 : extern JS_FRIEND_API(int32_t*)
2169 : JS_GetInt32ArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoRequireNoGC&);
2170 : extern JS_FRIEND_API(uint32_t*)
2171 : JS_GetUint32ArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoRequireNoGC&);
2172 : extern JS_FRIEND_API(float*)
2173 : JS_GetFloat32ArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoRequireNoGC&);
2174 : extern JS_FRIEND_API(double*)
2175 : JS_GetFloat64ArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoRequireNoGC&);
2176 :
2177 : /**
2178 : * Same as above, but for any kind of ArrayBufferView. Prefer the type-specific
2179 : * versions when possible.
2180 : */
2181 : extern JS_FRIEND_API(void*)
2182 : JS_GetArrayBufferViewData(JSObject* obj, bool* isSharedMemory, const JS::AutoRequireNoGC&);
2183 :
2184 : /**
2185 : * Return the ArrayBuffer or SharedArrayBuffer underlying an ArrayBufferView.
2186 : * This may return a detached buffer. |obj| must be an object that would
2187 : * return true for JS_IsArrayBufferViewObject().
2188 : */
2189 : extern JS_FRIEND_API(JSObject*)
2190 : JS_GetArrayBufferViewBuffer(JSContext* cx, JS::HandleObject obj, bool* isSharedMemory);
2191 :
2192 : /**
2193 : * Detach an ArrayBuffer, causing all associated views to no longer refer to
2194 : * the ArrayBuffer's original attached memory.
2195 : *
2196 : * The |changeData| argument is obsolete and ignored.
2197 : */
2198 : extern JS_FRIEND_API(bool)
2199 : JS_DetachArrayBuffer(JSContext* cx, JS::HandleObject obj);
2200 :
2201 : /**
2202 : * Check whether the obj is a detached ArrayBufferObject. Note that this may
2203 : * return false if a security wrapper is encountered that denies the
2204 : * unwrapping.
2205 : */
2206 : extern JS_FRIEND_API(bool)
2207 : JS_IsDetachedArrayBufferObject(JSObject* obj);
2208 :
2209 : /**
2210 : * Check whether obj supports JS_GetDataView* APIs.
2211 : */
2212 : JS_FRIEND_API(bool)
2213 : JS_IsDataViewObject(JSObject* obj);
2214 :
2215 : /**
2216 : * Create a new DataView using the given buffer for storage. The given buffer
2217 : * must be an ArrayBuffer or SharedArrayBuffer (or a cross-compartment wrapper
2218 : * of either type), and the offset and length must fit within the bounds of the
2219 : * buffer. Currently, nullptr will be returned and an exception will be thrown
2220 : * if these conditions do not hold, but do not depend on that behavior.
2221 : */
2222 : JS_FRIEND_API(JSObject*)
2223 : JS_NewDataView(JSContext* cx, JS::HandleObject buffer, uint32_t byteOffset, int32_t byteLength);
2224 :
2225 : /**
2226 : * Return the byte offset of a data view into its array buffer. |obj| must be a
2227 : * DataView.
2228 : *
2229 : * |obj| must have passed a JS_IsDataViewObject test, or somehow be known that
2230 : * it would pass such a test: it is a data view or a wrapper of a data view,
2231 : * and the unwrapping will succeed.
2232 : */
2233 : JS_FRIEND_API(uint32_t)
2234 : JS_GetDataViewByteOffset(JSObject* obj);
2235 :
2236 : /**
2237 : * Return the byte length of a data view.
2238 : *
2239 : * |obj| must have passed a JS_IsDataViewObject test, or somehow be known that
2240 : * it would pass such a test: it is a data view or a wrapper of a data view,
2241 : * and the unwrapping will succeed. If cx is nullptr, then DEBUG builds may be
2242 : * unable to assert when unwrapping should be disallowed.
2243 : */
2244 : JS_FRIEND_API(uint32_t)
2245 : JS_GetDataViewByteLength(JSObject* obj);
2246 :
2247 : /**
2248 : * Return a pointer to the beginning of the data referenced by a DataView.
2249 : *
2250 : * |obj| must have passed a JS_IsDataViewObject test, or somehow be known that
2251 : * it would pass such a test: it is a data view or a wrapper of a data view,
2252 : * and the unwrapping will succeed. If cx is nullptr, then DEBUG builds may be
2253 : * unable to assert when unwrapping should be disallowed.
2254 : *
2255 : * |*isSharedMemory| will be set to true if the DataView maps a SharedArrayBuffer,
2256 : * otherwise to false.
2257 : */
2258 : JS_FRIEND_API(void*)
2259 : JS_GetDataViewData(JSObject* obj, bool* isSharedMemory, const JS::AutoRequireNoGC&);
2260 :
2261 : namespace js {
2262 : namespace jit {
2263 :
2264 : enum class InlinableNative : uint16_t;
2265 :
2266 : } // namespace jit
2267 : } // namespace js
2268 :
2269 : /**
2270 : * A class, expected to be passed by value, which represents the CallArgs for a
2271 : * JSJitGetterOp.
2272 : */
2273 : class JSJitGetterCallArgs : protected JS::MutableHandleValue
2274 : {
2275 : public:
2276 : explicit JSJitGetterCallArgs(const JS::CallArgs& args)
2277 : : JS::MutableHandleValue(args.rval())
2278 : {}
2279 :
2280 : explicit JSJitGetterCallArgs(JS::RootedValue* rooted)
2281 : : JS::MutableHandleValue(rooted)
2282 : {}
2283 :
2284 : JS::MutableHandleValue rval() {
2285 : return *this;
2286 : }
2287 : };
2288 :
2289 : /**
2290 : * A class, expected to be passed by value, which represents the CallArgs for a
2291 : * JSJitSetterOp.
2292 : */
2293 : class JSJitSetterCallArgs : protected JS::MutableHandleValue
2294 : {
2295 : public:
2296 : explicit JSJitSetterCallArgs(const JS::CallArgs& args)
2297 : : JS::MutableHandleValue(args[0])
2298 : {}
2299 :
2300 : JS::MutableHandleValue operator[](unsigned i) {
2301 : MOZ_ASSERT(i == 0);
2302 : return *this;
2303 : }
2304 :
2305 : unsigned length() const { return 1; }
2306 :
2307 : // Add get() or maybe hasDefined() as needed
2308 : };
2309 :
2310 : struct JSJitMethodCallArgsTraits;
2311 :
2312 : /**
2313 : * A class, expected to be passed by reference, which represents the CallArgs
2314 : * for a JSJitMethodOp.
2315 : */
2316 : class JSJitMethodCallArgs : protected JS::detail::CallArgsBase<JS::detail::NoUsedRval>
2317 : {
2318 : private:
2319 : typedef JS::detail::CallArgsBase<JS::detail::NoUsedRval> Base;
2320 : friend struct JSJitMethodCallArgsTraits;
2321 :
2322 : public:
2323 : explicit JSJitMethodCallArgs(const JS::CallArgs& args) {
2324 : argv_ = args.array();
2325 : argc_ = args.length();
2326 : }
2327 :
2328 : JS::MutableHandleValue rval() const {
2329 : return Base::rval();
2330 : }
2331 :
2332 : unsigned length() const { return Base::length(); }
2333 :
2334 : JS::MutableHandleValue operator[](unsigned i) const {
2335 : return Base::operator[](i);
2336 : }
2337 :
2338 : bool hasDefined(unsigned i) const {
2339 : return Base::hasDefined(i);
2340 : }
2341 :
2342 : JSObject& callee() const {
2343 : // We can't use Base::callee() because that will try to poke at
2344 : // this->usedRval_, which we don't have.
2345 : return argv_[-2].toObject();
2346 : }
2347 :
2348 : JS::HandleValue get(unsigned i) const {
2349 : return Base::get(i);
2350 : }
2351 : };
2352 :
2353 : struct JSJitMethodCallArgsTraits
2354 : {
2355 : static const size_t offsetOfArgv = offsetof(JSJitMethodCallArgs, argv_);
2356 : static const size_t offsetOfArgc = offsetof(JSJitMethodCallArgs, argc_);
2357 : };
2358 :
2359 : typedef bool
2360 : (* JSJitGetterOp)(JSContext* cx, JS::HandleObject thisObj,
2361 : void* specializedThis, JSJitGetterCallArgs args);
2362 : typedef bool
2363 : (* JSJitSetterOp)(JSContext* cx, JS::HandleObject thisObj,
2364 : void* specializedThis, JSJitSetterCallArgs args);
2365 : typedef bool
2366 : (* JSJitMethodOp)(JSContext* cx, JS::HandleObject thisObj,
2367 : void* specializedThis, const JSJitMethodCallArgs& args);
2368 :
2369 : /**
2370 : * This struct contains metadata passed from the DOM to the JS Engine for JIT
2371 : * optimizations on DOM property accessors. Eventually, this should be made
2372 : * available to general JSAPI users, but we are not currently ready to do so.
2373 : */
2374 : struct JSJitInfo {
2375 : enum OpType {
2376 : Getter,
2377 : Setter,
2378 : Method,
2379 : StaticMethod,
2380 : InlinableNative,
2381 : IgnoresReturnValueNative,
2382 : // Must be last
2383 : OpTypeCount
2384 : };
2385 :
2386 : enum ArgType {
2387 : // Basic types
2388 : String = (1 << 0),
2389 : Integer = (1 << 1), // Only 32-bit or less
2390 : Double = (1 << 2), // Maybe we want to add Float sometime too
2391 : Boolean = (1 << 3),
2392 : Object = (1 << 4),
2393 : Null = (1 << 5),
2394 :
2395 : // And derived types
2396 : Numeric = Integer | Double,
2397 : // Should "Primitive" use the WebIDL definition, which
2398 : // excludes string and null, or the typical JS one that includes them?
2399 : Primitive = Numeric | Boolean | Null | String,
2400 : ObjectOrNull = Object | Null,
2401 : Any = ObjectOrNull | Primitive,
2402 :
2403 : // Our sentinel value.
2404 : ArgTypeListEnd = (1 << 31)
2405 : };
2406 :
2407 : static_assert(Any & String, "Any must include String.");
2408 : static_assert(Any & Integer, "Any must include Integer.");
2409 : static_assert(Any & Double, "Any must include Double.");
2410 : static_assert(Any & Boolean, "Any must include Boolean.");
2411 : static_assert(Any & Object, "Any must include Object.");
2412 : static_assert(Any & Null, "Any must include Null.");
2413 :
2414 : /**
2415 : * An enum that describes what this getter/setter/method aliases. This
2416 : * determines what things can be hoisted past this call, and if this
2417 : * call is movable what it can be hoisted past.
2418 : */
2419 : enum AliasSet {
2420 : /**
2421 : * Alias nothing: a constant value, getting it can't affect any other
2422 : * values, nothing can affect it.
2423 : */
2424 : AliasNone,
2425 :
2426 : /**
2427 : * Alias things that can modify the DOM but nothing else. Doing the
2428 : * call can't affect the behavior of any other function.
2429 : */
2430 : AliasDOMSets,
2431 :
2432 : /**
2433 : * Alias the world. Calling this can change arbitrary values anywhere
2434 : * in the system. Most things fall in this bucket.
2435 : */
2436 : AliasEverything,
2437 :
2438 : /** Must be last. */
2439 : AliasSetCount
2440 : };
2441 :
2442 : bool needsOuterizedThisObject() const
2443 : {
2444 : return type() != Getter && type() != Setter;
2445 78038 : }
2446 :
2447 : bool isTypedMethodJitInfo() const
2448 : {
2449 : return isTypedMethod;
2450 0 : }
2451 :
2452 : OpType type() const
2453 : {
2454 : return OpType(type_);
2455 0 : }
2456 :
2457 : AliasSet aliasSet() const
2458 : {
2459 : return AliasSet(aliasSet_);
2460 0 : }
2461 :
2462 : JSValueType returnType() const
2463 : {
2464 : return JSValueType(returnType_);
2465 0 : }
2466 :
2467 : union {
2468 : JSJitGetterOp getter;
2469 : JSJitSetterOp setter;
2470 : JSJitMethodOp method;
2471 : /** A DOM static method, used for Promise wrappers */
2472 : JSNative staticMethod;
2473 : JSNative ignoresReturnValueMethod;
2474 : };
2475 :
2476 : static unsigned offsetOfIgnoresReturnValueNative() {
2477 : return offsetof(JSJitInfo, ignoresReturnValueMethod);
2478 : }
2479 :
2480 : union {
2481 : uint16_t protoID;
2482 : js::jit::InlinableNative inlinableNative;
2483 : };
2484 :
2485 : union {
2486 : uint16_t depth;
2487 :
2488 : // Additional opcode for some InlinableNative functions.
2489 : uint16_t nativeOp;
2490 : };
2491 :
2492 : // These fields are carefully packed to take up 4 bytes. If you need more
2493 : // bits for whatever reason, please see if you can steal bits from existing
2494 : // fields before adding more members to this structure.
2495 :
2496 : #define JITINFO_OP_TYPE_BITS 4
2497 : #define JITINFO_ALIAS_SET_BITS 4
2498 : #define JITINFO_RETURN_TYPE_BITS 8
2499 : #define JITINFO_SLOT_INDEX_BITS 10
2500 :
2501 : /** The OpType that says what sort of function we are. */
2502 : uint32_t type_ : JITINFO_OP_TYPE_BITS;
2503 :
2504 : /**
2505 : * The alias set for this op. This is a _minimal_ alias set; in
2506 : * particular for a method it does not include whatever argument
2507 : * conversions might do. That's covered by argTypes and runtime
2508 : * analysis of the actual argument types being passed in.
2509 : */
2510 : uint32_t aliasSet_ : JITINFO_ALIAS_SET_BITS;
2511 :
2512 : /** The return type tag. Might be JSVAL_TYPE_UNKNOWN. */
2513 : uint32_t returnType_ : JITINFO_RETURN_TYPE_BITS;
2514 :
2515 : static_assert(OpTypeCount <= (1 << JITINFO_OP_TYPE_BITS),
2516 : "Not enough space for OpType");
2517 : static_assert(AliasSetCount <= (1 << JITINFO_ALIAS_SET_BITS),
2518 : "Not enough space for AliasSet");
2519 : static_assert((sizeof(JSValueType) * 8) <= JITINFO_RETURN_TYPE_BITS,
2520 : "Not enough space for JSValueType");
2521 :
2522 : #undef JITINFO_RETURN_TYPE_BITS
2523 : #undef JITINFO_ALIAS_SET_BITS
2524 : #undef JITINFO_OP_TYPE_BITS
2525 :
2526 : /** Is op fallible? False in setters. */
2527 : uint32_t isInfallible : 1;
2528 :
2529 : /**
2530 : * Is op movable? To be movable the op must
2531 : * not AliasEverything, but even that might
2532 : * not be enough (e.g. in cases when it can
2533 : * throw or is explicitly not movable).
2534 : */
2535 : uint32_t isMovable : 1;
2536 :
2537 : /**
2538 : * Can op be dead-code eliminated? Again, this
2539 : * depends on whether the op can throw, in
2540 : * addition to the alias set.
2541 : */
2542 : uint32_t isEliminatable : 1;
2543 :
2544 : // XXXbz should we have a JSValueType for the type of the member?
2545 : /**
2546 : * True if this is a getter that can always
2547 : * get the value from a slot of the "this" object.
2548 : */
2549 : uint32_t isAlwaysInSlot : 1;
2550 :
2551 : /**
2552 : * True if this is a getter that can sometimes (if the slot doesn't contain
2553 : * UndefinedValue()) get the value from a slot of the "this" object.
2554 : */
2555 : uint32_t isLazilyCachedInSlot : 1;
2556 :
2557 : /** True if this is an instance of JSTypedMethodJitInfo. */
2558 : uint32_t isTypedMethod : 1;
2559 :
2560 : /**
2561 : * If isAlwaysInSlot or isSometimesInSlot is true,
2562 : * the index of the slot to get the value from.
2563 : * Otherwise 0.
2564 : */
2565 : uint32_t slotIndex : JITINFO_SLOT_INDEX_BITS;
2566 :
2567 : static const size_t maxSlotIndex = (1 << JITINFO_SLOT_INDEX_BITS) - 1;
2568 :
2569 : #undef JITINFO_SLOT_INDEX_BITS
2570 : };
2571 :
2572 : static_assert(sizeof(JSJitInfo) == (sizeof(void*) + 2 * sizeof(uint32_t)),
2573 : "There are several thousand instances of JSJitInfo stored in "
2574 : "a binary. Please don't increase its space requirements without "
2575 : "verifying that there is no other way forward (better packing, "
2576 : "smaller datatypes for fields, subclassing, etc.).");
2577 :
2578 : struct JSTypedMethodJitInfo
2579 : {
2580 : // We use C-style inheritance here, rather than C++ style inheritance
2581 : // because not all compilers support brace-initialization for non-aggregate
2582 : // classes. Using C++ style inheritance and constructors instead of
2583 : // brace-initialization would also force the creation of static
2584 : // constructors (on some compilers) when JSJitInfo and JSTypedMethodJitInfo
2585 : // structures are declared. Since there can be several thousand of these
2586 : // structures present and we want to have roughly equivalent performance
2587 : // across a range of compilers, we do things manually.
2588 : JSJitInfo base;
2589 :
2590 : const JSJitInfo::ArgType* const argTypes; /* For a method, a list of sets of
2591 : types that the function
2592 : expects. This can be used,
2593 : for example, to figure out
2594 : when argument coercions can
2595 : have side-effects. */
2596 : };
2597 :
2598 : namespace js {
2599 :
2600 : static MOZ_ALWAYS_INLINE shadow::Function*
2601 : FunctionObjectToShadowFunction(JSObject* fun)
2602 : {
2603 : MOZ_ASSERT(GetObjectClass(fun) == FunctionClassPtr);
2604 : return reinterpret_cast<shadow::Function*>(fun);
2605 : }
2606 :
2607 : /* Statically asserted in JSFunction.h. */
2608 : static const unsigned JS_FUNCTION_INTERPRETED_BITS = 0x0201;
2609 :
2610 : // Return whether the given function object is native.
2611 : static MOZ_ALWAYS_INLINE bool
2612 : FunctionObjectIsNative(JSObject* fun)
2613 : {
2614 : return !(FunctionObjectToShadowFunction(fun)->flags & JS_FUNCTION_INTERPRETED_BITS);
2615 : }
2616 :
2617 : static MOZ_ALWAYS_INLINE JSNative
2618 : GetFunctionObjectNative(JSObject* fun)
2619 : {
2620 : MOZ_ASSERT(FunctionObjectIsNative(fun));
2621 : return FunctionObjectToShadowFunction(fun)->native;
2622 : }
2623 :
2624 : } // namespace js
2625 :
2626 : static MOZ_ALWAYS_INLINE const JSJitInfo*
2627 : FUNCTION_VALUE_TO_JITINFO(const JS::Value& v)
2628 : {
2629 : MOZ_ASSERT(js::FunctionObjectIsNative(&v.toObject()));
2630 : return js::FunctionObjectToShadowFunction(&v.toObject())->jitinfo;
2631 : }
2632 :
2633 : static MOZ_ALWAYS_INLINE void
2634 : SET_JITINFO(JSFunction * func, const JSJitInfo* info)
2635 : {
2636 : js::shadow::Function* fun = reinterpret_cast<js::shadow::Function*>(func);
2637 : MOZ_ASSERT(!(fun->flags & js::JS_FUNCTION_INTERPRETED_BITS));
2638 : fun->jitinfo = info;
2639 : }
2640 :
2641 : /*
2642 : * Engine-internal extensions of jsid. This code is here only until we
2643 : * eliminate Gecko's dependencies on it!
2644 : */
2645 :
2646 : static MOZ_ALWAYS_INLINE jsid
2647 : JSID_FROM_BITS(size_t bits)
2648 : {
2649 : jsid id;
2650 2 : JSID_BITS(id) = bits;
2651 2 : return id;
2652 : }
2653 :
2654 : namespace js {
2655 : namespace detail {
2656 : bool IdMatchesAtom(jsid id, JSAtom* atom);
2657 : bool IdMatchesAtom(jsid id, JSString* atom);
2658 : } // namespace detail
2659 : } // namespace js
2660 :
2661 : /**
2662 : * Must not be used on atoms that are representable as integer jsids.
2663 : * Prefer NameToId or AtomToId over this function:
2664 : *
2665 : * A PropertyName is an atom that does not contain an integer in the range
2666 : * [0, UINT32_MAX]. However, jsid can only hold an integer in the range
2667 : * [0, JSID_INT_MAX] (where JSID_INT_MAX == 2^31-1). Thus, for the range of
2668 : * integers (JSID_INT_MAX, UINT32_MAX], to represent as a jsid 'id', it must be
2669 : * the case JSID_IS_ATOM(id) and !JSID_TO_ATOM(id)->isPropertyName(). In most
2670 : * cases when creating a jsid, code does not have to care about this corner
2671 : * case because:
2672 : *
2673 : * - When given an arbitrary JSAtom*, AtomToId must be used, which checks for
2674 : * integer atoms representable as integer jsids, and does this conversion.
2675 : *
2676 : * - When given a PropertyName*, NameToId can be used which which does not need
2677 : * to do any dynamic checks.
2678 : *
2679 : * Thus, it is only the rare third case which needs this function, which
2680 : * handles any JSAtom* that is known not to be representable with an int jsid.
2681 : */
2682 : static MOZ_ALWAYS_INLINE jsid
2683 : NON_INTEGER_ATOM_TO_JSID(JSAtom* atom)
2684 1093886 : {
2685 : MOZ_ASSERT(((size_t)atom & JSID_TYPE_MASK) == 0);
2686 1093886 : jsid id = JSID_FROM_BITS((size_t)atom | JSID_TYPE_STRING);
2687 2187772 : MOZ_ASSERT(js::detail::IdMatchesAtom(id, atom));
2688 1093886 : return id;
2689 1093892 : }
2690 :
2691 : static MOZ_ALWAYS_INLINE jsid
2692 : NON_INTEGER_ATOM_TO_JSID(JSString* atom)
2693 : {
2694 : MOZ_ASSERT(((size_t)atom & JSID_TYPE_MASK) == 0);
2695 : jsid id = JSID_FROM_BITS((size_t)atom | JSID_TYPE_STRING);
2696 : MOZ_ASSERT(js::detail::IdMatchesAtom(id, atom));
2697 : return id;
2698 : }
2699 :
2700 : /* All strings stored in jsids are atomized, but are not necessarily property names. */
2701 : static MOZ_ALWAYS_INLINE bool
2702 : JSID_IS_ATOM(jsid id)
2703 : {
2704 : return JSID_IS_STRING(id);
2705 : }
2706 :
2707 : static MOZ_ALWAYS_INLINE bool
2708 : JSID_IS_ATOM(jsid id, JSAtom* atom)
2709 : {
2710 : return id == NON_INTEGER_ATOM_TO_JSID(atom);
2711 100836 : }
2712 :
2713 : static MOZ_ALWAYS_INLINE JSAtom*
2714 : JSID_TO_ATOM(jsid id)
2715 : {
2716 : return (JSAtom*)JSID_TO_STRING(id);
2717 0 : }
2718 :
2719 : JS_STATIC_ASSERT(sizeof(jsid) == sizeof(void*));
2720 :
2721 : namespace js {
2722 :
2723 : static MOZ_ALWAYS_INLINE JS::Value
2724 : IdToValue(jsid id)
2725 0 : {
2726 : if (JSID_IS_STRING(id))
2727 2 : return JS::StringValue(JSID_TO_STRING(id));
2728 0 : if (JSID_IS_INT(id))
2729 2 : return JS::Int32Value(JSID_TO_INT(id));
2730 2 : if (JSID_IS_SYMBOL(id))
2731 2 : return JS::SymbolValue(JSID_TO_SYMBOL(id));
2732 2 : MOZ_ASSERT(JSID_IS_VOID(id));
2733 0 : return JS::UndefinedValue();
2734 0 : }
2735 :
2736 : /**
2737 : * If the embedder has registered a ScriptEnvironmentPreparer,
2738 : * PrepareScriptEnvironmentAndInvoke will call the preparer's 'invoke' method
2739 : * with the given |closure|, with the assumption that the preparer will set up
2740 : * any state necessary to run script in |scope|, invoke |closure| with a valid
2741 : * JSContext*, report any exceptions thrown from the closure, and return.
2742 : *
2743 : * If no preparer is registered, PrepareScriptEnvironmentAndInvoke will assert
2744 : * that |rt| has exactly one JSContext associated with it, enter the compartment
2745 : * of |scope| on that context, and invoke |closure|.
2746 : *
2747 : * In both cases, PrepareScriptEnvironmentAndInvoke will report any exceptions
2748 : * that are thrown by the closure. Consumers who want to propagate back
2749 : * whether the closure succeeded should do so via members of the closure
2750 : * itself.
2751 : */
2752 :
2753 : struct ScriptEnvironmentPreparer {
2754 : struct Closure {
2755 : virtual bool operator()(JSContext* cx) = 0;
2756 : };
2757 :
2758 : virtual void invoke(JS::HandleObject scope, Closure& closure) = 0;
2759 : };
2760 :
2761 : extern JS_FRIEND_API(void)
2762 : PrepareScriptEnvironmentAndInvoke(JSContext* cx, JS::HandleObject scope,
2763 : ScriptEnvironmentPreparer::Closure& closure);
2764 :
2765 : JS_FRIEND_API(void)
2766 : SetScriptEnvironmentPreparer(JSContext* cx, ScriptEnvironmentPreparer* preparer);
2767 :
2768 : enum CTypesActivityType {
2769 : CTYPES_CALL_BEGIN,
2770 : CTYPES_CALL_END,
2771 : CTYPES_CALLBACK_BEGIN,
2772 : CTYPES_CALLBACK_END
2773 : };
2774 :
2775 : typedef void
2776 : (* CTypesActivityCallback)(JSContext* cx, CTypesActivityType type);
2777 :
2778 : /**
2779 : * Sets a callback that is run whenever js-ctypes is about to be used when
2780 : * calling into C.
2781 : */
2782 : JS_FRIEND_API(void)
2783 : SetCTypesActivityCallback(JSContext* cx, CTypesActivityCallback cb);
2784 :
2785 : class MOZ_RAII JS_FRIEND_API(AutoCTypesActivityCallback) {
2786 : private:
2787 : JSContext* cx;
2788 : CTypesActivityCallback callback;
2789 : CTypesActivityType endType;
2790 : MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
2791 :
2792 : public:
2793 : AutoCTypesActivityCallback(JSContext* cx, CTypesActivityType beginType,
2794 : CTypesActivityType endType
2795 : MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
2796 : ~AutoCTypesActivityCallback() {
2797 240 : DoEndCallback();
2798 120 : }
2799 120 : void DoEndCallback() {
2800 : if (callback) {
2801 240 : callback(cx, endType);
2802 118 : callback = nullptr;
2803 118 : }
2804 : }
2805 : };
2806 :
2807 : // Abstract base class for objects that build allocation metadata for JavaScript
2808 : // values.
2809 : struct AllocationMetadataBuilder {
2810 : AllocationMetadataBuilder() { }
2811 4 :
2812 : // Return a metadata object for the newly constructed object |obj|, or
2813 : // nullptr if there's no metadata to attach.
2814 : //
2815 : // Implementations should treat all errors as fatal; there is no way to
2816 : // report errors from this callback. In particular, the caller provides an
2817 : // oomUnsafe for overriding implementations to use.
2818 : virtual JSObject* build(JSContext* cx, JS::HandleObject obj,
2819 0 : AutoEnterOOMUnsafeRegion& oomUnsafe) const
2820 : {
2821 : return nullptr;
2822 0 : }
2823 : };
2824 :
2825 : /**
2826 : * Specify a callback to invoke when creating each JS object in the current
2827 : * compartment, which may return a metadata object to associate with the
2828 : * object.
2829 : */
2830 : JS_FRIEND_API(void)
2831 : SetAllocationMetadataBuilder(JSContext* cx, const AllocationMetadataBuilder *callback);
2832 :
2833 : /** Get the metadata associated with an object. */
2834 : JS_FRIEND_API(JSObject*)
2835 : GetAllocationMetadata(JSObject* obj);
2836 :
2837 : JS_FRIEND_API(bool)
2838 : GetElementsWithAdder(JSContext* cx, JS::HandleObject obj, JS::HandleObject receiver,
2839 : uint32_t begin, uint32_t end, js::ElementAdder* adder);
2840 :
2841 : JS_FRIEND_API(bool)
2842 : ForwardToNative(JSContext* cx, JSNative native, const JS::CallArgs& args);
2843 :
2844 : /**
2845 : * Helper function for HTMLDocument and HTMLFormElement.
2846 : *
2847 : * These are the only two interfaces that have [OverrideBuiltins], a named
2848 : * getter, and no named setter. They're implemented as proxies with a custom
2849 : * getOwnPropertyDescriptor() method. Unfortunately, overriding
2850 : * getOwnPropertyDescriptor() automatically affects the behavior of set(),
2851 : * which normally is just common sense but is *not* desired for these two
2852 : * interfaces.
2853 : *
2854 : * The fix is for these two interfaces to override set() to ignore the
2855 : * getOwnPropertyDescriptor() override.
2856 : *
2857 : * SetPropertyIgnoringNamedGetter is exposed to make it easier to override
2858 : * set() in this way. It carries out all the steps of BaseProxyHandler::set()
2859 : * except the initial getOwnPropertyDescriptor() call. The caller must supply
2860 : * that descriptor as the 'ownDesc' parameter.
2861 : *
2862 : * Implemented in proxy/BaseProxyHandler.cpp.
2863 : */
2864 : JS_FRIEND_API(bool)
2865 : SetPropertyIgnoringNamedGetter(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
2866 : JS::HandleValue v, JS::HandleValue receiver,
2867 : JS::Handle<JS::PropertyDescriptor> ownDesc,
2868 : JS::ObjectOpResult& result);
2869 :
2870 : // This function is for one specific use case, please don't use this for anything else!
2871 : extern JS_FRIEND_API(bool)
2872 : ExecuteInGlobalAndReturnScope(JSContext* cx, JS::HandleObject obj, JS::HandleScript script,
2873 : JS::MutableHandleObject scope);
2874 :
2875 : // These functions are provided for the JSM component loader in Gecko.
2876 : //
2877 : // A 'JSMEnvironment' refers to an environment chain constructed for JSM loading
2878 : // in a shared global. Internally it is a NonSyntacticVariablesObject with a
2879 : // corresponding extensible LexicalEnvironmentObject that is accessible by
2880 : // JS_ExtensibleLexicalEnvironment. The |this| value of that lexical environment
2881 : // is the NSVO itself.
2882 : //
2883 : // Normal global environment (ES6): JSM "global" environment:
2884 : //
2885 : // * - extensible lexical environment
2886 : // | (code runs in this environment;
2887 : // | `let/const` bindings go here)
2888 : // |
2889 : // * - JSMEnvironment (=== `this`)
2890 : // | (`var` bindings go here)
2891 : // |
2892 : // * - extensible lexical environment * - extensible lexical environment
2893 : // | (code runs in this environment; | (empty)
2894 : // | `let/const` bindings go here) |
2895 : // | |
2896 : // * - actual global (=== `this`) * - shared JSM global
2897 : // (var bindings go here; and (Object, Math, etc. live here)
2898 : // Object, Math, etc. live here)
2899 :
2900 : // Allocate a new environment in current compartment that is compatible with JSM
2901 : // shared loading.
2902 : extern JS_FRIEND_API(JSObject*)
2903 : NewJSMEnvironment(JSContext* cx);
2904 :
2905 : // Execute the given script (copied into compartment if necessary) in the given
2906 : // JSMEnvironment. The script must have been compiled for hasNonSyntacticScope.
2907 : // The |jsmEnv| must have been previously allocated by NewJSMEnvironment.
2908 : //
2909 : // NOTE: The associated extensible lexical environment is reused.
2910 : extern JS_FRIEND_API(bool)
2911 : ExecuteInJSMEnvironment(JSContext* cx, JS::HandleScript script, JS::HandleObject jsmEnv);
2912 :
2913 : // Additionally, target objects may be specified as required by the Gecko
2914 : // subscript loader. These are wrapped in non-syntactic WithEnvironments and
2915 : // temporarily placed on environment chain.
2916 : //
2917 : // See also: JS::CloneAndExecuteScript(...)
2918 : extern JS_FRIEND_API(bool)
2919 : ExecuteInJSMEnvironment(JSContext* cx, JS::HandleScript script, JS::HandleObject jsmEnv,
2920 : JS::AutoObjectVector& targetObj);
2921 :
2922 : // Used by native methods to determine the JSMEnvironment of caller if possible
2923 : // by looking at stack frames. Returns nullptr if top frame isn't a scripted
2924 : // caller in a JSM.
2925 : //
2926 : // NOTE: This may find NonSyntacticVariablesObject generated by other embedding
2927 : // such as a Gecko FrameScript. Caller can check the compartment if needed.
2928 : extern JS_FRIEND_API(JSObject*)
2929 : GetJSMEnvironmentOfScriptedCaller(JSContext* cx);
2930 :
2931 : // Determine if obj is a JSMEnvironment
2932 : //
2933 : // NOTE: This may return true for an NonSyntacticVariablesObject generated by
2934 : // other embedding such as a Gecko FrameScript. Caller can check compartment.
2935 : extern JS_FRIEND_API(bool)
2936 : IsJSMEnvironment(JSObject* obj);
2937 :
2938 :
2939 : #if defined(XP_WIN) && defined(_WIN64)
2940 : // Parameters use void* types to avoid #including windows.h. The return value of
2941 : // this function is returned from the exception handler.
2942 : typedef long
2943 : (*JitExceptionHandler)(void* exceptionRecord, // PEXECTION_RECORD
2944 : void* context); // PCONTEXT
2945 :
2946 : /**
2947 : * Windows uses "structured exception handling" to handle faults. When a fault
2948 : * occurs, the stack is searched for a handler (similar to C++ exception
2949 : * handling). If the search does not find a handler, the "unhandled exception
2950 : * filter" is called. Breakpad uses the unhandled exception filter to do crash
2951 : * reporting. Unfortunately, on Win64, JIT code on the stack completely throws
2952 : * off this unwinding process and prevents the unhandled exception filter from
2953 : * being called. The reason is that Win64 requires unwind information be
2954 : * registered for all code regions and JIT code has none. While it is possible
2955 : * to register full unwind information for JIT code, this is a lot of work (one
2956 : * has to be able to recover the frame pointer at any PC) so instead we register
2957 : * a handler for all JIT code that simply calls breakpad's unhandled exception
2958 : * filter (which will perform crash reporting and then terminate the process).
2959 : * This would be wrong if there was an outer __try block that expected to handle
2960 : * the fault, but this is not generally allowed.
2961 : *
2962 : * Gecko must call SetJitExceptionFilter before any JIT code is compiled and
2963 : * only once per process.
2964 : */
2965 : extern JS_FRIEND_API(void)
2966 : SetJitExceptionHandler(JitExceptionHandler handler);
2967 : #endif
2968 :
2969 : /**
2970 : * Get the first SavedFrame object in this SavedFrame stack whose principals are
2971 : * subsumed by the cx's principals. If there is no such frame, return nullptr.
2972 : *
2973 : * Do NOT pass a non-SavedFrame object here.
2974 : *
2975 : * The savedFrame and cx do not need to be in the same compartment.
2976 : */
2977 : extern JS_FRIEND_API(JSObject*)
2978 : GetFirstSubsumedSavedFrame(JSContext* cx, JS::HandleObject savedFrame, JS::SavedFrameSelfHosted selfHosted);
2979 :
2980 : /**
2981 : * Get the first SavedFrame object in this SavedFrame stack whose principals are
2982 : * subsumed by the given |principals|. If there is no such frame, return nullptr.
2983 : *
2984 : * Do NOT pass a non-SavedFrame object here.
2985 : */
2986 : extern JS_FRIEND_API(JSObject*)
2987 : GetFirstSubsumedSavedFrame(JSContext* cx, JSPrincipals* principals, JS::HandleObject savedFrame, JS::SavedFrameSelfHosted selfHosted);
2988 :
2989 : extern JS_FRIEND_API(bool)
2990 : ReportIsNotFunction(JSContext* cx, JS::HandleValue v);
2991 :
2992 : extern JS_FRIEND_API(JSObject*)
2993 : ConvertArgsToArray(JSContext* cx, const JS::CallArgs& args);
2994 :
2995 : /**
2996 : * Window and WindowProxy
2997 : *
2998 : * The functions below have to do with Windows and WindowProxies. There's an
2999 : * invariant that actual Window objects (the global objects of web pages) are
3000 : * never directly exposed to script. Instead we often substitute a WindowProxy.
3001 : *
3002 : * The environment chain, on the other hand, contains the Window and never its
3003 : * WindowProxy.
3004 : *
3005 : * As a result, we have calls to these "substitute-this-object-for-that-object"
3006 : * functions sprinkled at apparently arbitrary (but actually *very* carefully
3007 : * and nervously selected) places throughout the engine and indeed the
3008 : * universe.
3009 : */
3010 :
3011 : /**
3012 : * Tell the JS engine which Class is used for WindowProxy objects. Used by the
3013 : * functions below.
3014 : */
3015 : extern JS_FRIEND_API(void)
3016 : SetWindowProxyClass(JSContext* cx, const Class* clasp);
3017 :
3018 : /**
3019 : * Associates a WindowProxy with a Window (global object). `windowProxy` must
3020 : * have the Class set by SetWindowProxyClass.
3021 : */
3022 : extern JS_FRIEND_API(void)
3023 : SetWindowProxy(JSContext* cx, JS::HandleObject global, JS::HandleObject windowProxy);
3024 :
3025 : namespace detail {
3026 :
3027 : JS_FRIEND_API(bool)
3028 : IsWindowSlow(JSObject* obj);
3029 :
3030 : JS_FRIEND_API(JSObject*)
3031 : ToWindowProxyIfWindowSlow(JSObject* obj);
3032 :
3033 : } // namespace detail
3034 :
3035 : /**
3036 : * Returns true iff `obj` is a global object with an associated WindowProxy,
3037 : * see SetWindowProxy.
3038 : */
3039 : inline bool
3040 : IsWindow(JSObject* obj)
3041 : {
3042 : if (GetObjectClass(obj)->flags & JSCLASS_IS_GLOBAL)
3043 2 : return detail::IsWindowSlow(obj);
3044 0 : return false;
3045 : }
3046 :
3047 : /**
3048 : * Returns true iff `obj` has the WindowProxy Class (see SetWindowProxyClass).
3049 : */
3050 : JS_FRIEND_API(bool)
3051 : IsWindowProxy(JSObject* obj);
3052 :
3053 : /**
3054 : * If `obj` is a Window, get its associated WindowProxy (or a CCW or dead
3055 : * wrapper if the page was navigated away from), else return `obj`. This
3056 : * function is infallible and never returns nullptr.
3057 : */
3058 : MOZ_ALWAYS_INLINE JSObject*
3059 : ToWindowProxyIfWindow(JSObject* obj)
3060 0 : {
3061 : if (GetObjectClass(obj)->flags & JSCLASS_IS_GLOBAL)
3062 2 : return detail::ToWindowProxyIfWindowSlow(obj);
3063 0 : return obj;
3064 : }
3065 :
3066 : /**
3067 : * If `obj` is a WindowProxy, get its associated Window (the compartment's
3068 : * global), else return `obj`. This function is infallible and never returns
3069 : * nullptr.
3070 : */
3071 : extern JS_FRIEND_API(JSObject*)
3072 : ToWindowIfWindowProxy(JSObject* obj);
3073 :
3074 : // Create and add the Intl.MozDateTimeFormat constructor function to the provided
3075 : // object.
3076 : //
3077 : // This custom date/time formatter constructor gives users the ability
3078 : // to specify a custom format pattern. This pattern is passed *directly*
3079 : // to ICU with NO SYNTAX PARSING OR VALIDATION WHATSOEVER. ICU appears to
3080 : // have a a modicum of testing of this, and it won't fall over completely
3081 : // if passed bad input. But the current behavior is entirely under-specified
3082 : // and emphatically not shippable on the web, and it *must* be fixed before
3083 : // this functionality can be exposed in the real world. (There are also some
3084 : // questions about whether the format exposed here is the *right* one to
3085 : // standardize, that will also need to be resolved to ship this.)
3086 : extern bool
3087 : AddMozDateTimeFormatConstructor(JSContext* cx, JS::Handle<JSObject*> intl);
3088 :
3089 : // Create and add the Intl.RelativeTimeFormat constructor function to the provided
3090 : // object. This function throws if called more than once per realm/global
3091 : // object.
3092 : extern bool
3093 : AddRelativeTimeFormatConstructor(JSContext* cx, JS::Handle<JSObject*> intl);
3094 :
3095 : class MOZ_STACK_CLASS JS_FRIEND_API(AutoAssertNoContentJS)
3096 : {
3097 : public:
3098 : explicit AutoAssertNoContentJS(JSContext* cx);
3099 : ~AutoAssertNoContentJS();
3100 :
3101 : private:
3102 : JSContext* context_;
3103 : bool prevAllowContentJS_;
3104 : };
3105 :
3106 : // Turn on assertions so that we assert that
3107 : // !realm->validAccessPtr || *realm->validAccessPtr
3108 : // is true for every |realm| that we run JS code in. The realm's validAccessPtr
3109 : // is set via SetRealmValidAccessPtr.
3110 : extern JS_FRIEND_API(void)
3111 : EnableAccessValidation(JSContext* cx, bool enabled);
3112 :
3113 : // See EnableAccessValidation above. The caller must guarantee that accessp will
3114 : // live at least as long as |global| is alive. The JS engine reads accessp from
3115 : // threads that are allowed to run code on |global|, so all changes to *accessp
3116 : // should be made from whichever thread owns |global| at a given time.
3117 : extern JS_FRIEND_API(void)
3118 : SetRealmValidAccessPtr(JSContext* cx, JS::HandleObject global, bool* accessp);
3119 :
3120 : // Returns true if the system zone is available (i.e., if no cooperative contexts
3121 : // are using it now).
3122 : extern JS_FRIEND_API(bool)
3123 : SystemZoneAvailable(JSContext* cx);
3124 :
3125 : typedef void
3126 : (* LogCtorDtor)(void* self, const char* type, uint32_t sz);
3127 :
3128 : /**
3129 : * Set global function used to monitor a few internal classes to highlight
3130 : * leaks, and to hint at the origin of the leaks.
3131 : */
3132 : extern JS_FRIEND_API(void)
3133 : SetLogCtorDtorFunctions(LogCtorDtor ctor, LogCtorDtor dtor);
3134 :
3135 : extern JS_FRIEND_API(void)
3136 : LogCtor(void* self, const char* type, uint32_t sz);
3137 :
3138 : extern JS_FRIEND_API(void)
3139 : LogDtor(void* self, const char* type, uint32_t sz);
3140 :
3141 : #define JS_COUNT_CTOR(Class) \
3142 : LogCtor((void*) this, #Class, sizeof(Class))
3143 :
3144 : #define JS_COUNT_DTOR(Class) \
3145 : LogDtor((void*) this, #Class, sizeof(Class))
3146 :
3147 : } /* namespace js */
3148 :
3149 : #endif /* jsfriendapi_h */
|