Source code

Revision control

Other Tools

1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2
* vim: set ts=8 sts=2 et sw=2 tw=80:
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/TimeStamp.h"
15
#include "mozilla/UniquePtr.h"
16
17
#include "jspubtd.h"
18
19
#include "js/CallArgs.h"
20
#include "js/CallNonGenericMethod.h"
21
#include "js/CharacterEncoding.h"
22
#include "js/Class.h"
23
#include "js/ErrorReport.h"
24
#include "js/HeapAPI.h"
25
#include "js/StableStringChars.h"
26
#include "js/TypeDecls.h"
27
#include "js/Utility.h"
28
29
#ifndef JS_STACK_GROWTH_DIRECTION
30
# ifdef __hppa
31
# define JS_STACK_GROWTH_DIRECTION (1)
32
# else
33
# define JS_STACK_GROWTH_DIRECTION (-1)
34
# endif
35
#endif
36
37
#if JS_STACK_GROWTH_DIRECTION > 0
38
# define JS_CHECK_STACK_SIZE(limit, sp) (MOZ_LIKELY((uintptr_t)(sp) < (limit)))
39
#else
40
# define JS_CHECK_STACK_SIZE(limit, sp) (MOZ_LIKELY((uintptr_t)(sp) > (limit)))
41
#endif
42
43
struct JSErrorFormatString;
44
struct JSJitInfo;
45
46
namespace JS {
47
template <class T>
48
class Heap;
49
} /* namespace JS */
50
51
namespace js {
52
class JS_FRIEND_API BaseProxyHandler;
53
class InterpreterFrame;
54
} /* namespace js */
55
56
extern JS_FRIEND_API void JS_SetGrayGCRootsTracer(JSContext* cx,
57
JSTraceDataOp traceOp,
58
void* data);
59
60
extern JS_FRIEND_API JSObject* JS_FindCompilationScope(JSContext* cx,
61
JS::HandleObject obj);
62
63
extern JS_FRIEND_API JSFunction* JS_GetObjectFunction(JSObject* obj);
64
65
extern JS_FRIEND_API bool JS_SplicePrototype(JSContext* cx,
66
JS::HandleObject obj,
67
JS::HandleObject proto);
68
69
extern JS_FRIEND_API JSObject* JS_NewObjectWithUniqueType(
70
JSContext* cx, const JSClass* clasp, JS::HandleObject proto);
71
72
/**
73
* Allocate an object in exactly the same way as JS_NewObjectWithGivenProto, but
74
* without invoking the metadata callback on it. This allows creation of
75
* internal bookkeeping objects that are guaranteed to not have metadata
76
* attached to them.
77
*/
78
extern JS_FRIEND_API JSObject* JS_NewObjectWithoutMetadata(
79
JSContext* cx, const JSClass* clasp, JS::Handle<JSObject*> proto);
80
81
extern JS_FRIEND_API bool JS_NondeterministicGetWeakMapKeys(
82
JSContext* cx, JS::HandleObject obj, JS::MutableHandleObject ret);
83
84
extern JS_FRIEND_API bool JS_NondeterministicGetWeakSetKeys(
85
JSContext* cx, JS::HandleObject obj, JS::MutableHandleObject ret);
86
87
// Raw JSScript* because this needs to be callable from a signal handler.
88
extern JS_FRIEND_API unsigned JS_PCToLineNumber(JSScript* script,
89
jsbytecode* pc,
90
unsigned* columnp = nullptr);
91
92
/**
93
* Determine whether the given object is backed by a DeadObjectProxy.
94
*
95
* Such objects hold no other objects (they have no outgoing reference edges)
96
* and will throw if you touch them (e.g. by reading/writing a property).
97
*/
98
extern JS_FRIEND_API bool JS_IsDeadWrapper(JSObject* obj);
99
100
/**
101
* Creates a new dead wrapper object in the given scope. To be used when
102
* attempting to wrap objects from scopes which are already dead.
103
*
104
* If origObject is passed, it must be an proxy object, and will be
105
* used to determine the characteristics of the new dead wrapper.
106
*/
107
extern JS_FRIEND_API JSObject* JS_NewDeadWrapper(
108
JSContext* cx, JSObject* origObject = nullptr);
109
110
namespace js {
111
112
/**
113
* Get the script private value associated with an object, if any.
114
*
115
* The private value is set with SetScriptPrivate() or SetModulePrivate() and is
116
* internally stored on the relevant ScriptSourceObject.
117
*
118
* This is used by the cycle collector to trace through
119
* ScriptSourceObjects. This allows private values to contain an nsISupports
120
* pointer and hence support references to cycle collected C++ objects.
121
*/
122
JS_FRIEND_API JS::Value MaybeGetScriptPrivate(JSObject* object);
123
124
} // namespace js
125
126
/*
127
* Used by the cycle collector to trace through a shape or object group and
128
* all cycle-participating data it reaches, using bounded stack space.
129
*/
130
extern JS_FRIEND_API void JS_TraceShapeCycleCollectorChildren(
131
JS::CallbackTracer* trc, JS::GCCellPtr shape);
132
extern JS_FRIEND_API void JS_TraceObjectGroupCycleCollectorChildren(
133
JS::CallbackTracer* trc, JS::GCCellPtr group);
134
135
/*
136
* Telemetry reasons passed to the accumulate telemetry callback.
137
*
138
* It's OK for these enum values to change as they will be mapped to a fixed
139
* member of the mozilla::Telemetry::HistogramID enum by the callback.
140
*/
141
enum {
142
JS_TELEMETRY_GC_REASON,
143
JS_TELEMETRY_GC_IS_ZONE_GC,
144
JS_TELEMETRY_GC_MS,
145
JS_TELEMETRY_GC_BUDGET_MS,
146
JS_TELEMETRY_GC_BUDGET_OVERRUN,
147
JS_TELEMETRY_GC_ANIMATION_MS,
148
JS_TELEMETRY_GC_MAX_PAUSE_MS_2,
149
JS_TELEMETRY_GC_MARK_MS,
150
JS_TELEMETRY_GC_SWEEP_MS,
151
JS_TELEMETRY_GC_COMPACT_MS,
152
JS_TELEMETRY_GC_MARK_ROOTS_MS,
153
JS_TELEMETRY_GC_MARK_GRAY_MS,
154
JS_TELEMETRY_GC_SLICE_MS,
155
JS_TELEMETRY_GC_SLOW_PHASE,
156
JS_TELEMETRY_GC_SLOW_TASK,
157
JS_TELEMETRY_GC_MMU_50,
158
JS_TELEMETRY_GC_RESET,
159
JS_TELEMETRY_GC_RESET_REASON,
160
JS_TELEMETRY_GC_INCREMENTAL_DISABLED,
161
JS_TELEMETRY_GC_NON_INCREMENTAL,
162
JS_TELEMETRY_GC_NON_INCREMENTAL_REASON,
163
JS_TELEMETRY_GC_SCC_SWEEP_TOTAL_MS,
164
JS_TELEMETRY_GC_SCC_SWEEP_MAX_PAUSE_MS,
165
JS_TELEMETRY_GC_MINOR_REASON,
166
JS_TELEMETRY_GC_MINOR_REASON_LONG,
167
JS_TELEMETRY_GC_MINOR_US,
168
JS_TELEMETRY_GC_NURSERY_BYTES,
169
JS_TELEMETRY_GC_PRETENURE_COUNT,
170
JS_TELEMETRY_GC_NURSERY_PROMOTION_RATE,
171
JS_TELEMETRY_GC_TENURED_SURVIVAL_RATE,
172
JS_TELEMETRY_GC_MARK_RATE,
173
JS_TELEMETRY_GC_TIME_BETWEEN_S,
174
JS_TELEMETRY_GC_TIME_BETWEEN_SLICES_MS,
175
JS_TELEMETRY_GC_SLICE_COUNT,
176
JS_TELEMETRY_GC_EFFECTIVENESS,
177
JS_TELEMETRY_PRIVILEGED_PARSER_COMPILE_LAZY_AFTER_MS,
178
JS_TELEMETRY_WEB_PARSER_COMPILE_LAZY_AFTER_MS,
179
JS_TELEMETRY_END
180
};
181
182
typedef void (*JSAccumulateTelemetryDataCallback)(int id, uint32_t sample,
183
const char* key);
184
185
extern JS_FRIEND_API void JS_SetAccumulateTelemetryCallback(
186
JSContext* cx, JSAccumulateTelemetryDataCallback callback);
187
188
/*
189
* Use counter names passed to the accumulate use counter callback.
190
*
191
* It's OK to for these enum values to change as they will be mapped to a
192
* fixed member of the mozilla::UseCounter enum by the callback.
193
*/
194
195
enum class JSUseCounter { ASMJS, WASM };
196
197
typedef void (*JSSetUseCounterCallback)(JSObject* obj, JSUseCounter counter);
198
199
extern JS_FRIEND_API void JS_SetSetUseCounterCallback(
200
JSContext* cx, JSSetUseCounterCallback callback);
201
202
extern JS_FRIEND_API void JS_ReportFirstCompileTime(
203
JS::HandleScript script, mozilla::TimeDuration& parse,
204
mozilla::TimeDuration& emit);
205
206
extern JS_FRIEND_API JSPrincipals* JS_GetScriptPrincipals(JSScript* script);
207
208
namespace js {
209
210
// Release-assert the compartment contains exactly one realm.
211
extern JS_FRIEND_API void AssertCompartmentHasSingleRealm(
212
JS::Compartment* comp);
213
214
extern JS_FRIEND_API JS::Realm* GetScriptRealm(JSScript* script);
215
} /* namespace js */
216
217
extern JS_FRIEND_API bool JS_ScriptHasMutedErrors(JSScript* script);
218
219
extern JS_FRIEND_API JSObject* JS_CloneObject(JSContext* cx,
220
JS::HandleObject obj,
221
JS::HandleObject proto);
222
223
/**
224
* Copy the own properties of src to dst in a fast way. src and dst must both
225
* be native and must be in the compartment of cx. They must have the same
226
* class, the same parent, and the same prototype. Class reserved slots will
227
* NOT be copied.
228
*
229
* dst must not have any properties on it before this function is called.
230
*
231
* src must have been allocated via JS_NewObjectWithoutMetadata so that we can
232
* be sure it has no metadata that needs copying to dst. This also means that
233
* dst needs to have the compartment global as its parent. This function will
234
* preserve the existing metadata on dst, if any.
235
*/
236
extern JS_FRIEND_API bool JS_InitializePropertiesFromCompatibleNativeObject(
237
JSContext* cx, JS::HandleObject dst, JS::HandleObject src);
238
239
namespace js {
240
241
JS_FRIEND_API bool GetBuiltinClass(JSContext* cx, JS::HandleObject obj,
242
ESClass* cls);
243
244
JS_FRIEND_API bool IsArgumentsObject(JS::HandleObject obj);
245
246
JS_FRIEND_API const char* ObjectClassName(JSContext* cx, JS::HandleObject obj);
247
248
JS_FRIEND_API void ReportOverRecursed(JSContext* maybecx);
249
250
JS_FRIEND_API bool AddRawValueRoot(JSContext* cx, JS::Value* vp,
251
const char* name);
252
253
JS_FRIEND_API void RemoveRawValueRoot(JSContext* cx, JS::Value* vp);
254
255
JS_FRIEND_API JSAtom* GetPropertyNameFromPC(JSScript* script, jsbytecode* pc);
256
257
#if defined(DEBUG) || defined(JS_JITSPEW)
258
259
/*
260
* Routines to print out values during debugging. These are FRIEND_API to help
261
* the debugger find them and to support temporarily hacking js::Dump* calls
262
* into other code. Note that there are overloads that do not require the FILE*
263
* parameter, which will default to stderr.
264
*/
265
266
extern JS_FRIEND_API void DumpString(JSString* str, FILE* fp);
267
268
extern JS_FRIEND_API void DumpAtom(JSAtom* atom, FILE* fp);
269
270
extern JS_FRIEND_API void DumpObject(JSObject* obj, FILE* fp);
271
272
extern JS_FRIEND_API void DumpChars(const char16_t* s, size_t n, FILE* fp);
273
274
extern JS_FRIEND_API void DumpValue(const JS::Value& val, FILE* fp);
275
276
extern JS_FRIEND_API void DumpId(jsid id, FILE* fp);
277
278
extern JS_FRIEND_API void DumpInterpreterFrame(
279
JSContext* cx, FILE* fp, InterpreterFrame* start = nullptr);
280
281
extern JS_FRIEND_API bool DumpPC(JSContext* cx, FILE* fp);
282
283
extern JS_FRIEND_API bool DumpScript(JSContext* cx, JSScript* scriptArg,
284
FILE* fp);
285
286
// Versions for use directly in a debugger (default parameters are not handled
287
// well in gdb; built-in handles like stderr are not handled well in lldb.)
288
extern JS_FRIEND_API void DumpString(JSString* str);
289
extern JS_FRIEND_API void DumpAtom(JSAtom* atom);
290
extern JS_FRIEND_API void DumpObject(JSObject* obj);
291
extern JS_FRIEND_API void DumpChars(const char16_t* s, size_t n);
292
extern JS_FRIEND_API void DumpValue(const JS::Value& val);
293
extern JS_FRIEND_API void DumpId(jsid id);
294
extern JS_FRIEND_API void DumpInterpreterFrame(
295
JSContext* cx, InterpreterFrame* start = nullptr);
296
extern JS_FRIEND_API bool DumpPC(JSContext* cx);
297
extern JS_FRIEND_API bool DumpScript(JSContext* cx, JSScript* scriptArg);
298
299
#endif
300
301
extern JS_FRIEND_API void DumpBacktrace(JSContext* cx, FILE* fp);
302
303
extern JS_FRIEND_API void DumpBacktrace(JSContext* cx);
304
305
} // namespace js
306
307
namespace JS {
308
309
/** Exposed for DumpJSStack */
310
extern JS_FRIEND_API JS::UniqueChars FormatStackDump(JSContext* cx,
311
bool showArgs,
312
bool showLocals,
313
bool showThisProps);
314
315
/**
316
* Set all of the uninitialized lexicals on an object to undefined. Return
317
* true if any lexicals were initialized and false otherwise.
318
* */
319
extern JS_FRIEND_API bool ForceLexicalInitialization(JSContext* cx,
320
HandleObject obj);
321
322
/**
323
* Whether we are poisoning unused/released data for error detection. Governed
324
* by the JS_GC_POISONING #ifdef as well as the $JSGC_DISABLE_POISONING
325
* environment variable.
326
*/
327
extern JS_FRIEND_API int IsGCPoisoning();
328
329
extern JS_FRIEND_API JSPrincipals* GetRealmPrincipals(JS::Realm* realm);
330
331
extern JS_FRIEND_API void SetRealmPrincipals(JS::Realm* realm,
332
JSPrincipals* principals);
333
334
extern JS_FRIEND_API bool GetIsSecureContext(JS::Realm* realm);
335
336
} // namespace JS
337
338
/**
339
* Copies all own properties from |obj| to |target|. Both |obj| and |target|
340
* must not be cross-compartment wrappers because we have to enter their realms.
341
*
342
* This function immediately enters a realm, and does not impose any
343
* restrictions on the realm of |cx|.
344
*/
345
extern JS_FRIEND_API bool JS_CopyPropertiesFrom(JSContext* cx,
346
JS::HandleObject target,
347
JS::HandleObject obj);
348
349
/*
350
* Single-property version of the above. This function asserts that an |own|
351
* property of the given name exists on |obj|.
352
*
353
* On entry, |cx| must be same-compartment with |obj|. |target| must not be a
354
* cross-compartment wrapper because we have to enter its realm.
355
*
356
* The copyBehavior argument controls what happens with
357
* non-configurable properties.
358
*/
359
typedef enum {
360
MakeNonConfigurableIntoConfigurable,
361
CopyNonConfigurableAsIs
362
} PropertyCopyBehavior;
363
364
extern JS_FRIEND_API bool JS_CopyPropertyFrom(
365
JSContext* cx, JS::HandleId id, JS::HandleObject target,
366
JS::HandleObject obj,
367
PropertyCopyBehavior copyBehavior = CopyNonConfigurableAsIs);
368
369
extern JS_FRIEND_API bool JS_WrapPropertyDescriptor(
370
JSContext* cx, JS::MutableHandle<JS::PropertyDescriptor> desc);
371
372
struct JSFunctionSpecWithHelp {
373
const char* name;
374
JSNative call;
375
uint16_t nargs;
376
uint16_t flags;
377
const JSJitInfo* jitInfo;
378
const char* usage;
379
const char* help;
380
};
381
382
#define JS_FN_HELP(name, call, nargs, flags, usage, help) \
383
{ name, call, nargs, (flags) | JSPROP_ENUMERATE, nullptr, usage, help }
384
#define JS_INLINABLE_FN_HELP(name, call, nargs, flags, native, usage, help) \
385
{ \
386
name, call, nargs, (flags) | JSPROP_ENUMERATE, &js::jit::JitInfo_##native, \
387
usage, help \
388
}
389
#define JS_FS_HELP_END \
390
{ nullptr, nullptr, 0, 0, nullptr, nullptr }
391
392
extern JS_FRIEND_API bool JS_DefineFunctionsWithHelp(
393
JSContext* cx, JS::HandleObject obj, const JSFunctionSpecWithHelp* fs);
394
395
namespace js {
396
397
/**
398
* Use the runtime's internal handling of job queues for Promise jobs.
399
*
400
* Most embeddings, notably web browsers, will have their own task scheduling
401
* systems and need to integrate handling of Promise jobs into that, so they
402
* will want to manage job queues themselves. For basic embeddings such as the
403
* JS shell that don't have an event loop of their own, it's easier to have
404
* SpiderMonkey handle job queues internally.
405
*
406
* Note that the embedding still has to trigger processing of job queues at
407
* right time(s), such as after evaluation of a script has run to completion.
408
*/
409
extern JS_FRIEND_API bool UseInternalJobQueues(JSContext* cx);
410
411
/**
412
* Enqueue |job| on the internal job queue.
413
*
414
* This is useful in tests for creating situations where a call occurs with no
415
* other JavaScript on the stack.
416
*/
417
extern JS_FRIEND_API bool EnqueueJob(JSContext* cx, JS::HandleObject job);
418
419
/**
420
* Instruct the runtime to stop draining the internal job queue.
421
*
422
* Useful if the embedding is in the process of quitting in reaction to a
423
* builtin being called, or if it wants to resume executing jobs later on.
424
*/
425
extern JS_FRIEND_API void StopDrainingJobQueue(JSContext* cx);
426
427
extern JS_FRIEND_API void RunJobs(JSContext* cx);
428
429
extern JS_FRIEND_API JS::Zone* GetRealmZone(JS::Realm* realm);
430
431
typedef bool (*PreserveWrapperCallback)(JSContext* cx, JS::HandleObject obj);
432
433
typedef enum {
434
CollectNurseryBeforeDump,
435
IgnoreNurseryObjects
436
} DumpHeapNurseryBehaviour;
437
438
/**
439
* Dump the complete object graph of heap-allocated things.
440
* fp is the file for the dump output.
441
*/
442
extern JS_FRIEND_API void DumpHeap(
443
JSContext* cx, FILE* fp, DumpHeapNurseryBehaviour nurseryBehaviour,
444
mozilla::MallocSizeOf mallocSizeOf = nullptr);
445
446
extern JS_FRIEND_API bool IsSystemRealm(JS::Realm* realm);
447
448
extern JS_FRIEND_API bool IsSystemCompartment(JS::Compartment* comp);
449
450
extern JS_FRIEND_API bool IsSystemZone(JS::Zone* zone);
451
452
extern JS_FRIEND_API bool IsAtomsZone(JS::Zone* zone);
453
454
struct WeakMapTracer {
455
JSRuntime* runtime;
456
457
explicit WeakMapTracer(JSRuntime* rt) : runtime(rt) {}
458
459
// Weak map tracer callback, called once for every binding of every
460
// weak map that was live at the time of the last garbage collection.
461
//
462
// m will be nullptr if the weak map is not contained in a JS Object.
463
//
464
// The callback should not GC (and will assert in a debug build if it does
465
// so.)
466
virtual void trace(JSObject* m, JS::GCCellPtr key, JS::GCCellPtr value) = 0;
467
};
468
469
extern JS_FRIEND_API void TraceWeakMaps(WeakMapTracer* trc);
470
471
extern JS_FRIEND_API bool AreGCGrayBitsValid(JSRuntime* rt);
472
473
extern JS_FRIEND_API bool ZoneGlobalsAreAllGray(JS::Zone* zone);
474
475
extern JS_FRIEND_API bool IsCompartmentZoneSweepingOrCompacting(
476
JS::Compartment* comp);
477
478
typedef void (*GCThingCallback)(void* closure, JS::GCCellPtr thing);
479
480
extern JS_FRIEND_API void VisitGrayWrapperTargets(JS::Zone* zone,
481
GCThingCallback callback,
482
void* closure);
483
484
/**
485
* Invoke cellCallback on every gray JSObject in the given zone.
486
*/
487
extern JS_FRIEND_API void IterateGrayObjects(JS::Zone* zone,
488
GCThingCallback cellCallback,
489
void* data);
490
491
/**
492
* Invoke cellCallback on every gray JSObject in the given zone while cycle
493
* collection is in progress.
494
*/
495
extern JS_FRIEND_API void IterateGrayObjectsUnderCC(
496
JS::Zone* zone, GCThingCallback cellCallback, void* data);
497
498
#if defined(JS_GC_ZEAL) || defined(DEBUG)
499
// Trace the heap and check there are no black to gray edges. These are
500
// not allowed since the cycle collector could throw away the gray thing and
501
// leave a dangling pointer.
502
//
503
// This doesn't trace weak maps as these are handled separately.
504
extern JS_FRIEND_API bool CheckGrayMarkingState(JSRuntime* rt);
505
#endif
506
507
#ifdef JS_HAS_CTYPES
508
extern JS_FRIEND_API size_t
509
SizeOfDataIfCDataObject(mozilla::MallocSizeOf mallocSizeOf, JSObject* obj);
510
#endif
511
512
// Note: this returns nullptr iff |zone| is the atoms zone.
513
extern JS_FRIEND_API JS::Realm* GetAnyRealmInZone(JS::Zone* zone);
514
515
// Returns the first realm's global in a compartment. Note: this is not
516
// guaranteed to always be the same realm because individual realms can be
517
// collected by the GC.
518
extern JS_FRIEND_API JSObject* GetFirstGlobalInCompartment(
519
JS::Compartment* comp);
520
521
// Returns true if the compartment contains a global object and this global is
522
// not being collected.
523
extern JS_FRIEND_API bool CompartmentHasLiveGlobal(JS::Compartment* comp);
524
525
// Returns true if this compartment can be shared across multiple Realms. Used
526
// when we're looking for an existing compartment to place a new Realm in.
527
extern JS_FRIEND_API bool IsSharableCompartment(JS::Compartment* comp);
528
529
/*
530
* Shadow declarations of JS internal structures, for access by inline access
531
* functions below. Do not use these structures in any other way. When adding
532
* new fields for access by inline methods, make sure to add static asserts to
533
* the original header file to ensure that offsets are consistent.
534
*/
535
namespace shadow {
536
537
struct ObjectGroup {
538
const JSClass* clasp;
539
JSObject* proto;
540
JS::Realm* realm;
541
};
542
543
struct BaseShape {
544
const JSClass* clasp_;
545
JSObject* parent;
546
};
547
548
class Shape {
549
public:
550
shadow::BaseShape* base;
551
jsid _1;
552
uint32_t immutableFlags;
553
554
static const uint32_t FIXED_SLOTS_SHIFT = 24;
555
static const uint32_t FIXED_SLOTS_MASK = 0x1f << FIXED_SLOTS_SHIFT;
556
};
557
558
/**
559
* This layout is shared by all native objects. For non-native objects, the
560
* group may always be accessed safely, and other members may be as well,
561
* depending on the object's specific layout.
562
*/
563
struct Object {
564
shadow::ObjectGroup* group;
565
shadow::Shape* shape;
566
JS::Value* slots;
567
void* _1;
568
569
static constexpr size_t MAX_FIXED_SLOTS = 16;
570
571
size_t numFixedSlots() const {
572
return (shape->immutableFlags & Shape::FIXED_SLOTS_MASK) >>
573
Shape::FIXED_SLOTS_SHIFT;
574
}
575
576
JS::Value* fixedSlots() const {
577
return (JS::Value*)(uintptr_t(this) + sizeof(shadow::Object));
578
}
579
580
JS::Value& slotRef(size_t slot) const {
581
size_t nfixed = numFixedSlots();
582
if (slot < nfixed) {
583
return fixedSlots()[slot];
584
}
585
return slots[slot - nfixed];
586
}
587
};
588
589
struct Function {
590
Object base;
591
uint16_t nargs;
592
uint16_t flags;
593
/* Used only for natives */
594
JSNative native;
595
const JSJitInfo* jitinfo;
596
void* _1;
597
};
598
599
} /* namespace shadow */
600
601
// This is equal to |&JSObject::class_|. Use it in places where you don't want
602
// to #include vm/JSObject.h.
603
extern JS_FRIEND_DATA const JSClass* const ObjectClassPtr;
604
605
inline const JSClass* GetObjectClass(const JSObject* obj) {
606
return reinterpret_cast<const shadow::Object*>(obj)->group->clasp;
607
}
608
609
JS_FRIEND_API const JSClass* ProtoKeyToClass(JSProtoKey key);
610
611
// Returns the key for the class inherited by a given standard class (that
612
// is to say, the prototype of this standard class's prototype).
613
//
614
// You must be sure that this corresponds to a standard class with a cached
615
// JSProtoKey before calling this function. In general |key| will match the
616
// cached proto key, except in cases where multiple JSProtoKeys share a
617
// JSClass.
618
inline JSProtoKey InheritanceProtoKeyForStandardClass(JSProtoKey key) {
619
// [Object] has nothing to inherit from.
620
if (key == JSProto_Object) {
621
return JSProto_Null;
622
}
623
624
// If we're ClassSpec defined return the proto key from that
625
if (ProtoKeyToClass(key)->specDefined()) {
626
return ProtoKeyToClass(key)->specInheritanceProtoKey();
627
}
628
629
// Otherwise, we inherit [Object].
630
return JSProto_Object;
631
}
632
633
JS_FRIEND_API bool ShouldIgnorePropertyDefinition(JSContext* cx, JSProtoKey key,
634
jsid id);
635
636
JS_FRIEND_API bool IsFunctionObject(JSObject* obj);
637
638
JS_FRIEND_API bool UninlinedIsCrossCompartmentWrapper(const JSObject* obj);
639
640
static MOZ_ALWAYS_INLINE JS::Compartment* GetObjectCompartment(JSObject* obj) {
641
JS::Realm* realm = reinterpret_cast<shadow::Object*>(obj)->group->realm;
642
return JS::GetCompartmentForRealm(realm);
643
}
644
645
// CrossCompartmentWrappers are shared by all realms within the compartment, so
646
// getting a wrapper's realm usually doesn't make sense.
647
static MOZ_ALWAYS_INLINE JS::Realm* GetNonCCWObjectRealm(JSObject* obj) {
648
MOZ_ASSERT(!js::UninlinedIsCrossCompartmentWrapper(obj));
649
return reinterpret_cast<shadow::Object*>(obj)->group->realm;
650
}
651
652
JS_FRIEND_API JSObject* GetPrototypeNoProxy(JSObject* obj);
653
654
JS_FRIEND_API void AssertSameCompartment(JSContext* cx, JSObject* obj);
655
656
JS_FRIEND_API void AssertSameCompartment(JSContext* cx, JS::HandleValue v);
657
658
#ifdef JS_DEBUG
659
JS_FRIEND_API void AssertSameCompartment(JSObject* objA, JSObject* objB);
660
#else
661
inline void AssertSameCompartment(JSObject* objA, JSObject* objB) {}
662
#endif
663
664
JS_FRIEND_API void NotifyAnimationActivity(JSObject* obj);
665
666
JS_FRIEND_API JSFunction* DefineFunctionWithReserved(
667
JSContext* cx, JSObject* obj, const char* name, JSNative call,
668
unsigned nargs, unsigned attrs);
669
670
JS_FRIEND_API JSFunction* NewFunctionWithReserved(JSContext* cx, JSNative call,
671
unsigned nargs,
672
unsigned flags,
673
const char* name);
674
675
JS_FRIEND_API JSFunction* NewFunctionByIdWithReserved(JSContext* cx,
676
JSNative native,
677
unsigned nargs,
678
unsigned flags, jsid id);
679
680
JS_FRIEND_API const JS::Value& GetFunctionNativeReserved(JSObject* fun,
681
size_t which);
682
683
JS_FRIEND_API void SetFunctionNativeReserved(JSObject* fun, size_t which,
684
const JS::Value& val);
685
686
JS_FRIEND_API bool FunctionHasNativeReserved(JSObject* fun);
687
688
JS_FRIEND_API bool GetObjectProto(JSContext* cx, JS::HandleObject obj,
689
JS::MutableHandleObject proto);
690
691
extern JS_FRIEND_API JSObject* GetStaticPrototype(JSObject* obj);
692
693
JS_FRIEND_API bool GetRealmOriginalEval(JSContext* cx,
694
JS::MutableHandleObject eval);
695
696
inline void* GetObjectPrivate(JSObject* obj) {
697
MOZ_ASSERT(GetObjectClass(obj)->flags & JSCLASS_HAS_PRIVATE);
698
const shadow::Object* nobj = reinterpret_cast<const shadow::Object*>(obj);
699
void** addr =
700
reinterpret_cast<void**>(&nobj->fixedSlots()[nobj->numFixedSlots()]);
701
return *addr;
702
}
703
704
/**
705
* Get the value stored in an object's reserved slot. This can be used with
706
* both native objects and proxies, but if |obj| is known to be a proxy
707
* GetProxyReservedSlot is a bit more efficient.
708
*/
709
inline const JS::Value& GetReservedSlot(JSObject* obj, size_t slot) {
710
MOZ_ASSERT(slot < JSCLASS_RESERVED_SLOTS(GetObjectClass(obj)));
711
return reinterpret_cast<const shadow::Object*>(obj)->slotRef(slot);
712
}
713
714
JS_FRIEND_API void SetReservedSlotWithBarrier(JSObject* obj, size_t slot,
715
const JS::Value& value);
716
717
/**
718
* Store a value in an object's reserved slot. This can be used with
719
* both native objects and proxies, but if |obj| is known to be a proxy
720
* SetProxyReservedSlot is a bit more efficient.
721
*/
722
inline void SetReservedSlot(JSObject* obj, size_t slot,
723
const JS::Value& value) {
724
MOZ_ASSERT(slot < JSCLASS_RESERVED_SLOTS(GetObjectClass(obj)));
725
shadow::Object* sobj = reinterpret_cast<shadow::Object*>(obj);
726
if (sobj->slotRef(slot).isGCThing() || value.isGCThing()) {
727
SetReservedSlotWithBarrier(obj, slot, value);
728
} else {
729
sobj->slotRef(slot) = value;
730
}
731
}
732
733
JS_FRIEND_API uint32_t GetObjectSlotSpan(JSObject* obj);
734
735
inline const JS::Value& GetObjectSlot(JSObject* obj, size_t slot) {
736
MOZ_ASSERT(slot < GetObjectSlotSpan(obj));
737
return reinterpret_cast<const shadow::Object*>(obj)->slotRef(slot);
738
}
739
740
MOZ_ALWAYS_INLINE size_t GetAtomLength(JSAtom* atom) {
741
return reinterpret_cast<JS::shadow::String*>(atom)->length();
742
}
743
744
// Maximum length of a JS string. This is chosen so that the number of bytes
745
// allocated for a null-terminated TwoByte string still fits in int32_t.
746
static const uint32_t MaxStringLength = (1 << 30) - 2;
747
748
static_assert((uint64_t(MaxStringLength) + 1) * sizeof(char16_t) <= INT32_MAX,
749
"size of null-terminated JSString char buffer must fit in "
750
"INT32_MAX");
751
752
MOZ_ALWAYS_INLINE size_t GetLinearStringLength(JSLinearString* s) {
753
return reinterpret_cast<JS::shadow::String*>(s)->length();
754
}
755
756
MOZ_ALWAYS_INLINE bool LinearStringHasLatin1Chars(JSLinearString* s) {
757
return reinterpret_cast<JS::shadow::String*>(s)->flags() &
758
JS::shadow::String::LATIN1_CHARS_BIT;
759
}
760
761
MOZ_ALWAYS_INLINE bool AtomHasLatin1Chars(JSAtom* atom) {
762
return reinterpret_cast<JS::shadow::String*>(atom)->flags() &
763
JS::shadow::String::LATIN1_CHARS_BIT;
764
}
765
766
MOZ_ALWAYS_INLINE bool StringHasLatin1Chars(JSString* s) {
767
return reinterpret_cast<JS::shadow::String*>(s)->flags() &
768
JS::shadow::String::LATIN1_CHARS_BIT;
769
}
770
771
MOZ_ALWAYS_INLINE const JS::Latin1Char* GetLatin1LinearStringChars(
772
const JS::AutoRequireNoGC& nogc, JSLinearString* linear) {
773
MOZ_ASSERT(LinearStringHasLatin1Chars(linear));
774
775
using JS::shadow::String;
776
String* s = reinterpret_cast<String*>(linear);
777
if (s->flags() & String::INLINE_CHARS_BIT) {
778
return s->inlineStorageLatin1;
779
}
780
return s->nonInlineCharsLatin1;
781
}
782
783
MOZ_ALWAYS_INLINE const char16_t* GetTwoByteLinearStringChars(
784
const JS::AutoRequireNoGC& nogc, JSLinearString* linear) {
785
MOZ_ASSERT(!LinearStringHasLatin1Chars(linear));
786
787
using JS::shadow::String;
788
String* s = reinterpret_cast<String*>(linear);
789
if (s->flags() & String::INLINE_CHARS_BIT) {
790
return s->inlineStorageTwoByte;
791
}
792
return s->nonInlineCharsTwoByte;
793
}
794
795
MOZ_ALWAYS_INLINE char16_t GetLinearStringCharAt(JSLinearString* linear,
796
size_t index) {
797
MOZ_ASSERT(index < GetLinearStringLength(linear));
798
JS::AutoCheckCannotGC nogc;
799
return LinearStringHasLatin1Chars(linear)
800
? GetLatin1LinearStringChars(nogc, linear)[index]
801
: GetTwoByteLinearStringChars(nogc, linear)[index];
802
}
803
804
MOZ_ALWAYS_INLINE JSLinearString* AtomToLinearString(JSAtom* atom) {
805
return reinterpret_cast<JSLinearString*>(atom);
806
}
807
808
MOZ_ALWAYS_INLINE const JS::Latin1Char* GetLatin1AtomChars(
809
const JS::AutoRequireNoGC& nogc, JSAtom* atom) {
810
return GetLatin1LinearStringChars(nogc, AtomToLinearString(atom));
811
}
812
813
MOZ_ALWAYS_INLINE const char16_t* GetTwoByteAtomChars(
814
const JS::AutoRequireNoGC& nogc, JSAtom* atom) {
815
return GetTwoByteLinearStringChars(nogc, AtomToLinearString(atom));
816
}
817
818
MOZ_ALWAYS_INLINE bool IsExternalString(
819
JSString* str, const JSExternalStringCallbacks** callbacks,
820
const char16_t** chars) {
821
using JS::shadow::String;
822
String* s = reinterpret_cast<String*>(str);
823
824
if ((s->flags() & String::TYPE_FLAGS_MASK) != String::EXTERNAL_FLAGS) {
825
return false;
826
}
827
828
MOZ_ASSERT(JS_IsExternalString(str));
829
*callbacks = s->externalCallbacks;
830
*chars = s->nonInlineCharsTwoByte;
831
return true;
832
}
833
834
JS_FRIEND_API JSLinearString* StringToLinearStringSlow(JSContext* cx,
835
JSString* str);
836
837
MOZ_ALWAYS_INLINE JSLinearString* StringToLinearString(JSContext* cx,
838
JSString* str) {
839
using JS::shadow::String;
840
String* s = reinterpret_cast<String*>(str);
841
if (MOZ_UNLIKELY(!(s->flags() & String::LINEAR_BIT))) {
842
return StringToLinearStringSlow(cx, str);
843
}
844
return reinterpret_cast<JSLinearString*>(str);
845
}
846
847
template <typename CharType>
848
MOZ_ALWAYS_INLINE void CopyLinearStringChars(CharType* dest, JSLinearString* s,
849
size_t len, size_t start = 0);
850
851
MOZ_ALWAYS_INLINE void CopyLinearStringChars(char16_t* dest, JSLinearString* s,
852
size_t len, size_t start = 0) {
853
MOZ_ASSERT(start + len <= GetLinearStringLength(s));
854
JS::AutoCheckCannotGC nogc;
855
if (LinearStringHasLatin1Chars(s)) {
856
const JS::Latin1Char* src = GetLatin1LinearStringChars(nogc, s);
857
for (size_t i = 0; i < len; i++) {
858
dest[i] = src[start + i];
859
}
860
} else {
861
const char16_t* src = GetTwoByteLinearStringChars(nogc, s);
862
mozilla::PodCopy(dest, src + start, len);
863
}
864
}
865
866
MOZ_ALWAYS_INLINE void CopyLinearStringChars(char* dest, JSLinearString* s,
867
size_t len, size_t start = 0) {
868
MOZ_ASSERT(start + len <= GetLinearStringLength(s));
869
JS::AutoCheckCannotGC nogc;
870
if (LinearStringHasLatin1Chars(s)) {
871
const JS::Latin1Char* src = GetLatin1LinearStringChars(nogc, s);
872
for (size_t i = 0; i < len; i++) {
873
dest[i] = char(src[start + i]);
874
}
875
} else {
876
const char16_t* src = GetTwoByteLinearStringChars(nogc, s);
877
for (size_t i = 0; i < len; i++) {
878
dest[i] = char(src[start + i]);
879
}
880
}
881
}
882
883
template <typename CharType>
884
inline bool CopyStringChars(JSContext* cx, CharType* dest, JSString* s,
885
size_t len, size_t start = 0) {
886
JSLinearString* linear = StringToLinearString(cx, s);
887
if (!linear) {
888
return false;
889
}
890
891
CopyLinearStringChars(dest, linear, len, start);
892
return true;
893
}
894
895
/**
896
* Add some or all property keys of obj to the id vector *props.
897
*
898
* The flags parameter controls which property keys are added. Pass a
899
* combination of the following bits:
900
*
901
* JSITER_OWNONLY - Don't also search the prototype chain; only consider
902
* obj's own properties.
903
*
904
* JSITER_HIDDEN - Include nonenumerable properties.
905
*
906
* JSITER_SYMBOLS - Include property keys that are symbols. The default
907
* behavior is to filter out symbols.
908
*
909
* JSITER_SYMBOLSONLY - Exclude non-symbol property keys.
910
*
911
* This is the closest C++ API we have to `Reflect.ownKeys(obj)`, or
912
* equivalently, the ES6 [[OwnPropertyKeys]] internal method. Pass
913
* `JSITER_OWNONLY | JSITER_HIDDEN | JSITER_SYMBOLS` as flags to get
914
* results that match the output of Reflect.ownKeys.
915
*/
916
JS_FRIEND_API bool GetPropertyKeys(JSContext* cx, JS::HandleObject obj,
917
unsigned flags,
918
JS::MutableHandleIdVector props);
919
920
JS_FRIEND_API bool AppendUnique(JSContext* cx, JS::MutableHandleIdVector base,
921
JS::HandleIdVector others);
922
923
/**
924
* Determine whether the given string is an array index in the sense of
926
*
927
* If it isn't, returns false.
928
*
929
* If it is, returns true and outputs the index in *indexp.
930
*/
931
JS_FRIEND_API bool StringIsArrayIndex(JSLinearString* str, uint32_t* indexp);
932
933
/**
934
* Overloads of StringIsArrayIndex taking (char*,length) pairs. These
935
* behave the same as the JSLinearString version.
936
*/
937
JS_FRIEND_API bool StringIsArrayIndex(const char* str, uint32_t length,
938
uint32_t* indexp);
939
940
JS_FRIEND_API bool StringIsArrayIndex(const char16_t* str, uint32_t length,
941
uint32_t* indexp);
942
943
JS_FRIEND_API void SetPreserveWrapperCallback(JSContext* cx,
944
PreserveWrapperCallback callback);
945
946
JS_FRIEND_API bool IsObjectInContextCompartment(JSObject* obj,
947
const JSContext* cx);
948
949
/*
950
* NB: keep these in sync with the copy in builtin/SelfHostingDefines.h.
951
*/
952
/* 0x1 is no longer used */
953
/* 0x2 is no longer used */
954
/* 0x4 is no longer used */
955
#define JSITER_OWNONLY 0x8 /* iterate over obj's own properties only */
956
#define JSITER_HIDDEN 0x10 /* also enumerate non-enumerable properties */
957
#define JSITER_SYMBOLS 0x20 /* also include symbol property keys */
958
#define JSITER_SYMBOLSONLY 0x40 /* exclude string property keys */
959
#define JSITER_FORAWAITOF 0x80 /* for-await-of */
960
961
JS_FRIEND_API bool RunningWithTrustedPrincipals(JSContext* cx);
962
963
MOZ_ALWAYS_INLINE uintptr_t GetNativeStackLimit(JSContext* cx,
964
JS::StackKind kind,
965
int extraAllowance = 0) {
966
uintptr_t limit = JS::RootingContext::get(cx)->nativeStackLimit[kind];
967
#if JS_STACK_GROWTH_DIRECTION > 0
968
limit += extraAllowance;
969
#else
970
limit -= extraAllowance;
971
#endif
972
return limit;
973
}
974
975
MOZ_ALWAYS_INLINE uintptr_t GetNativeStackLimit(JSContext* cx,
976
int extraAllowance = 0) {
977
JS::StackKind kind = RunningWithTrustedPrincipals(cx)
978
? JS::StackForTrustedScript
979
: JS::StackForUntrustedScript;
980
return GetNativeStackLimit(cx, kind, extraAllowance);
981
}
982
983
/*
984
* These functions return |false| if we are close to using up the C++ stack.
985
* They also report an overrecursion error, except for the DontReport variants.
986
* The CheckSystemRecursionLimit variant gives us a little extra space so we
987
* can ensure that crucial code is able to run. CheckRecursionLimitConservative
988
* allows less space than any other check, including a safety buffer (as in, it
989
* uses the untrusted limit and subtracts a little more from it).
990
*/
991
992
MOZ_ALWAYS_INLINE bool CheckRecursionLimit(JSContext* cx, uintptr_t limit) {
993
int stackDummy;
994
995
JS_STACK_OOM_POSSIBLY_FAIL_REPORT();
996
997
if (!JS_CHECK_STACK_SIZE(limit, &stackDummy)) {
998
ReportOverRecursed(cx);
999
return false;
1000
}
1001
return true;
1002
}
1003
1004
MOZ_ALWAYS_INLINE bool CheckRecursionLimitDontReport(uintptr_t limit) {
1005
int stackDummy;
1006
1007
JS_STACK_OOM_POSSIBLY_FAIL();
1008
1009
return JS_CHECK_STACK_SIZE(limit, &stackDummy);
1010
}
1011
1012
MOZ_ALWAYS_INLINE bool CheckRecursionLimit(JSContext* cx) {
1013
JS_STACK_OOM_POSSIBLY_FAIL_REPORT();
1014
1015
// GetNativeStackLimit(cx) is pretty slow because it has to do an uninlined
1016
// call to RunningWithTrustedPrincipals to determine which stack limit to
1017
// use. To work around this, check the untrusted limit first to avoid the
1018
// overhead in most cases.
1019
uintptr_t untrustedLimit =
1020
GetNativeStackLimit(cx, JS::StackForUntrustedScript);
1021
if (MOZ_LIKELY(CheckRecursionLimitDontReport(untrustedLimit))) {
1022
return true;
1023
}
1024
return CheckRecursionLimit(cx, GetNativeStackLimit(cx));
1025
}
1026
1027
MOZ_ALWAYS_INLINE bool CheckRecursionLimitDontReport(JSContext* cx) {
1028
return CheckRecursionLimitDontReport(GetNativeStackLimit(cx));
1029
}
1030
1031
MOZ_ALWAYS_INLINE bool CheckRecursionLimitWithStackPointerDontReport(
1032
JSContext* cx, void* sp) {
1033
JS_STACK_OOM_POSSIBLY_FAIL();
1034
1035
return JS_CHECK_STACK_SIZE(GetNativeStackLimit(cx), sp);
1036
}
1037
1038
MOZ_ALWAYS_INLINE bool CheckRecursionLimitWithStackPointer(JSContext* cx,
1039
void* sp) {
1040
JS_STACK_OOM_POSSIBLY_FAIL_REPORT();
1041
1042
if (!JS_CHECK_STACK_SIZE(GetNativeStackLimit(cx), sp)) {
1043
ReportOverRecursed(cx);
1044
return false;
1045
}
1046
return true;
1047
}
1048
1049
MOZ_ALWAYS_INLINE bool CheckRecursionLimitWithExtra(JSContext* cx,
1050
size_t extra) {
1051
char stackDummy;
1052
char* sp = &stackDummy;
1053
#if JS_STACK_GROWTH_DIRECTION > 0
1054
sp += extra;
1055
#else
1056
sp -= extra;
1057
#endif
1058
return CheckRecursionLimitWithStackPointer(cx, sp);
1059
}
1060
1061
MOZ_ALWAYS_INLINE bool CheckSystemRecursionLimit(JSContext* cx) {
1062
return CheckRecursionLimit(cx,
1063
GetNativeStackLimit(cx, JS::StackForSystemCode));
1064
}
1065
1066
MOZ_ALWAYS_INLINE bool CheckRecursionLimitConservative(JSContext* cx) {
1067
return CheckRecursionLimit(
1068
cx, GetNativeStackLimit(cx, JS::StackForUntrustedScript,
1069
-1024 * int(sizeof(size_t))));
1070
}
1071
1072
MOZ_ALWAYS_INLINE bool CheckRecursionLimitConservativeDontReport(
1073
JSContext* cx) {
1074
return CheckRecursionLimitDontReport(GetNativeStackLimit(
1075
cx, JS::StackForUntrustedScript, -1024 * int(sizeof(size_t))));
1076
}
1077
1078
JS_FRIEND_API void StartPCCountProfiling(JSContext* cx);
1079
1080
JS_FRIEND_API void StopPCCountProfiling(JSContext* cx);
1081
1082
JS_FRIEND_API void PurgePCCounts(JSContext* cx);
1083
1084
JS_FRIEND_API size_t GetPCCountScriptCount(JSContext* cx);
1085
1086
JS_FRIEND_API JSString* GetPCCountScriptSummary(JSContext* cx, size_t script);
1087
1088
JS_FRIEND_API JSString* GetPCCountScriptContents(JSContext* cx, size_t script);
1089
1090
/**
1091
* Generate lcov trace file content for the current realm, and allocate a new
1092
* buffer and return the content in it, the size of the newly allocated content
1093
* within the buffer would be set to the length out-param. The 'All' variant
1094
* will collect data for all realms in the runtime.
1095
*
1096
* In case of out-of-memory, this function returns nullptr. The length
1097
* out-param is undefined on failure.
1098
*/
1099
JS_FRIEND_API JS::UniqueChars GetCodeCoverageSummary(JSContext* cx,
1100
size_t* length);
1101
JS_FRIEND_API JS::UniqueChars GetCodeCoverageSummaryAll(JSContext* cx,
1102
size_t* length);
1103
1104
typedef bool (*DOMInstanceClassHasProtoAtDepth)(const JSClass* instanceClass,
1105
uint32_t protoID,
1106
uint32_t depth);
1107
struct JSDOMCallbacks {
1108
DOMInstanceClassHasProtoAtDepth instanceClassMatchesProto;
1109
};
1110
typedef struct JSDOMCallbacks DOMCallbacks;
1111
1112
extern JS_FRIEND_API void SetDOMCallbacks(JSContext* cx,
1113
const DOMCallbacks* callbacks);
1114
1115
extern JS_FRIEND_API const DOMCallbacks* GetDOMCallbacks(JSContext* cx);
1116
1117
extern JS_FRIEND_API JSObject* GetTestingFunctions(JSContext* cx);
1118
1119
/* Implemented in jsexn.cpp. */
1120
1121
/**
1122
* Get an error type name from a JSExnType constant.
1123
* Returns nullptr for invalid arguments and JSEXN_INTERNALERR
1124
*/
1125
extern JS_FRIEND_API JSLinearString* GetErrorTypeName(JSContext* cx,
1126
int16_t exnType);
1127
1128
extern JS_FRIEND_API RegExpShared* RegExpToSharedNonInline(
1129
JSContext* cx, JS::HandleObject regexp);
1130
1131
/* Implemented in CrossCompartmentWrapper.cpp. */
1132
typedef enum NukeReferencesToWindow {
1133
NukeWindowReferences,
1134
DontNukeWindowReferences
1135
} NukeReferencesToWindow;
1136
1137
typedef enum NukeReferencesFromTarget {
1138
NukeAllReferences,
1139
NukeIncomingReferences,
1140
} NukeReferencesFromTarget;
1141
1142
/*
1143
* These filters are designed to be ephemeral stack classes, and thus don't
1144
* do any rooting or holding of their members.
1145
*/
1146
struct CompartmentFilter {
1147
virtual bool match(JS::Compartment* c) const = 0;
1148
};
1149
1150
struct AllCompartments : public CompartmentFilter {
1151
virtual bool match(JS::Compartment* c) const override { return true; }
1152
};
1153
1154
struct ContentCompartmentsOnly : public CompartmentFilter {
1155
virtual bool match(JS::Compartment* c) const override {
1156
return !IsSystemCompartment(c);
1157
}
1158
};
1159
1160
struct ChromeCompartmentsOnly : public CompartmentFilter {
1161
virtual bool match(JS::Compartment* c) const override {
1162
return IsSystemCompartment(c);
1163
}
1164
};
1165
1166
struct SingleCompartment : public CompartmentFilter {
1167
JS::Compartment* ours;
1168
explicit SingleCompartment(JS::Compartment* c) : ours(c) {}
1169
virtual bool match(JS::Compartment* c) const override { return c == ours; }
1170
};
1171
1172
extern JS_FRIEND_API bool NukeCrossCompartmentWrappers(
1173
JSContext* cx, const CompartmentFilter& sourceFilter, JS::Realm* target,
1174
NukeReferencesToWindow nukeReferencesToWindow,
1175
NukeReferencesFromTarget nukeReferencesFromTarget);
1176
1177
extern JS_FRIEND_API bool AllowNewWrapper(JS::Compartment* target,
1178
JSObject* obj);
1179
1180
extern JS_FRIEND_API bool NukedObjectRealm(JSObject* obj);
1181
1182
/* Specify information about DOMProxy proxies in the DOM, for use by ICs. */
1183
1184
/*
1185
* The DOMProxyShadowsCheck function will be called to check if the property for
1186
* id should be gotten from the prototype, or if there is an own property that
1187
* shadows it.
1188
* * If ShadowsViaDirectExpando is returned, then the slot at
1189
* listBaseExpandoSlot contains an expando object which has the property in
1190
* question.
1191
* * If ShadowsViaIndirectExpando is returned, then the slot at
1192
* listBaseExpandoSlot contains a private pointer to an ExpandoAndGeneration
1193
* and the expando object in the ExpandoAndGeneration has the property in
1194
* question.
1195
* * If DoesntShadow is returned then the slot at listBaseExpandoSlot should
1196
* either be undefined or point to an expando object that would contain the
1197
* own property.
1198
* * If DoesntShadowUnique is returned then the slot at listBaseExpandoSlot
1199
* should contain a private pointer to a ExpandoAndGeneration, which contains
1200
* a JS::Value that should either be undefined or point to an expando object,
1201
* and a uint64 value. If that value changes then the IC for getting a
1202
* property will be invalidated.
1203
* * If Shadows is returned, that means the property is an own property of the
1204
* proxy but doesn't live on the expando object.
1205
*/
1206
1207
struct ExpandoAndGeneration {
1208
ExpandoAndGeneration() : expando(JS::UndefinedValue()), generation(0) {}
1209
1210
void OwnerUnlinked() { ++generation; }
1211
1212
static size_t offsetOfExpando() {
1213
return offsetof(ExpandoAndGeneration, expando);
1214
}
1215
1216
static size_t offsetOfGeneration() {
1217
return offsetof(ExpandoAndGeneration, generation);
1218
}
1219
1220
JS::Heap<JS::Value> expando;
1221
uint64_t generation;
1222
};
1223
1224
typedef enum DOMProxyShadowsResult {
1225
ShadowCheckFailed,
1226
Shadows,
1227
DoesntShadow,
1228
DoesntShadowUnique,
1229
ShadowsViaDirectExpando,
1230
ShadowsViaIndirectExpando
1231
} DOMProxyShadowsResult;
1232
typedef DOMProxyShadowsResult (*DOMProxyShadowsCheck)(JSContext* cx,
1233
JS::HandleObject object,
1234
JS::HandleId id);
1235
JS_FRIEND_API void SetDOMProxyInformation(
1236
const void* domProxyHandlerFamily,
1237
DOMProxyShadowsCheck domProxyShadowsCheck,
1238
const void* domRemoteProxyHandlerFamily);
1239
1240
const void* GetDOMProxyHandlerFamily();
1241
DOMProxyShadowsCheck GetDOMProxyShadowsCheck();
1242
inline bool DOMProxyIsShadowing(DOMProxyShadowsResult result) {
1243
return result == Shadows || result == ShadowsViaDirectExpando ||
1244
result == ShadowsViaIndirectExpando;
1245
}
1246
1247
const void* GetDOMRemoteProxyHandlerFamily();
1248
1249
extern JS_FRIEND_API bool IsDOMRemoteProxyObject(JSObject* object);
1250
1251
// Callbacks and other information for use by the JITs when optimizing accesses
1252
// on xray wrappers.
1253
struct XrayJitInfo {
1254
// Test whether a proxy handler is a cross compartment xray with no
1255
// security checks.
1256
bool (*isCrossCompartmentXray)(const BaseProxyHandler* handler);
1257
1258
// Test whether xrays in |obj|'s compartment have expandos of their own,
1259
// instead of sharing them with Xrays from other compartments.
1260
bool (*compartmentHasExclusiveExpandos)(JSObject* obj);
1261
1262
// Proxy reserved slot used by xrays in sandboxes to store their holder
1263
// object.
1264
size_t xrayHolderSlot;
1265
1266
// Reserved slot used by xray holders to store the xray's expando object.
1267
size_t holderExpandoSlot;
1268
1269
// Reserved slot used by xray expandos to store a custom prototype.
1270
size_t expandoProtoSlot;
1271
};
1272
1273
JS_FRIEND_API void SetXrayJitInfo(XrayJitInfo* info);
1274
1275
XrayJitInfo* GetXrayJitInfo();
1276
1277
/* Implemented in jsdate.cpp. */
1278
1279
/** Detect whether the internal date value is NaN. */
1280
extern JS_FRIEND_API bool DateIsValid(JSContext* cx, JS::HandleObject obj,
1281
bool* isValid);
1282
1283
extern JS_FRIEND_API bool DateGetMsecSinceEpoch(JSContext* cx,
1284
JS::HandleObject obj,
1285
double* msecSinceEpoch);
1286
1287
} /* namespace js */
1288
1289
typedef enum JSErrNum {
1290
#define MSG_DEF(name, count, exception, format) name,
1291
#include "js.msg"
1292
#undef MSG_DEF
1293
JSErr_Limit
1294
} JSErrNum;
1295
1296
namespace js {
1297
1298
/* Implemented in vm/JSContext.cpp. */
1299
1300
extern JS_FRIEND_API const JSErrorFormatString* GetErrorMessage(
1301
void* userRef, const unsigned errorNumber);
1302
1303
struct MOZ_STACK_CLASS JS_FRIEND_API ErrorReport {
1304
explicit ErrorReport(JSContext* cx);
1305
~ErrorReport();
1306
1307
enum SniffingBehavior { WithSideEffects, NoSideEffects };
1308
1309
/**
1310
* Generate a JSErrorReport from the provided thrown value.
1311
*
1312
* If the value is a (possibly wrapped) Error object, the JSErrorReport will
1313
* be exactly initialized from the Error object's information, without
1314
* observable side effects. (The Error object's JSErrorReport is reused, if
1315
* it has one.)
1316
*
1317
* Otherwise various attempts are made to derive JSErrorReport information
1318
* from |exn| and from the current execution state. This process is
1319
* *definitely* inconsistent with any standard, and particulars of the
1320
* behavior implemented here generally shouldn't be relied upon.
1321
*
1322
* If the value of |sniffingBehavior| is |WithSideEffects|, some of these
1323
* attempts *may* invoke user-configurable behavior when |exn| is an object:
1324
* converting |exn| to a string, detecting and getting properties on |exn|,
1325
* accessing |exn|'s prototype chain, and others are possible. Users *must*
1326
* tolerate |ErrorReport::init| potentially having arbitrary effects. Any
1327
* exceptions thrown by these operations will be caught and silently
1328
* ignored, and "default" values will be substituted into the JSErrorReport.
1329
*
1330
* But if the value of |sniffingBehavior| is |NoSideEffects|, these attempts
1331
* *will not* invoke any observable side effects. The JSErrorReport will
1332
* simply contain fewer, less precise details.
1333
*
1334
* Unlike some functions involved in error handling, this function adheres
1335
* to the usual JSAPI return value error behavior.
1336
*/
1337
bool init(JSContext* cx, JS::HandleValue exn,
1338
SniffingBehavior sniffingBehavior);
1339
1340
JSErrorReport* report() { return reportp; }
1341
1342
const JS::ConstUTF8CharsZ toStringResult() { return toStringResult_; }
1343
1344
private:
1345
// More or less an equivalent of JS_ReportErrorNumber/js::ReportErrorNumberVA
1346
// but fills in an ErrorReport instead of reporting it. Uses varargs to
1347
// make it simpler to call js::ExpandErrorArgumentsVA.
1348
//
1349
// Returns false if we fail to actually populate the ErrorReport
1350
// for some reason (probably out of memory).
1351
bool populateUncaughtExceptionReportUTF8(JSContext* cx, ...);
1352
bool populateUncaughtExceptionReportUTF8VA(JSContext* cx, va_list ap);
1353
1354
// Reports exceptions from add-on scopes to telemetry.
1355
void ReportAddonExceptionToTelemetry(JSContext* cx);
1356
1357
// We may have a provided JSErrorReport, so need a way to represent that.
1358
JSErrorReport* reportp;
1359
1360
// Or we may need to synthesize a JSErrorReport one of our own.
1361
JSErrorReport ownedReport;
1362
1363
// Root our exception value to keep a possibly borrowed |reportp| alive.
1364
JS::RootedObject exnObject;
1365
1366
// And for our filename.
1367
JS::UniqueChars filename;
1368
1369
// We may have a result of error.toString().
1370
// FIXME: We should not call error.toString(), since it could have side
1371
// effect (see bug 633623).
1372
JS::ConstUTF8CharsZ toStringResult_;
1373
JS::UniqueChars toStringResultBytesStorage;
1374
};
1375
1376
/* Implemented in vm/StructuredClone.cpp. */
1377
extern JS_FRIEND_API uint64_t GetSCOffset(JSStructuredCloneWriter* writer);
1378
1379
namespace Scalar {
1380
1381
// Scalar types that can appear in typed arrays and typed objects.
1382
// The enum values must be kept in sync with:
1383
// * the JS_SCALARTYPEREPR constants
1384
// * the TYPEDARRAY_KIND constants
1385
// * the SCTAG_TYPED_ARRAY constants
1386
// * JS_FOR_EACH_TYPEDARRAY
1387
// * JS_FOR_PROTOTYPES_
1388
// * JS_FOR_EACH_UNIQUE_SCALAR_TYPE_REPR_CTYPE
1389
// * JIT compilation
1390
enum Type {
1391
Int8 = 0,
1392
Uint8,
1393
Int16,
1394
Uint16,
1395
Int32,
1396
Uint32,
1397
Float32,
1398
Float64,
1399
1400
/**
1401
* Special type that is a uint8_t, but assignments are clamped to [0, 256).
1402
* Treat the raw data type as a uint8_t.
1403
*/
1404
Uint8Clamped,
1405
1406
BigInt64,
1407
BigUint64,
1408
1409
/**
1410
* Types that don't have their own TypedArray equivalent, for now.
1411
*/
1412
MaxTypedArrayViewType,
1413
1414
Int64,
1415
};
1416
1417
static inline size_t byteSize(Type atype) {
1418
switch (atype) {
1419
case Int8:
1420
case Uint8:
1421
case Uint8Clamped:
1422
return 1;
1423
case Int16:
1424
case Uint16:
1425
return 2;
1426
case Int32:
1427
case Uint32:
1428
case Float32:
1429
return 4;
1430
case Int64:
1431
case Float64:
1432
case BigInt64:
1433
case BigUint64:
1434
return 8;
1435
case MaxTypedArrayViewType:
1436
break;
1437
}
1438
MOZ_CRASH("invalid scalar type");
1439
}
1440
1441
static inline bool isSignedIntType(Type atype) {
1442
switch (atype) {
1443
case Int8:
1444
case Int16:
1445
case Int32:
1446
case Int64:
1447
case BigInt64:
1448
return true;
1449
case Uint8:
1450
case Uint8Clamped:
1451
case Uint16:
1452
case Uint32:
1453
case Float32:
1454
case Float64:
1455
case BigUint64:
1456
return false;
1457
case MaxTypedArrayViewType:
1458
break;
1459
}
1460
MOZ_CRASH("invalid scalar type");
1461
}
1462
1463
static inline bool isBigIntType(Type atype) {
1464
switch (atype) {
1465
case BigInt64:
1466
case BigUint64:
1467
return true;
1468
case Int8:
1469
case Int16:
1470
case Int32:
1471
case Int64:
1472
case Uint8:
1473
case Uint8Clamped:
1474
case Uint16:
1475
case Uint32:
1476
case Float32:
1477
case Float64:
1478
return false;
1479
case MaxTypedArrayViewType:
1480
break;
1481
}
1482
MOZ_CRASH("invalid scalar type");
1483
}
1484
1485
} /* namespace Scalar */
1486
} /* namespace js */
1487
1488
/*
1489
* Create a new typed array with nelements elements.
1490
*
1491
* These functions (except the WithBuffer variants) fill in the array with
1492
* zeros.
1493
*/
1494
1495
extern JS_FRIEND_API JSObject* JS_NewInt8Array(JSContext* cx,
1496
uint32_t nelements);
1497
extern JS_FRIEND_API JSObject* JS_NewUint8Array(JSContext* cx,
1498
uint32_t nelements);
1499
extern JS_FRIEND_API JSObject* JS_NewUint8ClampedArray(JSContext* cx,
1500
uint32_t nelements);
1501
extern JS_FRIEND_API JSObject* JS_NewInt16Array(JSContext* cx,
1502
uint32_t nelements);
1503
extern JS_FRIEND_API JSObject* JS_NewUint16Array(JSContext* cx,
1504
uint32_t nelements);
1505
extern JS_FRIEND_API JSObject* JS_NewInt32Array(JSContext* cx,
1506
uint32_t nelements);
1507
extern JS_FRIEND_API JSObject* JS_NewUint32Array(JSContext* cx,
1508
uint32_t nelements);
1509
extern JS_FRIEND_API JSObject* JS_NewFloat32Array(JSContext* cx,
1510
uint32_t nelements);
1511
extern JS_FRIEND_API JSObject* JS_NewFloat64Array(JSContext* cx,
1512
uint32_t nelements);
1513
1514
/*
1515
* Create a new typed array and copy in values from the given object. The
1516
* object is used as if it were an array; that is, the new array (if
1517
* successfully created) will have length given by array.length, and its
1518
* elements will be those specified by array[0], array[1], and so on, after
1519
* conversion to the typed array element type.
1520
*/
1521
1522
extern JS_FRIEND_API JSObject* JS_NewInt8ArrayFromArray(JSContext* cx,
1523
JS::HandleObject array);
1524
extern JS_FRIEND_API JSObject* JS_NewUint8ArrayFromArray(
1525
JSContext* cx, JS::HandleObject array);
1526
extern JS_FRIEND_API JSObject* JS_NewUint8ClampedArrayFromArray(
1527
JSContext* cx, JS::HandleObject array);
1528
extern JS_FRIEND_API JSObject* JS_NewInt16ArrayFromArray(
1529
JSContext* cx, JS::HandleObject array);
1530
extern JS_FRIEND_API JSObject* JS_NewUint16ArrayFromArray(
1531
JSContext* cx, JS::HandleObject array);
1532
extern JS_FRIEND_API JSObject* JS_NewInt32ArrayFromArray(
1533
JSContext* cx, JS::HandleObject array);
1534
extern JS_FRIEND_API JSObject* JS_NewUint32ArrayFromArray(
1535
JSContext* cx, JS::HandleObject array);
1536
extern JS_FRIEND_API JSObject* JS_NewFloat32ArrayFromArray(
1537
JSContext* cx, JS::HandleObject array);
1538
extern JS_FRIEND_API JSObject* JS_NewFloat64ArrayFromArray(
1539
JSContext* cx, JS::HandleObject array);
1540
1541
/*
1542
* Create a new typed array using the given ArrayBuffer or
1543
* SharedArrayBuffer for storage. The length value is optional; if -1
1544
* is passed, enough elements to use up the remainder of the byte
1545
* array is used as the default value.
1546
*/
1547
1548
extern JS_FRIEND_API JSObject* JS_NewInt8ArrayWithBuffer(
1549
JSContext* cx, JS::HandleObject arrayBuffer, uint32_t byteOffset,
1550
int32_t length);
1551
extern JS_FRIEND_API JSObject* JS_NewUint8ArrayWithBuffer(
1552
JSContext* cx, JS::HandleObject arrayBuffer, uint32_t byteOffset,
1553
int32_t length);
1554
extern JS_FRIEND_API JSObject* JS_NewUint8ClampedArrayWithBuffer(
1555
JSContext* cx, JS::HandleObject arrayBuffer, uint32_t byteOffset,
1556
int32_t length);
1557
extern JS_FRIEND_API JSObject* JS_NewInt16ArrayWithBuffer(
1558
JSContext* cx, JS::HandleObject arrayBuffer, uint32_t byteOffset,
1559
int32_t length);
1560
extern JS_FRIEND_API JSObject* JS_NewUint16ArrayWithBuffer(
1561
JSContext* cx, JS::HandleObject arrayBuffer, uint32_t byteOffset,
1562
int32_t length);
1563
extern JS_FRIEND_API JSObject* JS_NewInt32ArrayWithBuffer(
1564
JSContext* cx, JS::HandleObject arrayBuffer, uint32_t byteOffset,
1565
int32_t length);
1566
extern JS_FRIEND_API JSObject* JS_NewUint32ArrayWithBuffer(
1567
JSContext* cx, JS::HandleObject arrayBuffer, uint32_t byteOffset,
1568
int32_t length);
1569
extern JS_FRIEND_API JSObject* JS_NewBigInt64ArrayWithBuffer(
1570
JSContext* cx, JS::HandleObject arrayBuffer, uint32_t byteOffset,
1571
int32_t length);
1572
extern JS_FRIEND_API JSObject* JS_NewBigUint64ArrayWithBuffer(
1573
JSContext* cx, JS::HandleObject arrayBuffer, uint32_t byteOffset,
1574
int32_t length);
1575
extern JS_FRIEND_API JSObject* JS_NewFloat32ArrayWithBuffer(
1576
JSContext* cx, JS::HandleObject arrayBuffer, uint32_t byteOffset,
1577
int32_t length);
1578
extern JS_FRIEND_API JSObject* JS_NewFloat64ArrayWithBuffer(
1579
JSContext* cx, JS::HandleObject arrayBuffer, uint32_t byteOffset,
1580
int32_t length);
1581
1582
/**
1583
* Check whether obj supports JS_GetTypedArray* APIs. Note that this may return
1584
* false if a security wrapper is encountered that denies the unwrapping. If
1585
* this test or one of the JS_Is*Array tests succeeds, then it is safe to call
1586
* the various accessor JSAPI calls defined below.
1587
*/
1588
extern JS_FRIEND_API bool JS_IsTypedArrayObject(JSObject* obj);
1589
1590
/**
1591
* Check whether obj supports JS_GetArrayBufferView* APIs. Note that this may
1592
* return false if a security wrapper is encountered that denies the
1593
* unwrapping. If this test or one of the more specific tests succeeds, then it
1594
* is safe to call the various ArrayBufferView accessor JSAPI calls defined
1595
* below.
1596
*/
1597
extern JS_FRIEND_API bool JS_IsArrayBufferViewObject(JSObject* obj);
1598
1599
/*
1600
* Test for specific typed array types (ArrayBufferView subtypes)
1601
*/
1602
1603
extern JS_FRIEND_API bool JS_IsInt8Array(JSObject* obj);
1604
extern JS_FRIEND_API bool JS_IsUint8Array(JSObject* obj);
1605
extern JS_FRIEND_API bool JS_IsUint8ClampedArray(JSObject* obj);
1606
extern JS_FRIEND_API bool JS_IsInt16Array(JSObject* obj);
1607
extern JS_FRIEND_API bool JS_IsUint16Array(JSObject* obj);
1608
extern JS_FRIEND_API bool JS_IsInt32Array(JSObject* obj);
1609
extern JS_FRIEND_API bool JS_IsUint32Array(JSObject* obj);
1610
extern JS_FRIEND_API bool JS_IsFloat32Array(JSObject* obj);
1611
extern JS_FRIEND_API bool JS_IsFloat64Array(JSObject* obj);
1612
1613
/**
1614
* Return the isShared flag of a typed array, which denotes whether
1615
* the underlying buffer is a SharedArrayBuffer.
1616
*
1617
* |obj| must have passed a JS_IsTypedArrayObject/JS_Is*Array test, or somehow
1618
* be known that it would pass such a test: it is a typed array or a wrapper of
1619
* a typed array, and the unwrapping will succeed.
1620
*/
1621
extern JS_FRIEND_API bool JS_GetTypedArraySharedness(JSObject* obj);
1622
1623
/*
1624
* Test for specific typed array types (ArrayBufferView subtypes) and return
1625
* the unwrapped object if so, else nullptr. Never throws.
1626
*/
1627
1628
namespace js {
1629
1630
extern JS_FRIEND_API JSObject* UnwrapInt8Array(JSObject* obj);
1631
extern JS_FRIEND_API JSObject* UnwrapUint8Array(JSObject* obj);
1632
extern JS_FRIEND_API JSObject* UnwrapUint8ClampedArray(JSObject* obj);
1633
extern JS_FRIEND_API JSObject* UnwrapInt16Array(JSObject* obj);
1634
extern JS_FRIEND_API JSObject* UnwrapUint16Array(JSObject* obj);
1635
extern JS_FRIEND_API JSObject* UnwrapInt32Array(JSObject* obj);
1636
extern JS_FRIEND_API JSObject* UnwrapUint32Array(JSObject* obj);
1637
extern JS_FRIEND_API JSObject* UnwrapBigInt64Array(JSObject* obj);
1638
extern JS_FRIEND_API JSObject* UnwrapBigUint64Array(JSObject* obj);
1639
extern JS_FRIEND_API JSObject* UnwrapFloat32Array(JSObject* obj);
1640
extern JS_FRIEND_API JSObject* UnwrapFloat64Array(JSObject* obj);
1641
1642
extern JS_FRIEND_API JSObject* UnwrapArrayBufferView(JSObject* obj);
1643
1644
extern JS_FRIEND_API JSObject* UnwrapReadableStream(JSObject* obj);
1645
1646
namespace detail {
1647
1648
extern JS_FRIEND_DATA const JSClass* const Int8ArrayClassPtr;
1649
extern JS_FRIEND_DATA const JSClass* const Uint8ArrayClassPtr;
1650
extern JS_FRIEND_DATA const JSClass* const Uint8ClampedArrayClassPtr;
1651
extern JS_FRIEND_DATA const JSClass* const Int16ArrayClassPtr;
1652
extern JS_FRIEND_DATA const JSClass* const Uint16ArrayClassPtr;
1653
extern JS_FRIEND_DATA const JSClass* const Int32ArrayClassPtr;
1654
extern JS_FRIEND_DATA const JSClass* const Uint32ArrayClassPtr;
1655
extern JS_FRIEND_DATA const JSClass* const BigInt64ArrayClassPtr;
1656
extern JS_FRIEND_DATA const JSClass* const BigUint64ArrayClassPtr;
1657
extern JS_FRIEND_DATA const JSClass* const Float32ArrayClassPtr;
1658
extern JS_FRIEND_DATA const JSClass* const Float64ArrayClassPtr;
1659
1660
const size_t TypedArrayLengthSlot = 1;
1661
1662
} // namespace detail
1663
1664
#define JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Type, type) \
1665
inline void Get##Type##ArrayLengthAndData( \
1666
JSObject* obj, uint32_t* length, bool* isSharedMemory, type** data) { \
1667
MOZ_ASSERT(GetObjectClass(obj) == detail::Type##ArrayClassPtr); \
1668
const JS::Value& lenSlot = \
1669
GetReservedSlot(obj, detail::TypedArrayLengthSlot); \
1670
*length = mozilla::AssertedCast<uint32_t>(lenSlot.toInt32()); \
1671
*isSharedMemory = JS_GetTypedArraySharedness(obj); \
1672
*data = static_cast<type*>(GetObjectPrivate(obj)); \
1673
}
1674
1675
JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Int8, int8_t)
1676
JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Uint8, uint8_t)
1677
JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Uint8Clamped, uint8_t)
1678
JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Int16, int16_t)
1679
JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Uint16, uint16_t)
1680
JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Int32, int32_t)
1681
JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Uint32, uint32_t)
1682
JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Float32, float)
1683
JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Float64, double)
1684
1685
#undef JS_DEFINE_DATA_AND_LENGTH_ACCESSOR
1686
1687
// This one isn't inlined because it's rather tricky (by dint of having to deal
1688
// with a dozen-plus classes and varying slot layouts.
1689
extern JS_FRIEND_API void GetArrayBufferViewLengthAndData(JSObject* obj,
1690
uint32_t* length,
1691
bool* isSharedMemory,
1692
uint8_t** data);
1693
1694
} // namespace js
1695
1696
/*
1697
* Unwrap Typed arrays all at once. Return nullptr without throwing if the
1698
* object cannot be viewed as the correct typed array, or the typed array
1699
* object on success, filling both outparameters.
1700
*/
1701
extern JS_FRIEND_API JSObject* JS_GetObjectAsInt8Array(JSObject* obj,
1702
uint32_t* length,
1703
bool* isSharedMemory,
1704
int8_t** data);
1705
extern JS_FRIEND_API JSObject* JS_GetObjectAsUint8Array(JSObject* obj,
1706
uint32_t* length,
1707
bool* isSharedMemory,
1708
uint8_t** data);
1709
extern JS_FRIEND_API JSObject* JS_GetObjectAsUint8ClampedArray(
1710
JSObject* obj, uint32_t* length, bool* isSharedMemory, uint8_t** data);
1711
extern JS_FRIEND_API JSObject* JS_GetObjectAsInt16Array(JSObject* obj,
1712
uint32_t* length,
1713
bool* isSharedMemory,
1714
int16_t** data);
1715
extern JS_FRIEND_API JSObject* JS_GetObjectAsUint16Array(JSObject* obj,
1716
uint32_t* length,
1717
bool* isSharedMemory,
1718
uint16_t** data);
1719
extern JS_FRIEND_API JSObject* JS_GetObjectAsInt32Array(JSObject* obj,
1720
uint32_t* length,
1721
bool* isSharedMemory,
1722
int32_t** data);
1723
extern JS_FRIEND_API JSObject* JS_GetObjectAsUint32Array(JSObject* obj,
1724
uint32_t* length,
1725
bool* isSharedMemory,
1726
uint32_t** data);
1727
extern JS_FRIEND_API JSObject* JS_GetObjectAsFloat32Array(JSObject* obj,
1728
uint32_t* length,
1729
bool* isSharedMemory,
1730
float** data);
1731
extern JS_FRIEND_API JSObject* JS_GetObjectAsFloat64Array(JSObject* obj,
1732
uint32_t* length,
1733
bool* isSharedMemory,
1734
double** data);
1735
extern JS_FRIEND_API JSObject* JS_GetObjectAsArrayBufferView(
1736
JSObject* obj, uint32_t* length, bool* isSharedMemory, uint8_t** data);
1737
1738
/*
1739
* Get the type of elements in a typed array, or MaxTypedArrayViewType if a
1740
* DataView.
1741
*
1742
* |obj| must have passed a JS_IsArrayBufferView/JS_Is*Array test, or somehow
1743
* be known that it would pass such a test: it is an ArrayBufferView or a
1744
* wrapper of an ArrayBufferView, and the unwrapping will succeed.
1745
*/
1746
extern JS_FRIEND_API js::Scalar::Type JS_GetArrayBufferViewType(JSObject* obj);
1747
1748
extern JS_FRIEND_API js::Scalar::Type JS_GetSharedArrayBufferViewType(
1749
JSObject* obj);
1750
1751
/**
1752
* Return the number of elements in a typed array.
1753
*
1754
* |obj| must have passed a JS_IsTypedArrayObject/JS_Is*Array test, or somehow
1755
* be known that it would pass such a test: it is a typed array or a wrapper of
1756
* a typed array, and the unwrapping will succeed.
1757
*/
1758
extern JS_FRIEND_API uint32_t JS_GetTypedArrayLength(JSObject* obj);
1759
1760
/**
1761
* Return the byte offset from the start of an ArrayBuffer to the start of a
1762
* typed array view.
1763
*
1764
* |obj| must have passed a JS_IsTypedArrayObject/JS_Is*Array test, or somehow
1765
* be known that it would pass such a test: it is a typed array or a wrapper of
1766
* a typed array, and the unwrapping will succeed.
1767
*/
1768
extern JS_FRIEND_API uint32_t JS_GetTypedArrayByteOffset(JSObject* obj);
1769
1770