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