Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : * vim: set ts=8 sts=4 et sw=4 tw=99:
3 : * This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : /*
8 : * JavaScript API.
9 : */
10 :
11 : #include "jsapi.h"
12 :
13 : #include "mozilla/FloatingPoint.h"
14 : #include "mozilla/Maybe.h"
15 : #include "mozilla/PodOperations.h"
16 : #include "mozilla/Sprintf.h"
17 :
18 : #include <ctype.h>
19 : #ifdef __linux__
20 : # include <dlfcn.h>
21 : #endif
22 : #include <stdarg.h>
23 : #include <string.h>
24 : #include <sys/stat.h>
25 :
26 : #include "jsdate.h"
27 : #include "jsexn.h"
28 : #include "jsfriendapi.h"
29 : #include "jsmath.h"
30 : #include "jsnum.h"
31 : #include "jstypes.h"
32 : #include "jsutil.h"
33 :
34 : #include "builtin/Array.h"
35 : #include "builtin/AtomicsObject.h"
36 : #include "builtin/Boolean.h"
37 : #include "builtin/Eval.h"
38 : #include "builtin/JSON.h"
39 : #include "builtin/MapObject.h"
40 : #include "builtin/Promise.h"
41 : #include "builtin/RegExp.h"
42 : #include "builtin/Stream.h"
43 : #include "builtin/String.h"
44 : #include "builtin/Symbol.h"
45 : #ifdef ENABLE_SIMD
46 : # include "builtin/SIMD.h"
47 : #endif
48 : #ifdef ENABLE_BINARYDATA
49 : # include "builtin/TypedObject.h"
50 : #endif
51 : #include "frontend/BytecodeCompiler.h"
52 : #include "frontend/FullParseHandler.h" // for JS_BufferIsCompileableUnit
53 : #include "frontend/Parser.h" // for JS_BufferIsCompileableUnit
54 : #include "gc/FreeOp.h"
55 : #include "gc/Marking.h"
56 : #include "gc/Policy.h"
57 : #include "gc/PublicIterators.h"
58 : #include "gc/WeakMap.h"
59 : #include "jit/JitCommon.h"
60 : #include "js/CharacterEncoding.h"
61 : #include "js/Conversions.h"
62 : #include "js/Date.h"
63 : #include "js/Initialization.h"
64 : #include "js/Proxy.h"
65 : #include "js/SliceBudget.h"
66 : #include "js/StructuredClone.h"
67 : #include "js/Utility.h"
68 : #include "js/Wrapper.h"
69 : #include "util/StringBuffer.h"
70 : #include "util/Text.h"
71 : #include "vm/AsyncFunction.h"
72 : #include "vm/AsyncIteration.h"
73 : #include "vm/DateObject.h"
74 : #include "vm/Debugger.h"
75 : #include "vm/EnvironmentObject.h"
76 : #include "vm/ErrorObject.h"
77 : #include "vm/HelperThreads.h"
78 : #include "vm/Interpreter.h"
79 : #include "vm/Iteration.h"
80 : #include "vm/JSAtom.h"
81 : #include "vm/JSContext.h"
82 : #include "vm/JSFunction.h"
83 : #include "vm/JSObject.h"
84 : #include "vm/JSScript.h"
85 : #include "vm/RegExpStatics.h"
86 : #include "vm/Runtime.h"
87 : #include "vm/SavedStacks.h"
88 : #include "vm/SelfHosting.h"
89 : #include "vm/Shape.h"
90 : #include "vm/StringType.h"
91 : #include "vm/SymbolType.h"
92 : #include "vm/WrapperObject.h"
93 : #include "vm/Xdr.h"
94 : #include "wasm/AsmJS.h"
95 : #include "wasm/WasmModule.h"
96 :
97 : #include "vm/Compartment-inl.h"
98 : #include "vm/Interpreter-inl.h"
99 : #include "vm/JSAtom-inl.h"
100 : #include "vm/JSFunction-inl.h"
101 : #include "vm/JSScript-inl.h"
102 : #include "vm/NativeObject-inl.h"
103 : #include "vm/SavedStacks-inl.h"
104 : #include "vm/StringType-inl.h"
105 :
106 : using namespace js;
107 : using namespace js::gc;
108 :
109 : using mozilla::Maybe;
110 : using mozilla::PodCopy;
111 : using mozilla::Some;
112 :
113 : #ifdef HAVE_VA_LIST_AS_ARRAY
114 : #define JS_ADDRESSOF_VA_LIST(ap) ((va_list*)(ap))
115 : #else
116 : #define JS_ADDRESSOF_VA_LIST(ap) (&(ap))
117 : #endif
118 :
119 : JS_PUBLIC_API(bool)
120 7 : JS::CallArgs::requireAtLeast(JSContext* cx, const char* fnname, unsigned required) const
121 : {
122 7 : if (length() < required) {
123 : char numArgsStr[40];
124 0 : SprintfLiteral(numArgsStr, "%u", required - 1);
125 0 : JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_MORE_ARGS_NEEDED,
126 0 : fnname, numArgsStr, required == 2 ? "" : "s");
127 : return false;
128 : }
129 :
130 : return true;
131 : }
132 :
133 : static bool
134 0 : ErrorTakesArguments(unsigned msg)
135 : {
136 0 : MOZ_ASSERT(msg < JSErr_Limit);
137 0 : unsigned argCount = js_ErrorFormatString[msg].argCount;
138 0 : MOZ_ASSERT(argCount <= 2);
139 0 : return argCount == 1 || argCount == 2;
140 : }
141 :
142 : static bool
143 0 : ErrorTakesObjectArgument(unsigned msg)
144 : {
145 0 : MOZ_ASSERT(msg < JSErr_Limit);
146 0 : unsigned argCount = js_ErrorFormatString[msg].argCount;
147 0 : MOZ_ASSERT(argCount <= 2);
148 0 : return argCount == 2;
149 : }
150 :
151 : JS_PUBLIC_API(bool)
152 0 : JS::ObjectOpResult::reportStrictErrorOrWarning(JSContext* cx, HandleObject obj, HandleId id,
153 : bool strict)
154 : {
155 : static_assert(unsigned(OkCode) == unsigned(JSMSG_NOT_AN_ERROR),
156 : "unsigned value of OkCode must not be an error code");
157 0 : MOZ_ASSERT(code_ != Uninitialized);
158 0 : MOZ_ASSERT(!ok());
159 0 : assertSameCompartment(cx, obj);
160 :
161 0 : unsigned flags = strict ? JSREPORT_ERROR : (JSREPORT_WARNING | JSREPORT_STRICT);
162 0 : if (code_ == JSMSG_OBJECT_NOT_EXTENSIBLE) {
163 0 : RootedValue val(cx, ObjectValue(*obj));
164 0 : return ReportValueErrorFlags(cx, flags, code_, JSDVG_IGNORE_STACK, val,
165 0 : nullptr, nullptr, nullptr);
166 : }
167 :
168 0 : if (ErrorTakesArguments(code_)) {
169 0 : RootedValue idv(cx, IdToValue(id));
170 0 : RootedString str(cx, ValueToSource(cx, idv));
171 0 : if (!str)
172 : return false;
173 :
174 0 : JSAutoByteString propName;
175 0 : if (!propName.encodeUtf8(cx, str))
176 : return false;
177 :
178 0 : if (code_ == JSMSG_SET_NON_OBJECT_RECEIVER) {
179 : // We know that the original receiver was a primitive, so unbox it.
180 0 : RootedValue val(cx, ObjectValue(*obj));
181 0 : if (!obj->is<ProxyObject>()) {
182 0 : if (!Unbox(cx, obj, &val))
183 : return false;
184 : }
185 0 : return ReportValueErrorFlags(cx, flags, code_, JSDVG_IGNORE_STACK, val,
186 0 : nullptr, propName.ptr(), nullptr);
187 : }
188 :
189 0 : if (ErrorTakesObjectArgument(code_)) {
190 0 : return JS_ReportErrorFlagsAndNumberUTF8(cx, flags, GetErrorMessage, nullptr, code_,
191 0 : obj->getClass()->name, propName.ptr());
192 : }
193 :
194 0 : return JS_ReportErrorFlagsAndNumberUTF8(cx, flags, GetErrorMessage, nullptr, code_,
195 0 : propName.ptr());
196 : }
197 0 : return JS_ReportErrorFlagsAndNumberASCII(cx, flags, GetErrorMessage, nullptr, code_);
198 : }
199 :
200 : JS_PUBLIC_API(bool)
201 0 : JS::ObjectOpResult::reportStrictErrorOrWarning(JSContext* cx, HandleObject obj, bool strict)
202 : {
203 0 : MOZ_ASSERT(code_ != Uninitialized);
204 0 : MOZ_ASSERT(!ok());
205 0 : MOZ_ASSERT(!ErrorTakesArguments(code_));
206 0 : assertSameCompartment(cx, obj);
207 :
208 0 : unsigned flags = strict ? JSREPORT_ERROR : (JSREPORT_WARNING | JSREPORT_STRICT);
209 0 : return JS_ReportErrorFlagsAndNumberASCII(cx, flags, GetErrorMessage, nullptr, code_);
210 : }
211 :
212 : JS_PUBLIC_API(bool)
213 0 : JS::ObjectOpResult::failCantRedefineProp()
214 : {
215 0 : return fail(JSMSG_CANT_REDEFINE_PROP);
216 : }
217 :
218 : JS_PUBLIC_API(bool)
219 0 : JS::ObjectOpResult::failReadOnly()
220 : {
221 0 : return fail(JSMSG_READ_ONLY);
222 : }
223 :
224 : JS_PUBLIC_API(bool)
225 0 : JS::ObjectOpResult::failGetterOnly()
226 : {
227 0 : return fail(JSMSG_GETTER_ONLY);
228 : }
229 :
230 : JS_PUBLIC_API(bool)
231 0 : JS::ObjectOpResult::failCantDelete()
232 : {
233 0 : return fail(JSMSG_CANT_DELETE);
234 : }
235 :
236 : JS_PUBLIC_API(bool)
237 0 : JS::ObjectOpResult::failCantSetInterposed()
238 : {
239 0 : return fail(JSMSG_CANT_SET_INTERPOSED);
240 : }
241 :
242 : JS_PUBLIC_API(bool)
243 0 : JS::ObjectOpResult::failCantDefineWindowElement()
244 : {
245 0 : return fail(JSMSG_CANT_DEFINE_WINDOW_ELEMENT);
246 : }
247 :
248 : JS_PUBLIC_API(bool)
249 0 : JS::ObjectOpResult::failCantDeleteWindowElement()
250 : {
251 0 : return fail(JSMSG_CANT_DELETE_WINDOW_ELEMENT);
252 : }
253 :
254 : JS_PUBLIC_API(bool)
255 0 : JS::ObjectOpResult::failCantDeleteWindowNamedProperty()
256 : {
257 0 : return fail(JSMSG_CANT_DELETE_WINDOW_NAMED_PROPERTY);
258 : }
259 :
260 : JS_PUBLIC_API(bool)
261 0 : JS::ObjectOpResult::failCantPreventExtensions()
262 : {
263 0 : return fail(JSMSG_CANT_PREVENT_EXTENSIONS);
264 : }
265 :
266 : JS_PUBLIC_API(bool)
267 0 : JS::ObjectOpResult::failCantSetProto()
268 : {
269 0 : return fail(JSMSG_CANT_SET_PROTO);
270 : }
271 :
272 : JS_PUBLIC_API(bool)
273 0 : JS::ObjectOpResult::failNoNamedSetter()
274 : {
275 0 : return fail(JSMSG_NO_NAMED_SETTER);
276 : }
277 :
278 : JS_PUBLIC_API(bool)
279 0 : JS::ObjectOpResult::failNoIndexedSetter()
280 : {
281 0 : return fail(JSMSG_NO_INDEXED_SETTER);
282 : }
283 :
284 : JS_PUBLIC_API(int64_t)
285 98 : JS_Now()
286 : {
287 98 : return PRMJ_Now();
288 : }
289 :
290 : JS_PUBLIC_API(Value)
291 0 : JS_GetNaNValue(JSContext* cx)
292 : {
293 0 : return cx->runtime()->NaNValue;
294 : }
295 :
296 : JS_PUBLIC_API(Value)
297 0 : JS_GetNegativeInfinityValue(JSContext* cx)
298 : {
299 0 : return cx->runtime()->negativeInfinityValue;
300 : }
301 :
302 : JS_PUBLIC_API(Value)
303 0 : JS_GetPositiveInfinityValue(JSContext* cx)
304 : {
305 0 : return cx->runtime()->positiveInfinityValue;
306 : }
307 :
308 : JS_PUBLIC_API(Value)
309 88 : JS_GetEmptyStringValue(JSContext* cx)
310 : {
311 264 : return StringValue(cx->runtime()->emptyString);
312 : }
313 :
314 : JS_PUBLIC_API(JSString*)
315 0 : JS_GetEmptyString(JSContext* cx)
316 : {
317 0 : MOZ_ASSERT(cx->emptyString());
318 0 : return cx->emptyString();
319 : }
320 :
321 : namespace js {
322 :
323 : void
324 206207 : AssertHeapIsIdle()
325 : {
326 0 : MOZ_ASSERT(!JS::RuntimeHeapIsBusy());
327 206211 : }
328 :
329 : } // namespace js
330 :
331 : static void
332 72967 : AssertHeapIsIdleOrIterating()
333 : {
334 0 : MOZ_ASSERT(!JS::RuntimeHeapIsCollecting());
335 72966 : }
336 :
337 : static void
338 1698 : AssertHeapIsIdleOrStringIsFlat(JSString* str)
339 : {
340 : /*
341 : * We allow some functions to be called during a GC as long as the argument
342 : * is a flat string, since that will not cause allocation.
343 : */
344 0 : MOZ_ASSERT_IF(JS::RuntimeHeapIsBusy(), str->isFlat());
345 1698 : }
346 :
347 : JS_PUBLIC_API(bool)
348 100 : JS_ValueToObject(JSContext* cx, HandleValue value, MutableHandleObject objp)
349 : {
350 0 : AssertHeapIsIdle();
351 0 : CHECK_REQUEST(cx);
352 0 : assertSameCompartment(cx, value);
353 0 : if (value.isNullOrUndefined()) {
354 0 : objp.set(nullptr);
355 0 : return true;
356 : }
357 0 : JSObject* obj = ToObject(cx, value);
358 100 : if (!obj)
359 : return false;
360 0 : objp.set(obj);
361 100 : return true;
362 : }
363 :
364 : JS_PUBLIC_API(JSFunction*)
365 0 : JS_ValueToFunction(JSContext* cx, HandleValue value)
366 : {
367 0 : AssertHeapIsIdle();
368 0 : CHECK_REQUEST(cx);
369 0 : assertSameCompartment(cx, value);
370 0 : return ReportIfNotFunction(cx, value);
371 : }
372 :
373 : JS_PUBLIC_API(JSFunction*)
374 0 : JS_ValueToConstructor(JSContext* cx, HandleValue value)
375 : {
376 0 : AssertHeapIsIdle();
377 0 : CHECK_REQUEST(cx);
378 0 : assertSameCompartment(cx, value);
379 0 : return ReportIfNotFunction(cx, value);
380 : }
381 :
382 : JS_PUBLIC_API(JSString*)
383 0 : JS_ValueToSource(JSContext* cx, HandleValue value)
384 : {
385 0 : AssertHeapIsIdle();
386 0 : CHECK_REQUEST(cx);
387 0 : assertSameCompartment(cx, value);
388 0 : return ValueToSource(cx, value);
389 : }
390 :
391 : JS_PUBLIC_API(bool)
392 0 : JS_DoubleIsInt32(double d, int32_t* ip)
393 : {
394 0 : return mozilla::NumberIsInt32(d, ip);
395 : }
396 :
397 : JS_PUBLIC_API(JSType)
398 7044 : JS_TypeOfValue(JSContext* cx, HandleValue value)
399 : {
400 0 : AssertHeapIsIdle();
401 0 : CHECK_REQUEST(cx);
402 0 : assertSameCompartment(cx, value);
403 14088 : return TypeOfValue(value);
404 : }
405 :
406 : JS_PUBLIC_API(bool)
407 0 : JS_StrictlyEqual(JSContext* cx, HandleValue value1, HandleValue value2, bool* equal)
408 : {
409 0 : AssertHeapIsIdle();
410 0 : CHECK_REQUEST(cx);
411 0 : assertSameCompartment(cx, value1, value2);
412 0 : MOZ_ASSERT(equal);
413 0 : return StrictlyEqual(cx, value1, value2, equal);
414 : }
415 :
416 : JS_PUBLIC_API(bool)
417 0 : JS_LooselyEqual(JSContext* cx, HandleValue value1, HandleValue value2, bool* equal)
418 : {
419 0 : AssertHeapIsIdle();
420 0 : CHECK_REQUEST(cx);
421 0 : assertSameCompartment(cx, value1, value2);
422 0 : MOZ_ASSERT(equal);
423 0 : return LooselyEqual(cx, value1, value2, equal);
424 : }
425 :
426 : JS_PUBLIC_API(bool)
427 0 : JS_SameValue(JSContext* cx, HandleValue value1, HandleValue value2, bool* same)
428 : {
429 0 : AssertHeapIsIdle();
430 0 : CHECK_REQUEST(cx);
431 0 : assertSameCompartment(cx, value1, value2);
432 0 : MOZ_ASSERT(same);
433 0 : return SameValue(cx, value1, value2, same);
434 : }
435 :
436 : JS_PUBLIC_API(bool)
437 398 : JS_IsBuiltinEvalFunction(JSFunction* fun)
438 : {
439 398 : return IsAnyBuiltinEval(fun);
440 : }
441 :
442 : JS_PUBLIC_API(bool)
443 398 : JS_IsBuiltinFunctionConstructor(JSFunction* fun)
444 : {
445 398 : return fun->isBuiltinFunctionConstructor();
446 : }
447 :
448 : JS_PUBLIC_API(bool)
449 0 : JS_IsFunctionBound(JSFunction* fun)
450 : {
451 0 : return fun->isBoundFunction();
452 : }
453 :
454 : JS_PUBLIC_API(JSObject*)
455 0 : JS_GetBoundFunctionTarget(JSFunction* fun)
456 : {
457 0 : return fun->isBoundFunction() ?
458 0 : fun->getBoundFunctionTarget() : nullptr;
459 : }
460 :
461 : /************************************************************************/
462 :
463 : JS_PUBLIC_API(JSContext*)
464 4 : JS_NewContext(uint32_t maxbytes, uint32_t maxNurseryBytes, JSRuntime* parentRuntime)
465 : {
466 4 : MOZ_ASSERT(JS::detail::libraryInitState == JS::detail::InitState::Running,
467 : "must call JS_Init prior to creating any JSContexts");
468 :
469 : // Make sure that all parent runtimes are the topmost parent.
470 4 : while (parentRuntime && parentRuntime->parentRuntime)
471 : parentRuntime = parentRuntime->parentRuntime;
472 :
473 4 : return NewContext(maxbytes, maxNurseryBytes, parentRuntime);
474 : }
475 :
476 : JS_PUBLIC_API(JSContext*)
477 0 : JS_NewCooperativeContext(JSContext* siblingContext)
478 : {
479 0 : MOZ_CRASH("Cooperative scheduling is unsupported");
480 : }
481 :
482 : JS_PUBLIC_API(void)
483 0 : JS_YieldCooperativeContext(JSContext* cx)
484 : {
485 0 : MOZ_CRASH("Cooperative scheduling is unsupported");
486 : }
487 :
488 : JS_PUBLIC_API(void)
489 0 : JS_ResumeCooperativeContext(JSContext* cx)
490 : {
491 0 : MOZ_CRASH("Cooperative scheduling is unsupported");
492 : }
493 :
494 : JS_PUBLIC_API(void)
495 0 : JS_DestroyContext(JSContext* cx)
496 : {
497 0 : DestroyContext(cx);
498 0 : }
499 :
500 : JS_PUBLIC_API(void*)
501 844 : JS_GetContextPrivate(JSContext* cx)
502 : {
503 1688 : return cx->data;
504 : }
505 :
506 : JS_PUBLIC_API(void)
507 4 : JS_SetContextPrivate(JSContext* cx, void* data)
508 : {
509 0 : cx->data = data;
510 4 : }
511 :
512 : JS_PUBLIC_API(void)
513 3 : JS_SetFutexCanWait(JSContext* cx)
514 : {
515 0 : cx->fx.setCanWait(true);
516 3 : }
517 :
518 : static void
519 26913 : StartRequest(JSContext* cx)
520 : {
521 26913 : MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx->runtime()));
522 :
523 0 : if (cx->requestDepth) {
524 25765 : cx->requestDepth++;
525 : } else {
526 : /* Indicate that a request is running. */
527 0 : cx->requestDepth = 1;
528 1148 : cx->triggerActivityCallback(true);
529 : }
530 26913 : }
531 :
532 : static void
533 26910 : StopRequest(JSContext* cx)
534 : {
535 26910 : MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx->runtime()));
536 :
537 0 : MOZ_ASSERT(cx->requestDepth != 0);
538 0 : if (cx->requestDepth != 1) {
539 25765 : cx->requestDepth--;
540 : } else {
541 0 : cx->requestDepth = 0;
542 1145 : cx->triggerActivityCallback(false);
543 : }
544 26910 : }
545 :
546 : JS_PUBLIC_API(void)
547 26913 : JS_BeginRequest(JSContext* cx)
548 : {
549 0 : cx->outstandingRequests++;
550 0 : StartRequest(cx);
551 26913 : }
552 :
553 : JS_PUBLIC_API(void)
554 26910 : JS_EndRequest(JSContext* cx)
555 : {
556 0 : MOZ_ASSERT(cx->outstandingRequests != 0);
557 0 : cx->outstandingRequests--;
558 0 : StopRequest(cx);
559 26910 : }
560 :
561 : JS_PUBLIC_API(JSRuntime*)
562 3 : JS_GetParentRuntime(JSContext* cx)
563 : {
564 6 : return cx->runtime()->parentRuntime ? cx->runtime()->parentRuntime : cx->runtime();
565 : }
566 :
567 : JS_PUBLIC_API(JSRuntime*)
568 5 : JS_GetRuntime(JSContext* cx)
569 : {
570 5 : return cx->runtime();
571 : }
572 :
573 : JS_PUBLIC_API(JS::ContextOptions&)
574 615 : JS::ContextOptionsRef(JSContext* cx)
575 : {
576 615 : return cx->options();
577 : }
578 :
579 : JS_PUBLIC_API(bool)
580 4 : JS::InitSelfHostedCode(JSContext* cx)
581 : {
582 4 : MOZ_RELEASE_ASSERT(!cx->runtime()->hasInitializedSelfHosting(),
583 : "JS::InitSelfHostedCode() called more than once");
584 :
585 4 : AutoNoteSingleThreadedRegion anstr;
586 :
587 4 : JSRuntime* rt = cx->runtime();
588 :
589 0 : JSAutoRequest ar(cx);
590 4 : if (!rt->initializeAtoms(cx))
591 : return false;
592 :
593 : #ifndef JS_CODEGEN_NONE
594 4 : if (!rt->getJitRuntime(cx))
595 : return false;
596 : #endif
597 :
598 4 : if (!rt->initSelfHosting(cx))
599 : return false;
600 :
601 4 : if (!rt->parentRuntime && !rt->transformToPermanentAtoms(cx))
602 : return false;
603 :
604 4 : return true;
605 : }
606 :
607 : JS_PUBLIC_API(const char*)
608 0 : JS_GetImplementationVersion(void)
609 : {
610 0 : return "JavaScript-C" MOZILLA_VERSION;
611 : }
612 :
613 : JS_PUBLIC_API(void)
614 1 : JS_SetDestroyCompartmentCallback(JSContext* cx, JSDestroyCompartmentCallback callback)
615 : {
616 0 : cx->runtime()->destroyCompartmentCallback = callback;
617 1 : }
618 :
619 : JS_PUBLIC_API(void)
620 1 : JS_SetSizeOfIncludingThisCompartmentCallback(JSContext* cx,
621 : JSSizeOfIncludingThisCompartmentCallback callback)
622 : {
623 0 : cx->runtime()->sizeOfIncludingThisCompartmentCallback = callback;
624 1 : }
625 :
626 : #if defined(NIGHTLY_BUILD)
627 : JS_PUBLIC_API(void)
628 0 : JS_SetErrorInterceptorCallback(JSRuntime* rt, JSErrorInterceptor* callback)
629 : {
630 4 : rt->errorInterception.interceptor = callback;
631 4 : }
632 :
633 : JS_PUBLIC_API(JSErrorInterceptor*)
634 0 : JS_GetErrorInterceptorCallback(JSRuntime* rt)
635 : {
636 0 : return rt->errorInterception.interceptor;
637 : }
638 :
639 : JS_PUBLIC_API(Maybe<JSExnType>)
640 45 : JS_GetErrorType(const JS::Value& val)
641 : {
642 : // All errors are objects.
643 45 : if (!val.isObject())
644 : return mozilla::Nothing();
645 :
646 45 : const JSObject& obj = val.toObject();
647 :
648 : // All errors are `ErrorObject`.
649 45 : if (!obj.is<js::ErrorObject>()) {
650 : // Not one of the primitive errors.
651 : return mozilla::Nothing();
652 : }
653 :
654 0 : const js::ErrorObject& err = obj.as<js::ErrorObject>();
655 26 : return mozilla::Some(err.type());
656 : }
657 :
658 : #endif // defined(NIGHTLY_BUILD)
659 :
660 : JS_PUBLIC_API(void)
661 4 : JS_SetWrapObjectCallbacks(JSContext* cx, const JSWrapObjectCallbacks* callbacks)
662 : {
663 8 : cx->runtime()->wrapObjectCallbacks = callbacks;
664 4 : }
665 :
666 : JS_PUBLIC_API(void)
667 4 : JS_SetExternalStringSizeofCallback(JSContext* cx, JSExternalStringSizeofCallback callback)
668 : {
669 0 : cx->runtime()->externalStringSizeofCallback = callback;
670 4 : }
671 :
672 : JS_PUBLIC_API(Realm*)
673 0 : JS::EnterRealm(JSContext* cx, JSObject* target)
674 : {
675 0 : AssertHeapIsIdle();
676 0 : CHECK_REQUEST(cx);
677 :
678 0 : Realm* oldRealm = cx->realm();
679 0 : cx->enterRealmOf(target);
680 0 : return oldRealm;
681 : }
682 :
683 : JS_PUBLIC_API(void)
684 0 : JS::LeaveRealm(JSContext* cx, JS::Realm* oldRealm)
685 : {
686 0 : AssertHeapIsIdle();
687 0 : CHECK_REQUEST(cx);
688 0 : cx->leaveRealm(oldRealm);
689 0 : }
690 :
691 0 : JSAutoRealm::JSAutoRealm(JSContext* cx, JSObject* target
692 0 : MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
693 : : cx_(cx),
694 0 : oldRealm_(cx->realm())
695 : {
696 0 : AssertHeapIsIdleOrIterating();
697 0 : MOZ_GUARD_OBJECT_NOTIFIER_INIT;
698 36161 : cx_->enterRealmOf(target);
699 0 : }
700 :
701 0 : JSAutoRealm::JSAutoRealm(JSContext* cx, JSScript* target
702 0 : MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
703 : : cx_(cx),
704 0 : oldRealm_(cx->realm())
705 : {
706 0 : AssertHeapIsIdleOrIterating();
707 0 : MOZ_GUARD_OBJECT_NOTIFIER_INIT;
708 270 : cx_->enterRealmOf(target);
709 0 : }
710 :
711 0 : JSAutoRealm::~JSAutoRealm()
712 : {
713 0 : cx_->leaveRealm(oldRealm_);
714 0 : }
715 :
716 0 : JSAutoNullableRealm::JSAutoNullableRealm(JSContext* cx,
717 : JSObject* targetOrNull
718 0 : MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
719 : : cx_(cx),
720 29313 : oldRealm_(cx->realm())
721 : {
722 9771 : AssertHeapIsIdleOrIterating();
723 0 : MOZ_GUARD_OBJECT_NOTIFIER_INIT;
724 9771 : if (targetOrNull)
725 0 : cx_->enterRealmOf(targetOrNull);
726 : else
727 0 : cx_->enterNullRealm();
728 0 : }
729 :
730 0 : JSAutoNullableRealm::~JSAutoNullableRealm()
731 : {
732 0 : cx_->leaveRealm(oldRealm_);
733 0 : }
734 :
735 : JS_PUBLIC_API(void)
736 43 : JS_SetCompartmentPrivate(JS::Compartment* compartment, void* data)
737 : {
738 0 : compartment->data = data;
739 43 : }
740 :
741 : JS_PUBLIC_API(void*)
742 93494 : JS_GetCompartmentPrivate(JS::Compartment* compartment)
743 : {
744 0 : return compartment->data;
745 : }
746 :
747 : JS_PUBLIC_API(void)
748 221 : JS_MarkCrossZoneId(JSContext* cx, jsid id)
749 : {
750 221 : cx->markId(id);
751 221 : }
752 :
753 : JS_PUBLIC_API(void)
754 363 : JS_MarkCrossZoneIdValue(JSContext* cx, const Value& value)
755 : {
756 0 : cx->markAtomValue(value);
757 363 : }
758 :
759 : JS_PUBLIC_API(void)
760 0 : JS_SetZoneUserData(JS::Zone* zone, void* data)
761 : {
762 0 : zone->data = data;
763 0 : }
764 :
765 : JS_PUBLIC_API(void*)
766 0 : JS_GetZoneUserData(JS::Zone* zone)
767 : {
768 0 : return zone->data;
769 : }
770 :
771 : JS_PUBLIC_API(bool)
772 7772 : JS_WrapObject(JSContext* cx, MutableHandleObject objp)
773 : {
774 7772 : AssertHeapIsIdle();
775 15544 : CHECK_REQUEST(cx);
776 7772 : if (objp)
777 0 : JS::ExposeObjectToActiveJS(objp);
778 15544 : return cx->compartment()->wrap(cx, objp);
779 : }
780 :
781 : JS_PUBLIC_API(bool)
782 0 : JS_WrapValue(JSContext* cx, MutableHandleValue vp)
783 : {
784 2531 : AssertHeapIsIdle();
785 5062 : CHECK_REQUEST(cx);
786 2531 : JS::ExposeValueToActiveJS(vp);
787 0 : return cx->compartment()->wrap(cx, vp);
788 : }
789 :
790 : static void
791 0 : ReleaseAssertObjectHasNoWrappers(JSContext* cx, HandleObject target)
792 : {
793 18 : RootedValue origv(cx, ObjectValue(*target));
794 :
795 382 : for (CompartmentsIter c(cx->runtime()); !c.done(); c.next()) {
796 0 : if (c->lookupWrapper(origv))
797 0 : MOZ_CRASH("wrapper found for target object");
798 : }
799 6 : }
800 :
801 : /*
802 : * Brain transplants. Not for beginners or the squeamish.
803 : *
804 : * Sometimes a web spec requires us to transplant an object from one
805 : * compartment to another, like when a DOM node is inserted into a document in
806 : * another window and thus gets "adopted". We cannot literally change the
807 : * `.compartment()` of a `JSObject`; that would break the compartment
808 : * invariants. However, as usual, we have a workaround using wrappers.
809 : *
810 : * Of all the wrapper-based workarounds we do, it's safe to say this is the
811 : * most spectacular and questionable.
812 : *
813 : * `JS_TransplantObject(cx, origobj, target)` changes `origobj` into a
814 : * simulacrum of `target`, using highly esoteric means. To JS code, the effect
815 : * is as if `origobj` magically "became" `target`, but most often what actually
816 : * happens is that `origobj` gets turned into a cross-compartment wrapper for
817 : * `target`. The old behavior and contents of `origobj` are overwritten or
818 : * discarded.
819 : *
820 : * Thus, to "transplant" an object from one compartment to another:
821 : *
822 : * 1. Let `origobj` be the object that you want to move. First, create a
823 : * clone of it, `target`, in the destination compartment.
824 : *
825 : * In our DOM adoption example, `target` will be a Node of the same type as
826 : * `origobj`, same content, but in the adopting document. We're not done
827 : * yet: the spec for DOM adoption requires that `origobj.ownerDocument`
828 : * actually change. All we've done so far is make a copy.
829 : *
830 : * 2. Call `JS_TransplantObject(cx, origobj, target)`. This typically turns
831 : * `origobj` into a wrapper for `target`, so that any JS code that has a
832 : * reference to `origobj` will observe it to have the behavior of `target`
833 : * going forward. In addition, all existing wrappers for `origobj` are
834 : * changed into wrappers for `target`, extending the illusion to those
835 : * compartments as well.
836 : *
837 : * During navigation, we use the above technique to transplant the WindowProxy
838 : * into the new Window's compartment.
839 : *
840 : * A few rules:
841 : *
842 : * - `origobj` and `target` must be two distinct objects of the same `JSClass`.
843 : * Some classes may not support transplantation; WindowProxy objects and DOM
844 : * nodes are OK.
845 : *
846 : * - `target` should be created specifically to be passed to this function.
847 : * There must be no existing cross-compartment wrappers for it; ideally
848 : * there shouldn't be any pointers to it at all, except the one passed in.
849 : *
850 : * - `target` shouldn't be used afterwards. Instead, `JS_TransplantObject`
851 : * returns a pointer to the transplanted object, which might be `target`
852 : * but might be some other object in the same compartment. Use that.
853 : *
854 : * The reason for this last rule is that JS_TransplantObject does very strange
855 : * things in some cases, like swapping `target`'s brain with that of another
856 : * object. Leaving `target` behaving like its former self is not a goal.
857 : *
858 : * We don't have a good way to recover from failure in this function, so
859 : * we intentionally crash instead.
860 : */
861 :
862 : JS_PUBLIC_API(JSObject*)
863 6 : JS_TransplantObject(JSContext* cx, HandleObject origobj, HandleObject target)
864 : {
865 6 : AssertHeapIsIdle();
866 6 : MOZ_ASSERT(origobj != target);
867 12 : MOZ_ASSERT(!origobj->is<CrossCompartmentWrapperObject>());
868 0 : MOZ_ASSERT(!target->is<CrossCompartmentWrapperObject>());
869 24 : MOZ_ASSERT(origobj->getClass() == target->getClass());
870 0 : ReleaseAssertObjectHasNoWrappers(cx, target);
871 0 : MOZ_ASSERT(JS::CellIsNotGray(target));
872 :
873 0 : RootedValue origv(cx, ObjectValue(*origobj));
874 0 : RootedObject newIdentity(cx);
875 :
876 : // Don't allow a compacting GC to observe any intermediate state.
877 12 : AutoDisableCompactingGC nocgc(cx);
878 :
879 0 : AutoDisableProxyCheck adpc;
880 :
881 12 : JS::Compartment* destination = target->compartment();
882 :
883 12 : if (origobj->compartment() == destination) {
884 : // If the original object is in the same compartment as the
885 : // destination, then we know that we won't find a wrapper in the
886 : // destination's cross compartment map and that the same
887 : // object will continue to work.
888 0 : AutoRealmUnchecked ar(cx, origobj->realm());
889 0 : if (!JSObject::swap(cx, origobj, target))
890 0 : MOZ_CRASH();
891 0 : newIdentity = origobj;
892 12 : } else if (WrapperMap::Ptr p = destination->lookupWrapper(origv)) {
893 : // There might already be a wrapper for the original object in
894 : // the new compartment. If there is, we use its identity and swap
895 : // in the contents of |target|.
896 0 : newIdentity = &p->value().get().toObject();
897 :
898 : // When we remove origv from the wrapper map, its wrapper, newIdentity,
899 : // must immediately cease to be a cross-compartment wrapper. Nuke it.
900 0 : destination->removeWrapper(p);
901 0 : NukeCrossCompartmentWrapper(cx, newIdentity);
902 :
903 0 : AutoRealm ar(cx, newIdentity);
904 0 : if (!JSObject::swap(cx, newIdentity, target))
905 0 : MOZ_CRASH();
906 : } else {
907 : // Otherwise, we use |target| for the new identity object.
908 0 : newIdentity = target;
909 : }
910 :
911 : // Now, iterate through other scopes looking for references to the old
912 : // object, and update the relevant cross-compartment wrappers. We do this
913 : // even if origobj is in the same compartment as target and thus
914 : // `newIdentity == origobj`, because this process also clears out any
915 : // cached wrapper state.
916 12 : if (!RemapAllWrappersForObject(cx, origobj, newIdentity))
917 0 : MOZ_CRASH();
918 :
919 : // Lastly, update the original object to point to the new one.
920 12 : if (origobj->compartment() != destination) {
921 0 : RootedObject newIdentityWrapper(cx, newIdentity);
922 1 : AutoRealmUnchecked ar(cx, origobj->realm());
923 6 : if (!JS_WrapObject(cx, &newIdentityWrapper))
924 0 : MOZ_CRASH();
925 0 : MOZ_ASSERT(Wrapper::wrappedObject(newIdentityWrapper) == newIdentity);
926 0 : if (!JSObject::swap(cx, origobj, newIdentityWrapper))
927 0 : MOZ_CRASH();
928 0 : if (!origobj->compartment()->putWrapper(cx, CrossCompartmentKey(newIdentity), origv))
929 0 : MOZ_CRASH();
930 : }
931 :
932 : // The new identity object might be one of several things. Return it to avoid
933 : // ambiguity.
934 1 : MOZ_ASSERT(JS::CellIsNotGray(newIdentity));
935 12 : return newIdentity;
936 : }
937 :
938 : /*
939 : * Recompute all cross-compartment wrappers for an object, resetting state.
940 : * Gecko uses this to clear Xray wrappers when doing a navigation that reuses
941 : * the inner window and global object.
942 : */
943 : JS_PUBLIC_API(bool)
944 1 : JS_RefreshCrossCompartmentWrappers(JSContext* cx, HandleObject obj)
945 : {
946 2 : return RemapAllWrappersForObject(cx, obj, obj);
947 : }
948 :
949 : typedef struct JSStdName {
950 7 : size_t atomOffset; /* offset of atom pointer in JSAtomState */
951 : JSProtoKey key;
952 14 : bool isDummy() const { return key == JSProto_Null; }
953 7 : bool isSentinel() const { return key == JSProto_LIMIT; }
954 14 : } JSStdName;
955 :
956 7 : static const JSStdName*
957 : LookupStdName(const JSAtomState& names, JSAtom* name, const JSStdName* table)
958 0 : {
959 0 : for (unsigned i = 0; !table[i].isSentinel(); i++) {
960 : if (table[i].isDummy())
961 : continue;
962 : JSAtom* atom = AtomStateOffsetToName(names, table[i].atomOffset);
963 : MOZ_ASSERT(atom);
964 : if (name == atom)
965 : return &table[i];
966 : }
967 :
968 : return nullptr;
969 : }
970 11892 :
971 : /*
972 501091 : * Table of standard classes, indexed by JSProtoKey. For entries where the
973 489286 : * JSProtoKey does not correspond to a class with a meaningful constructor, we
974 : * insert a null entry into the table.
975 0 : */
976 423592 : #define STD_NAME_ENTRY(name, init, clasp) { NAME_OFFSET(name), JSProto_##name },
977 0 : #define STD_DUMMY_ENTRY(name, init, dummy) { 0, JSProto_Null },
978 : static const JSStdName standard_class_names[] = {
979 : JS_FOR_PROTOTYPES(STD_NAME_ENTRY, STD_DUMMY_ENTRY)
980 : { 0, JSProto_LIMIT }
981 : };
982 :
983 : /*
984 : * Table of top-level function and constant names and the JSProtoKey of the
985 : * standard class that initializes them.
986 : */
987 : static const JSStdName builtin_property_names[] = {
988 : { NAME_OFFSET(eval), JSProto_Object },
989 :
990 : /* Global properties and functions defined by the Number class. */
991 : { NAME_OFFSET(NaN), JSProto_Number },
992 : { NAME_OFFSET(Infinity), JSProto_Number },
993 : { NAME_OFFSET(isNaN), JSProto_Number },
994 : { NAME_OFFSET(isFinite), JSProto_Number },
995 : { NAME_OFFSET(parseFloat), JSProto_Number },
996 : { NAME_OFFSET(parseInt), JSProto_Number },
997 :
998 : /* String global functions. */
999 : { NAME_OFFSET(escape), JSProto_String },
1000 : { NAME_OFFSET(unescape), JSProto_String },
1001 : { NAME_OFFSET(decodeURI), JSProto_String },
1002 : { NAME_OFFSET(encodeURI), JSProto_String },
1003 : { NAME_OFFSET(decodeURIComponent), JSProto_String },
1004 : { NAME_OFFSET(encodeURIComponent), JSProto_String },
1005 : { NAME_OFFSET(uneval), JSProto_String },
1006 :
1007 : { 0, JSProto_LIMIT }
1008 : };
1009 :
1010 : JS_PUBLIC_API(bool)
1011 : JS_ResolveStandardClass(JSContext* cx, HandleObject obj, HandleId id, bool* resolved)
1012 : {
1013 : const JSStdName* stdnm;
1014 :
1015 : AssertHeapIsIdle();
1016 : CHECK_REQUEST(cx);
1017 : assertSameCompartment(cx, obj, id);
1018 :
1019 : Handle<GlobalObject*> global = obj.as<GlobalObject>();
1020 : *resolved = false;
1021 :
1022 : if (!JSID_IS_ATOM(id))
1023 : return true;
1024 5873 :
1025 : /* Check whether we're resolving 'undefined', and define it if so. */
1026 : JSAtom* idAtom = JSID_TO_ATOM(id);
1027 : JSAtom* undefinedAtom = cx->names().undefined;
1028 5873 : if (idAtom == undefinedAtom) {
1029 0 : *resolved = true;
1030 5873 : return DefineDataProperty(cx, global, id, UndefinedHandleValue,
1031 : JSPROP_PERMANENT | JSPROP_READONLY | JSPROP_RESOLVING);
1032 5873 : }
1033 0 :
1034 : /* Try for class constructors/prototypes named by well-known atoms. */
1035 0 : stdnm = LookupStdName(cx->names(), idAtom, standard_class_names);
1036 :
1037 : /* Try less frequently used top-level functions and constants. */
1038 : if (!stdnm)
1039 11746 : stdnm = LookupStdName(cx->names(), idAtom, builtin_property_names);
1040 0 :
1041 5873 : if (stdnm && GlobalObject::skipDeselectedConstructor(cx, stdnm->key))
1042 3 : stdnm = nullptr;
1043 6 :
1044 0 : // If this class is anonymous, then it doesn't exist as a global
1045 : // property, so we won't resolve anything.
1046 : JSProtoKey key = stdnm ? stdnm->key : JSProto_Null;
1047 : if (key != JSProto_Null) {
1048 0 : const Class* clasp = ProtoKeyToClass(key);
1049 : if (!clasp || !(clasp->flags & JSCLASS_IS_ANONYMOUS)) {
1050 : if (!GlobalObject::ensureConstructor(cx, global, key))
1051 5870 : return false;
1052 5834 :
1053 : *resolved = true;
1054 5870 : return true;
1055 0 : }
1056 : }
1057 :
1058 : // There is no such property to resolve. An ordinary resolve hook would
1059 0 : // just return true at this point. But the global object is special in one
1060 0 : // more way: its prototype chain is lazily initialized. That is,
1061 40 : // global->getProto() might be null right now because we haven't created
1062 40 : // Object.prototype yet. Force it now.
1063 40 : return GlobalObject::getOrCreateObjectPrototype(cx, global);
1064 : }
1065 :
1066 0 : JS_PUBLIC_API(bool)
1067 0 : JS_MayResolveStandardClass(const JSAtomState& names, jsid id, JSObject* maybeObj)
1068 : {
1069 : MOZ_ASSERT_IF(maybeObj, maybeObj->is<GlobalObject>());
1070 :
1071 : // The global object's resolve hook is special: JS_ResolveStandardClass
1072 : // initializes the prototype chain lazily. Only attempt to optimize here
1073 : // if we know the prototype chain has been initialized.
1074 : if (!maybeObj || !maybeObj->staticPrototype())
1075 : return true;
1076 5830 :
1077 : if (!JSID_IS_ATOM(id))
1078 : return false;
1079 :
1080 46 : JSAtom* atom = JSID_TO_ATOM(id);
1081 :
1082 92 : // This will return true even for deselected constructors. (To do
1083 : // better, we need a JSContext here; it's fine as it is.)
1084 :
1085 : return atom == names.undefined ||
1086 : LookupStdName(names, atom, standard_class_names) ||
1087 0 : LookupStdName(names, atom, builtin_property_names);
1088 : }
1089 :
1090 46 : JS_PUBLIC_API(bool)
1091 : JS_EnumerateStandardClasses(JSContext* cx, HandleObject obj)
1092 : {
1093 46 : AssertHeapIsIdle();
1094 : CHECK_REQUEST(cx);
1095 : assertSameCompartment(cx, obj);
1096 : Handle<GlobalObject*> global = obj.as<GlobalObject>();
1097 : return GlobalObject::initStandardClasses(cx, global);
1098 0 : }
1099 68 :
1100 22 : static bool
1101 : EnumerateUnresolvedStandardClasses(JSContext* cx, Handle<GlobalObject*> global,
1102 : AutoIdVector& properties, const JSStdName* table)
1103 : {
1104 0 : for (unsigned i = 0; !table[i].isSentinel(); i++) {
1105 : if (table[i].isDummy())
1106 0 : continue;
1107 0 :
1108 0 : JSProtoKey key = table[i].key;
1109 0 :
1110 0 : // If the standard class has been resolved, the properties have been
1111 : // defined on the global so we don't need to add them here.
1112 : if (global->isStandardClassResolved(key))
1113 : continue;
1114 0 :
1115 : if (GlobalObject::skipDeselectedConstructor(cx, key))
1116 : continue;
1117 0 :
1118 0 : if (const Class* clasp = ProtoKeyToClass(key)) {
1119 0 : if (clasp->flags & JSCLASS_IS_ANONYMOUS)
1120 : continue;
1121 0 : if (!clasp->specShouldDefineConstructor())
1122 : continue;
1123 : }
1124 :
1125 0 : jsid id = NameToId(AtomStateOffsetToName(cx->names(), table[i].atomOffset));
1126 : if (!properties.append(id))
1127 : return false;
1128 0 : }
1129 :
1130 : return true;
1131 0 : }
1132 0 :
1133 : JS_PUBLIC_API(bool)
1134 0 : JS_NewEnumerateStandardClasses(JSContext* cx, JS::HandleObject obj, JS::AutoIdVector& properties,
1135 : bool enumerableOnly)
1136 : {
1137 : if (enumerableOnly) {
1138 0 : // There are no enumerable lazy properties.
1139 0 : return true;
1140 0 : }
1141 :
1142 : Handle<GlobalObject*> global = obj.as<GlobalObject>();
1143 :
1144 : // It's fine to always append |undefined| here, it's non-configurable and
1145 : // the enumeration code filters duplicates.
1146 : if (!properties.append(NameToId(cx->names().undefined)))
1147 0 : return false;
1148 :
1149 : if (!EnumerateUnresolvedStandardClasses(cx, global, properties, standard_class_names))
1150 0 : return false;
1151 : if (!EnumerateUnresolvedStandardClasses(cx, global, properties, builtin_property_names))
1152 : return false;
1153 :
1154 : return true;
1155 0 : }
1156 :
1157 : JS_PUBLIC_API(bool)
1158 : JS_GetClassObject(JSContext* cx, JSProtoKey key, MutableHandleObject objp)
1159 0 : {
1160 : AssertHeapIsIdle();
1161 : CHECK_REQUEST(cx);
1162 0 : JSObject* obj = GlobalObject::getOrCreateConstructor(cx, key);
1163 : if (!obj)
1164 0 : return false;
1165 : objp.set(obj);
1166 : return true;
1167 0 : }
1168 :
1169 : JS_PUBLIC_API(bool)
1170 : JS_GetClassPrototype(JSContext* cx, JSProtoKey key, MutableHandleObject objp)
1171 24 : {
1172 : AssertHeapIsIdle();
1173 24 : CHECK_REQUEST(cx);
1174 48 : JSObject* proto = GlobalObject::getOrCreatePrototype(cx, key);
1175 24 : if (!proto)
1176 0 : return false;
1177 : objp.set(proto);
1178 0 : return true;
1179 0 : }
1180 :
1181 : namespace JS {
1182 :
1183 0 : JS_PUBLIC_API(void)
1184 : ProtoKeyToId(JSContext* cx, JSProtoKey key, MutableHandleId idp)
1185 15 : {
1186 30 : idp.set(NameToId(ClassName(key, cx)));
1187 15 : }
1188 0 :
1189 : } /* namespace JS */
1190 0 :
1191 0 : JS_PUBLIC_API(JSProtoKey)
1192 : JS_IdToProtoKey(JSContext* cx, HandleId id)
1193 : {
1194 : AssertHeapIsIdle();
1195 : CHECK_REQUEST(cx);
1196 : assertSameCompartment(cx, id);
1197 0 :
1198 : if (!JSID_IS_ATOM(id))
1199 0 : return JSProto_Null;
1200 0 :
1201 : JSAtom* atom = JSID_TO_ATOM(id);
1202 : const JSStdName* stdnm = LookupStdName(cx->names(), atom, standard_class_names);
1203 : if (!stdnm)
1204 : return JSProto_Null;
1205 1 :
1206 : if (GlobalObject::skipDeselectedConstructor(cx, stdnm->key))
1207 122 : return JSProto_Null;
1208 244 :
1209 122 : MOZ_ASSERT(MOZ_ARRAY_LENGTH(standard_class_names) == JSProto_LIMIT + 1);
1210 : return static_cast<JSProtoKey>(stdnm - standard_class_names);
1211 244 : }
1212 :
1213 : JS_PUBLIC_API(JSObject*)
1214 0 : JS_GetGlobalForObject(JSContext* cx, JSObject* obj)
1215 122 : {
1216 0 : AssertHeapIsIdle();
1217 : assertSameCompartment(cx, obj);
1218 : return &obj->deprecatedGlobal();
1219 0 : }
1220 :
1221 : extern JS_PUBLIC_API(bool)
1222 : JS_IsGlobalObject(JSObject* obj)
1223 22 : {
1224 : return obj->is<GlobalObject>();
1225 : }
1226 :
1227 1504 : extern JS_PUBLIC_API(JSObject*)
1228 : JS_GlobalLexicalEnvironment(JSObject* obj)
1229 3008 : {
1230 1504 : return &obj->as<GlobalObject>().lexicalEnvironment();
1231 4512 : }
1232 0 :
1233 : extern JS_PUBLIC_API(bool)
1234 : JS_HasExtensibleLexicalEnvironment(JSObject* obj)
1235 : {
1236 0 : return obj->is<GlobalObject>() || ObjectRealm::get(obj).getNonSyntacticLexicalEnvironment(obj);
1237 : }
1238 0 :
1239 0 : extern JS_PUBLIC_API(JSObject*)
1240 0 : JS_ExtensibleLexicalEnvironment(JSObject* obj)
1241 0 : {
1242 : JSObject* lexical = nullptr;
1243 : if (obj->is<GlobalObject>())
1244 : lexical = JS_GlobalLexicalEnvironment(obj);
1245 0 : else
1246 : lexical = ObjectRealm::get(obj).getNonSyntacticLexicalEnvironment(obj);
1247 0 : MOZ_ASSERT(lexical);
1248 0 : return lexical;
1249 0 : }
1250 0 :
1251 : JS_PUBLIC_API(JSObject*)
1252 : JS::CurrentGlobalOrNull(JSContext* cx)
1253 : {
1254 0 : AssertHeapIsIdleOrIterating();
1255 : CHECK_REQUEST(cx);
1256 0 : if (!cx->compartment())
1257 0 : return nullptr;
1258 0 : return cx->global();
1259 : }
1260 :
1261 : JS_PUBLIC_API(bool)
1262 0 : JS::detail::ComputeThis(JSContext* cx, Value* vp, MutableHandleObject thisObject)
1263 : {
1264 0 : AssertHeapIsIdle();
1265 0 : assertSameCompartment(cx, vp[0], vp[1]);
1266 0 :
1267 : MutableHandleValue thisv = MutableHandleValue::fromMarkedLocation(&vp[1]);
1268 : if (!BoxNonStrictThis(cx, thisv, thisv))
1269 : return false;
1270 1 :
1271 : thisObject.set(&thisv.toObject());
1272 1282 : return true;
1273 1282 : }
1274 2564 :
1275 : static bool gProfileTimelineRecordingEnabled = false;
1276 :
1277 : JS_PUBLIC_API(void)
1278 0 : JS::SetProfileTimelineRecordingEnabled(bool enabled)
1279 : {
1280 27130 : gProfileTimelineRecordingEnabled = enabled;
1281 : }
1282 :
1283 : JS_PUBLIC_API(bool)
1284 0 : JS::IsProfileTimelineRecordingEnabled()
1285 : {
1286 133 : return gProfileTimelineRecordingEnabled;
1287 : }
1288 :
1289 : JS_PUBLIC_API(void*)
1290 1330 : JS_malloc(JSContext* cx, size_t nbytes)
1291 : {
1292 2527 : AssertHeapIsIdle();
1293 : CHECK_REQUEST(cx);
1294 : return static_cast<void*>(cx->zone()->pod_malloc<uint8_t>(nbytes));
1295 : }
1296 1518 :
1297 : JS_PUBLIC_API(void*)
1298 1518 : JS_realloc(JSContext* cx, void* p, size_t oldBytes, size_t newBytes)
1299 1518 : {
1300 133 : AssertHeapIsIdle();
1301 : CHECK_REQUEST(cx);
1302 1385 : return static_cast<void*>(cx->zone()->pod_realloc<uint8_t>(static_cast<uint8_t*>(p), oldBytes,
1303 0 : newBytes));
1304 0 : }
1305 :
1306 : JS_PUBLIC_API(void)
1307 : JS_free(JSContext* cx, void* p)
1308 0 : {
1309 : return js_free(p);
1310 26766 : }
1311 53532 :
1312 26766 : JS_PUBLIC_API(void)
1313 : JS_freeop(JSFreeOp* fop, void* p)
1314 53414 : {
1315 : return FreeOp::get(fop)->free_(p);
1316 : }
1317 :
1318 0 : JS_PUBLIC_API(void)
1319 : JS_updateMallocCounter(JSContext* cx, size_t nbytes)
1320 0 : {
1321 0 : return cx->updateMallocCounter(nbytes);
1322 : }
1323 0 :
1324 0 : #undef JS_AddRoot
1325 :
1326 : JS_PUBLIC_API(bool)
1327 0 : JS_AddExtraGCRootsTracer(JSContext* cx, JSTraceDataOp traceOp, void* data)
1328 0 : {
1329 : return cx->runtime()->gc.addBlackRootsTracer(traceOp, data);
1330 : }
1331 :
1332 : JS_PUBLIC_API(void)
1333 : JS_RemoveExtraGCRootsTracer(JSContext* cx, JSTraceDataOp traceOp, void* data)
1334 0 : {
1335 : return cx->runtime()->gc.removeBlackRootsTracer(traceOp, data);
1336 0 : }
1337 0 :
1338 : JS_PUBLIC_API(bool)
1339 : JS::IsIdleGCTaskNeeded(JSRuntime* rt) {
1340 132 : // Currently, we only collect nursery during idle time.
1341 : return rt->gc.nursery().needIdleTimeCollection();
1342 0 : }
1343 :
1344 : JS_PUBLIC_API(void)
1345 : JS::RunIdleTimeGCTask(JSRuntime* rt) {
1346 214 : GCRuntime& gc = rt->gc;
1347 : if (gc.nursery().needIdleTimeCollection()) {
1348 214 : gc.minorGC(JS::gcreason::IDLE_TIME_COLLECTION);
1349 428 : }
1350 428 : }
1351 :
1352 : JS_PUBLIC_API(void)
1353 : JS_GC(JSContext* cx)
1354 0 : {
1355 : AssertHeapIsIdle();
1356 0 : JS::PrepareForFullGC(cx);
1357 0 : cx->runtime()->gc.gc(GC_NORMAL, JS::gcreason::API);
1358 0 : }
1359 0 :
1360 : JS_PUBLIC_API(void)
1361 : JS_MaybeGC(JSContext* cx)
1362 : {
1363 1 : GCRuntime& gc = cx->runtime()->gc;
1364 : gc.maybeGC(cx->zone());
1365 1123 : }
1366 :
1367 : JS_PUBLIC_API(void)
1368 : JS_SetGCCallback(JSContext* cx, JSGCCallback cb, void* data)
1369 0 : {
1370 : AssertHeapIsIdle();
1371 0 : cx->runtime()->gc.setGCCallback(cb, data);
1372 : }
1373 :
1374 : JS_PUBLIC_API(void)
1375 2044 : JS_SetObjectsTenuredCallback(JSContext* cx, JSObjectsTenuredCallback cb,
1376 : void* data)
1377 2044 : {
1378 : AssertHeapIsIdle();
1379 : cx->runtime()->gc.setObjectsTenuredCallback(cb, data);
1380 : }
1381 :
1382 : JS_PUBLIC_API(bool)
1383 7 : JS_AddFinalizeCallback(JSContext* cx, JSFinalizeCallback cb, void* data)
1384 : {
1385 7 : AssertHeapIsIdle();
1386 : return cx->runtime()->gc.addFinalizeCallback(cb, data);
1387 : }
1388 :
1389 0 : JS_PUBLIC_API(void)
1390 : JS_RemoveFinalizeCallback(JSContext* cx, JSFinalizeCallback cb)
1391 0 : {
1392 : cx->runtime()->gc.removeFinalizeCallback(cb);
1393 : }
1394 :
1395 0 : JS_PUBLIC_API(bool)
1396 : JS_AddWeakPointerZonesCallback(JSContext* cx, JSWeakPointerZonesCallback cb, void* data)
1397 0 : {
1398 : AssertHeapIsIdle();
1399 : return cx->runtime()->gc.addWeakPointerZonesCallback(cb, data);
1400 : }
1401 0 :
1402 1 : JS_PUBLIC_API(void)
1403 0 : JS_RemoveWeakPointerZonesCallback(JSContext* cx, JSWeakPointerZonesCallback cb)
1404 1 : {
1405 : cx->runtime()->gc.removeWeakPointerZonesCallback(cb);
1406 1 : }
1407 :
1408 : JS_PUBLIC_API(bool)
1409 0 : JS_AddWeakPointerCompartmentCallback(JSContext* cx, JSWeakPointerCompartmentCallback cb,
1410 : void* data)
1411 0 : {
1412 0 : AssertHeapIsIdle();
1413 0 : return cx->runtime()->gc.addWeakPointerCompartmentCallback(cb, data);
1414 0 : }
1415 :
1416 : JS_PUBLIC_API(void)
1417 236 : JS_RemoveWeakPointerCompartmentCallback(JSContext* cx, JSWeakPointerCompartmentCallback cb)
1418 : {
1419 236 : cx->runtime()->gc.removeWeakPointerCompartmentCallback(cb);
1420 236 : }
1421 0 :
1422 :
1423 : JS_PUBLIC_API(void)
1424 0 : JS_UpdateWeakPointerAfterGC(JS::Heap<JSObject*>* objp)
1425 : {
1426 0 : JS_UpdateWeakPointerAfterGCUnbarriered(objp->unsafeGet());
1427 4 : }
1428 4 :
1429 : JS_PUBLIC_API(void)
1430 : JS_UpdateWeakPointerAfterGCUnbarriered(JSObject** objp)
1431 0 : {
1432 : if (IsAboutToBeFinalizedUnbarriered(objp))
1433 : *objp = nullptr;
1434 4 : }
1435 4 :
1436 0 : JS_PUBLIC_API(void)
1437 : JS_SetGCParameter(JSContext* cx, JSGCParamKey key, uint32_t value)
1438 : {
1439 0 : cx->runtime()->gc.waitBackgroundSweepEnd();
1440 : AutoLockGC lock(cx->runtime());
1441 1 : MOZ_ALWAYS_TRUE(cx->runtime()->gc.setParameter(key, value, lock));
1442 1 : }
1443 :
1444 : JS_PUBLIC_API(void)
1445 : JS_ResetGCParameter(JSContext* cx, JSGCParamKey key)
1446 0 : {
1447 : cx->runtime()->gc.waitBackgroundSweepEnd();
1448 0 : AutoLockGC lock(cx->runtime());
1449 0 : cx->runtime()->gc.resetParameter(key, lock);
1450 : }
1451 :
1452 1 : JS_PUBLIC_API(uint32_t)
1453 : JS_GetGCParameter(JSContext* cx, JSGCParamKey key)
1454 0 : {
1455 1 : AutoLockGC lock(cx->runtime());
1456 : return cx->runtime()->gc.getParameter(key, lock);
1457 : }
1458 :
1459 0 : static const size_t NumGCConfigs = 14;
1460 : struct JSGCConfig {
1461 0 : JSGCParamKey key;
1462 0 : uint32_t value;
1463 : };
1464 :
1465 1 : JS_PUBLIC_API(void)
1466 : JS_SetGCParametersBasedOnAvailableMemory(JSContext* cx, uint32_t availMem)
1467 : {
1468 1 : static const JSGCConfig minimal[NumGCConfigs] = {
1469 1 : {JSGC_MAX_MALLOC_BYTES, 6 * 1024 * 1024},
1470 : {JSGC_SLICE_TIME_BUDGET, 30},
1471 : {JSGC_HIGH_FREQUENCY_TIME_LIMIT, 1500},
1472 : {JSGC_HIGH_FREQUENCY_HIGH_LIMIT, 40},
1473 0 : {JSGC_HIGH_FREQUENCY_LOW_LIMIT, 0},
1474 : {JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MAX, 300},
1475 0 : {JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MIN, 120},
1476 0 : {JSGC_LOW_FREQUENCY_HEAP_GROWTH, 120},
1477 : {JSGC_HIGH_FREQUENCY_TIME_LIMIT, 1500},
1478 : {JSGC_HIGH_FREQUENCY_TIME_LIMIT, 1500},
1479 : {JSGC_HIGH_FREQUENCY_TIME_LIMIT, 1500},
1480 0 : {JSGC_ALLOCATION_THRESHOLD, 1},
1481 : {JSGC_MODE, JSGC_MODE_INCREMENTAL}
1482 0 : };
1483 0 :
1484 : const JSGCConfig* config = minimal;
1485 : if (availMem > 512) {
1486 0 : static const JSGCConfig nominal[NumGCConfigs] = {
1487 : {JSGC_MAX_MALLOC_BYTES, 6 * 1024 * 1024},
1488 0 : {JSGC_SLICE_TIME_BUDGET, 30},
1489 0 : {JSGC_HIGH_FREQUENCY_TIME_LIMIT, 1000},
1490 0 : {JSGC_HIGH_FREQUENCY_HIGH_LIMIT, 500},
1491 : {JSGC_HIGH_FREQUENCY_LOW_LIMIT, 100},
1492 : {JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MAX, 300},
1493 50 : {JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MIN, 150},
1494 : {JSGC_LOW_FREQUENCY_HEAP_GROWTH, 150},
1495 0 : {JSGC_HIGH_FREQUENCY_TIME_LIMIT, 1500},
1496 200 : {JSGC_HIGH_FREQUENCY_TIME_LIMIT, 1500},
1497 50 : {JSGC_HIGH_FREQUENCY_TIME_LIMIT, 1500},
1498 0 : {JSGC_ALLOCATION_THRESHOLD, 30},
1499 : {JSGC_MODE, JSGC_MODE_ZONE}
1500 : };
1501 0 :
1502 : config = nominal;
1503 2 : }
1504 4 :
1505 0 : for (size_t i = 0; i < NumGCConfigs; i++)
1506 1 : JS_SetGCParameter(cx, config[i].key, config[i].value);
1507 : }
1508 :
1509 0 :
1510 : JS_PUBLIC_API(JSString*)
1511 0 : JS_NewExternalString(JSContext* cx, const char16_t* chars, size_t length,
1512 0 : const JSStringFinalizer* fin)
1513 : {
1514 : AssertHeapIsIdle();
1515 : CHECK_REQUEST(cx);
1516 : JSString* s = JSExternalString::new_(cx, chars, length, fin);
1517 : return s;
1518 : }
1519 :
1520 : JS_PUBLIC_API(JSString*)
1521 : JS_NewMaybeExternalString(JSContext* cx, const char16_t* chars, size_t length,
1522 0 : const JSStringFinalizer* fin, bool* allocatedExternal)
1523 : {
1524 : AssertHeapIsIdle();
1525 : CHECK_REQUEST(cx);
1526 : return NewMaybeExternalString(cx, chars, length, fin, allocatedExternal);
1527 : }
1528 :
1529 : extern JS_PUBLIC_API(bool)
1530 : JS_IsExternalString(JSString* str)
1531 : {
1532 : return str->isExternal();
1533 : }
1534 :
1535 : extern JS_PUBLIC_API(const JSStringFinalizer*)
1536 : JS_GetExternalStringFinalizer(JSString* str)
1537 : {
1538 : return str->asExternal().externalFinalizer();
1539 : }
1540 0 :
1541 0 : static void
1542 : SetNativeStackQuotaAndLimit(JSContext* cx, JS::StackKind kind, size_t stackSize)
1543 : {
1544 : cx->nativeStackQuota[kind] = stackSize;
1545 :
1546 : #if JS_STACK_GROWTH_DIRECTION > 0
1547 : if (stackSize == 0) {
1548 : cx->nativeStackLimit[kind] = UINTPTR_MAX;
1549 : } else {
1550 : MOZ_ASSERT(cx->nativeStackBase <= size_t(-1) - stackSize);
1551 : cx->nativeStackLimit[kind] = cx->nativeStackBase + stackSize - 1;
1552 : }
1553 : #else
1554 : if (stackSize == 0) {
1555 : cx->nativeStackLimit[kind] = 0;
1556 : } else {
1557 : MOZ_ASSERT(cx->nativeStackBase >= stackSize);
1558 0 : cx->nativeStackLimit[kind] = cx->nativeStackBase - (stackSize - 1);
1559 : }
1560 : #endif
1561 0 : }
1562 0 :
1563 0 : JS_PUBLIC_API(void)
1564 : JS_SetNativeStackQuota(JSContext* cx, size_t systemCodeStackSize, size_t trustedScriptStackSize,
1565 : size_t untrustedScriptStackSize)
1566 : {
1567 0 : MOZ_ASSERT(cx->requestDepth == 0);
1568 :
1569 : if (!trustedScriptStackSize)
1570 0 : trustedScriptStackSize = systemCodeStackSize;
1571 0 : else
1572 0 : MOZ_ASSERT(trustedScriptStackSize < systemCodeStackSize);
1573 0 :
1574 : if (!untrustedScriptStackSize)
1575 : untrustedScriptStackSize = trustedScriptStackSize;
1576 : else
1577 8442 : MOZ_ASSERT(untrustedScriptStackSize < trustedScriptStackSize);
1578 :
1579 : SetNativeStackQuotaAndLimit(cx, JS::StackForSystemCode, systemCodeStackSize);
1580 8442 : SetNativeStackQuotaAndLimit(cx, JS::StackForTrustedScript, trustedScriptStackSize);
1581 16884 : SetNativeStackQuotaAndLimit(cx, JS::StackForUntrustedScript, untrustedScriptStackSize);
1582 0 :
1583 : if (cx->isMainThreadContext())
1584 : cx->initJitStackLimit();
1585 : }
1586 460 :
1587 : /************************************************************************/
1588 920 :
1589 : JS_PUBLIC_API(bool)
1590 : JS_ValueToId(JSContext* cx, HandleValue value, MutableHandleId idp)
1591 : {
1592 0 : AssertHeapIsIdle();
1593 : CHECK_REQUEST(cx);
1594 0 : assertSameCompartment(cx, value);
1595 : return ValueToId<CanGC>(cx, value, idp);
1596 : }
1597 :
1598 0 : JS_PUBLIC_API(bool)
1599 : JS_StringToId(JSContext* cx, HandleString string, MutableHandleId idp)
1600 0 : {
1601 : AssertHeapIsIdle();
1602 : CHECK_REQUEST(cx);
1603 : assertSameCompartment(cx, string);
1604 : RootedValue value(cx, StringValue(string));
1605 : return ValueToId<CanGC>(cx, value, idp);
1606 : }
1607 :
1608 : JS_PUBLIC_API(bool)
1609 : JS_IdToValue(JSContext* cx, jsid id, MutableHandleValue vp)
1610 0 : {
1611 0 : AssertHeapIsIdle();
1612 : CHECK_REQUEST(cx);
1613 24 : assertSameCompartment(cx, id);
1614 24 : vp.set(IdToValue(id));
1615 : assertSameCompartment(cx, vp);
1616 : return true;
1617 24 : }
1618 :
1619 : JS_PUBLIC_API(bool)
1620 8 : JS::ToPrimitive(JSContext* cx, HandleObject obj, JSType hint, MutableHandleValue vp)
1621 : {
1622 : AssertHeapIsIdle();
1623 1 : CHECK_REQUEST(cx);
1624 : assertSameCompartment(cx, obj);
1625 0 : MOZ_ASSERT(obj != nullptr);
1626 : MOZ_ASSERT(hint == JSTYPE_UNDEFINED || hint == JSTYPE_STRING || hint == JSTYPE_NUMBER);
1627 : vp.setObject(*obj);
1628 1 : return ToPrimitiveSlow(cx, hint, vp);
1629 : }
1630 8 :
1631 : JS_PUBLIC_API(bool)
1632 : JS::GetFirstArgumentAsTypeHint(JSContext* cx, CallArgs args, JSType *result)
1633 1 : {
1634 : if (!args.get(0).isString()) {
1635 0 : JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_NOT_EXPECTED_TYPE,
1636 8 : "Symbol.toPrimitive",
1637 0 : "\"string\", \"number\", or \"default\"",
1638 : InformalValueTypeName(args.get(0)));
1639 8 : return false;
1640 0 : }
1641 8 :
1642 : RootedString str(cx, args.get(0).toString());
1643 : bool match;
1644 :
1645 : if (!EqualStrings(cx, str, cx->names().default_, &match))
1646 1395 : return false;
1647 : if (match) {
1648 0 : *result = JSTYPE_UNDEFINED;
1649 0 : return true;
1650 1395 : }
1651 0 :
1652 : if (!EqualStrings(cx, str, cx->names().string, &match))
1653 : return false;
1654 : if (match) {
1655 395 : *result = JSTYPE_STRING;
1656 : return true;
1657 395 : }
1658 0 :
1659 395 : if (!EqualStrings(cx, str, cx->names().number, &match))
1660 0 : return false;
1661 0 : if (match) {
1662 : *result = JSTYPE_NUMBER;
1663 : return true;
1664 : }
1665 6 :
1666 : JSAutoByteString bytes;
1667 0 : const char* source = ValueToSourceForError(cx, args.get(0), bytes);
1668 12 : if (!source) {
1669 0 : ReportOutOfMemory(cx);
1670 0 : return false;
1671 0 : }
1672 0 :
1673 : JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr, JSMSG_NOT_EXPECTED_TYPE,
1674 : "Symbol.toPrimitive",
1675 : "\"string\", \"number\", or \"default\"", source);
1676 0 : return false;
1677 : }
1678 0 :
1679 0 : JS_PUBLIC_API(JSObject*)
1680 0 : JS_InitClass(JSContext* cx, HandleObject obj, HandleObject parent_proto,
1681 0 : const JSClass* clasp, JSNative constructor, unsigned nargs,
1682 0 : const JSPropertySpec* ps, const JSFunctionSpec* fs,
1683 0 : const JSPropertySpec* static_ps, const JSFunctionSpec* static_fs)
1684 0 : {
1685 : AssertHeapIsIdle();
1686 : CHECK_REQUEST(cx);
1687 : assertSameCompartment(cx, obj, parent_proto);
1688 0 : return InitClass(cx, obj, parent_proto, Valueify(clasp), constructor,
1689 : nargs, ps, fs, static_ps, static_fs);
1690 0 : }
1691 0 :
1692 : JS_PUBLIC_API(bool)
1693 : JS_LinkConstructorAndPrototype(JSContext* cx, HandleObject ctor, HandleObject proto)
1694 0 : {
1695 0 : return LinkConstructorAndPrototype(cx, ctor, proto);
1696 : }
1697 :
1698 396 : JS_PUBLIC_API(const JSClass*)
1699 : JS_GetClass(JSObject* obj)
1700 : {
1701 528 : return obj->getJSClass();
1702 : }
1703 0 :
1704 17 : JS_PUBLIC_API(bool)
1705 17 : JS_InstanceOf(JSContext* cx, HandleObject obj, const JSClass* clasp, CallArgs* args)
1706 : {
1707 : AssertHeapIsIdle();
1708 460 : CHECK_REQUEST(cx);
1709 : #ifdef DEBUG
1710 0 : if (args) {
1711 46 : assertSameCompartment(cx, obj);
1712 46 : assertSameCompartment(cx, args->thisv(), args->calleev());
1713 : }
1714 : #endif
1715 0 : if (!obj || obj->getJSClass() != clasp) {
1716 : if (args)
1717 0 : ReportIncompatibleMethod(cx, *args, Valueify(clasp));
1718 69 : return false;
1719 69 : }
1720 : return true;
1721 : }
1722 0 :
1723 0 : JS_PUBLIC_API(bool)
1724 0 : JS_HasInstance(JSContext* cx, HandleObject obj, HandleValue value, bool* bp)
1725 0 : {
1726 0 : AssertHeapIsIdle();
1727 : assertSameCompartment(cx, obj, value);
1728 : return HasInstance(cx, obj, value, bp);
1729 : }
1730 :
1731 0 : JS_PUBLIC_API(void*)
1732 0 : JS_GetPrivate(JSObject* obj)
1733 : {
1734 : /* This function can be called by a finalizer. */
1735 : return obj->as<NativeObject>().getPrivate();
1736 0 : }
1737 :
1738 : JS_PUBLIC_API(void)
1739 : JS_SetPrivate(JSObject* obj, void* data)
1740 : {
1741 8 : /* This function can be called by a finalizer. */
1742 16 : obj->as<NativeObject>().setPrivate(data);
1743 0 : }
1744 0 :
1745 16 : JS_PUBLIC_API(void*)
1746 : JS_GetInstancePrivate(JSContext* cx, HandleObject obj, const JSClass* clasp, CallArgs* args)
1747 : {
1748 : if (!JS_InstanceOf(cx, obj, clasp, args))
1749 494 : return nullptr;
1750 : return obj->as<NativeObject>().getPrivate();
1751 988 : }
1752 :
1753 : JS_PUBLIC_API(JSObject*)
1754 : JS_GetConstructor(JSContext* cx, HandleObject proto)
1755 0 : {
1756 : AssertHeapIsIdle();
1757 0 : CHECK_REQUEST(cx);
1758 : assertSameCompartment(cx, proto);
1759 :
1760 : RootedValue cval(cx);
1761 0 : if (!GetProperty(cx, proto, proto, cx->names().constructor, &cval))
1762 : return nullptr;
1763 0 : if (!IsFunctionObject(cval)) {
1764 0 : JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_NO_CONSTRUCTOR,
1765 : proto->getClass()->name);
1766 0 : return nullptr;
1767 0 : }
1768 0 : return &cval.toObject();
1769 : }
1770 :
1771 0 : bool
1772 0 : JS::RealmBehaviors::extraWarnings(JSContext* cx) const
1773 0 : {
1774 : return extraWarningsOverride_.get(cx->options().extraWarnings());
1775 : }
1776 :
1777 : JS::RealmCreationOptions&
1778 : JS::RealmCreationOptions::setNewCompartmentInSystemZone()
1779 : {
1780 0 : compSpec_ = CompartmentSpecifier::NewCompartmentInSystemZone;
1781 : comp_ = nullptr;
1782 0 : return *this;
1783 0 : }
1784 0 :
1785 : JS::RealmCreationOptions&
1786 : JS::RealmCreationOptions::setNewCompartmentInExistingZone(JSObject* obj)
1787 : {
1788 81 : compSpec_ = CompartmentSpecifier::NewCompartmentInExistingZone;
1789 : zone_ = obj->zone();
1790 : return *this;
1791 162 : }
1792 :
1793 : JS::RealmCreationOptions&
1794 : JS::RealmCreationOptions::setExistingCompartment(JSObject* obj)
1795 1 : {
1796 : compSpec_ = CompartmentSpecifier::ExistingCompartment;
1797 : comp_ = obj->compartment();
1798 2690 : return *this;
1799 2690 : }
1800 :
1801 : JS::RealmCreationOptions&
1802 0 : JS::RealmCreationOptions::setNewCompartmentAndZone()
1803 : {
1804 0 : compSpec_ = CompartmentSpecifier::NewCompartmentAndZone;
1805 : comp_ = nullptr;
1806 0 : return *this;
1807 : }
1808 :
1809 : const JS::RealmCreationOptions&
1810 0 : JS::RealmCreationOptionsRef(Realm* realm)
1811 : {
1812 8 : return realm->creationOptions();
1813 16 : }
1814 0 :
1815 : const JS::RealmCreationOptions&
1816 0 : JS::RealmCreationOptionsRef(JSContext* cx)
1817 24 : {
1818 : return cx->realm()->creationOptions();
1819 8 : }
1820 :
1821 0 : bool
1822 0 : JS::RealmCreationOptions::getSharedMemoryAndAtomicsEnabled() const
1823 : {
1824 0 : #if defined(ENABLE_SHARED_ARRAY_BUFFER)
1825 : return sharedMemoryAndAtomics_;
1826 : #else
1827 : return false;
1828 0 : #endif
1829 : }
1830 29601 :
1831 : JS::RealmCreationOptions&
1832 : JS::RealmCreationOptions::setSharedMemoryAndAtomicsEnabled(bool flag)
1833 : {
1834 1 : #if defined(ENABLE_SHARED_ARRAY_BUFFER)
1835 : sharedMemoryAndAtomics_ = flag;
1836 0 : #endif
1837 24 : return *this;
1838 24 : }
1839 :
1840 : JS::RealmBehaviors&
1841 : JS::RealmBehaviorsRef(JS::Realm* realm)
1842 0 : {
1843 : return realm->behaviors();
1844 7 : }
1845 7 :
1846 0 : JS::RealmBehaviors&
1847 : JS::RealmBehaviorsRef(JSContext* cx)
1848 : {
1849 : return cx->realm()->behaviors();
1850 0 : }
1851 :
1852 0 : JS_PUBLIC_API(JSObject*)
1853 0 : JS_NewGlobalObject(JSContext* cx, const JSClass* clasp, JSPrincipals* principals,
1854 0 : JS::OnNewGlobalHookOption hookOption,
1855 : const JS::RealmOptions& options)
1856 : {
1857 : MOZ_RELEASE_ASSERT(cx->runtime()->hasInitializedSelfHosting(),
1858 0 : "Must call JS::InitSelfHostedCode() before creating a global");
1859 :
1860 13 : AssertHeapIsIdle();
1861 13 : CHECK_REQUEST(cx);
1862 0 :
1863 : return GlobalObject::new_(cx, Valueify(clasp), principals, hookOption, options);
1864 : }
1865 :
1866 0 : JS_PUBLIC_API(void)
1867 : JS_GlobalObjectTraceHook(JSTracer* trc, JSObject* global)
1868 0 : {
1869 : MOZ_ASSERT(global->is<GlobalObject>());
1870 :
1871 : // Off thread parsing and compilation tasks create a dummy global which is
1872 0 : // then merged back into the host realm. Since it used to be a global, it
1873 : // will still have this trace hook, but it does not have a meaning relative
1874 0 : // to its new realm. We can safely skip it.
1875 : //
1876 : // Similarly, if we GC when creating the global, we may not have set that
1877 : // global's realm's global pointer yet. In this case, the realm will not yet
1878 0 : // contain anything that needs to be traced.
1879 : if (!global->isOwnGlobal(trc))
1880 : return;
1881 14 :
1882 : // Trace the realm for any GC things that should only stick around if we
1883 : // know the global is live.
1884 : global->realm()->traceGlobal(trc);
1885 :
1886 : if (JSTraceOp trace = global->realm()->creationOptions().getTrace())
1887 : trace(trc, global);
1888 3 : }
1889 :
1890 : JS_PUBLIC_API(void)
1891 3 : JS_FireOnNewGlobalObject(JSContext* cx, JS::HandleObject global)
1892 : {
1893 3 : // This hook is infallible, because we don't really want arbitrary script
1894 : // to be able to throw errors during delicate global creation routines.
1895 : // This infallibility will eat OOM and slow script, but if that happens
1896 : // we'll likely run up into them again soon in a fallible context.
1897 0 : assertSameCompartment(cx, global);
1898 : Rooted<js::GlobalObject*> globalObject(cx, &global->as<GlobalObject>());
1899 0 : Debugger::onNewGlobalObject(cx, globalObject);
1900 : }
1901 :
1902 : JS_PUBLIC_API(JSObject*)
1903 0 : JS_NewObject(JSContext* cx, const JSClass* jsclasp)
1904 : {
1905 0 : MOZ_ASSERT(!cx->zone()->isAtomsZone());
1906 : AssertHeapIsIdle();
1907 : CHECK_REQUEST(cx);
1908 :
1909 0 : const Class* clasp = Valueify(jsclasp);
1910 : if (!clasp)
1911 : clasp = &PlainObject::class_; /* default class is Object */
1912 :
1913 0 : MOZ_ASSERT(clasp != &JSFunction::class_);
1914 : MOZ_ASSERT(!(clasp->flags & JSCLASS_IS_GLOBAL));
1915 :
1916 46 : return NewObjectWithClassProto(cx, clasp, nullptr);
1917 0 : }
1918 :
1919 92 : JS_PUBLIC_API(JSObject*)
1920 : JS_NewObjectWithGivenProto(JSContext* cx, const JSClass* jsclasp, HandleObject proto)
1921 : {
1922 : MOZ_ASSERT(!cx->zone()->isAtomsZone());
1923 0 : AssertHeapIsIdle();
1924 : CHECK_REQUEST(cx);
1925 18 : assertSameCompartment(cx, proto);
1926 :
1927 : const Class* clasp = Valueify(jsclasp);
1928 : if (!clasp)
1929 : clasp = &PlainObject::class_; /* default class is Object */
1930 :
1931 : MOZ_ASSERT(clasp != &JSFunction::class_);
1932 : MOZ_ASSERT(!(clasp->flags & JSCLASS_IS_GLOBAL));
1933 :
1934 : return NewObjectWithGivenProto(cx, clasp, proto);
1935 36 : }
1936 :
1937 : JS_PUBLIC_API(JSObject*)
1938 : JS_NewPlainObject(JSContext* cx)
1939 : {
1940 18 : MOZ_ASSERT(!cx->zone()->isAtomsZone());
1941 : AssertHeapIsIdle();
1942 18 : CHECK_REQUEST(cx);
1943 18 :
1944 : return NewBuiltinClassInstance<PlainObject>(cx);
1945 : }
1946 :
1947 0 : JS_PUBLIC_API(JSObject*)
1948 : JS_NewObjectForConstructor(JSContext* cx, const JSClass* clasp, const CallArgs& args)
1949 : {
1950 : AssertHeapIsIdle();
1951 : CHECK_REQUEST(cx);
1952 :
1953 42 : Value callee = args.calleev();
1954 84 : assertSameCompartment(cx, callee);
1955 42 : RootedObject obj(cx, &callee.toObject());
1956 42 : return CreateThis(cx, Valueify(clasp), obj);
1957 : }
1958 :
1959 0 : JS_PUBLIC_API(bool)
1960 : JS_IsNative(JSObject* obj)
1961 94 : {
1962 47 : return obj->isNative();
1963 0 : }
1964 :
1965 0 : JS_PUBLIC_API(void)
1966 0 : JS::AssertObjectBelongsToCurrentThread(JSObject* obj)
1967 0 : {
1968 : JSRuntime* rt = obj->compartment()->runtimeFromAnyThread();
1969 0 : MOZ_RELEASE_ASSERT(CurrentThreadCanAccessRuntime(rt));
1970 0 : }
1971 :
1972 94 :
1973 : /*** Standard internal methods *******************************************************************/
1974 :
1975 : JS_PUBLIC_API(bool)
1976 0 : JS_GetPrototype(JSContext* cx, HandleObject obj, MutableHandleObject result)
1977 : {
1978 20568 : assertSameCompartment(cx, obj);
1979 10284 : return GetPrototype(cx, obj, result);
1980 0 : }
1981 10284 :
1982 : JS_PUBLIC_API(bool)
1983 0 : JS_SetPrototype(JSContext* cx, HandleObject obj, HandleObject proto)
1984 0 : {
1985 0 : AssertHeapIsIdle();
1986 : CHECK_REQUEST(cx);
1987 0 : assertSameCompartment(cx, obj, proto);
1988 0 :
1989 : return SetPrototype(cx, obj, proto);
1990 20568 : }
1991 :
1992 : JS_PUBLIC_API(bool)
1993 : JS_GetPrototypeIfOrdinary(JSContext* cx, HandleObject obj, bool* isOrdinary,
1994 0 : MutableHandleObject result)
1995 : {
1996 710 : assertSameCompartment(cx, obj);
1997 355 : return GetPrototypeIfOrdinary(cx, obj, isOrdinary, result);
1998 0 : }
1999 :
2000 0 : JS_PUBLIC_API(bool)
2001 : JS_IsExtensible(JSContext* cx, HandleObject obj, bool* extensible)
2002 : {
2003 : assertSameCompartment(cx, obj);
2004 0 : return IsExtensible(cx, obj, extensible);
2005 : }
2006 0 :
2007 0 : JS_PUBLIC_API(bool)
2008 : JS_PreventExtensions(JSContext* cx, JS::HandleObject obj, ObjectOpResult& result)
2009 0 : {
2010 0 : assertSameCompartment(cx, obj);
2011 0 : return PreventExtensions(cx, obj, result);
2012 0 : }
2013 :
2014 : JS_PUBLIC_API(bool)
2015 : JS_SetImmutablePrototype(JSContext *cx, JS::HandleObject obj, bool *succeeded)
2016 0 : {
2017 : assertSameCompartment(cx, obj);
2018 0 : return SetImmutablePrototype(cx, obj, succeeded);
2019 : }
2020 :
2021 : JS_PUBLIC_API(bool)
2022 1 : JS_GetOwnPropertyDescriptorById(JSContext* cx, HandleObject obj, HandleId id,
2023 : MutableHandle<PropertyDescriptor> desc)
2024 5111 : {
2025 5111 : AssertHeapIsIdle();
2026 0 : CHECK_REQUEST(cx);
2027 : assertSameCompartment(cx, obj, id);
2028 :
2029 : return GetOwnPropertyDescriptor(cx, obj, id, desc);
2030 : }
2031 :
2032 712 : JS_PUBLIC_API(bool)
2033 : JS_GetOwnPropertyDescriptor(JSContext* cx, HandleObject obj, const char* name,
2034 12475 : MutableHandle<PropertyDescriptor> desc)
2035 12475 : {
2036 : JSAtom* atom = Atomize(cx, name, strlen(name));
2037 : if (!atom)
2038 : return false;
2039 0 : RootedId id(cx, AtomToId(atom));
2040 : return JS_GetOwnPropertyDescriptorById(cx, obj, id, desc);
2041 316 : }
2042 632 :
2043 0 : JS_PUBLIC_API(bool)
2044 : JS_GetOwnUCPropertyDescriptor(JSContext* cx, HandleObject obj, const char16_t* name,
2045 0 : MutableHandle<PropertyDescriptor> desc)
2046 : {
2047 : JSAtom* atom = AtomizeChars(cx, name, js_strlen(name));
2048 : if (!atom)
2049 0 : return false;
2050 : RootedId id(cx, AtomToId(atom));
2051 : return JS_GetOwnPropertyDescriptorById(cx, obj, id, desc);
2052 0 : }
2053 0 :
2054 : JS_PUBLIC_API(bool)
2055 : JS_GetPropertyDescriptorById(JSContext* cx, HandleObject obj, HandleId id,
2056 : MutableHandle<PropertyDescriptor> desc)
2057 0 : {
2058 : assertSameCompartment(cx, obj, id);
2059 0 : return GetPropertyDescriptor(cx, obj, id, desc);
2060 0 : }
2061 :
2062 : JS_PUBLIC_API(bool)
2063 : JS_GetPropertyDescriptor(JSContext* cx, HandleObject obj, const char* name,
2064 0 : MutableHandle<PropertyDescriptor> desc)
2065 : {
2066 0 : JSAtom* atom = Atomize(cx, name, strlen(name));
2067 0 : if (!atom)
2068 : return false;
2069 : RootedId id(cx, AtomToId(atom));
2070 : return atom && JS_GetPropertyDescriptorById(cx, obj, id, desc);
2071 0 : }
2072 :
2073 85 : static bool
2074 85 : DefinePropertyByDescriptor(JSContext* cx, HandleObject obj, HandleId id,
2075 : Handle<PropertyDescriptor> desc, ObjectOpResult& result)
2076 : {
2077 : AssertHeapIsIdle();
2078 0 : CHECK_REQUEST(cx);
2079 : assertSameCompartment(cx, obj, id, desc);
2080 : return DefineProperty(cx, obj, id, desc, result);
2081 1392 : }
2082 0 :
2083 1392 : JS_PUBLIC_API(bool)
2084 : JS_DefinePropertyById(JSContext* cx, HandleObject obj, HandleId id,
2085 0 : Handle<PropertyDescriptor> desc, ObjectOpResult& result)
2086 : {
2087 : return DefinePropertyByDescriptor(cx, obj, id, desc, result);
2088 : }
2089 0 :
2090 : JS_PUBLIC_API(bool)
2091 : JS_DefinePropertyById(JSContext* cx, HandleObject obj, HandleId id,
2092 594 : Handle<PropertyDescriptor> desc)
2093 0 : {
2094 : ObjectOpResult result;
2095 594 : return DefinePropertyByDescriptor(cx, obj, id, desc, result) &&
2096 0 : result.checkStrict(cx, obj, id);
2097 : }
2098 :
2099 : static bool
2100 0 : DefineAccessorPropertyById(JSContext* cx, HandleObject obj, HandleId id,
2101 : const JSNativeWrapper& get, const JSNativeWrapper& set,
2102 : unsigned attrs)
2103 297 : {
2104 0 : JSGetterOp getter = JS_CAST_NATIVE_TO(get.op, JSGetterOp);
2105 : JSSetterOp setter = JS_CAST_NATIVE_TO(set.op, JSSetterOp);
2106 594 :
2107 0 : // JSPROP_READONLY has no meaning when accessors are involved. Ideally we'd
2108 : // throw if this happens, but we've accepted it for long enough that it's
2109 : // not worth trying to make callers change their ways. Just flip it off on
2110 : // its way through the API layer so that we can enforce this internally.
2111 0 : if (attrs & (JSPROP_GETTER | JSPROP_SETTER))
2112 : attrs &= ~JSPROP_READONLY;
2113 :
2114 0 : // When we use DefineProperty, we need full scriptable Function objects rather
2115 0 : // than JSNatives. However, we might be pulling this property descriptor off
2116 : // of something with JSNative property descriptors. If we are, wrap them in
2117 : // JS Function objects.
2118 :
2119 0 : // If !(attrs & JSPROP_PROPOP_ACCESSORS), then getter/setter are both
2120 : // possibly-null JSNatives (or possibly-null JSFunction* if JSPROP_GETTER or
2121 : // JSPROP_SETTER is appropriately set).
2122 0 : if (!(attrs & JSPROP_PROPOP_ACCESSORS)) {
2123 0 : if (getter && !(attrs & JSPROP_GETTER)) {
2124 : RootedAtom atom(cx, IdToFunctionName(cx, id, FunctionPrefixKind::Get));
2125 0 : if (!atom)
2126 0 : return false;
2127 : JSFunction* getobj = NewNativeFunction(cx, (Native) getter, 0, atom);
2128 : if (!getobj)
2129 : return false;
2130 0 :
2131 : if (get.info)
2132 : getobj->setJitInfo(get.info);
2133 60 :
2134 0 : getter = JS_DATA_TO_FUNC_PTR(GetterOp, getobj);
2135 60 : attrs |= JSPROP_GETTER;
2136 120 : }
2137 : if (setter && !(attrs & JSPROP_SETTER)) {
2138 : // Root just the getter, since the setter is not yet a JSObject.
2139 : AutoRooterGetterSetter getRoot(cx, JSPROP_GETTER, &getter, nullptr);
2140 0 : RootedAtom atom(cx, IdToFunctionName(cx, id, FunctionPrefixKind::Set));
2141 : if (!atom)
2142 : return false;
2143 0 : JSFunction* setobj = NewNativeFunction(cx, (Native) setter, 1, atom);
2144 : if (!setobj)
2145 : return false;
2146 :
2147 0 : if (set.info)
2148 : setobj->setJitInfo(set.info);
2149 :
2150 60 : setter = JS_DATA_TO_FUNC_PTR(SetterOp, setobj);
2151 0 : attrs |= JSPROP_SETTER;
2152 120 : }
2153 : } else {
2154 : attrs &= ~JSPROP_PROPOP_ACCESSORS;
2155 : }
2156 0 :
2157 : AssertHeapIsIdle();
2158 : CHECK_REQUEST(cx);
2159 : assertSameCompartment(cx, obj, id,
2160 0 : (attrs & JSPROP_GETTER)
2161 12002 : ? JS_FUNC_TO_DATA_PTR(JSObject*, getter)
2162 : : nullptr,
2163 : (attrs & JSPROP_SETTER)
2164 : ? JS_FUNC_TO_DATA_PTR(JSObject*, setter)
2165 : : nullptr);
2166 :
2167 12002 : return js::DefineAccessorProperty(cx, obj, id, getter, setter, attrs);
2168 2109 : }
2169 :
2170 : static bool
2171 : DefineDataPropertyById(JSContext* cx, HandleObject obj, HandleId id, HandleValue value,
2172 : unsigned attrs)
2173 : {
2174 : MOZ_ASSERT(!(attrs & (JSPROP_GETTER | JSPROP_SETTER | JSPROP_PROPOP_ACCESSORS)));
2175 :
2176 : AssertHeapIsIdle();
2177 : CHECK_REQUEST(cx);
2178 12002 : assertSameCompartment(cx, obj, id, value);
2179 12002 :
2180 19786 : return js::DefineDataProperty(cx, obj, id, value, attrs);
2181 9893 : }
2182 0 :
2183 0 : /*
2184 0 : * Wrapper functions to create wrappers with no corresponding JSJitInfo from API
2185 : * function arguments.
2186 : */
2187 0 : static JSNativeWrapper
2188 0 : NativeOpWrapper(Native native)
2189 : {
2190 9893 : JSNativeWrapper ret;
2191 0 : ret.op = native;
2192 : ret.info = nullptr;
2193 12002 : return ret;
2194 : }
2195 0 :
2196 12570 : JS_PUBLIC_API(bool)
2197 0 : JS_DefinePropertyById(JSContext* cx, HandleObject obj, HandleId id, HandleValue value,
2198 0 : unsigned attrs)
2199 0 : {
2200 0 : return DefineDataPropertyById(cx, obj, id, value, attrs);
2201 : }
2202 :
2203 0 : JS_PUBLIC_API(bool)
2204 0 : JS_DefinePropertyById(JSContext* cx, HandleObject obj, HandleId id, Native getter, Native setter,
2205 : unsigned attrs)
2206 6285 : {
2207 0 : return DefineAccessorPropertyById(cx, obj, id,
2208 : NativeOpWrapper(getter), NativeOpWrapper(setter),
2209 : attrs);
2210 0 : }
2211 :
2212 : JS_PUBLIC_API(bool)
2213 12002 : JS_DefinePropertyById(JSContext* cx, HandleObject obj, HandleId id, HandleObject valueArg,
2214 0 : unsigned attrs)
2215 : {
2216 12002 : RootedValue value(cx, ObjectValue(*valueArg));
2217 0 : return DefineDataPropertyById(cx, obj, id, value, attrs);
2218 : }
2219 12002 :
2220 0 : JS_PUBLIC_API(bool)
2221 0 : JS_DefinePropertyById(JSContext* cx, HandleObject obj, HandleId id, HandleString valueArg,
2222 : unsigned attrs)
2223 0 : {
2224 : RootedValue value(cx, StringValue(valueArg));
2225 : return DefineDataPropertyById(cx, obj, id, value, attrs);
2226 : }
2227 0 :
2228 : JS_PUBLIC_API(bool)
2229 : JS_DefinePropertyById(JSContext* cx, HandleObject obj, HandleId id, int32_t valueArg,
2230 8653 : unsigned attrs)
2231 : {
2232 8653 : Value value = Int32Value(valueArg);
2233 17306 : return DefineDataPropertyById(cx, obj, id, HandleValue::fromMarkedLocation(&value), attrs);
2234 0 : }
2235 :
2236 0 : JS_PUBLIC_API(bool)
2237 : JS_DefinePropertyById(JSContext* cx, HandleObject obj, HandleId id, uint32_t valueArg,
2238 : unsigned attrs)
2239 : {
2240 : Value value = NumberValue(valueArg);
2241 : return DefineDataPropertyById(cx, obj, id, HandleValue::fromMarkedLocation(&value), attrs);
2242 : }
2243 :
2244 : JS_PUBLIC_API(bool)
2245 : JS_DefinePropertyById(JSContext* cx, HandleObject obj, HandleId id, double valueArg,
2246 : unsigned attrs)
2247 4224 : {
2248 4224 : Value value = NumberValue(valueArg);
2249 : return DefineDataPropertyById(cx, obj, id, HandleValue::fromMarkedLocation(&value), attrs);
2250 : }
2251 :
2252 : static bool
2253 2079 : DefineAccessorProperty(JSContext* cx, HandleObject obj, const char* name,
2254 : const JSNativeWrapper& getter, const JSNativeWrapper& setter,
2255 : unsigned attrs)
2256 2079 : {
2257 : AutoRooterGetterSetter gsRoot(cx, attrs, const_cast<JSNative*>(&getter.op),
2258 : const_cast<JSNative*>(&setter.op));
2259 :
2260 0 : JSAtom* atom = Atomize(cx, name, strlen(name));
2261 : if (!atom)
2262 : return false;
2263 : RootedId id(cx, AtomToId(atom));
2264 0 :
2265 3232 : return DefineAccessorPropertyById(cx, obj, id, getter, setter, attrs);
2266 : }
2267 :
2268 : static bool
2269 0 : DefineDataProperty(JSContext* cx, HandleObject obj, const char* name, HandleValue value,
2270 : unsigned attrs)
2271 : {
2272 1356 : JSAtom* atom = Atomize(cx, name, strlen(name));
2273 0 : if (!atom)
2274 : return false;
2275 : RootedId id(cx, AtomToId(atom));
2276 :
2277 0 : return DefineDataPropertyById(cx, obj, id, value, attrs);
2278 : }
2279 :
2280 0 : JS_PUBLIC_API(bool)
2281 0 : JS_DefineProperty(JSContext* cx, HandleObject obj, const char* name, HandleValue value,
2282 : unsigned attrs)
2283 : {
2284 : return DefineDataProperty(cx, obj, name, value, attrs);
2285 0 : }
2286 :
2287 : JS_PUBLIC_API(bool)
2288 0 : JS_DefineProperty(JSContext* cx, HandleObject obj, const char* name, Native getter, Native setter,
2289 1 : unsigned attrs)
2290 : {
2291 : return DefineAccessorProperty(cx, obj, name, NativeOpWrapper(getter), NativeOpWrapper(setter),
2292 : attrs);
2293 0 : }
2294 :
2295 : JS_PUBLIC_API(bool)
2296 2 : JS_DefineProperty(JSContext* cx, HandleObject obj, const char* name, HandleObject valueArg,
2297 0 : unsigned attrs)
2298 : {
2299 : RootedValue value(cx, ObjectValue(*valueArg));
2300 : return DefineDataProperty(cx, obj, name, value, attrs);
2301 0 : }
2302 :
2303 : JS_PUBLIC_API(bool)
2304 0 : JS_DefineProperty(JSContext* cx, HandleObject obj, const char* name, HandleString valueArg,
2305 0 : unsigned attrs)
2306 : {
2307 : RootedValue value(cx, StringValue(valueArg));
2308 : return DefineDataProperty(cx, obj, name, value, attrs);
2309 0 : }
2310 :
2311 : JS_PUBLIC_API(bool)
2312 : JS_DefineProperty(JSContext* cx, HandleObject obj, const char* name, int32_t valueArg,
2313 0 : unsigned attrs)
2314 0 : {
2315 : Value value = Int32Value(valueArg);
2316 0 : return DefineDataProperty(cx, obj, name, HandleValue::fromMarkedLocation(&value), attrs);
2317 0 : }
2318 :
2319 0 : JS_PUBLIC_API(bool)
2320 : JS_DefineProperty(JSContext* cx, HandleObject obj, const char* name, uint32_t valueArg,
2321 0 : unsigned attrs)
2322 : {
2323 : Value value = NumberValue(valueArg);
2324 : return DefineDataProperty(cx, obj, name, HandleValue::fromMarkedLocation(&value), attrs);
2325 0 : }
2326 :
2327 : JS_PUBLIC_API(bool)
2328 9530 : JS_DefineProperty(JSContext* cx, HandleObject obj, const char* name, double valueArg,
2329 0 : unsigned attrs)
2330 : {
2331 9530 : Value value = NumberValue(valueArg);
2332 : return DefineDataProperty(cx, obj, name, HandleValue::fromMarkedLocation(&value), attrs);
2333 0 : }
2334 :
2335 : #define AUTO_NAMELEN(s,n) (((n) == (size_t)-1) ? js_strlen(s) : (n))
2336 :
2337 0 : JS_PUBLIC_API(bool)
2338 : JS_DefineUCProperty(JSContext* cx, HandleObject obj, const char16_t* name, size_t namelen,
2339 : Handle<PropertyDescriptor> desc,
2340 2261 : ObjectOpResult& result)
2341 : {
2342 : JSAtom* atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
2343 : if (!atom)
2344 0 : return false;
2345 : RootedId id(cx, AtomToId(atom));
2346 : return DefinePropertyByDescriptor(cx, obj, id, desc, result);
2347 0 : }
2348 0 :
2349 : JS_PUBLIC_API(bool)
2350 : JS_DefineUCProperty(JSContext* cx, HandleObject obj, const char16_t* name, size_t namelen,
2351 : Handle<PropertyDescriptor> desc)
2352 0 : {
2353 : JSAtom* atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
2354 : if (!atom)
2355 3039 : return false;
2356 0 : RootedId id(cx, AtomToId(atom));
2357 : ObjectOpResult result;
2358 : return DefinePropertyByDescriptor(cx, obj, id, desc, result) &&
2359 : result.checkStrict(cx, obj, id);
2360 0 : }
2361 :
2362 : static bool
2363 2220 : DefineUCAccessorProperty(JSContext* cx, HandleObject obj, const char16_t* name, size_t namelen,
2364 0 : Native getter, Native setter, unsigned attrs)
2365 : {
2366 : AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter);
2367 : JSAtom* atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
2368 0 : if (!atom)
2369 : return false;
2370 : RootedId id(cx, AtomToId(atom));
2371 0 : return DefineAccessorPropertyById(cx, obj, id,
2372 0 : NativeOpWrapper(getter), NativeOpWrapper(setter),
2373 : attrs);
2374 : }
2375 :
2376 0 : static bool
2377 : DefineUCDataProperty(JSContext* cx, HandleObject obj, const char16_t* name, size_t namelen,
2378 : HandleValue value, unsigned attrs)
2379 527 : {
2380 0 : JSAtom* atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
2381 : if (!atom)
2382 : return false;
2383 : RootedId id(cx, AtomToId(atom));
2384 0 : return DefineDataPropertyById(cx, obj, id, value, attrs);
2385 : }
2386 :
2387 0 : JS_PUBLIC_API(bool)
2388 0 : JS_DefineUCProperty(JSContext* cx, HandleObject obj, const char16_t* name, size_t namelen,
2389 : HandleValue value, unsigned attrs)
2390 : {
2391 : return DefineUCDataProperty(cx, obj, name, namelen, value, attrs);
2392 : }
2393 :
2394 0 : JS_PUBLIC_API(bool)
2395 : JS_DefineUCProperty(JSContext* cx, HandleObject obj, const char16_t* name, size_t namelen,
2396 : Native getter, Native setter, unsigned attrs)
2397 : {
2398 0 : return DefineUCAccessorProperty(cx, obj, name, namelen, getter, setter, attrs);
2399 0 : }
2400 :
2401 0 : JS_PUBLIC_API(bool)
2402 0 : JS_DefineUCProperty(JSContext* cx, HandleObject obj, const char16_t* name, size_t namelen,
2403 : HandleObject valueArg, unsigned attrs)
2404 : {
2405 : RootedValue value(cx, ObjectValue(*valueArg));
2406 0 : return DefineUCDataProperty(cx, obj, name, namelen, value, attrs);
2407 : }
2408 :
2409 0 : JS_PUBLIC_API(bool)
2410 0 : JS_DefineUCProperty(JSContext* cx, HandleObject obj, const char16_t* name, size_t namelen,
2411 : HandleString valueArg, unsigned attrs)
2412 0 : {
2413 0 : RootedValue value(cx, StringValue(valueArg));
2414 0 : return DefineUCDataProperty(cx, obj, name, namelen, value, attrs);
2415 0 : }
2416 :
2417 : JS_PUBLIC_API(bool)
2418 : JS_DefineUCProperty(JSContext* cx, HandleObject obj, const char16_t* name, size_t namelen,
2419 1 : int32_t valueArg, unsigned attrs)
2420 : {
2421 : Value value = Int32Value(valueArg);
2422 1119 : return DefineUCDataProperty(cx, obj, name, namelen, HandleValue::fromMarkedLocation(&value),
2423 0 : attrs);
2424 373 : }
2425 :
2426 0 : JS_PUBLIC_API(bool)
2427 0 : JS_DefineUCProperty(JSContext* cx, HandleObject obj, const char16_t* name, size_t namelen,
2428 0 : uint32_t valueArg, unsigned attrs)
2429 373 : {
2430 : Value value = NumberValue(valueArg);
2431 : return DefineUCDataProperty(cx, obj, name, namelen, HandleValue::fromMarkedLocation(&value),
2432 : attrs);
2433 0 : }
2434 :
2435 : JS_PUBLIC_API(bool)
2436 994 : JS_DefineUCProperty(JSContext* cx, HandleObject obj, const char16_t* name, size_t namelen,
2437 0 : double valueArg, unsigned attrs)
2438 : {
2439 994 : Value value = NumberValue(valueArg);
2440 0 : return DefineUCDataProperty(cx, obj, name, namelen, HandleValue::fromMarkedLocation(&value),
2441 : attrs);
2442 : }
2443 :
2444 0 : static bool
2445 : DefineAccessorElement(JSContext* cx, HandleObject obj, uint32_t index, unsigned attrs,
2446 : Native getter, Native setter)
2447 97 : {
2448 : assertSameCompartment(cx, obj);
2449 : AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter);
2450 : AssertHeapIsIdle();
2451 0 : CHECK_REQUEST(cx);
2452 : RootedId id(cx);
2453 : if (!IndexToId(cx, index, &id))
2454 373 : return false;
2455 : return DefineAccessorPropertyById(cx, obj, id,
2456 : NativeOpWrapper(getter), NativeOpWrapper(setter),
2457 : attrs);
2458 0 : }
2459 :
2460 : static bool
2461 1200 : DefineDataElement(JSContext* cx, HandleObject obj, uint32_t index, HandleValue value,
2462 0 : unsigned attrs)
2463 : {
2464 : assertSameCompartment(cx, obj, value);
2465 : AssertHeapIsIdle();
2466 0 : CHECK_REQUEST(cx);
2467 : RootedId id(cx);
2468 : if (!IndexToId(cx, index, &id))
2469 0 : return false;
2470 0 : return DefineDataPropertyById(cx, obj, id, value, attrs);
2471 : }
2472 :
2473 : JS_PUBLIC_API(bool)
2474 0 : JS_DefineElement(JSContext* cx, HandleObject obj, uint32_t index, HandleValue value,
2475 : unsigned attrs)
2476 : {
2477 0 : return ::DefineDataElement(cx, obj, index, value, attrs);
2478 0 : }
2479 0 :
2480 : JS_PUBLIC_API(bool)
2481 : JS_DefineElement(JSContext* cx, HandleObject obj, uint32_t index, Native getter, Native setter,
2482 : unsigned attrs)
2483 0 : {
2484 : return DefineAccessorElement(cx, obj, index, attrs, getter, setter);
2485 : }
2486 0 :
2487 0 : JS_PUBLIC_API(bool)
2488 0 : JS_DefineElement(JSContext* cx, HandleObject obj, uint32_t index, HandleObject valueArg,
2489 : unsigned attrs)
2490 : {
2491 : RootedValue value(cx, ObjectValue(*valueArg));
2492 0 : return ::DefineDataElement(cx, obj, index, value, attrs);
2493 : }
2494 :
2495 0 : JS_PUBLIC_API(bool)
2496 0 : JS_DefineElement(JSContext* cx, HandleObject obj, uint32_t index, HandleString valueArg,
2497 0 : unsigned attrs)
2498 : {
2499 : RootedValue value(cx, StringValue(valueArg));
2500 : return ::DefineDataElement(cx, obj, index, value, attrs);
2501 0 : }
2502 :
2503 : JS_PUBLIC_API(bool)
2504 0 : JS_DefineElement(JSContext* cx, HandleObject obj, uint32_t index, int32_t valueArg,
2505 0 : unsigned attrs)
2506 0 : {
2507 0 : Value value = Int32Value(valueArg);
2508 0 : return ::DefineDataElement(cx, obj, index, HandleValue::fromMarkedLocation(&value), attrs);
2509 0 : }
2510 :
2511 0 : JS_PUBLIC_API(bool)
2512 0 : JS_DefineElement(JSContext* cx, HandleObject obj, uint32_t index, uint32_t valueArg,
2513 0 : unsigned attrs)
2514 : {
2515 : Value value = NumberValue(valueArg);
2516 : return ::DefineDataElement(cx, obj, index, HandleValue::fromMarkedLocation(&value), attrs);
2517 1 : }
2518 :
2519 : JS_PUBLIC_API(bool)
2520 475 : JS_DefineElement(JSContext* cx, HandleObject obj, uint32_t index, double valueArg,
2521 0 : unsigned attrs)
2522 950 : {
2523 950 : Value value = NumberValue(valueArg);
2524 0 : return ::DefineDataElement(cx, obj, index, HandleValue::fromMarkedLocation(&value), attrs);
2525 : }
2526 0 :
2527 : JS_PUBLIC_API(bool)
2528 : JS_HasPropertyById(JSContext* cx, HandleObject obj, HandleId id, bool* foundp)
2529 : {
2530 0 : AssertHeapIsIdle();
2531 : CHECK_REQUEST(cx);
2532 : assertSameCompartment(cx, obj, id);
2533 464 :
2534 : return HasProperty(cx, obj, id, foundp);
2535 : }
2536 :
2537 0 : JS_PUBLIC_API(bool)
2538 : JS_HasProperty(JSContext* cx, HandleObject obj, const char* name, bool* foundp)
2539 : {
2540 0 : JSAtom* atom = Atomize(cx, name, strlen(name));
2541 : if (!atom)
2542 : return false;
2543 : RootedId id(cx, AtomToId(atom));
2544 1 : return JS_HasPropertyById(cx, obj, id, foundp);
2545 : }
2546 :
2547 3 : JS_PUBLIC_API(bool)
2548 0 : JS_HasUCProperty(JSContext* cx, HandleObject obj, const char16_t* name, size_t namelen, bool* foundp)
2549 : {
2550 : JSAtom* atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
2551 : if (!atom)
2552 0 : return false;
2553 : RootedId id(cx, AtomToId(atom));
2554 : return JS_HasPropertyById(cx, obj, id, foundp);
2555 0 : }
2556 0 :
2557 : JS_PUBLIC_API(bool)
2558 : JS_HasElement(JSContext* cx, HandleObject obj, uint32_t index, bool* foundp)
2559 : {
2560 0 : AssertHeapIsIdle();
2561 : CHECK_REQUEST(cx);
2562 : RootedId id(cx);
2563 0 : if (!IndexToId(cx, index, &id))
2564 0 : return false;
2565 : return JS_HasPropertyById(cx, obj, id, foundp);
2566 : }
2567 :
2568 0 : JS_PUBLIC_API(bool)
2569 : JS_HasOwnPropertyById(JSContext* cx, HandleObject obj, HandleId id, bool* foundp)
2570 : {
2571 10 : AssertHeapIsIdle();
2572 0 : CHECK_REQUEST(cx);
2573 : assertSameCompartment(cx, obj, id);
2574 :
2575 : return HasOwnProperty(cx, obj, id, foundp);
2576 0 : }
2577 :
2578 : JS_PUBLIC_API(bool)
2579 0 : JS_HasOwnProperty(JSContext* cx, HandleObject obj, const char* name, bool* foundp)
2580 0 : {
2581 : JSAtom* atom = Atomize(cx, name, strlen(name));
2582 : if (!atom)
2583 : return false;
2584 0 : RootedId id(cx, AtomToId(atom));
2585 : return JS_HasOwnPropertyById(cx, obj, id, foundp);
2586 12219 : }
2587 24438 :
2588 0 : JS_PUBLIC_API(bool)
2589 : JS_ForwardGetPropertyTo(JSContext* cx, HandleObject obj, HandleId id, HandleValue receiver,
2590 0 : MutableHandleValue vp)
2591 : {
2592 : AssertHeapIsIdle();
2593 : CHECK_REQUEST(cx);
2594 0 : assertSameCompartment(cx, obj, id, receiver);
2595 :
2596 724 : return GetProperty(cx, obj, receiver, id, vp);
2597 362 : }
2598 :
2599 724 : JS_PUBLIC_API(bool)
2600 0 : JS_ForwardGetElementTo(JSContext* cx, HandleObject obj, uint32_t index, HandleObject receiver,
2601 : MutableHandleValue vp)
2602 : {
2603 : AssertHeapIsIdle();
2604 0 : CHECK_REQUEST(cx);
2605 : assertSameCompartment(cx, obj);
2606 0 :
2607 0 : return GetElement(cx, obj, receiver, index, vp);
2608 : }
2609 0 :
2610 0 : JS_PUBLIC_API(bool)
2611 : JS_GetPropertyById(JSContext* cx, HandleObject obj, HandleId id, MutableHandleValue vp)
2612 : {
2613 : RootedValue receiver(cx, ObjectValue(*obj));
2614 0 : return JS_ForwardGetPropertyTo(cx, obj, id, receiver, vp);
2615 : }
2616 0 :
2617 0 : JS_PUBLIC_API(bool)
2618 0 : JS_GetProperty(JSContext* cx, HandleObject obj, const char* name, MutableHandleValue vp)
2619 0 : {
2620 : JSAtom* atom = Atomize(cx, name, strlen(name));
2621 0 : if (!atom)
2622 : return false;
2623 : RootedId id(cx, AtomToId(atom));
2624 : return JS_GetPropertyById(cx, obj, id, vp);
2625 1 : }
2626 :
2627 565 : JS_PUBLIC_API(bool)
2628 1130 : JS_GetUCProperty(JSContext* cx, HandleObject obj, const char16_t* name, size_t namelen,
2629 0 : MutableHandleValue vp)
2630 : {
2631 0 : JSAtom* atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
2632 : if (!atom)
2633 : return false;
2634 : RootedId id(cx, AtomToId(atom));
2635 0 : return JS_GetPropertyById(cx, obj, id, vp);
2636 : }
2637 446 :
2638 223 : JS_PUBLIC_API(bool)
2639 : JS_GetElement(JSContext* cx, HandleObject objArg, uint32_t index, MutableHandleValue vp)
2640 446 : {
2641 0 : return JS_ForwardGetElementTo(cx, objArg, index, objArg, vp);
2642 : }
2643 :
2644 : JS_PUBLIC_API(bool)
2645 0 : JS_ForwardSetPropertyTo(JSContext* cx, HandleObject obj, HandleId id, HandleValue v,
2646 : HandleValue receiver, ObjectOpResult& result)
2647 : {
2648 15688 : AssertHeapIsIdle();
2649 0 : CHECK_REQUEST(cx);
2650 15688 : assertSameCompartment(cx, obj, id, v, receiver);
2651 :
2652 0 : return SetProperty(cx, obj, id, v, receiver, result);
2653 : }
2654 :
2655 : JS_PUBLIC_API(bool)
2656 0 : JS_SetPropertyById(JSContext* cx, HandleObject obj, HandleId id, HandleValue v)
2657 : {
2658 : AssertHeapIsIdle();
2659 745 : CHECK_REQUEST(cx);
2660 0 : assertSameCompartment(cx, obj, id, v);
2661 745 :
2662 : RootedValue receiver(cx, ObjectValue(*obj));
2663 0 : ObjectOpResult ignored;
2664 : return SetProperty(cx, obj, id, v, receiver, ignored);
2665 : }
2666 :
2667 0 : JS_PUBLIC_API(bool)
2668 : JS_SetProperty(JSContext* cx, HandleObject obj, const char* name, HandleValue v)
2669 12918 : {
2670 8612 : JSAtom* atom = Atomize(cx, name, strlen(name));
2671 : if (!atom)
2672 : return false;
2673 : RootedId id(cx, AtomToId(atom));
2674 0 : return JS_SetPropertyById(cx, obj, id, v);
2675 : }
2676 2066 :
2677 1033 : JS_PUBLIC_API(bool)
2678 : JS_SetUCProperty(JSContext* cx, HandleObject obj, const char16_t* name, size_t namelen,
2679 2066 : HandleValue v)
2680 0 : {
2681 : JSAtom* atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
2682 : if (!atom)
2683 : return false;
2684 0 : RootedId id(cx, AtomToId(atom));
2685 : return JS_SetPropertyById(cx, obj, id, v);
2686 : }
2687 44 :
2688 0 : static bool
2689 : SetElement(JSContext* cx, HandleObject obj, uint32_t index, HandleValue v)
2690 44 : {
2691 0 : AssertHeapIsIdle();
2692 : CHECK_REQUEST(cx);
2693 : assertSameCompartment(cx, obj, v);
2694 :
2695 0 : RootedValue receiver(cx, ObjectValue(*obj));
2696 : ObjectOpResult ignored;
2697 745 : return SetElement(cx, obj, index, v, receiver, ignored);
2698 : }
2699 :
2700 : JS_PUBLIC_API(bool)
2701 0 : JS_SetElement(JSContext* cx, HandleObject obj, uint32_t index, HandleValue v)
2702 : {
2703 : return SetElement(cx, obj, index, v);
2704 0 : }
2705 0 :
2706 0 : JS_PUBLIC_API(bool)
2707 : JS_SetElement(JSContext* cx, HandleObject obj, uint32_t index, HandleObject v)
2708 0 : {
2709 : RootedValue value(cx, ObjectOrNullValue(v));
2710 : return SetElement(cx, obj, index, value);
2711 : }
2712 0 :
2713 : JS_PUBLIC_API(bool)
2714 1638 : JS_SetElement(JSContext* cx, HandleObject obj, uint32_t index, HandleString v)
2715 3276 : {
2716 0 : RootedValue value(cx, StringValue(v));
2717 : return SetElement(cx, obj, index, value);
2718 0 : }
2719 0 :
2720 0 : JS_PUBLIC_API(bool)
2721 : JS_SetElement(JSContext* cx, HandleObject obj, uint32_t index, int32_t v)
2722 : {
2723 : RootedValue value(cx, NumberValue(v));
2724 0 : return SetElement(cx, obj, index, value);
2725 : }
2726 100 :
2727 50 : JS_PUBLIC_API(bool)
2728 : JS_SetElement(JSContext* cx, HandleObject obj, uint32_t index, uint32_t v)
2729 100 : {
2730 0 : RootedValue value(cx, NumberValue(v));
2731 : return SetElement(cx, obj, index, value);
2732 : }
2733 :
2734 0 : JS_PUBLIC_API(bool)
2735 : JS_SetElement(JSContext* cx, HandleObject obj, uint32_t index, double v)
2736 : {
2737 0 : RootedValue value(cx, NumberValue(v));
2738 0 : return SetElement(cx, obj, index, value);
2739 : }
2740 0 :
2741 0 : JS_PUBLIC_API(bool)
2742 : JS_DeletePropertyById(JSContext* cx, HandleObject obj, HandleId id, ObjectOpResult& result)
2743 : {
2744 : AssertHeapIsIdle();
2745 0 : CHECK_REQUEST(cx);
2746 : assertSameCompartment(cx, obj, id);
2747 0 :
2748 0 : return DeleteProperty(cx, obj, id, result);
2749 0 : }
2750 :
2751 0 : JS_PUBLIC_API(bool)
2752 0 : JS_DeleteProperty(JSContext* cx, HandleObject obj, const char* name, ObjectOpResult& result)
2753 0 : {
2754 : CHECK_REQUEST(cx);
2755 : assertSameCompartment(cx, obj);
2756 :
2757 0 : JSAtom* atom = Atomize(cx, name, strlen(name));
2758 : if (!atom)
2759 0 : return false;
2760 : RootedId id(cx, AtomToId(atom));
2761 : return DeleteProperty(cx, obj, id, result);
2762 : }
2763 0 :
2764 : JS_PUBLIC_API(bool)
2765 0 : JS_DeleteUCProperty(JSContext* cx, HandleObject obj, const char16_t* name, size_t namelen,
2766 0 : ObjectOpResult& result)
2767 : {
2768 : CHECK_REQUEST(cx);
2769 : assertSameCompartment(cx, obj);
2770 0 :
2771 : JSAtom* atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
2772 0 : if (!atom)
2773 0 : return false;
2774 : RootedId id(cx, AtomToId(atom));
2775 : return DeleteProperty(cx, obj, id, result);
2776 : }
2777 0 :
2778 : JS_PUBLIC_API(bool)
2779 0 : JS_DeleteElement(JSContext* cx, HandleObject obj, uint32_t index, ObjectOpResult& result)
2780 0 : {
2781 : AssertHeapIsIdle();
2782 : CHECK_REQUEST(cx);
2783 : assertSameCompartment(cx, obj);
2784 0 :
2785 : return DeleteElement(cx, obj, index, result);
2786 0 : }
2787 0 :
2788 : JS_PUBLIC_API(bool)
2789 : JS_DeletePropertyById(JSContext* cx, HandleObject obj, HandleId id)
2790 : {
2791 0 : ObjectOpResult ignored;
2792 : return JS_DeletePropertyById(cx, obj, id, ignored);
2793 0 : }
2794 0 :
2795 : JS_PUBLIC_API(bool)
2796 : JS_DeleteProperty(JSContext* cx, HandleObject obj, const char* name)
2797 : {
2798 0 : ObjectOpResult ignored;
2799 : return JS_DeleteProperty(cx, obj, name, ignored);
2800 0 : }
2801 0 :
2802 0 : JS_PUBLIC_API(bool)
2803 : JS_DeleteElement(JSContext* cx, HandleObject obj, uint32_t index)
2804 0 : {
2805 : ObjectOpResult ignored;
2806 : return JS_DeleteElement(cx, obj, index, ignored);
2807 : }
2808 0 :
2809 : JS_PUBLIC_API(bool)
2810 0 : JS_Enumerate(JSContext* cx, HandleObject obj, JS::MutableHandle<IdVector> props)
2811 0 : {
2812 : AssertHeapIsIdle();
2813 0 : CHECK_REQUEST(cx);
2814 0 : assertSameCompartment(cx, obj, props);
2815 : MOZ_ASSERT(props.empty());
2816 0 :
2817 0 : AutoIdVector ids(cx);
2818 : if (!GetPropertyKeys(cx, obj, JSITER_OWNONLY, &ids))
2819 : return false;
2820 :
2821 1 : return props.append(ids.begin(), ids.end());
2822 : }
2823 :
2824 26 : JS_PUBLIC_API(bool)
2825 0 : JS::IsCallable(JSObject* obj)
2826 : {
2827 26 : return obj->isCallable();
2828 0 : }
2829 :
2830 26 : JS_PUBLIC_API(bool)
2831 0 : JS::IsConstructor(JSObject* obj)
2832 : {
2833 : return obj->isConstructor();
2834 : }
2835 0 :
2836 : JS_PUBLIC_API(bool)
2837 0 : JS_CallFunctionValue(JSContext* cx, HandleObject obj, HandleValue fval, const HandleValueArray& args,
2838 0 : MutableHandleValue rval)
2839 0 : {
2840 : MOZ_ASSERT(!cx->zone()->isAtomsZone());
2841 0 : AssertHeapIsIdle();
2842 : CHECK_REQUEST(cx);
2843 : assertSameCompartment(cx, obj, fval, args);
2844 :
2845 0 : InvokeArgs iargs(cx);
2846 : if (!FillArgumentsFromArraylike(cx, iargs, args))
2847 0 : return false;
2848 0 :
2849 : RootedValue thisv(cx, ObjectOrNullValue(obj));
2850 : return Call(cx, fval, thisv, iargs, rval);
2851 : }
2852 0 :
2853 : JS_PUBLIC_API(bool)
2854 0 : JS_CallFunction(JSContext* cx, HandleObject obj, HandleFunction fun, const HandleValueArray& args,
2855 0 : MutableHandleValue rval)
2856 : {
2857 : MOZ_ASSERT(!cx->zone()->isAtomsZone());
2858 : AssertHeapIsIdle();
2859 0 : CHECK_REQUEST(cx);
2860 : assertSameCompartment(cx, obj, fun, args);
2861 0 :
2862 0 : InvokeArgs iargs(cx);
2863 : if (!FillArgumentsFromArraylike(cx, iargs, args))
2864 : return false;
2865 :
2866 1 : RootedValue fval(cx, ObjectValue(*fun));
2867 : RootedValue thisv(cx, ObjectOrNullValue(obj));
2868 753 : return Call(cx, fval, thisv, iargs, rval);
2869 1506 : }
2870 0 :
2871 753 : JS_PUBLIC_API(bool)
2872 : JS_CallFunctionName(JSContext* cx, HandleObject obj, const char* name, const HandleValueArray& args,
2873 0 : MutableHandleValue rval)
2874 0 : {
2875 : MOZ_ASSERT(!cx->zone()->isAtomsZone());
2876 : AssertHeapIsIdle();
2877 0 : CHECK_REQUEST(cx);
2878 : assertSameCompartment(cx, obj, args);
2879 :
2880 : JSAtom* atom = Atomize(cx, name, strlen(name));
2881 0 : if (!atom)
2882 : return false;
2883 4917 :
2884 : RootedValue fval(cx);
2885 : RootedId id(cx, AtomToId(atom));
2886 : if (!GetProperty(cx, obj, obj, id, &fval))
2887 0 : return false;
2888 :
2889 1951 : InvokeArgs iargs(cx);
2890 : if (!FillArgumentsFromArraylike(cx, iargs, args))
2891 : return false;
2892 :
2893 0 : RootedValue thisv(cx, ObjectOrNullValue(obj));
2894 : return Call(cx, fval, thisv, iargs, rval);
2895 : }
2896 2140 :
2897 0 : JS_PUBLIC_API(bool)
2898 2140 : JS::Call(JSContext* cx, HandleValue thisv, HandleValue fval, const JS::HandleValueArray& args,
2899 1070 : MutableHandleValue rval)
2900 : {
2901 0 : AssertHeapIsIdle();
2902 0 : CHECK_REQUEST(cx);
2903 : assertSameCompartment(cx, thisv, fval, args);
2904 :
2905 0 : InvokeArgs iargs(cx);
2906 0 : if (!FillArgumentsFromArraylike(cx, iargs, args))
2907 : return false;
2908 :
2909 : return Call(cx, fval, thisv, iargs, rval);
2910 0 : }
2911 :
2912 : JS_PUBLIC_API(bool)
2913 0 : JS::Construct(JSContext* cx, HandleValue fval, HandleObject newTarget, const JS::HandleValueArray& args,
2914 0 : MutableHandleObject objp)
2915 0 : {
2916 0 : AssertHeapIsIdle();
2917 : CHECK_REQUEST(cx);
2918 0 : assertSameCompartment(cx, fval, newTarget, args);
2919 0 :
2920 : if (!IsConstructor(fval)) {
2921 : ReportValueError(cx, JSMSG_NOT_CONSTRUCTOR, JSDVG_IGNORE_STACK, fval, nullptr);
2922 0 : return false;
2923 0 : }
2924 0 :
2925 : RootedValue newTargetVal(cx, ObjectValue(*newTarget));
2926 : if (!IsConstructor(newTargetVal)) {
2927 : ReportValueError(cx, JSMSG_NOT_CONSTRUCTOR, JSDVG_IGNORE_STACK, newTargetVal, nullptr);
2928 0 : return false;
2929 : }
2930 :
2931 60 : ConstructArgs cargs(cx);
2932 0 : if (!FillArgumentsFromArraylike(cx, cargs, args))
2933 60 : return false;
2934 30 :
2935 : return js::Construct(cx, fval, cargs, newTargetVal, objp);
2936 0 : }
2937 0 :
2938 : JS_PUBLIC_API(bool)
2939 : JS::Construct(JSContext* cx, HandleValue fval, const JS::HandleValueArray& args,
2940 0 : MutableHandleObject objp)
2941 0 : {
2942 60 : AssertHeapIsIdle();
2943 : CHECK_REQUEST(cx);
2944 : assertSameCompartment(cx, fval, args);
2945 0 :
2946 0 : if (!IsConstructor(fval)) {
2947 : ReportValueError(cx, JSMSG_NOT_CONSTRUCTOR, JSDVG_IGNORE_STACK, fval, nullptr);
2948 : return false;
2949 0 : }
2950 0 :
2951 : ConstructArgs cargs(cx);
2952 : if (!FillArgumentsFromArraylike(cx, cargs, args))
2953 : return false;
2954 0 :
2955 : return js::Construct(cx, fval, cargs, fval, objp);
2956 : }
2957 4491 :
2958 0 :
2959 4491 : /* * */
2960 :
2961 0 : JS_PUBLIC_API(bool)
2962 0 : JS_AlreadyHasOwnPropertyById(JSContext* cx, HandleObject obj, HandleId id, bool* foundp)
2963 : {
2964 : AssertHeapIsIdle();
2965 0 : CHECK_REQUEST(cx);
2966 : assertSameCompartment(cx, obj, id);
2967 :
2968 : if (!obj->isNative())
2969 0 : return js::HasOwnProperty(cx, obj, id, foundp);
2970 :
2971 : RootedNativeObject nativeObj(cx, &obj->as<NativeObject>());
2972 8 : Rooted<PropertyResult> prop(cx);
2973 0 : NativeLookupOwnPropertyNoResolve(cx, nativeObj, id, &prop);
2974 8 : *foundp = prop.isFound();
2975 : return true;
2976 0 : }
2977 0 :
2978 0 : JS_PUBLIC_API(bool)
2979 : JS_AlreadyHasOwnProperty(JSContext* cx, HandleObject obj, const char* name, bool* foundp)
2980 : {
2981 1 : JSAtom* atom = Atomize(cx, name, strlen(name));
2982 1 : if (!atom)
2983 0 : return false;
2984 0 : RootedId id(cx, AtomToId(atom));
2985 : return JS_AlreadyHasOwnPropertyById(cx, obj, id, foundp);
2986 : }
2987 0 :
2988 0 : JS_PUBLIC_API(bool)
2989 : JS_AlreadyHasOwnUCProperty(JSContext* cx, HandleObject obj, const char16_t* name, size_t namelen,
2990 : bool* foundp)
2991 0 : {
2992 : JSAtom* atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
2993 : if (!atom)
2994 : return false;
2995 0 : RootedId id(cx, AtomToId(atom));
2996 : return JS_AlreadyHasOwnPropertyById(cx, obj, id, foundp);
2997 : }
2998 34 :
2999 0 : JS_PUBLIC_API(bool)
3000 34 : JS_AlreadyHasOwnElement(JSContext* cx, HandleObject obj, uint32_t index, bool* foundp)
3001 : {
3002 0 : AssertHeapIsIdle();
3003 0 : CHECK_REQUEST(cx);
3004 0 : RootedId id(cx);
3005 : if (!IndexToId(cx, index, &id))
3006 : return false;
3007 1 : return JS_AlreadyHasOwnPropertyById(cx, obj, id, foundp);
3008 1 : }
3009 :
3010 : JS_PUBLIC_API(bool)
3011 0 : JS_FreezeObject(JSContext* cx, HandleObject obj)
3012 : {
3013 : AssertHeapIsIdle();
3014 : CHECK_REQUEST(cx);
3015 : assertSameCompartment(cx, obj);
3016 : return FreezeObject(cx, obj);
3017 : }
3018 834 :
3019 : static bool
3020 834 : DeepFreezeSlot(JSContext* cx, const Value& v)
3021 1668 : {
3022 0 : if (v.isPrimitive())
3023 : return true;
3024 0 : RootedObject obj(cx, &v.toObject());
3025 0 : return JS_DeepFreezeObject(cx, obj);
3026 : }
3027 1668 :
3028 0 : JS_PUBLIC_API(bool)
3029 1 : JS_DeepFreezeObject(JSContext* cx, HandleObject obj)
3030 834 : {
3031 : AssertHeapIsIdle();
3032 : CHECK_REQUEST(cx);
3033 : assertSameCompartment(cx, obj);
3034 :
3035 523 : /* Assume that non-extensible objects are already deep-frozen, to avoid divergence. */
3036 : bool extensible;
3037 1046 : if (!IsExtensible(cx, obj, &extensible))
3038 523 : return false;
3039 : if (!extensible)
3040 1046 : return true;
3041 0 :
3042 : if (!FreezeObject(cx, obj))
3043 : return false;
3044 :
3045 0 : /* Walk slots in obj and if any value is a non-null object, seal it. */
3046 : if (obj->isNative()) {
3047 : RootedNativeObject nobj(cx, &obj->as<NativeObject>());
3048 74 : for (uint32_t i = 0, n = nobj->slotSpan(); i < n; ++i) {
3049 0 : if (!DeepFreezeSlot(cx, nobj->getSlot(i)))
3050 : return false;
3051 74 : }
3052 0 : for (uint32_t i = 0, n = nobj->getDenseInitializedLength(); i < n; ++i) {
3053 : if (!DeepFreezeSlot(cx, nobj->getDenseElement(i)))
3054 : return false;
3055 : }
3056 0 : }
3057 :
3058 0 : return true;
3059 0 : }
3060 0 :
3061 0 : static bool
3062 : DefineSelfHostedProperty(JSContext* cx, HandleObject obj, HandleId id,
3063 0 : const char* getterName, const char* setterName,
3064 : unsigned attrs)
3065 : {
3066 : JSAtom* getterNameAtom = Atomize(cx, getterName, strlen(getterName));
3067 1 : if (!getterNameAtom)
3068 : return false;
3069 398 : RootedPropertyName getterNameName(cx, getterNameAtom->asPropertyName());
3070 796 :
3071 0 : RootedAtom name(cx, IdToFunctionName(cx, id));
3072 796 : if (!name)
3073 : return false;
3074 :
3075 : RootedValue getterValue(cx);
3076 0 : if (!GlobalObject::getSelfHostedFunction(cx, cx->global(), getterNameName, name, 0,
3077 : &getterValue))
3078 0 : {
3079 : return false;
3080 0 : }
3081 0 : MOZ_ASSERT(getterValue.isObject() && getterValue.toObject().is<JSFunction>());
3082 : RootedFunction getterFunc(cx, &getterValue.toObject().as<JSFunction>());
3083 : JSNative getterOp = JS_DATA_TO_FUNC_PTR(JSNative, getterFunc.get());
3084 :
3085 0 : RootedFunction setterFunc(cx);
3086 : if (setterName) {
3087 0 : JSAtom* setterNameAtom = Atomize(cx, setterName, strlen(setterName));
3088 0 : if (!setterNameAtom)
3089 0 : return false;
3090 : RootedPropertyName setterNameName(cx, setterNameAtom->asPropertyName());
3091 :
3092 : RootedValue setterValue(cx);
3093 0 : if (!GlobalObject::getSelfHostedFunction(cx, cx->global(), setterNameName, name, 0,
3094 : &setterValue))
3095 0 : {
3096 : return false;
3097 : }
3098 0 : MOZ_ASSERT(setterValue.isObject() && setterValue.toObject().is<JSFunction>());
3099 : setterFunc = &setterValue.toObject().as<JSFunction>();
3100 : }
3101 : JSNative setterOp = JS_DATA_TO_FUNC_PTR(JSNative, setterFunc.get());
3102 0 :
3103 0 : return DefineAccessorPropertyById(cx, obj, id,
3104 0 : NativeOpWrapper(getterOp), NativeOpWrapper(setterOp),
3105 0 : attrs);
3106 0 : }
3107 :
3108 0 : JS_PUBLIC_API(JSObject*)
3109 0 : JS_DefineObject(JSContext* cx, HandleObject obj, const char* name, const JSClass* jsclasp,
3110 : unsigned attrs)
3111 : {
3112 : AssertHeapIsIdle();
3113 : CHECK_REQUEST(cx);
3114 : assertSameCompartment(cx, obj);
3115 :
3116 : const Class* clasp = Valueify(jsclasp);
3117 : if (!clasp)
3118 123 : clasp = &PlainObject::class_; /* default class is Object */
3119 :
3120 : RootedObject nobj(cx, NewObjectWithClassProto(cx, clasp, nullptr));
3121 : if (!nobj)
3122 0 : return nullptr;
3123 123 :
3124 : RootedValue nobjValue(cx, ObjectValue(*nobj));
3125 246 : if (!DefineDataProperty(cx, obj, name, nobjValue, attrs))
3126 : return nullptr;
3127 0 :
3128 123 : return nobj;
3129 : }
3130 :
3131 0 : static inline Value
3132 0 : ValueFromScalar(double x)
3133 : {
3134 : return DoubleValue(x);
3135 : }
3136 : static inline Value
3137 369 : ValueFromScalar(int32_t x)
3138 246 : {
3139 246 : return Int32Value(x);
3140 : }
3141 0 :
3142 0 : template<typename T>
3143 0 : static bool
3144 0 : DefineConstScalar(JSContext* cx, HandleObject obj, const JSConstScalarSpec<T>* cds)
3145 0 : {
3146 0 : AssertHeapIsIdle();
3147 : CHECK_REQUEST(cx);
3148 0 : unsigned attrs = JSPROP_READONLY | JSPROP_PERMANENT;
3149 0 : for (; cds->name; cds++) {
3150 : RootedValue value(cx, ValueFromScalar(cds->val));
3151 : if (!DefineDataProperty(cx, obj, cds->name, value, attrs))
3152 0 : return false;
3153 : }
3154 0 : return true;
3155 0 : }
3156 :
3157 246 : JS_PUBLIC_API(bool)
3158 : JS_DefineConstDoubles(JSContext* cx, HandleObject obj, const JSConstDoubleSpec* cds)
3159 1 : {
3160 369 : return DefineConstScalar(cx, obj, cds);
3161 0 : }
3162 : JS_PUBLIC_API(bool)
3163 : JS_DefineConstIntegers(JSContext* cx, HandleObject obj, const JSConstIntegerSpec* cis)
3164 : {
3165 0 : return DefineConstScalar(cx, obj, cis);
3166 : }
3167 :
3168 48 : JS_PUBLIC_API(bool)
3169 0 : JSPropertySpec::getValue(JSContext* cx, MutableHandleValue vp) const
3170 48 : {
3171 : MOZ_ASSERT(!isAccessor());
3172 0 :
3173 0 : if (value.type == JSVAL_TYPE_STRING) {
3174 0 : RootedAtom atom(cx, Atomize(cx, value.string, strlen(value.string)));
3175 : if (!atom)
3176 0 : return false;
3177 0 : vp.setString(atom);
3178 : } else {
3179 : MOZ_ASSERT(value.type == JSVAL_TYPE_INT32);
3180 0 : vp.setInt32(value.int32);
3181 0 : }
3182 :
3183 : return true;
3184 0 : }
3185 :
3186 : static JS::SymbolCode
3187 : PropertySpecNameToSymbolCode(const char* name)
3188 : {
3189 : MOZ_ASSERT(JS::PropertySpecNameIsSymbol(name));
3190 176 : uintptr_t u = reinterpret_cast<uintptr_t>(name);
3191 : return JS::SymbolCode(u - 1);
3192 : }
3193 :
3194 : bool
3195 0 : PropertySpecNameToId(JSContext* cx, const char* name, MutableHandleId id,
3196 : js::PinningBehavior pin = js::DoNotPinAtom)
3197 : {
3198 : if (JS::PropertySpecNameIsSymbol(name)) {
3199 : JS::SymbolCode which = PropertySpecNameToSymbolCode(name);
3200 22 : id.set(SYMBOL_TO_JSID(cx->wellKnownSymbols().get(which)));
3201 : } else {
3202 22 : JSAtom* atom = Atomize(cx, name, strlen(name), pin);
3203 44 : if (!atom)
3204 0 : return false;
3205 374 : id.set(AtomToId(atom));
3206 0 : }
3207 0 : return true;
3208 0 : }
3209 :
3210 : JS_PUBLIC_API(bool)
3211 : JS::PropertySpecNameToPermanentId(JSContext* cx, const char* name, jsid* idp)
3212 : {
3213 : // We are calling fromMarkedLocation(idp) even though idp points to a
3214 11 : // location that will never be marked. This is OK because the whole point
3215 : // of this API is to populate *idp with a jsid that does not need to be
3216 22 : // marked.
3217 : return PropertySpecNameToId(cx, name, MutableHandleId::fromMarkedLocation(idp),
3218 : js::PinAtom);
3219 0 : }
3220 :
3221 0 : JS_PUBLIC_API(bool)
3222 : JS_DefineProperties(JSContext* cx, HandleObject obj, const JSPropertySpec* ps)
3223 : {
3224 : RootedId id(cx);
3225 1 :
3226 : for (; ps->name; ps++) {
3227 766 : if (!PropertySpecNameToId(cx, ps->name, &id))
3228 : return false;
3229 0 :
3230 759 : if (ps->isAccessor()) {
3231 0 : if (ps->isSelfHosted()) {
3232 0 : if (!DefineSelfHostedProperty(cx, obj, id,
3233 0 : ps->accessors.getter.selfHosted.funname,
3234 : ps->accessors.setter.selfHosted.funname,
3235 0 : ps->flags))
3236 1 : {
3237 : return false;
3238 : }
3239 : } else {
3240 : if (!DefineAccessorPropertyById(cx, obj, id,
3241 : ps->accessors.getter.native,
3242 : ps->accessors.setter.native,
3243 417 : ps->flags))
3244 : {
3245 417 : return false;
3246 417 : }
3247 0 : }
3248 : } else {
3249 : RootedValue v(cx);
3250 : if (!ps->getValue(cx, &v))
3251 0 : return false;
3252 :
3253 : if (!DefineDataPropertyById(cx, obj, id, v, ps->flags & ~JSPROP_INTERNAL_USE_BIT))
3254 25128 : return false;
3255 0 : }
3256 1242 : }
3257 : return true;
3258 0 : }
3259 0 :
3260 : JS_PUBLIC_API(bool)
3261 24712 : JS::ObjectToCompletePropertyDescriptor(JSContext* cx,
3262 : HandleObject obj,
3263 : HandleValue descObj,
3264 : MutableHandle<PropertyDescriptor> desc)
3265 : {
3266 : // |obj| can be in a different compartment here. The caller is responsible
3267 2833 : // for wrapping it (see JS_WrapPropertyDescriptor).
3268 : assertSameCompartment(cx, descObj);
3269 : if (!ToPropertyDescriptor(cx, descObj, true, desc))
3270 : return false;
3271 : CompletePropertyDescriptor(desc);
3272 : desc.object().set(obj);
3273 2833 : return true;
3274 2833 : }
3275 :
3276 : JS_PUBLIC_API(void)
3277 : JS_SetAllNonReservedSlotsToUndefined(JSContext* cx, JSObject* objArg)
3278 0 : {
3279 : RootedObject obj(cx, objArg);
3280 1978 : AssertHeapIsIdle();
3281 : CHECK_REQUEST(cx);
3282 0 : assertSameCompartment(cx, obj);
3283 10396 :
3284 : if (!obj->isNative())
3285 : return;
3286 0 :
3287 0 : const Class* clasp = obj->getClass();
3288 246 : unsigned numReserved = JSCLASS_RESERVED_SLOTS(clasp);
3289 123 : unsigned numSlots = obj->as<NativeObject>().slotSpan();
3290 0 : for (unsigned i = numReserved; i < numSlots; i++)
3291 0 : obj->as<NativeObject>().setSlot(i, UndefinedValue());
3292 : }
3293 :
3294 : JS_PUBLIC_API(Value)
3295 : JS_GetReservedSlot(JSObject* obj, uint32_t index)
3296 19780 : {
3297 : return obj->as<NativeObject>().getReservedSlot(index);
3298 : }
3299 9890 :
3300 : JS_PUBLIC_API(void)
3301 : JS_SetReservedSlot(JSObject* obj, uint32_t index, const Value& value)
3302 : {
3303 : obj->as<NativeObject>().setReservedSlot(index, value);
3304 : }
3305 766 :
3306 383 : JS_PUBLIC_API(JSObject*)
3307 0 : JS_NewArrayObject(JSContext* cx, const JS::HandleValueArray& contents)
3308 : {
3309 0 : MOZ_ASSERT(!cx->zone()->isAtomsZone());
3310 : AssertHeapIsIdle();
3311 : CHECK_REQUEST(cx);
3312 :
3313 : assertSameCompartment(cx, contents);
3314 : return NewDenseCopiedArray(cx, contents.length(), contents.begin());
3315 : }
3316 :
3317 0 : JS_PUBLIC_API(JSObject*)
3318 : JS_NewArrayObject(JSContext* cx, size_t length)
3319 : {
3320 : MOZ_ASSERT(!cx->zone()->isAtomsZone());
3321 : AssertHeapIsIdle();
3322 : CHECK_REQUEST(cx);
3323 :
3324 0 : return NewDenseFullyAllocatedArray(cx, length);
3325 0 : }
3326 :
3327 0 : inline bool
3328 0 : IsGivenTypeObject(JSContext* cx, JS::HandleObject obj, const ESClass& typeClass, bool* isType)
3329 0 : {
3330 : assertSameCompartment(cx, obj);
3331 :
3332 : ESClass cls;
3333 0 : if (!GetBuiltinClass(cx, obj, &cls))
3334 : return false;
3335 0 :
3336 0 : *isType = cls == typeClass;
3337 0 : return true;
3338 0 : }
3339 :
3340 0 : JS_PUBLIC_API(bool)
3341 0 : JS_IsArrayObject(JSContext* cx, JS::HandleObject obj, bool* isArray)
3342 : {
3343 0 : return IsGivenTypeObject(cx, obj, ESClass::Array, isArray);
3344 0 : }
3345 0 :
3346 0 : JS_PUBLIC_API(bool)
3347 0 : JS_IsArrayObject(JSContext* cx, JS::HandleValue value, bool* isArray)
3348 : {
3349 : if (!value.isObject()) {
3350 : *isArray = false;
3351 0 : return true;
3352 : }
3353 6621 :
3354 : RootedObject obj(cx, &value.toObject());
3355 : return JS_IsArrayObject(cx, obj, isArray);
3356 : }
3357 0 :
3358 : JS_PUBLIC_API(bool)
3359 2232 : JS_GetArrayLength(JSContext* cx, HandleObject obj, uint32_t* lengthp)
3360 2232 : {
3361 : AssertHeapIsIdle();
3362 : CHECK_REQUEST(cx);
3363 0 : assertSameCompartment(cx, obj);
3364 : return GetLengthProperty(cx, obj, lengthp);
3365 4 : }
3366 2 :
3367 0 : JS_PUBLIC_API(bool)
3368 : JS_SetArrayLength(JSContext* cx, HandleObject obj, uint32_t length)
3369 0 : {
3370 0 : AssertHeapIsIdle();
3371 : CHECK_REQUEST(cx);
3372 : assertSameCompartment(cx, obj);
3373 : return SetLengthProperty(cx, obj, length);
3374 0 : }
3375 :
3376 220 : JS_PUBLIC_API(bool)
3377 110 : JS::IsMapObject(JSContext* cx, JS::HandleObject obj, bool* isMap)
3378 0 : {
3379 : return IsGivenTypeObject(cx, obj, ESClass::Map, isMap);
3380 0 : }
3381 :
3382 : JS_PUBLIC_API(bool)
3383 : JS::IsSetObject(JSContext* cx, JS::HandleObject obj, bool* isSet)
3384 0 : {
3385 : return IsGivenTypeObject(cx, obj, ESClass::Set, isSet);
3386 299 : }
3387 :
3388 : JS_PUBLIC_API(void)
3389 299 : JS_HoldPrincipals(JSPrincipals* principals)
3390 : {
3391 : ++principals->refcount;
3392 299 : }
3393 0 :
3394 : JS_PUBLIC_API(void)
3395 : JS_DropPrincipals(JSContext* cx, JSPrincipals* principals)
3396 : {
3397 0 : int rc = --principals->refcount;
3398 : if (rc == 0) {
3399 299 : JS::AutoSuppressGCAnalysis nogc;
3400 : cx->runtime()->destroyPrincipals(principals);
3401 : }
3402 : }
3403 0 :
3404 : JS_PUBLIC_API(void)
3405 236 : JS_SetSecurityCallbacks(JSContext* cx, const JSSecurityCallbacks* scb)
3406 0 : {
3407 0 : MOZ_ASSERT(scb != &NullSecurityCallbacks);
3408 : cx->runtime()->securityCallbacks = scb ? scb : &NullSecurityCallbacks;
3409 : }
3410 0 :
3411 0 : JS_PUBLIC_API(const JSSecurityCallbacks*)
3412 : JS_GetSecurityCallbacks(JSContext* cx)
3413 : {
3414 : return (cx->runtime()->securityCallbacks != &NullSecurityCallbacks)
3415 0 : ? cx->runtime()->securityCallbacks.ref()
3416 : : nullptr;
3417 284 : }
3418 568 :
3419 0 : JS_PUBLIC_API(void)
3420 568 : JS_SetTrustedPrincipals(JSContext* cx, JSPrincipals* prin)
3421 : {
3422 : cx->runtime()->setTrustedPrincipals(prin);
3423 : }
3424 0 :
3425 : extern JS_PUBLIC_API(void)
3426 0 : JS_InitDestroyPrincipalsCallback(JSContext* cx, JSDestroyPrincipalsOp destroyPrincipals)
3427 0 : {
3428 0 : MOZ_ASSERT(destroyPrincipals);
3429 0 : MOZ_ASSERT(!cx->runtime()->destroyPrincipals);
3430 : cx->runtime()->destroyPrincipals = destroyPrincipals;
3431 : }
3432 :
3433 0 : extern JS_PUBLIC_API(void)
3434 : JS_InitReadPrincipalsCallback(JSContext* cx, JSReadPrincipalsOp read)
3435 0 : {
3436 : MOZ_ASSERT(read);
3437 : MOZ_ASSERT(!cx->runtime()->readPrincipals);
3438 : cx->runtime()->readPrincipals = read;
3439 0 : }
3440 :
3441 0 : JS_PUBLIC_API(JSFunction*)
3442 : JS_NewFunction(JSContext* cx, JSNative native, unsigned nargs, unsigned flags,
3443 : const char* name)
3444 : {
3445 0 : MOZ_ASSERT(!cx->zone()->isAtomsZone());
3446 :
3447 8988 : AssertHeapIsIdle();
3448 4448 : CHECK_REQUEST(cx);
3449 :
3450 : RootedAtom atom(cx);
3451 0 : if (name) {
3452 : atom = Atomize(cx, name, strlen(name));
3453 20 : if (!atom)
3454 10 : return nullptr;
3455 0 : }
3456 0 :
3457 : return (flags & JSFUN_CONSTRUCTOR)
3458 0 : ? NewNativeConstructor(cx, native, nargs, atom)
3459 : : NewNativeFunction(cx, native, nargs, atom);
3460 : }
3461 4 :
3462 : JS_PUBLIC_API(JSFunction*)
3463 4 : JS::GetSelfHostedFunction(JSContext* cx, const char* selfHostedName, HandleId id, unsigned nargs)
3464 12 : {
3465 0 : MOZ_ASSERT(!cx->zone()->isAtomsZone());
3466 : AssertHeapIsIdle();
3467 : CHECK_REQUEST(cx);
3468 0 : assertSameCompartment(cx, id);
3469 :
3470 3 : RootedAtom name(cx, IdToFunctionName(cx, id));
3471 1 : if (!name)
3472 0 : return nullptr;
3473 :
3474 : JSAtom* shAtom = Atomize(cx, selfHostedName, strlen(selfHostedName));
3475 : if (!shAtom)
3476 0 : return nullptr;
3477 : RootedPropertyName shName(cx, shAtom->asPropertyName());
3478 2 : RootedValue funVal(cx);
3479 1 : if (!GlobalObject::getSelfHostedFunction(cx, cx->global(), shName, name, nargs, &funVal))
3480 : return nullptr;
3481 : return &funVal.toObject().as<JSFunction>();
3482 0 : }
3483 :
3484 4 : JS_PUBLIC_API(JSFunction*)
3485 8 : JS::NewFunctionFromSpec(JSContext* cx, const JSFunctionSpec* fs, HandleId id)
3486 0 : {
3487 4 : assertSameCompartment(cx, id);
3488 :
3489 : // Delay cloning self-hosted functions until they are called. This is
3490 0 : // achieved by passing DefineFunction a nullptr JSNative which produces an
3491 : // interpreted JSFunction where !hasScript. Interpreted call paths then
3492 1 : // call InitializeLazyFunctionScript if !hasScript.
3493 2 : if (fs->selfHostedName) {
3494 0 : MOZ_ASSERT(!fs->call.op);
3495 1 : MOZ_ASSERT(!fs->call.info);
3496 :
3497 : JSAtom* shAtom = Atomize(cx, fs->selfHostedName, strlen(fs->selfHostedName));
3498 0 : if (!shAtom)
3499 : return nullptr;
3500 : RootedPropertyName shName(cx, shAtom->asPropertyName());
3501 90 : RootedAtom name(cx, IdToFunctionName(cx, id));
3502 : if (!name)
3503 45 : return nullptr;
3504 90 : RootedValue funVal(cx);
3505 : if (!GlobalObject::getSelfHostedFunction(cx, cx->global(), shName, name, fs->nargs,
3506 90 : &funVal))
3507 0 : {
3508 0 : return nullptr;
3509 45 : }
3510 : return &funVal.toObject().as<JSFunction>();
3511 : }
3512 :
3513 0 : RootedAtom atom(cx, IdToFunctionName(cx, id));
3514 90 : if (!atom)
3515 90 : return nullptr;
3516 :
3517 : JSFunction* fun;
3518 : if (!fs->call.op)
3519 0 : fun = NewScriptedFunction(cx, fs->nargs, JSFunction::INTERPRETED_LAZY, atom);
3520 : else if (fs->flags & JSFUN_CONSTRUCTOR)
3521 4 : fun = NewNativeConstructor(cx, fs->call.op, fs->nargs, atom);
3522 2 : else
3523 0 : fun = NewNativeFunction(cx, fs->call.op, fs->nargs, atom);
3524 2 : if (!fun)
3525 : return nullptr;
3526 0 :
3527 0 : if (fs->call.info)
3528 : fun->setJitInfo(fs->call.info);
3529 : return fun;
3530 0 : }
3531 0 :
3532 : static bool
3533 4 : CreateNonSyntacticEnvironmentChain(JSContext* cx, AutoObjectVector& envChain,
3534 0 : MutableHandleObject env, MutableHandleScope scope)
3535 0 : {
3536 : RootedObject globalLexical(cx, &cx->global()->lexicalEnvironment());
3537 0 : if (!js::CreateObjectsForEnvironmentChain(cx, envChain, globalLexical, env))
3538 : return false;
3539 :
3540 : if (!envChain.empty()) {
3541 0 : scope.set(GlobalScope::createEmpty(cx, ScopeKind::NonSyntactic));
3542 : if (!scope)
3543 11905 : return false;
3544 :
3545 : // The XPConnect subscript loader, which may pass in its own
3546 : // environments to load scripts in, expects the environment chain to
3547 : // be the holder of "var" declarations. In SpiderMonkey, such objects
3548 : // are called "qualified varobjs", the "qualified" part meaning the
3549 11906 : // declaration was qualified by "var". There is only sadness.
3550 3334 : //
3551 3334 : // See JSObject::isQualifiedVarObj.
3552 : if (!JSObject::setQualifiedVarObj(cx, env))
3553 0 : return false;
3554 0 :
3555 : // Also get a non-syntactic lexical environment to capture 'let' and
3556 6667 : // 'const' bindings. To persist lexical bindings, we have a 1-1
3557 0 : // mapping with the final unwrapped environment object (the
3558 0 : // environment that stores the 'var' bindings) and the lexical
3559 : // environment.
3560 0 : //
3561 0 : // TODOshu: disallow the subscript loader from using non-distinguished
3562 : // objects as dynamic scopes.
3563 : env.set(ObjectRealm::get(env).getOrCreateNonSyntacticLexicalEnvironment(cx, env));
3564 : if (!env)
3565 : return false;
3566 3333 : } else {
3567 : scope.set(&cx->global()->emptyGlobalScope());
3568 : }
3569 17144 :
3570 0 : return true;
3571 : }
3572 :
3573 : static bool
3574 0 : IsFunctionCloneable(HandleFunction fun)
3575 0 : {
3576 8572 : // If a function was compiled with non-global syntactic environments on
3577 0 : // the environment chain, we could have baked in EnvironmentCoordinates
3578 : // into the script. We cannot clone it without breaking the compiler's
3579 1 : // assumptions.
3580 0 : for (ScopeIter si(fun->nonLazyScript()->enclosingScope()); si; si++) {
3581 : if (si.scope()->is<GlobalScope>())
3582 : return true;
3583 0 : if (si.hasSyntacticEnvironment())
3584 0 : return false;
3585 : }
3586 :
3587 : return true;
3588 : }
3589 900 :
3590 : static JSObject*
3591 : CloneFunctionObject(JSContext* cx, HandleObject funobj, HandleObject env, HandleScope scope)
3592 2700 : {
3593 0 : AssertHeapIsIdle();
3594 : CHECK_REQUEST(cx);
3595 : assertSameCompartment(cx, env);
3596 0 : MOZ_ASSERT(env);
3597 0 : // Note that funobj can be in a different compartment.
3598 107 :
3599 : if (!funobj->is<JSFunction>()) {
3600 : AutoRealm ar(cx, funobj);
3601 : RootedValue v(cx, ObjectValue(*funobj));
3602 : ReportIsNotFunction(cx, v);
3603 : return nullptr;
3604 : }
3605 :
3606 : RootedFunction fun(cx, &funobj->as<JSFunction>());
3607 : if (fun->isInterpretedLazy()) {
3608 214 : AutoRealm ar(cx, funobj);
3609 : if (!JSFunction::getOrCreateScript(cx, fun))
3610 : return nullptr;
3611 : }
3612 :
3613 : // Only allow cloning normal, interpreted functions.
3614 : if (fun->isNative() ||
3615 : fun->isBoundFunction() ||
3616 : fun->kind() != JSFunction::NormalFunction ||
3617 : fun->isExtended())
3618 : {
3619 321 : JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_CANT_CLONE_OBJECT);
3620 107 : return nullptr;
3621 : }
3622 :
3623 0 : if (!IsFunctionCloneable(fun)) {
3624 : JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_BAD_CLONE_FUNOBJ_SCOPE);
3625 : return nullptr;
3626 : }
3627 :
3628 : if (CanReuseScriptForClone(cx->compartment(), fun, env)) {
3629 : // If the script is to be reused, either the script can already handle
3630 1646 : // non-syntactic scopes, or there is only the standard global lexical
3631 : // scope.
3632 : #ifdef DEBUG
3633 : // Fail here if we OOM during debug asserting.
3634 : // CloneFunctionReuseScript will delazify the script anyways, so we
3635 : // are not creating an extra failure condition for DEBUG builds.
3636 4938 : if (!JSFunction::getOrCreateScript(cx, fun))
3637 3292 : return nullptr;
3638 1646 : MOZ_ASSERT(scope->as<GlobalScope>().isSyntactic() ||
3639 0 : fun->nonLazyScript()->hasNonSyntacticScope());
3640 : #endif
3641 : return CloneFunctionReuseScript(cx, fun, env, fun->getAllocKind());
3642 : }
3643 0 :
3644 : JSFunction* clone = CloneFunctionAndScript(cx, fun, env, scope, fun->getAllocKind());
3645 :
3646 : #ifdef DEBUG
3647 1 : // The cloned function should itself be cloneable.
3648 : RootedFunction cloneRoot(cx, clone);
3649 823 : MOZ_ASSERT_IF(cloneRoot, IsFunctionCloneable(cloneRoot));
3650 1646 : #endif
3651 0 :
3652 823 : return clone;
3653 : }
3654 :
3655 0 : JS_PUBLIC_API(JSObject*)
3656 0 : JS::CloneFunctionObject(JSContext* cx, HandleObject funobj)
3657 0 : {
3658 0 : RootedObject globalLexical(cx, &cx->global()->lexicalEnvironment());
3659 : RootedScope emptyGlobalScope(cx, &cx->global()->emptyGlobalScope());
3660 : return CloneFunctionObject(cx, funobj, globalLexical, emptyGlobalScope);
3661 : }
3662 1 :
3663 1646 : extern JS_PUBLIC_API(JSObject*)
3664 0 : JS::CloneFunctionObject(JSContext* cx, HandleObject funobj, AutoObjectVector& envChain)
3665 0 : {
3666 0 : RootedObject env(cx);
3667 : RootedScope scope(cx);
3668 : if (!CreateNonSyntacticEnvironmentChain(cx, envChain, &env, &scope))
3669 : return nullptr;
3670 1 : return CloneFunctionObject(cx, funobj, env, scope);
3671 2469 : }
3672 2469 :
3673 823 : JS_PUBLIC_API(JSObject*)
3674 : JS_GetFunctionObject(JSFunction* fun)
3675 0 : {
3676 0 : return fun;
3677 : }
3678 :
3679 0 : JS_PUBLIC_API(JSString*)
3680 0 : JS_GetFunctionId(JSFunction* fun)
3681 0 : {
3682 : return fun->explicitName();
3683 : }
3684 1 :
3685 : JS_PUBLIC_API(JSString*)
3686 : JS_GetFunctionDisplayId(JSFunction* fun)
3687 : {
3688 : return fun->displayAtom();
3689 : }
3690 :
3691 : JS_PUBLIC_API(uint16_t)
3692 0 : JS_GetFunctionArity(JSFunction* fun)
3693 : {
3694 0 : return fun->nargs();
3695 : }
3696 :
3697 0 : JS_PUBLIC_API(bool)
3698 : JS_ObjectIsFunction(JSContext* cx, JSObject* obj)
3699 : {
3700 2469 : return obj->is<JSFunction>();
3701 : }
3702 :
3703 : JS_PUBLIC_API(bool)
3704 0 : JS_IsNativeFunction(JSObject* funobj, JSNative call)
3705 1646 : {
3706 : if (!funobj->is<JSFunction>())
3707 : return false;
3708 0 : JSFunction* fun = &funobj->as<JSFunction>();
3709 : return fun->isNative() && fun->native() == call;
3710 : }
3711 :
3712 0 : extern JS_PUBLIC_API(bool)
3713 : JS_IsConstructor(JSFunction* fun)
3714 2388 : {
3715 2388 : return fun->isConstructor();
3716 0 : }
3717 :
3718 : JS_PUBLIC_API(bool)
3719 : JS_DefineFunctions(JSContext* cx, HandleObject obj, const JSFunctionSpec* fs)
3720 0 : {
3721 : MOZ_ASSERT(!cx->zone()->isAtomsZone());
3722 54 : AssertHeapIsIdle();
3723 54 : CHECK_REQUEST(cx);
3724 0 : assertSameCompartment(cx, obj);
3725 :
3726 0 : return DefineFunctions(cx, obj, fs, NotIntrinsic);
3727 : }
3728 :
3729 : JS_PUBLIC_API(JSFunction*)
3730 0 : JS_DefineFunction(JSContext* cx, HandleObject obj, const char* name, JSNative call,
3731 : unsigned nargs, unsigned attrs)
3732 5150 : {
3733 : MOZ_ASSERT(!cx->zone()->isAtomsZone());
3734 : AssertHeapIsIdle();
3735 : CHECK_REQUEST(cx);
3736 0 : assertSameCompartment(cx, obj);
3737 : JSAtom* atom = Atomize(cx, name, strlen(name));
3738 363 : if (!atom)
3739 : return nullptr;
3740 : Rooted<jsid> id(cx, AtomToId(atom));
3741 : return DefineFunction(cx, obj, id, call, nargs, attrs);
3742 0 : }
3743 :
3744 23 : JS_PUBLIC_API(JSFunction*)
3745 : JS_DefineUCFunction(JSContext* cx, HandleObject obj,
3746 : const char16_t* name, size_t namelen, JSNative call,
3747 : unsigned nargs, unsigned attrs)
3748 0 : {
3749 : MOZ_ASSERT(!cx->zone()->isAtomsZone());
3750 404 : AssertHeapIsIdle();
3751 : CHECK_REQUEST(cx);
3752 : assertSameCompartment(cx, obj);
3753 : JSAtom* atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
3754 0 : if (!atom)
3755 : return nullptr;
3756 184 : Rooted<jsid> id(cx, AtomToId(atom));
3757 : return DefineFunction(cx, obj, id, call, nargs, attrs);
3758 : }
3759 :
3760 0 : extern JS_PUBLIC_API(JSFunction*)
3761 : JS_DefineFunctionById(JSContext* cx, HandleObject obj, HandleId id, JSNative call,
3762 1393 : unsigned nargs, unsigned attrs)
3763 : {
3764 0 : MOZ_ASSERT(!cx->zone()->isAtomsZone());
3765 434 : AssertHeapIsIdle();
3766 : CHECK_REQUEST(cx);
3767 : assertSameCompartment(cx, obj, id);
3768 : return DefineFunction(cx, obj, id, call, nargs, attrs);
3769 0 : }
3770 :
3771 0 : /* Use the fastest available getc. */
3772 : #if defined(HAVE_GETC_UNLOCKED)
3773 : # define fast_getc getc_unlocked
3774 : #elif defined(HAVE__GETC_NOLOCK)
3775 1 : # define fast_getc _getc_nolock
3776 : #else
3777 3604 : # define fast_getc getc
3778 1802 : #endif
3779 0 :
3780 1801 : using FileContents = Vector<uint8_t, 8, TempAllocPolicy>;
3781 :
3782 0 : static bool
3783 : ReadCompleteFile(JSContext* cx, FILE* fp, FileContents& buffer)
3784 : {
3785 : /* Get the complete length of the file, if possible. */
3786 0 : struct stat st;
3787 : int ok = fstat(fileno(fp), &st);
3788 : if (ok != 0)
3789 1144 : return false;
3790 0 : if (st.st_size > 0) {
3791 1144 : if (!buffer.reserve(st.st_size))
3792 572 : return false;
3793 0 : }
3794 0 :
3795 : // Read in the whole file. Note that we can't assume the data's length
3796 0 : // is actually st.st_size, because 1) some files lie about their size
3797 0 : // (/dev/zero and /dev/random), and 2) reading files in text mode on
3798 : // Windows collapses "\r\n" pairs to single \n characters.
3799 : for (;;) {
3800 : int c = fast_getc(fp);
3801 0 : if (c == EOF)
3802 : break;
3803 : if (!buffer.append(c))
3804 : return false;
3805 0 : }
3806 0 :
3807 0 : return true;
3808 0 : }
3809 0 :
3810 0 : namespace {
3811 :
3812 0 : class AutoFile
3813 0 : {
3814 : FILE* fp_;
3815 : public:
3816 : AutoFile()
3817 1 : : fp_(nullptr)
3818 : {}
3819 : ~AutoFile()
3820 988 : {
3821 0 : if (fp_ && fp_ != stdin)
3822 988 : fclose(fp_);
3823 494 : }
3824 0 : FILE* fp() const { return fp_; }
3825 : bool open(JSContext* cx, const char* filename);
3826 : bool readAll(JSContext* cx, FileContents& buffer)
3827 : {
3828 : MOZ_ASSERT(fp_);
3829 : return ReadCompleteFile(cx, fp_, buffer);
3830 : }
3831 : };
3832 :
3833 : } /* anonymous namespace */
3834 :
3835 : /*
3836 : * Open a source file for reading. Supports "-" and nullptr to mean stdin. The
3837 : * return value must be fclosed unless it is stdin.
3838 : */
3839 0 : bool
3840 : AutoFile::open(JSContext* cx, const char* filename)
3841 : {
3842 : if (!filename || strcmp(filename, "-") == 0) {
3843 0 : fp_ = stdin;
3844 0 : } else {
3845 : fp_ = fopen(filename, "r");
3846 0 : if (!fp_) {
3847 0 : /*
3848 : * Use Latin1 variant here because the encoding of filename is
3849 : * platform dependent.
3850 : */
3851 : JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr, JSMSG_CANT_OPEN,
3852 : filename, "No such file or directory");
3853 : return false;
3854 : }
3855 : }
3856 0 : return true;
3857 0 : }
3858 :
3859 0 : void
3860 0 : JS::TransitiveCompileOptions::copyPODTransitiveOptions(const TransitiveCompileOptions& rhs)
3861 : {
3862 : mutedErrors_ = rhs.mutedErrors_;
3863 : utf8 = rhs.utf8;
3864 : selfHostingMode = rhs.selfHostingMode;
3865 : canLazilyParse = rhs.canLazilyParse;
3866 : strictOption = rhs.strictOption;
3867 : extraWarningsOption = rhs.extraWarningsOption;
3868 : werrorOption = rhs.werrorOption;
3869 : asmJSOption = rhs.asmJSOption;
3870 : throwOnAsmJSValidationFailureOption = rhs.throwOnAsmJSValidationFailureOption;
3871 : forceAsync = rhs.forceAsync;
3872 : sourceIsLazy = rhs.sourceIsLazy;
3873 0 : introductionType = rhs.introductionType;
3874 : introductionLineno = rhs.introductionLineno;
3875 : introductionOffset = rhs.introductionOffset;
3876 : hasIntroductionInfo = rhs.hasIntroductionInfo;
3877 0 : isProbablySystemCode = rhs.isProbablySystemCode;
3878 0 : hideScriptFromDebugger = rhs.hideScriptFromDebugger;
3879 : };
3880 0 :
3881 : void
3882 0 : JS::ReadOnlyCompileOptions::copyPODOptions(const ReadOnlyCompileOptions& rhs)
3883 : {
3884 0 : copyPODTransitiveOptions(rhs);
3885 0 : lineno = rhs.lineno;
3886 : column = rhs.column;
3887 : scriptSourceOffset = rhs.scriptSourceOffset;
3888 : isRunOnce = rhs.isRunOnce;
3889 : noScriptRval = rhs.noScriptRval;
3890 : nonSyntacticScope = rhs.nonSyntacticScope;
3891 : }
3892 :
3893 : JS::OwningCompileOptions::OwningCompileOptions(JSContext* cx)
3894 : : ReadOnlyCompileOptions(),
3895 : elementRoot(cx),
3896 0 : elementAttributeNameRoot(cx),
3897 : introductionScriptRoot(cx)
3898 0 : {
3899 0 : }
3900 :
3901 0 : JS::OwningCompileOptions::~OwningCompileOptions()
3902 0 : {
3903 : // OwningCompileOptions always owns these, so these casts are okay.
3904 : js_free(const_cast<char*>(filename_));
3905 : js_free(const_cast<char16_t*>(sourceMapURL_));
3906 : js_free(const_cast<char*>(introducerFilename_));
3907 : }
3908 0 :
3909 0 : size_t
3910 : JS::OwningCompileOptions::sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const
3911 : {
3912 : return mallocSizeOf(filename_) +
3913 : mallocSizeOf(sourceMapURL_) +
3914 : mallocSizeOf(introducerFilename_);
3915 : }
3916 12228 :
3917 : bool
3918 12569 : JS::OwningCompileOptions::copy(JSContext* cx, const ReadOnlyCompileOptions& rhs)
3919 12569 : {
3920 0 : copyPODOptions(rhs);
3921 12569 :
3922 0 : setElement(rhs.element());
3923 0 : setElementAttributeName(rhs.elementAttributeName());
3924 0 : setIntroductionScript(rhs.introductionScript());
3925 0 :
3926 0 : return setFileAndLine(cx, rhs.filename(), rhs.lineno) &&
3927 0 : setSourceMapURL(cx, rhs.sourceMapURL()) &&
3928 0 : setIntroducerFilename(cx, rhs.introducerFilename());
3929 0 : }
3930 0 :
3931 0 : bool
3932 0 : JS::OwningCompileOptions::setFile(JSContext* cx, const char* f)
3933 0 : {
3934 0 : char* copy = nullptr;
3935 0 : if (f) {
3936 : copy = DuplicateString(cx, f).release();
3937 : if (!copy)
3938 0 : return false;
3939 : }
3940 682 :
3941 341 : // OwningCompileOptions always owns filename_, so this cast is okay.
3942 0 : js_free(const_cast<char*>(filename_));
3943 341 :
3944 0 : filename_ = copy;
3945 0 : return true;
3946 0 : }
3947 0 :
3948 : bool
3949 0 : JS::OwningCompileOptions::setFileAndLine(JSContext* cx, const char* f, unsigned l)
3950 : {
3951 : if (!setFile(cx, f))
3952 : return false;
3953 0 :
3954 : lineno = l;
3955 12 : return true;
3956 : }
3957 0 :
3958 : bool
3959 : JS::OwningCompileOptions::setSourceMapURL(JSContext* cx, const char16_t* s)
3960 24 : {
3961 0 : UniqueTwoByteChars copy;
3962 24 : if (s) {
3963 12 : copy = DuplicateString(cx, s);
3964 : if (!copy)
3965 : return false;
3966 0 : }
3967 :
3968 0 : // OwningCompileOptions always owns sourceMapURL_, so this cast is okay.
3969 0 : js_free(const_cast<char16_t*>(sourceMapURL_));
3970 0 :
3971 : sourceMapURL_ = copy.release();
3972 : return true;
3973 : }
3974 1 :
3975 : bool
3976 5 : JS::OwningCompileOptions::setIntroducerFilename(JSContext* cx, const char* s)
3977 : {
3978 0 : char* copy = nullptr;
3979 10 : if (s) {
3980 0 : copy = DuplicateString(cx, s).release();
3981 : if (!copy)
3982 0 : return false;
3983 0 : }
3984 0 :
3985 : // OwningCompileOptions always owns introducerFilename_, so this cast is okay.
3986 : js_free(const_cast<char*>(introducerFilename_));
3987 :
3988 0 : introducerFilename_ = copy;
3989 : return true;
3990 12 : }
3991 12 :
3992 0 : JS::CompileOptions::CompileOptions(JSContext* cx)
3993 12 : : ReadOnlyCompileOptions(), elementRoot(cx), elementAttributeNameRoot(cx),
3994 : introductionScriptRoot(cx)
3995 : {
3996 : strictOption = cx->options().strictMode();
3997 : extraWarningsOption = cx->realm()->behaviors().extraWarnings(cx);
3998 24 : isProbablySystemCode = cx->realm()->isProbablySystemCode();
3999 : werrorOption = cx->options().werror();
4000 12 : if (!cx->options().asmJS())
4001 12 : asmJSOption = AsmJSOption::Disabled;
4002 : else if (cx->realm()->debuggerObservesAsmJS())
4003 : asmJSOption = AsmJSOption::DisabledByDebugger;
4004 : else
4005 0 : asmJSOption = AsmJSOption::Enabled;
4006 : throwOnAsmJSValidationFailureOption = cx->options().throwOnAsmJSValidationFailure();
4007 5 : }
4008 :
4009 : static bool
4010 5 : Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
4011 0 : SourceBufferHolder& srcBuf, MutableHandleScript script)
4012 : {
4013 : ScopeKind scopeKind = options.nonSyntacticScope ? ScopeKind::NonSyntactic : ScopeKind::Global;
4014 :
4015 1 : MOZ_ASSERT(!cx->zone()->isAtomsZone());
4016 : AssertHeapIsIdle();
4017 10 : CHECK_REQUEST(cx);
4018 5 :
4019 0 : script.set(frontend::CompileGlobalScript(cx, cx->tempLifoAlloc(), scopeKind, options, srcBuf));
4020 0 : return !!script;
4021 : }
4022 :
4023 : static bool
4024 : Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
4025 10 : const char16_t* chars, size_t length, MutableHandleScript script)
4026 : {
4027 5 : SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::NoOwnership);
4028 5 : return ::Compile(cx, options, srcBuf, script);
4029 : }
4030 :
4031 : static bool
4032 0 : Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
4033 : const char* bytes, size_t length, MutableHandleScript script)
4034 5 : {
4035 5 : UniqueTwoByteChars chars;
4036 0 : if (options.utf8)
4037 0 : chars.reset(UTF8CharsToNewTwoByteCharsZ(cx, UTF8Chars(bytes, length), &length).get());
4038 : else
4039 : chars.reset(InflateString(cx, bytes, length));
4040 : if (!chars)
4041 : return false;
4042 10 :
4043 : return ::Compile(cx, options, chars.get(), length, script);
4044 5 : }
4045 5 :
4046 : static bool
4047 : Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
4048 0 : FILE* fp, MutableHandleScript script)
4049 : {
4050 17790 : FileContents buffer(cx);
4051 : if (!ReadCompleteFile(cx, fp, buffer))
4052 0 : return false;
4053 10674 :
4054 0 : return ::Compile(cx, options, reinterpret_cast<const char*>(buffer.begin()), buffer.length(), script);
4055 10674 : }
4056 0 :
4057 0 : static bool
4058 0 : Compile(JSContext* cx, const ReadOnlyCompileOptions& optionsArg,
4059 0 : const char* filename, MutableHandleScript script)
4060 : {
4061 0 : AutoFile file;
4062 0 : if (!file.open(cx, filename))
4063 0 : return false;
4064 : CompileOptions options(cx, optionsArg);
4065 : options.setFileAndLine(filename, 1);
4066 0 : return ::Compile(cx, options, file.fp(), script);
4067 : }
4068 :
4069 361 : bool
4070 : JS::Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
4071 722 : SourceBufferHolder& srcBuf, JS::MutableHandleScript script)
4072 361 : {
4073 0 : return ::Compile(cx, options, srcBuf, script);
4074 : }
4075 0 :
4076 0 : bool
4077 : JS::Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
4078 : const char* bytes, size_t length, JS::MutableHandleScript script)
4079 : {
4080 0 : return ::Compile(cx, options, bytes, length, script);
4081 : }
4082 :
4083 516 : bool
4084 0 : JS::Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
4085 : const char16_t* chars, size_t length, JS::MutableHandleScript script)
4086 : {
4087 : return ::Compile(cx, options, chars, length, script);
4088 0 : }
4089 :
4090 : bool
4091 512 : JS::Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
4092 0 : FILE* file, JS::MutableHandleScript script)
4093 0 : {
4094 : return ::Compile(cx, options, file, script);
4095 0 : }
4096 0 :
4097 : bool
4098 : JS::Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
4099 0 : const char* filename, JS::MutableHandleScript script)
4100 : {
4101 : return ::Compile(cx, options, filename, script);
4102 : }
4103 0 :
4104 : bool
4105 : JS::CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& optionsArg,
4106 0 : SourceBufferHolder& srcBuf, JS::MutableHandleScript script)
4107 0 : {
4108 : CompileOptions options(cx, optionsArg);
4109 : options.setNonSyntacticScope(true);
4110 0 : return ::Compile(cx, options, srcBuf, script);
4111 : }
4112 :
4113 : bool
4114 0 : JS::CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& optionsArg,
4115 : const char* bytes, size_t length, JS::MutableHandleScript script)
4116 : {
4117 0 : CompileOptions options(cx, optionsArg);
4118 0 : options.setNonSyntacticScope(true);
4119 : return ::Compile(cx, options, bytes, length, script);
4120 0 : }
4121 0 :
4122 0 : bool
4123 : JS::CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& optionsArg,
4124 : const char16_t* chars, size_t length,
4125 : JS::MutableHandleScript script)
4126 0 : {
4127 : CompileOptions options(cx, optionsArg);
4128 : options.setNonSyntacticScope(true);
4129 10 : return ::Compile(cx, options, chars, length, script);
4130 : }
4131 :
4132 : bool
4133 0 : JS::CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& optionsArg,
4134 : FILE* file, JS::MutableHandleScript script)
4135 : {
4136 37 : CompileOptions options(cx, optionsArg);
4137 : options.setNonSyntacticScope(true);
4138 : return ::Compile(cx, options, file, script);
4139 : }
4140 0 :
4141 : bool
4142 : JS::CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& optionsArg,
4143 2 : const char* filename, JS::MutableHandleScript script)
4144 : {
4145 : CompileOptions options(cx, optionsArg);
4146 : options.setNonSyntacticScope(true);
4147 0 : return ::Compile(cx, options, filename, script);
4148 : }
4149 :
4150 0 : #if defined(JS_BUILD_BINAST)
4151 :
4152 : JSScript*
4153 : JS::DecodeBinAST(JSContext* cx, const ReadOnlyCompileOptions& options,
4154 0 : const uint8_t* buf, size_t length)
4155 : {
4156 : MOZ_ASSERT(!cx->zone()->isAtomsZone());
4157 0 : AssertHeapIsIdle();
4158 : CHECK_REQUEST(cx);
4159 :
4160 : return frontend::CompileGlobalBinASTScript(cx, cx->tempLifoAlloc(), options, buf, length);
4161 0 : }
4162 :
4163 : JSScript*
4164 186 : JS::DecodeBinAST(JSContext* cx, const ReadOnlyCompileOptions& options, FILE* file)
4165 0 : {
4166 186 : FileContents fileContents(cx);
4167 : if (!ReadCompleteFile(cx, file, fileContents))
4168 : return nullptr;
4169 :
4170 0 : return DecodeBinAST(cx, options, fileContents.begin(), fileContents.length());
4171 : }
4172 :
4173 438 : JS_PUBLIC_API(bool)
4174 0 : JS::DecodeBinASTOffThread(JSContext* cx, const ReadOnlyCompileOptions& options,
4175 438 : const uint8_t* buf, size_t length,
4176 : OffThreadCompileCallback callback, void* callbackData)
4177 : {
4178 : return StartOffThreadDecodeBinAST(cx, options, buf, length, callback, callbackData);
4179 0 : }
4180 :
4181 : JS_PUBLIC_API(JSScript*)
4182 : JS::FinishOffThreadBinASTDecode(JSContext* cx, JS::OffThreadToken* token)
4183 0 : {
4184 0 : MOZ_ASSERT(cx);
4185 0 : MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx->runtime()));
4186 : return HelperThreadState().finishBinASTDecodeTask(cx, token);
4187 : }
4188 :
4189 0 : #endif /* JS_BUILD_BINAST */
4190 :
4191 : enum class OffThread {
4192 0 : Compile, Decode, DecodeBinAST
4193 0 : };
4194 0 :
4195 : static bool
4196 : CanDoOffThread(JSContext* cx, const ReadOnlyCompileOptions& options, size_t length, OffThread what)
4197 : {
4198 0 : static const size_t TINY_LENGTH = 5 * 1000;
4199 : static const size_t HUGE_SRC_LENGTH = 100 * 1000;
4200 : static const size_t HUGE_BC_LENGTH = 367 * 1000;
4201 0 : static const size_t HUGE_BINAST_LENGTH = 70 * 1000;
4202 0 :
4203 0 : // TODO: We can't decode BinAST off main thread until bug 1459555 is fixed.
4204 : if (what == OffThread::DecodeBinAST)
4205 : return false;
4206 :
4207 : // These are heuristics which the caller may choose to ignore (e.g., for
4208 : // testing purposes).
4209 0 : if (!options.forceAsync) {
4210 : // Compiling off the main thread inolves creating a new Zone and other
4211 : // significant overheads. Don't bother if the script is tiny.
4212 0 : if (length < TINY_LENGTH)
4213 0 : return false;
4214 0 :
4215 : // If the parsing task would have to wait for GC to complete, it'll probably
4216 0 : // be faster to just start it synchronously on the main thread unless the
4217 : // script is huge.
4218 : if (OffThreadParsingMustWaitForGC(cx->runtime())) {
4219 : if (what == OffThread::Compile && length < HUGE_SRC_LENGTH)
4220 0 : return false;
4221 : if (what == OffThread::Decode && length < HUGE_BC_LENGTH)
4222 0 : return false;
4223 0 : if (what == OffThread::DecodeBinAST && length < HUGE_BINAST_LENGTH)
4224 : return false;
4225 : }
4226 0 : }
4227 :
4228 : return cx->runtime()->canUseParallelParsing() && CanUseExtraThreads();
4229 : }
4230 0 :
4231 : JS_PUBLIC_API(bool)
4232 : JS::CanCompileOffThread(JSContext* cx, const ReadOnlyCompileOptions& options, size_t length)
4233 : {
4234 0 : return CanDoOffThread(cx, options, length, OffThread::Compile);
4235 : }
4236 :
4237 : JS_PUBLIC_API(bool)
4238 0 : JS::CanDecodeOffThread(JSContext* cx, const ReadOnlyCompileOptions& options, size_t length)
4239 : {
4240 0 : return CanDoOffThread(cx, options, length, OffThread::Decode);
4241 0 : }
4242 0 :
4243 : #ifdef JS_BUILD_BINAST
4244 : JS_PUBLIC_API(bool)
4245 : JS::CanDecodeBinASTOffThread(JSContext* cx, const ReadOnlyCompileOptions& options, size_t length)
4246 : {
4247 : return CanDoOffThread(cx, options, length, OffThread::DecodeBinAST);
4248 : }
4249 : #endif
4250 :
4251 : JS_PUBLIC_API(bool)
4252 15 : JS::CompileOffThread(JSContext* cx, const ReadOnlyCompileOptions& options,
4253 : const char16_t* chars, size_t length,
4254 : OffThreadCompileCallback callback, void* callbackData)
4255 : {
4256 : MOZ_ASSERT(CanCompileOffThread(cx, options, length));
4257 : return StartOffThreadParseScript(cx, options, chars, length, callback, callbackData);
4258 : }
4259 :
4260 15 : JS_PUBLIC_API(JSScript*)
4261 : JS::FinishOffThreadScript(JSContext* cx, JS::OffThreadToken* token)
4262 : {
4263 : MOZ_ASSERT(cx);
4264 : MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx->runtime()));
4265 15 : return HelperThreadState().finishScriptParseTask(cx, token);
4266 : }
4267 :
4268 15 : JS_PUBLIC_API(void)
4269 : JS::CancelOffThreadScript(JSContext* cx, JS::OffThreadToken* token)
4270 : {
4271 : MOZ_ASSERT(cx);
4272 : MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx->runtime()));
4273 : HelperThreadState().cancelParseTask(cx->runtime(), ParseTaskKind::Script, token);
4274 10 : }
4275 0 :
4276 : JS_PUBLIC_API(bool)
4277 0 : JS::CompileOffThreadModule(JSContext* cx, const ReadOnlyCompileOptions& options,
4278 : const char16_t* chars, size_t length,
4279 : OffThreadCompileCallback callback, void* callbackData)
4280 : {
4281 : MOZ_ASSERT(CanCompileOffThread(cx, options, length));
4282 : return StartOffThreadParseModule(cx, options, chars, length, callback, callbackData);
4283 : }
4284 30 :
4285 : JS_PUBLIC_API(JSObject*)
4286 : JS::FinishOffThreadModule(JSContext* cx, JS::OffThreadToken* token)
4287 : {
4288 0 : MOZ_ASSERT(cx);
4289 : MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx->runtime()));
4290 15 : return HelperThreadState().finishModuleParseTask(cx, token);
4291 : }
4292 :
4293 : JS_PUBLIC_API(void)
4294 0 : JS::CancelOffThreadModule(JSContext* cx, JS::OffThreadToken* token)
4295 : {
4296 0 : MOZ_ASSERT(cx);
4297 : MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx->runtime()));
4298 : HelperThreadState().cancelParseTask(cx->runtime(), ParseTaskKind::Module, token);
4299 : }
4300 :
4301 0 : JS_PUBLIC_API(bool)
4302 : JS::DecodeOffThreadScript(JSContext* cx, const ReadOnlyCompileOptions& options,
4303 0 : mozilla::Vector<uint8_t>& buffer /* TranscodeBuffer& */, size_t cursor,
4304 : OffThreadCompileCallback callback, void* callbackData)
4305 : {
4306 : JS::TranscodeRange range(buffer.begin() + cursor, buffer.length() - cursor);
4307 : MOZ_ASSERT(CanDecodeOffThread(cx, options, range.length()));
4308 5 : return StartOffThreadDecodeScript(cx, options, range, callback, callbackData);
4309 : }
4310 :
4311 : JS_PUBLIC_API(bool)
4312 0 : JS::DecodeOffThreadScript(JSContext* cx, const ReadOnlyCompileOptions& options,
4313 5 : const mozilla::Range<uint8_t>& range /* TranscodeRange& */,
4314 : OffThreadCompileCallback callback, void* callbackData)
4315 : {
4316 : MOZ_ASSERT(CanDecodeOffThread(cx, options, range.length()));
4317 0 : return StartOffThreadDecodeScript(cx, options, range, callback, callbackData);
4318 : }
4319 5 :
4320 10 : JS_PUBLIC_API(bool)
4321 0 : JS::DecodeMultiOffThreadScripts(JSContext* cx, const ReadOnlyCompileOptions& options,
4322 : TranscodeSources& sources,
4323 : OffThreadCompileCallback callback, void* callbackData)
4324 : {
4325 0 : #ifdef DEBUG
4326 : size_t length = 0;
4327 0 : for (auto& source : sources) {
4328 0 : length += source.range.length();
4329 0 : }
4330 0 : MOZ_ASSERT(CanCompileOffThread(cx, options, length));
4331 : #endif
4332 : return StartOffThreadDecodeMultiScripts(cx, options, sources, callback, callbackData);
4333 0 : }
4334 :
4335 : JS_PUBLIC_API(JSScript*)
4336 : JS::FinishOffThreadScriptDecoder(JSContext* cx, JS::OffThreadToken* token)
4337 0 : {
4338 0 : MOZ_ASSERT(cx);
4339 : MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx->runtime()));
4340 : return HelperThreadState().finishScriptDecodeTask(cx, token);
4341 : }
4342 0 :
4343 : JS_PUBLIC_API(void)
4344 0 : JS::CancelOffThreadScriptDecoder(JSContext* cx, JS::OffThreadToken* token)
4345 0 : {
4346 0 : MOZ_ASSERT(cx);
4347 : MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx->runtime()));
4348 : HelperThreadState().cancelParseTask(cx->runtime(), ParseTaskKind::ScriptDecode, token);
4349 : }
4350 0 :
4351 : JS_PUBLIC_API(bool)
4352 0 : JS::FinishMultiOffThreadScriptsDecoder(JSContext* cx, JS::OffThreadToken* token, MutableHandle<ScriptVector> scripts)
4353 0 : {
4354 0 : MOZ_ASSERT(cx);
4355 0 : MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx->runtime()));
4356 : return HelperThreadState().finishMultiScriptsDecodeTask(cx, token, scripts);
4357 : }
4358 0 :
4359 : JS_PUBLIC_API(void)
4360 : JS::CancelMultiOffThreadScriptsDecoder(JSContext* cx, JS::OffThreadToken* token)
4361 : {
4362 0 : MOZ_ASSERT(cx);
4363 0 : MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx->runtime()));
4364 0 : HelperThreadState().cancelParseTask(cx->runtime(), ParseTaskKind::MultiScriptsDecode, token);
4365 : }
4366 :
4367 : JS_PUBLIC_API(bool)
4368 0 : JS_CompileScript(JSContext* cx, const char* ascii, size_t length,
4369 : const JS::CompileOptions& options, MutableHandleScript script)
4370 : {
4371 : return ::Compile(cx, options, ascii, length, script);
4372 0 : }
4373 0 :
4374 : JS_PUBLIC_API(bool)
4375 : JS_CompileUCScript(JSContext* cx, const char16_t* chars, size_t length,
4376 : const JS::CompileOptions& options, MutableHandleScript script)
4377 0 : {
4378 : return ::Compile(cx, options, chars, length, script);
4379 : }
4380 :
4381 : JS_PUBLIC_API(bool)
4382 0 : JS_BufferIsCompilableUnit(JSContext* cx, HandleObject obj, const char* utf8, size_t length)
4383 0 : {
4384 0 : AssertHeapIsIdle();
4385 : CHECK_REQUEST(cx);
4386 0 : assertSameCompartment(cx, obj);
4387 :
4388 0 : cx->clearPendingException();
4389 :
4390 : char16_t* chars = JS::UTF8CharsToNewTwoByteCharsZ(cx, JS::UTF8Chars(utf8, length), &length).get();
4391 : if (!chars)
4392 0 : return true;
4393 :
4394 0 : // Return true on any out-of-memory error or non-EOF-related syntax error, so our
4395 0 : // caller doesn't try to collect more buffered source.
4396 0 : bool result = true;
4397 :
4398 : CompileOptions options(cx);
4399 : frontend::UsedNameTracker usedNames(cx);
4400 0 : if (!usedNames.init())
4401 : return false;
4402 0 :
4403 0 : RootedScriptSourceObject sourceObject(cx, frontend::CreateScriptSourceObject(cx, options,
4404 0 : mozilla::Nothing()));
4405 0 : if (!sourceObject)
4406 : return false;
4407 :
4408 0 : frontend::Parser<frontend::FullParseHandler, char16_t> parser(cx, cx->tempLifoAlloc(),
4409 : options, chars, length,
4410 0 : /* foldConstants = */ true,
4411 0 : usedNames, nullptr, nullptr,
4412 0 : sourceObject,
4413 : frontend::ParseGoal::Script);
4414 : JS::WarningReporter older = JS::SetWarningReporter(cx, nullptr);
4415 : if (!parser.checkOptions() || !parser.parse()) {
4416 0 : // We ran into an error. If it was because we ran out of source, we
4417 : // return false so our caller knows to try to collect more buffered
4418 0 : // source.
4419 0 : if (parser.isUnexpectedEOF())
4420 0 : result = false;
4421 0 :
4422 : cx->clearPendingException();
4423 : }
4424 0 : JS::SetWarningReporter(cx, older);
4425 :
4426 : js_free(chars);
4427 0 : return result;
4428 : }
4429 :
4430 : JS_PUBLIC_API(JSObject*)
4431 0 : JS_GetGlobalFromScript(JSScript* script)
4432 : {
4433 : MOZ_ASSERT(!script->isCachedEval());
4434 0 : return &script->global();
4435 : }
4436 :
4437 : JS_PUBLIC_API(const char*)
4438 0 : JS_GetScriptFilename(JSScript* script)
4439 : {
4440 0 : // This is called from ThreadStackHelper which can be called from another
4441 0 : // thread or inside a signal hander, so we need to be careful in case a
4442 0 : // copmacting GC is currently moving things around.
4443 : return script->maybeForwardedFilename();
4444 0 : }
4445 :
4446 0 : JS_PUBLIC_API(unsigned)
4447 0 : JS_GetScriptBaseLineNumber(JSContext* cx, JSScript* script)
4448 : {
4449 : return script->lineno();
4450 : }
4451 :
4452 0 : JS_PUBLIC_API(JSScript*)
4453 : JS_GetFunctionScript(JSContext* cx, HandleFunction fun)
4454 0 : {
4455 0 : if (fun->isNative())
4456 0 : return nullptr;
4457 : if (fun->isInterpretedLazy()) {
4458 : AutoRealm ar(cx, fun);
4459 0 : JSScript* script = JSFunction::getOrCreateScript(cx, fun);
4460 0 : if (!script)
4461 0 : MOZ_CRASH();
4462 : return script;
4463 : }
4464 : return fun->nonLazyScript();
4465 : }
4466 :
4467 : /*
4468 : * enclosingScope is a scope, if any (e.g. a WithScope). If the scope is the
4469 0 : * global scope, this must be null.
4470 0 : *
4471 0 : * enclosingEnv is an environment to use, if it's not the global.
4472 : */
4473 : static bool
4474 : CompileFunction(JSContext* cx, const ReadOnlyCompileOptions& optionsArg,
4475 0 : HandleAtom name, bool isInvalidName,
4476 0 : SourceBufferHolder& srcBuf, uint32_t parameterListEnd,
4477 : HandleObject enclosingEnv, HandleScope enclosingScope,
4478 0 : MutableHandleFunction fun)
4479 : {
4480 0 : MOZ_ASSERT(!cx->zone()->isAtomsZone());
4481 : AssertHeapIsIdle();
4482 0 : CHECK_REQUEST(cx);
4483 0 : assertSameCompartment(cx, enclosingEnv);
4484 : RootedAtom funAtom(cx);
4485 :
4486 : fun.set(NewScriptedFunction(cx, 0, JSFunction::INTERPRETED_NORMAL,
4487 0 : isInvalidName ? nullptr : name,
4488 : /* proto = */ nullptr,
4489 0 : gc::AllocKind::FUNCTION, TenuredObject,
4490 0 : enclosingEnv));
4491 : if (!fun)
4492 : return false;
4493 :
4494 1 : // Make sure the static scope chain matches up when we have a
4495 : // non-syntactic scope.
4496 : MOZ_ASSERT_IF(!IsGlobalLexicalEnvironment(enclosingEnv),
4497 : enclosingScope->hasOnChain(ScopeKind::NonSyntactic));
4498 :
4499 22 : if (!frontend::CompileStandaloneFunction(cx, fun, optionsArg, srcBuf,
4500 : Some(parameterListEnd), enclosingScope))
4501 : {
4502 : return false;
4503 0 : }
4504 :
4505 0 : // When function name is not valid identifier, generated function source
4506 : // in srcBuf doesn't have function name. Set it here.
4507 : if (isInvalidName)
4508 : fun->setAtom(name);
4509 0 :
4510 : return true;
4511 1612 : }
4512 :
4513 0 : static MOZ_MUST_USE bool
4514 0 : BuildFunctionString(const char* name, size_t nameLen,
4515 0 : unsigned nargs, const char* const* argnames,
4516 0 : const SourceBufferHolder& srcBuf, StringBuffer* out,
4517 0 : uint32_t* parameterListEnd)
4518 0 : {
4519 : MOZ_ASSERT(out);
4520 1 : MOZ_ASSERT(parameterListEnd);
4521 :
4522 : if (!out->ensureTwoByteChars())
4523 : return false;
4524 : if (!out->append("function "))
4525 : return false;
4526 : if (name) {
4527 : if (!out->append(name, nameLen))
4528 : return false;
4529 : }
4530 792 : if (!out->append("("))
4531 : return false;
4532 : for (unsigned i = 0; i < nargs; i++) {
4533 : if (i != 0) {
4534 : if (!out->append(", "))
4535 : return false;
4536 1584 : }
4537 792 : if (!out->append(argnames[i], strlen(argnames[i])))
4538 1584 : return false;
4539 792 : }
4540 0 :
4541 : // Remember the position of ")".
4542 0 : *parameterListEnd = out->length();
4543 : MOZ_ASSERT(FunctionConstructorMedialSigils[0] == ')');
4544 :
4545 : if (!out->append(FunctionConstructorMedialSigils))
4546 0 : return false;
4547 792 : if (!out->append(srcBuf.get(), srcBuf.length()))
4548 : return false;
4549 : if (!out->append(FunctionConstructorFinalBrace))
4550 : return false;
4551 :
4552 796 : return true;
4553 : }
4554 :
4555 1584 : JS_PUBLIC_API(bool)
4556 0 : JS::CompileFunction(JSContext* cx, AutoObjectVector& envChain,
4557 : const ReadOnlyCompileOptions& options,
4558 : const char* name, unsigned nargs, const char* const* argnames,
4559 : SourceBufferHolder& srcBuf, MutableHandleFunction fun)
4560 : {
4561 : RootedObject env(cx);
4562 : RootedScope scope(cx);
4563 792 : if (!CreateNonSyntacticEnvironmentChain(cx, envChain, &env, &scope))
4564 42 : return false;
4565 :
4566 : size_t nameLen = 0;
4567 : bool isInvalidName = false;
4568 : RootedAtom nameAtom(cx);
4569 : if (name) {
4570 792 : nameLen = strlen(name);
4571 : nameAtom = Atomize(cx, name, nameLen);
4572 : if (!nameAtom)
4573 : return false;
4574 :
4575 792 : // If name is not valid identifier
4576 792 : if (!js::frontend::IsIdentifier(name, nameLen))
4577 : isInvalidName = true;
4578 1584 : }
4579 :
4580 0 : uint32_t parameterListEnd;
4581 : StringBuffer funStr(cx);
4582 0 : if (!BuildFunctionString(isInvalidName ? nullptr : name, nameLen, nargs, argnames, srcBuf,
4583 1542 : &funStr, ¶meterListEnd))
4584 : {
4585 : return false;
4586 0 : }
4587 :
4588 1742 : size_t newLen = funStr.length();
4589 475 : SourceBufferHolder newSrcBuf(funStr.stealChars(), newLen, SourceBufferHolder::GiveOwnership);
4590 0 :
4591 : return CompileFunction(cx, options, nameAtom, isInvalidName, newSrcBuf, parameterListEnd, env,
4592 : scope, fun);
4593 0 : }
4594 :
4595 : JS_PUBLIC_API(bool)
4596 : JS::CompileFunction(JSContext* cx, AutoObjectVector& envChain,
4597 : const ReadOnlyCompileOptions& options,
4598 792 : const char* name, unsigned nargs, const char* const* argnames,
4599 : const char16_t* chars, size_t length, MutableHandleFunction fun)
4600 : {
4601 1584 : SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::NoOwnership);
4602 : return CompileFunction(cx, envChain, options, name, nargs, argnames,
4603 1584 : srcBuf, fun);
4604 : }
4605 0 :
4606 : JS_PUBLIC_API(bool)
4607 : JS::CompileFunction(JSContext* cx, AutoObjectVector& envChain,
4608 792 : const ReadOnlyCompileOptions& options,
4609 : const char* name, unsigned nargs, const char* const* argnames,
4610 : const char* bytes, size_t length, MutableHandleFunction fun)
4611 : {
4612 0 : UniqueTwoByteChars chars;
4613 : if (options.utf8)
4614 : chars.reset(UTF8CharsToNewTwoByteCharsZ(cx, UTF8Chars(bytes, length), &length).get());
4615 : else
4616 : chars.reset(InflateString(cx, bytes, length));
4617 1584 : if (!chars)
4618 1584 : return false;
4619 1584 :
4620 : return CompileFunction(cx, envChain, options, name, nargs, argnames,
4621 : chars.get(), length, fun);
4622 0 : }
4623 0 :
4624 1584 : JS_PUBLIC_API(bool)
4625 792 : JS::InitScriptSourceElement(JSContext* cx, HandleScript script,
4626 0 : HandleObject element, HandleString elementAttrName)
4627 0 : {
4628 0 : MOZ_ASSERT(cx);
4629 : MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx->runtime()));
4630 :
4631 : RootedScriptSourceObject sso(cx, &script->sourceObject()->as<ScriptSourceObject>());
4632 0 : return ScriptSourceObject::initElementProperties(cx, sso, element, elementAttrName);
4633 21 : }
4634 :
4635 : JS_PUBLIC_API(void)
4636 : JS::ExposeScriptToDebugger(JSContext* cx, HandleScript script)
4637 0 : {
4638 792 : MOZ_ASSERT(cx);
4639 : MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx->runtime()));
4640 :
4641 : MOZ_ASSERT(script->hideScriptFromDebugger());
4642 : script->clearHideScriptFromDebugger();
4643 : Debugger::onNewScript(cx, script);
4644 792 : }
4645 1584 :
4646 : JS_PUBLIC_API(JSString*)
4647 3168 : JS_DecompileScript(JSContext* cx, HandleScript script)
4648 0 : {
4649 : MOZ_ASSERT(!cx->zone()->isAtomsZone());
4650 :
4651 : AssertHeapIsIdle();
4652 0 : CHECK_REQUEST(cx);
4653 : script->ensureNonLazyCanonicalFunction();
4654 : RootedFunction fun(cx, script->functionNonDelazifying());
4655 : if (fun)
4656 : return JS_DecompileFunction(cx, fun);
4657 1584 : bool haveSource = script->scriptSource()->hasSourceData();
4658 : if (!haveSource && !JSScript::loadSource(cx, script->scriptSource(), &haveSource))
4659 1584 : return nullptr;
4660 : return haveSource ? JSScript::sourceData(cx, script)
4661 : : NewStringCopyZ<CanGC>(cx, "[no source]");
4662 : }
4663 0 :
4664 : JS_PUBLIC_API(JSString*)
4665 : JS_DecompileFunction(JSContext* cx, HandleFunction fun)
4666 : {
4667 : MOZ_ASSERT(!cx->zone()->isAtomsZone());
4668 0 : AssertHeapIsIdle();
4669 0 : CHECK_REQUEST(cx);
4670 0 : assertSameCompartment(cx, fun);
4671 : return FunctionToString(cx, fun, /* isToSource = */ false);
4672 0 : }
4673 0 :
4674 : MOZ_NEVER_INLINE static bool
4675 : ExecuteScript(JSContext* cx, HandleObject scope, HandleScript script, Value* rval)
4676 0 : {
4677 0 : MOZ_ASSERT(!cx->zone()->isAtomsZone());
4678 : AssertHeapIsIdle();
4679 : CHECK_REQUEST(cx);
4680 : assertSameCompartment(cx, scope, script);
4681 0 : MOZ_ASSERT_IF(!IsGlobalLexicalEnvironment(scope), script->hasNonSyntacticScope());
4682 : return Execute(cx, script, *scope, rval);
4683 : }
4684 0 :
4685 0 : static bool
4686 : ExecuteScript(JSContext* cx, AutoObjectVector& envChain, HandleScript scriptArg, Value* rval)
4687 0 : {
4688 0 : RootedObject env(cx);
4689 : RootedScope dummy(cx);
4690 : if (!CreateNonSyntacticEnvironmentChain(cx, envChain, &env, &dummy))
4691 : return false;
4692 0 :
4693 : RootedScript script(cx, scriptArg);
4694 0 : if (!script->hasNonSyntacticScope() && !IsGlobalLexicalEnvironment(env)) {
4695 0 : script = CloneGlobalScript(cx, ScopeKind::NonSyntactic, script);
4696 : if (!script)
4697 0 : return false;
4698 0 : js::Debugger::onNewScript(cx, script);
4699 0 : }
4700 0 :
4701 : return ExecuteScript(cx, env, script, rval);
4702 : }
4703 0 :
4704 : MOZ_NEVER_INLINE JS_PUBLIC_API(bool)
4705 0 : JS_ExecuteScript(JSContext* cx, HandleScript scriptArg, MutableHandleValue rval)
4706 : {
4707 0 : RootedObject globalLexical(cx, &cx->global()->lexicalEnvironment());
4708 0 : return ExecuteScript(cx, globalLexical, scriptArg, rval.address());
4709 0 : }
4710 0 :
4711 0 : MOZ_NEVER_INLINE JS_PUBLIC_API(bool)
4712 0 : JS_ExecuteScript(JSContext* cx, HandleScript scriptArg)
4713 0 : {
4714 0 : RootedObject globalLexical(cx, &cx->global()->lexicalEnvironment());
4715 : return ExecuteScript(cx, globalLexical, scriptArg, nullptr);
4716 0 : }
4717 0 :
4718 : MOZ_NEVER_INLINE JS_PUBLIC_API(bool)
4719 : JS_ExecuteScript(JSContext* cx, AutoObjectVector& envChain,
4720 : HandleScript scriptArg, MutableHandleValue rval)
4721 0 : {
4722 : return ExecuteScript(cx, envChain, scriptArg, rval.address());
4723 0 : }
4724 0 :
4725 0 : MOZ_NEVER_INLINE JS_PUBLIC_API(bool)
4726 0 : JS_ExecuteScript(JSContext* cx, AutoObjectVector& envChain, HandleScript scriptArg)
4727 0 : {
4728 : return ExecuteScript(cx, envChain, scriptArg, nullptr);
4729 : }
4730 :
4731 0 : JS_PUBLIC_API(bool)
4732 : JS::CloneAndExecuteScript(JSContext* cx, HandleScript scriptArg,
4733 276 : JS::MutableHandleValue rval)
4734 138 : {
4735 0 : CHECK_REQUEST(cx);
4736 138 : RootedScript script(cx, scriptArg);
4737 0 : RootedObject globalLexical(cx, &cx->global()->lexicalEnvironment());
4738 0 : if (script->compartment() != cx->compartment()) {
4739 : script = CloneGlobalScript(cx, ScopeKind::Global, script);
4740 : if (!script)
4741 : return false;
4742 0 :
4743 : js::Debugger::onNewScript(cx, script);
4744 162 : }
4745 162 : return ExecuteScript(cx, globalLexical, script, rval.address());
4746 0 : }
4747 :
4748 : JS_PUBLIC_API(bool)
4749 0 : JS::CloneAndExecuteScript(JSContext* cx, JS::AutoObjectVector& envChain,
4750 0 : HandleScript scriptArg,
4751 0 : JS::MutableHandleValue rval)
4752 0 : {
4753 : CHECK_REQUEST(cx);
4754 0 : RootedScript script(cx, scriptArg);
4755 : if (script->compartment() != cx->compartment()) {
4756 : script = CloneGlobalScript(cx, ScopeKind::NonSyntactic, script);
4757 162 : if (!script)
4758 : return false;
4759 :
4760 : js::Debugger::onNewScript(cx, script);
4761 0 : }
4762 : return ExecuteScript(cx, envChain, script, rval.address());
4763 0 : }
4764 0 :
4765 : static bool
4766 : Evaluate(JSContext* cx, ScopeKind scopeKind, HandleObject env,
4767 : const ReadOnlyCompileOptions& optionsArg,
4768 0 : SourceBufferHolder& srcBuf, MutableHandleValue rval)
4769 : {
4770 0 : CompileOptions options(cx, optionsArg);
4771 0 : MOZ_ASSERT(!cx->zone()->isAtomsZone());
4772 : AssertHeapIsIdle();
4773 : CHECK_REQUEST(cx);
4774 : assertSameCompartment(cx, env);
4775 0 : MOZ_ASSERT_IF(!IsGlobalLexicalEnvironment(env), scopeKind == ScopeKind::NonSyntactic);
4776 :
4777 : options.setIsRunOnce(true);
4778 75 : RootedScript script(cx, frontend::CompileGlobalScript(cx, cx->tempLifoAlloc(),
4779 : scopeKind, options, srcBuf));
4780 : if (!script)
4781 : return false;
4782 0 :
4783 : bool result = Execute(cx, script, *env,
4784 0 : options.noScriptRval ? nullptr : rval.address());
4785 :
4786 : return result;
4787 : }
4788 0 :
4789 : static bool
4790 : Evaluate(JSContext* cx, AutoObjectVector& envChain, const ReadOnlyCompileOptions& optionsArg,
4791 114 : SourceBufferHolder& srcBuf, MutableHandleValue rval)
4792 0 : {
4793 171 : RootedObject env(cx);
4794 171 : RootedScope scope(cx);
4795 0 : if (!CreateNonSyntacticEnvironmentChain(cx, envChain, &env, &scope))
4796 0 : return false;
4797 : return ::Evaluate(cx, scope->kind(), env, optionsArg, srcBuf, rval);
4798 : }
4799 0 :
4800 : static bool
4801 171 : Evaluate(JSContext* cx, const ReadOnlyCompileOptions& optionsArg,
4802 : const char16_t* chars, size_t length, MutableHandleValue rval)
4803 : {
4804 : SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::NoOwnership);
4805 0 : RootedObject globalLexical(cx, &cx->global()->lexicalEnvironment());
4806 : return ::Evaluate(cx, ScopeKind::Global, globalLexical, optionsArg, srcBuf, rval);
4807 : }
4808 :
4809 0 : extern JS_PUBLIC_API(bool)
4810 12 : JS::Evaluate(JSContext* cx, const ReadOnlyCompileOptions& options,
4811 18 : const char* bytes, size_t length, MutableHandleValue rval)
4812 0 : {
4813 0 : char16_t* chars;
4814 : if (options.utf8)
4815 : chars = UTF8CharsToNewTwoByteCharsZ(cx, JS::UTF8Chars(bytes, length), &length).get();
4816 0 : else
4817 : chars = InflateString(cx, bytes, length);
4818 12 : if (!chars)
4819 : return false;
4820 :
4821 : SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::GiveOwnership);
4822 0 : RootedObject globalLexical(cx, &cx->global()->lexicalEnvironment());
4823 : bool ok = ::Evaluate(cx, ScopeKind::Global, globalLexical, options, srcBuf, rval);
4824 : return ok;
4825 : }
4826 0 :
4827 48 : static bool
4828 24 : Evaluate(JSContext* cx, const ReadOnlyCompileOptions& optionsArg,
4829 45 : const char* filename, MutableHandleValue rval)
4830 0 : {
4831 0 : FileContents buffer(cx);
4832 : {
4833 0 : AutoFile file;
4834 0 : if (!file.open(cx, filename) || !file.readAll(cx, buffer))
4835 0 : return false;
4836 24 : }
4837 :
4838 : CompileOptions options(cx, optionsArg);
4839 0 : options.setFileAndLine(filename, 1);
4840 0 : return Evaluate(cx, options, reinterpret_cast<const char*>(buffer.begin()), buffer.length(), rval);
4841 : }
4842 21 :
4843 : JS_PUBLIC_API(bool)
4844 : JS::Evaluate(JSContext* cx, const ReadOnlyCompileOptions& optionsArg,
4845 : SourceBufferHolder& srcBuf, MutableHandleValue rval)
4846 0 : {
4847 : RootedObject globalLexical(cx, &cx->global()->lexicalEnvironment());
4848 : return ::Evaluate(cx, ScopeKind::Global, globalLexical, optionsArg, srcBuf, rval);
4849 0 : }
4850 0 :
4851 0 : JS_PUBLIC_API(bool)
4852 : JS::Evaluate(JSContext* cx, AutoObjectVector& envChain, const ReadOnlyCompileOptions& optionsArg,
4853 0 : SourceBufferHolder& srcBuf, MutableHandleValue rval)
4854 : {
4855 : return ::Evaluate(cx, envChain, optionsArg, srcBuf, rval);
4856 : }
4857 0 :
4858 : JS_PUBLIC_API(bool)
4859 : JS::Evaluate(JSContext* cx, const ReadOnlyCompileOptions& optionsArg,
4860 0 : const char16_t* chars, size_t length, MutableHandleValue rval)
4861 0 : {
4862 0 : return ::Evaluate(cx, optionsArg, chars, length, rval);
4863 : }
4864 :
4865 : JS_PUBLIC_API(bool)
4866 0 : JS::Evaluate(JSContext* cx, AutoObjectVector& envChain, const ReadOnlyCompileOptions& optionsArg,
4867 : const char16_t* chars, size_t length, MutableHandleValue rval)
4868 : {
4869 : SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::NoOwnership);
4870 0 : return ::Evaluate(cx, envChain, optionsArg, srcBuf, rval);
4871 0 : }
4872 :
4873 1 : JS_PUBLIC_API(bool)
4874 0 : JS::Evaluate(JSContext* cx, const ReadOnlyCompileOptions& optionsArg,
4875 : const char* filename, MutableHandleValue rval)
4876 : {
4877 0 : return ::Evaluate(cx, optionsArg, filename, rval);
4878 0 : }
4879 1 :
4880 : JS_PUBLIC_API(JS::ModuleResolveHook)
4881 : JS::GetModuleResolveHook(JSRuntime* rt)
4882 : {
4883 : AssertHeapIsIdle();
4884 0 : return rt->moduleResolveHook;
4885 : }
4886 :
4887 0 : JS_PUBLIC_API(void)
4888 : JS::SetModuleResolveHook(JSRuntime* rt, JS::ModuleResolveHook func)
4889 0 : {
4890 0 : AssertHeapIsIdle();
4891 0 : rt->moduleResolveHook = func;
4892 : }
4893 :
4894 0 : JS_PUBLIC_API(JS::ModuleMetadataHook)
4895 0 : JS::GetModuleMetadataHook(JSRuntime* rt)
4896 0 : {
4897 : AssertHeapIsIdle();
4898 : return rt->moduleMetadataHook;
4899 : }
4900 0 :
4901 : JS_PUBLIC_API(void)
4902 : JS::SetModuleMetadataHook(JSRuntime* rt, JS::ModuleMetadataHook func)
4903 66 : {
4904 0 : AssertHeapIsIdle();
4905 : rt->moduleMetadataHook = func;
4906 : }
4907 :
4908 0 : JS_PUBLIC_API(bool)
4909 : JS::CompileModule(JSContext* cx, const ReadOnlyCompileOptions& options,
4910 : SourceBufferHolder& srcBuf, JS::MutableHandleObject module)
4911 0 : {
4912 : MOZ_ASSERT(!cx->zone()->isAtomsZone());
4913 : AssertHeapIsIdle();
4914 : CHECK_REQUEST(cx);
4915 0 :
4916 : module.set(frontend::CompileModule(cx, options, srcBuf));
4917 : return !!module;
4918 0 : }
4919 :
4920 : JS_PUBLIC_API(void)
4921 : JS::SetModuleHostDefinedField(JSObject* module, const JS::Value& value)
4922 0 : {
4923 : module->as<ModuleObject>().setHostDefinedField(value);
4924 : }
4925 0 :
4926 0 : JS_PUBLIC_API(JS::Value)
4927 : JS::GetModuleHostDefinedField(JSObject* module)
4928 : {
4929 : return module->as<ModuleObject>().hostDefinedField();
4930 0 : }
4931 :
4932 : JS_PUBLIC_API(bool)
4933 0 : JS::ModuleInstantiate(JSContext* cx, JS::HandleObject moduleArg)
4934 : {
4935 : AssertHeapIsIdle();
4936 : CHECK_REQUEST(cx);
4937 0 : assertSameCompartment(cx, moduleArg);
4938 : return ModuleObject::Instantiate(cx, moduleArg.as<ModuleObject>());
4939 0 : }
4940 0 :
4941 : JS_PUBLIC_API(bool)
4942 : JS::ModuleEvaluate(JSContext* cx, JS::HandleObject moduleArg)
4943 : {
4944 0 : AssertHeapIsIdle();
4945 : CHECK_REQUEST(cx);
4946 0 : assertSameCompartment(cx, moduleArg);
4947 0 : return ModuleObject::Evaluate(cx, moduleArg.as<ModuleObject>());
4948 0 : }
4949 :
4950 : JS_PUBLIC_API(JSObject*)
4951 0 : JS::GetRequestedModules(JSContext* cx, JS::HandleObject moduleArg)
4952 : {
4953 0 : AssertHeapIsIdle();
4954 0 : CHECK_REQUEST(cx);
4955 : assertSameCompartment(cx, moduleArg);
4956 : return &moduleArg->as<ModuleObject>().requestedModules();
4957 : }
4958 0 :
4959 : JS_PUBLIC_API(JSString*)
4960 0 : JS::GetRequestedModuleSpecifier(JSContext* cx, JS::HandleValue value)
4961 0 : {
4962 0 : AssertHeapIsIdle();
4963 : CHECK_REQUEST(cx);
4964 : assertSameCompartment(cx, value);
4965 0 : JSObject* obj = &value.toObject();
4966 : return obj->as<RequestedModuleObject>().moduleSpecifier();
4967 : }
4968 0 :
4969 0 : JS_PUBLIC_API(void)
4970 0 : JS::GetRequestedModuleSourcePos(JSContext* cx, JS::HandleValue value,
4971 : uint32_t* lineNumber, uint32_t* columnNumber)
4972 0 : {
4973 0 : AssertHeapIsIdle();
4974 : CHECK_REQUEST(cx);
4975 : assertSameCompartment(cx, value);
4976 : MOZ_ASSERT(lineNumber);
4977 0 : MOZ_ASSERT(columnNumber);
4978 : auto& requested = value.toObject().as<RequestedModuleObject>();
4979 0 : *lineNumber = requested.lineNumber();
4980 0 : *columnNumber = requested.columnNumber();
4981 : }
4982 :
4983 0 : JS_PUBLIC_API(JSScript*)
4984 : JS::GetModuleScript(JS::HandleObject moduleRecord)
4985 0 : {
4986 : AssertHeapIsIdle();
4987 : return moduleRecord->as<ModuleObject>().script();
4988 : }
4989 0 :
4990 : JS_PUBLIC_API(JSObject*)
4991 0 : JS_New(JSContext* cx, HandleObject ctor, const JS::HandleValueArray& inputArgs)
4992 0 : {
4993 0 : AssertHeapIsIdle();
4994 0 : CHECK_REQUEST(cx);
4995 : assertSameCompartment(cx, ctor, inputArgs);
4996 :
4997 : RootedValue ctorVal(cx, ObjectValue(*ctor));
4998 0 : if (!IsConstructor(ctorVal)) {
4999 : ReportValueError(cx, JSMSG_NOT_CONSTRUCTOR, JSDVG_IGNORE_STACK, ctorVal, nullptr);
5000 0 : return nullptr;
5001 0 : }
5002 0 :
5003 0 : ConstructArgs args(cx);
5004 : if (!FillArgumentsFromArraylike(cx, args, inputArgs))
5005 : return nullptr;
5006 :
5007 0 : RootedObject obj(cx);
5008 : if (!js::Construct(cx, ctorVal, args, ctorVal, &obj))
5009 0 : return nullptr;
5010 0 :
5011 0 : return obj;
5012 0 : }
5013 :
5014 : JS_PUBLIC_API(bool)
5015 : JS_CheckForInterrupt(JSContext* cx)
5016 0 : {
5017 : return js::CheckForInterrupt(cx);
5018 0 : }
5019 0 :
5020 0 : JS_PUBLIC_API(bool)
5021 0 : JS_AddInterruptCallback(JSContext* cx, JSInterruptCallback callback)
5022 0 : {
5023 : return cx->interruptCallbacks().append(callback);
5024 : }
5025 :
5026 0 : JS_PUBLIC_API(bool)
5027 : JS_DisableInterruptCallback(JSContext* cx)
5028 : {
5029 0 : bool result = cx->interruptCallbackDisabled;
5030 0 : cx->interruptCallbackDisabled = true;
5031 0 : return result;
5032 0 : }
5033 0 :
5034 0 : JS_PUBLIC_API(void)
5035 0 : JS_ResetInterruptCallback(JSContext* cx, bool enable)
5036 0 : {
5037 0 : cx->interruptCallbackDisabled = enable;
5038 : }
5039 :
5040 0 : /************************************************************************/
5041 :
5042 0 : /*
5043 0 : * Promises.
5044 : */
5045 : JS_PUBLIC_API(void)
5046 : JS::SetGetIncumbentGlobalCallback(JSContext* cx, JSGetIncumbentGlobalCallback callback)
5047 0 : {
5048 : cx->getIncumbentGlobalCallback = callback;
5049 0 : }
5050 0 :
5051 0 : JS_PUBLIC_API(void)
5052 : JS::SetEnqueuePromiseJobCallback(JSContext* cx, JSEnqueuePromiseJobCallback callback,
5053 0 : void* data /* = nullptr */)
5054 0 : {
5055 0 : cx->enqueuePromiseJobCallback = callback;
5056 0 : cx->enqueuePromiseJobCallbackData = data;
5057 : }
5058 :
5059 0 : extern JS_PUBLIC_API(void)
5060 0 : JS::SetPromiseRejectionTrackerCallback(JSContext* cx, JSPromiseRejectionTrackerCallback callback,
5061 : void* data /* = nullptr */)
5062 : {
5063 0 : cx->promiseRejectionTrackerCallback = callback;
5064 0 : cx->promiseRejectionTrackerCallbackData = data;
5065 : }
5066 :
5067 0 : JS_PUBLIC_API(JSObject*)
5068 : JS::NewPromiseObject(JSContext* cx, HandleObject executor, HandleObject proto /* = nullptr */)
5069 : {
5070 : MOZ_ASSERT(!cx->zone()->isAtomsZone());
5071 0 : AssertHeapIsIdle();
5072 : CHECK_REQUEST(cx);
5073 4148 : assertSameCompartment(cx, executor, proto);
5074 :
5075 : if (!executor)
5076 : return PromiseObject::createSkippingExecutor(cx);
5077 0 :
5078 : MOZ_ASSERT(IsCallable(executor));
5079 4 : return PromiseObject::create(cx, executor, proto);
5080 : }
5081 :
5082 : JS_PUBLIC_API(bool)
5083 0 : JS::IsPromiseObject(JS::HandleObject obj)
5084 : {
5085 0 : return obj->is<PromiseObject>();
5086 0 : }
5087 0 :
5088 : JS_PUBLIC_API(JSObject*)
5089 : JS::GetPromiseConstructor(JSContext* cx)
5090 : {
5091 0 : CHECK_REQUEST(cx);
5092 : Rooted<GlobalObject*> global(cx, cx->global());
5093 0 : return GlobalObject::getOrCreatePromiseConstructor(cx, global);
5094 0 : }
5095 :
5096 : JS_PUBLIC_API(JSObject*)
5097 : JS::GetPromisePrototype(JSContext* cx)
5098 : {
5099 : CHECK_REQUEST(cx);
5100 : Rooted<GlobalObject*> global(cx, cx->global());
5101 : return GlobalObject::getOrCreatePromisePrototype(cx, global);
5102 4 : }
5103 :
5104 8 : JS_PUBLIC_API(JS::PromiseState)
5105 4 : JS::GetPromiseState(JS::HandleObject promiseObj_)
5106 : {
5107 : JSObject* promiseObj = CheckedUnwrap(promiseObj_);
5108 0 : if (!promiseObj || !promiseObj->is<PromiseObject>())
5109 : return JS::PromiseState::Pending;
5110 :
5111 8 : return promiseObj->as<PromiseObject>().state();
5112 0 : }
5113 4 :
5114 : JS_PUBLIC_API(uint64_t)
5115 : JS::GetPromiseID(JS::HandleObject promise)
5116 0 : {
5117 : return promise->as<PromiseObject>().getID();
5118 : }
5119 8 :
5120 0 : JS_PUBLIC_API(JS::Value)
5121 4 : JS::GetPromiseResult(JS::HandleObject promiseObj)
5122 : {
5123 : PromiseObject* promise = &promiseObj->as<PromiseObject>();
5124 0 : MOZ_ASSERT(promise->state() != JS::PromiseState::Pending);
5125 : return promise->state() == JS::PromiseState::Fulfilled ? promise->value() : promise->reason();
5126 194 : }
5127 97 :
5128 0 : JS_PUBLIC_API(JSObject*)
5129 97 : JS::GetPromiseAllocationSite(JS::HandleObject promise)
5130 : {
5131 0 : return promise->as<PromiseObject>().allocationSite();
5132 0 : }
5133 :
5134 0 : JS_PUBLIC_API(JSObject*)
5135 0 : JS::GetPromiseResolutionSite(JS::HandleObject promise)
5136 : {
5137 : return promise->as<PromiseObject>().resolutionSite();
5138 : }
5139 0 :
5140 : #ifdef DEBUG
5141 62 : JS_PUBLIC_API(void)
5142 : JS::DumpPromiseAllocationSite(JSContext* cx, JS::HandleObject promise)
5143 : {
5144 : RootedObject stack(cx, promise->as<PromiseObject>().allocationSite());
5145 0 : UniqueChars stackStr(reinterpret_cast<char*>(BuildUTF8StackString(cx, stack).get()));
5146 : if (stackStr.get())
5147 2 : fputs(stackStr.get(), stderr);
5148 2 : }
5149 0 :
5150 : JS_PUBLIC_API(void)
5151 : JS::DumpPromiseResolutionSite(JSContext* cx, JS::HandleObject promise)
5152 : {
5153 0 : RootedObject stack(cx, promise->as<PromiseObject>().resolutionSite());
5154 : UniqueChars stackStr(reinterpret_cast<char*>(BuildUTF8StackString(cx, stack).get()));
5155 0 : if (stackStr.get())
5156 0 : fputs(stackStr.get(), stderr);
5157 0 : }
5158 : #endif
5159 :
5160 : JS_PUBLIC_API(JSObject*)
5161 1 : JS::CallOriginalPromiseResolve(JSContext* cx, JS::HandleValue resolutionValue)
5162 : {
5163 8 : AssertHeapIsIdle();
5164 16 : CHECK_REQUEST(cx);
5165 : assertSameCompartment(cx, resolutionValue);
5166 :
5167 0 : RootedObject promise(cx, PromiseObject::unforgeableResolve(cx, resolutionValue));
5168 : MOZ_ASSERT_IF(promise, CheckedUnwrap(promise)->is<PromiseObject>());
5169 : return promise;
5170 : }
5171 0 :
5172 : JS_PUBLIC_API(JSObject*)
5173 0 : JS::CallOriginalPromiseReject(JSContext* cx, JS::HandleValue rejectionValue)
5174 : {
5175 : AssertHeapIsIdle();
5176 : CHECK_REQUEST(cx);
5177 0 : assertSameCompartment(cx, rejectionValue);
5178 :
5179 1 : RootedObject promise(cx, PromiseObject::unforgeableReject(cx, rejectionValue));
5180 1 : MOZ_ASSERT_IF(promise, CheckedUnwrap(promise)->is<PromiseObject>());
5181 0 : return promise;
5182 : }
5183 :
5184 : static bool
5185 0 : ResolveOrRejectPromise(JSContext* cx, JS::HandleObject promiseObj, JS::HandleValue resultOrReason_,
5186 : bool reject)
5187 4053 : {
5188 : AssertHeapIsIdle();
5189 : CHECK_REQUEST(cx);
5190 : assertSameCompartment(cx, promiseObj, resultOrReason_);
5191 0 :
5192 : mozilla::Maybe<AutoRealm> ar;
5193 0 : Rooted<PromiseObject*> promise(cx);
5194 : RootedValue resultOrReason(cx, resultOrReason_);
5195 : if (IsWrapper(promiseObj)) {
5196 : JSObject* unwrappedPromiseObj = CheckedUnwrap(promiseObj);
5197 : if (!unwrappedPromiseObj) {
5198 0 : ReportAccessDenied(cx);
5199 : return false;
5200 0 : }
5201 0 : promise = &unwrappedPromiseObj->as<PromiseObject>();
5202 0 : ar.emplace(cx, promise);
5203 0 : if (!cx->compartment()->wrap(cx, &resultOrReason))
5204 0 : return false;
5205 : } else {
5206 : promise = promiseObj.as<PromiseObject>();
5207 0 : }
5208 :
5209 0 : return reject
5210 0 : ? PromiseObject::reject(cx, promise, resultOrReason)
5211 0 : : PromiseObject::resolve(cx, promise, resultOrReason);
5212 0 : }
5213 0 :
5214 : JS_PUBLIC_API(bool)
5215 : JS::ResolvePromise(JSContext* cx, JS::HandleObject promiseObj, JS::HandleValue resolutionValue)
5216 : {
5217 1 : return ResolveOrRejectPromise(cx, promiseObj, resolutionValue, false);
5218 : }
5219 1 :
5220 2 : JS_PUBLIC_API(bool)
5221 0 : JS::RejectPromise(JSContext* cx, JS::HandleObject promiseObj, JS::HandleValue rejectionValue)
5222 : {
5223 0 : return ResolveOrRejectPromise(cx, promiseObj, rejectionValue, true);
5224 0 : }
5225 0 :
5226 : static bool
5227 : CallOriginalPromiseThenImpl(JSContext* cx, JS::HandleObject promiseObj,
5228 : JS::HandleObject onResolvedObj_, JS::HandleObject onRejectedObj_,
5229 0 : JS::MutableHandleObject resultObj,
5230 : CreateDependentPromise createDependent)
5231 0 : {
5232 0 : AssertHeapIsIdle();
5233 0 : CHECK_REQUEST(cx);
5234 : assertSameCompartment(cx, promiseObj, onResolvedObj_, onRejectedObj_);
5235 0 :
5236 0 : MOZ_ASSERT_IF(onResolvedObj_, IsCallable(onResolvedObj_));
5237 0 : MOZ_ASSERT_IF(onRejectedObj_, IsCallable(onRejectedObj_));
5238 :
5239 : {
5240 : mozilla::Maybe<AutoRealm> ar;
5241 0 : Rooted<PromiseObject*> promise(cx);
5242 : RootedObject onResolvedObj(cx, onResolvedObj_);
5243 : RootedObject onRejectedObj(cx, onRejectedObj_);
5244 117 : if (IsWrapper(promiseObj)) {
5245 0 : JSObject* unwrappedPromiseObj = CheckedUnwrap(promiseObj);
5246 117 : if (!unwrappedPromiseObj) {
5247 : ReportAccessDenied(cx);
5248 0 : return false;
5249 0 : }
5250 0 : promise = &unwrappedPromiseObj->as<PromiseObject>();
5251 117 : ar.emplace(cx, promise);
5252 0 : if (!cx->compartment()->wrap(cx, &onResolvedObj) ||
5253 0 : !cx->compartment()->wrap(cx, &onRejectedObj))
5254 0 : {
5255 0 : return false;
5256 : }
5257 0 : } else {
5258 0 : promise = promiseObj.as<PromiseObject>();
5259 0 : }
5260 :
5261 : RootedValue onFulfilled(cx, ObjectOrNullValue(onResolvedObj));
5262 1 : RootedValue onRejected(cx, ObjectOrNullValue(onRejectedObj));
5263 : if (!OriginalPromiseThen(cx, promise, onFulfilled, onRejected, resultObj, createDependent))
5264 : return false;
5265 : }
5266 0 :
5267 351 : if (resultObj) {
5268 : if (!cx->compartment()->wrap(cx, resultObj))
5269 : return false;
5270 : }
5271 0 : return true;
5272 : }
5273 117 :
5274 : JS_PUBLIC_API(JSObject*)
5275 : JS::CallOriginalPromiseThen(JSContext* cx, JS::HandleObject promiseObj,
5276 : JS::HandleObject onResolvedObj, JS::HandleObject onRejectedObj)
5277 0 : {
5278 : RootedObject resultPromise(cx);
5279 0 : if (!CallOriginalPromiseThenImpl(cx, promiseObj, onResolvedObj, onRejectedObj, &resultPromise,
5280 : CreateDependentPromise::Always))
5281 : {
5282 : return nullptr;
5283 0 : }
5284 : return resultPromise;
5285 : }
5286 :
5287 : JS_PUBLIC_API(bool)
5288 1 : JS::AddPromiseReactions(JSContext* cx, JS::HandleObject promiseObj,
5289 2 : JS::HandleObject onResolvedObj, JS::HandleObject onRejectedObj)
5290 1 : {
5291 : RootedObject resultPromise(cx);
5292 0 : bool result = CallOriginalPromiseThenImpl(cx, promiseObj, onResolvedObj, onRejectedObj,
5293 0 : &resultPromise, CreateDependentPromise::Never);
5294 : MOZ_ASSERT(!resultPromise);
5295 : return result;
5296 0 : }
5297 0 :
5298 2 : /**
5299 2 : * Unforgeable version of Promise.all for internal use.
5300 0 : *
5301 0 : * Takes a dense array of Promise objects and returns a promise that's
5302 0 : * resolved with an array of resolution values when all those promises ahve
5303 0 : * been resolved, or rejected with the rejection value of the first rejected
5304 0 : * promise.
5305 : *
5306 0 : * Asserts that the array is dense and all entries are Promise objects.
5307 0 : */
5308 0 : JS_PUBLIC_API(JSObject*)
5309 0 : JS::GetWaitForAllPromise(JSContext* cx, const JS::AutoObjectVector& promises)
5310 : {
5311 : AssertHeapIsIdle();
5312 : CHECK_REQUEST(cx);
5313 :
5314 3 : return js::GetWaitForAllPromise(cx, promises);
5315 : }
5316 :
5317 3 : JS_PUBLIC_API(JSObject*)
5318 0 : JS::NewReadableDefaultStreamObject(JSContext* cx,
5319 3 : JS::HandleObject underlyingSource /* = nullptr */,
5320 0 : JS::HandleFunction size /* = nullptr */,
5321 : double highWaterMark /* = 1 */,
5322 : JS::HandleObject proto /* = nullptr */)
5323 0 : {
5324 0 : MOZ_ASSERT(!cx->zone()->isAtomsZone());
5325 : AssertHeapIsIdle();
5326 : CHECK_REQUEST(cx);
5327 :
5328 : RootedObject source(cx, underlyingSource);
5329 : if (!source) {
5330 : source = NewBuiltinClassInstance<PlainObject>(cx);
5331 0 : if (!source)
5332 : return nullptr;
5333 : }
5334 0 : RootedValue sourceVal(cx, ObjectValue(*source));
5335 0 : RootedValue sizeVal(cx, size ? ObjectValue(*size) : UndefinedValue());
5336 : RootedValue highWaterMarkVal(cx, NumberValue(highWaterMark));
5337 : return ReadableStream::createDefaultStream(cx, sourceVal, sizeVal, highWaterMarkVal, proto);
5338 : }
5339 :
5340 0 : JS_PUBLIC_API(JSObject*)
5341 : JS::NewReadableByteStreamObject(JSContext* cx,
5342 : JS::HandleObject underlyingSource /* = nullptr */,
5343 : double highWaterMark /* = 1 */,
5344 0 : JS::HandleObject proto /* = nullptr */)
5345 : {
5346 : MOZ_ASSERT(!cx->zone()->isAtomsZone());
5347 2 : AssertHeapIsIdle();
5348 0 : CHECK_REQUEST(cx);
5349 1 :
5350 1 : RootedObject source(cx, underlyingSource);
5351 0 : if (!source) {
5352 : source = NewBuiltinClassInstance<PlainObject>(cx);
5353 : if (!source)
5354 : return nullptr;
5355 : }
5356 : RootedValue sourceVal(cx, ObjectValue(*source));
5357 : RootedValue highWaterMarkVal(cx, NumberValue(highWaterMark));
5358 : return ReadableStream::createByteStream(cx, sourceVal, highWaterMarkVal, proto);
5359 : }
5360 :
5361 : extern JS_PUBLIC_API(void)
5362 : JS::SetReadableStreamCallbacks(JSContext* cx,
5363 : JS::RequestReadableStreamDataCallback dataRequestCallback,
5364 : JS::WriteIntoReadRequestBufferCallback writeIntoReadRequestCallback,
5365 0 : JS::CancelReadableStreamCallback cancelCallback,
5366 : JS::ReadableStreamClosedCallback closedCallback,
5367 0 : JS::ReadableStreamErroredCallback erroredCallback,
5368 0 : JS::ReadableStreamFinalizeCallback finalizeCallback)
5369 : {
5370 0 : MOZ_ASSERT(dataRequestCallback);
5371 : MOZ_ASSERT(writeIntoReadRequestCallback);
5372 : MOZ_ASSERT(cancelCallback);
5373 : MOZ_ASSERT(closedCallback);
5374 0 : MOZ_ASSERT(erroredCallback);
5375 : MOZ_ASSERT(finalizeCallback);
5376 :
5377 : JSRuntime* rt = cx->runtime();
5378 :
5379 : MOZ_ASSERT(!rt->readableStreamDataRequestCallback);
5380 0 : MOZ_ASSERT(!rt->readableStreamWriteIntoReadRequestCallback);
5381 0 : MOZ_ASSERT(!rt->readableStreamCancelCallback);
5382 0 : MOZ_ASSERT(!rt->readableStreamClosedCallback);
5383 : MOZ_ASSERT(!rt->readableStreamErroredCallback);
5384 0 : MOZ_ASSERT(!rt->readableStreamFinalizeCallback);
5385 0 :
5386 0 : rt->readableStreamDataRequestCallback = dataRequestCallback;
5387 0 : rt->readableStreamWriteIntoReadRequestCallback = writeIntoReadRequestCallback;
5388 : rt->readableStreamCancelCallback = cancelCallback;
5389 : rt->readableStreamClosedCallback = closedCallback;
5390 0 : rt->readableStreamErroredCallback = erroredCallback;
5391 0 : rt->readableStreamFinalizeCallback = finalizeCallback;
5392 0 : }
5393 0 :
5394 : JS_PUBLIC_API(bool)
5395 : JS::HasReadableStreamCallbacks(JSContext* cx)
5396 : {
5397 0 : return cx->runtime()->readableStreamDataRequestCallback;
5398 : }
5399 :
5400 : JS_PUBLIC_API(JSObject*)
5401 : JS::NewReadableExternalSourceStreamObject(JSContext* cx, void* underlyingSource,
5402 0 : uint8_t flags /* = 0 */,
5403 0 : HandleObject proto /* = nullptr */)
5404 0 : {
5405 : MOZ_ASSERT(!cx->zone()->isAtomsZone());
5406 0 : AssertHeapIsIdle();
5407 0 : CHECK_REQUEST(cx);
5408 0 :
5409 0 : #ifdef DEBUG
5410 : JSRuntime* rt = cx->runtime();
5411 : MOZ_ASSERT(rt->readableStreamDataRequestCallback);
5412 0 : MOZ_ASSERT(rt->readableStreamWriteIntoReadRequestCallback);
5413 0 : MOZ_ASSERT(rt->readableStreamCancelCallback);
5414 0 : MOZ_ASSERT(rt->readableStreamClosedCallback);
5415 : MOZ_ASSERT(rt->readableStreamErroredCallback);
5416 : MOZ_ASSERT(rt->readableStreamFinalizeCallback);
5417 : #endif // DEBUG
5418 0 :
5419 : return ReadableStream::createExternalSourceStream(cx, underlyingSource, flags, proto);
5420 : }
5421 :
5422 : JS_PUBLIC_API(uint8_t)
5423 : JS::ReadableStreamGetEmbeddingFlags(const JSObject* stream)
5424 : {
5425 : return stream->as<ReadableStream>().embeddingFlags();
5426 0 : }
5427 0 :
5428 0 : JS_PUBLIC_API(bool)
5429 0 : JS::IsReadableStream(const JSObject* obj)
5430 0 : {
5431 0 : return obj->is<ReadableStream>();
5432 : }
5433 0 :
5434 : JS_PUBLIC_API(bool)
5435 0 : JS::IsReadableStreamReader(const JSObject* obj)
5436 0 : {
5437 0 : return obj->is<ReadableStreamDefaultReader>() || obj->is<ReadableStreamBYOBReader>();
5438 0 : }
5439 0 :
5440 0 : JS_PUBLIC_API(bool)
5441 : JS::IsReadableStreamDefaultReader(const JSObject* obj)
5442 0 : {
5443 0 : return obj->is<ReadableStreamDefaultReader>();
5444 0 : }
5445 0 :
5446 0 : JS_PUBLIC_API(bool)
5447 0 : JS::IsReadableStreamBYOBReader(const JSObject* obj)
5448 0 : {
5449 : return obj->is<ReadableStreamBYOBReader>();
5450 : }
5451 0 :
5452 : JS_PUBLIC_API(bool)
5453 0 : JS::ReadableStreamIsReadable(const JSObject* stream)
5454 : {
5455 : return stream->as<ReadableStream>().readable();
5456 : }
5457 0 :
5458 : JS_PUBLIC_API(bool)
5459 : JS::ReadableStreamIsLocked(const JSObject* stream)
5460 : {
5461 0 : return stream->as<ReadableStream>().locked();
5462 0 : }
5463 0 :
5464 : JS_PUBLIC_API(bool)
5465 : JS::ReadableStreamIsDisturbed(const JSObject* stream)
5466 0 : {
5467 0 : return stream->as<ReadableStream>().disturbed();
5468 0 : }
5469 0 :
5470 0 : JS_PUBLIC_API(JSObject*)
5471 0 : JS::ReadableStreamCancel(JSContext* cx, HandleObject streamObj, HandleValue reason)
5472 0 : {
5473 : AssertHeapIsIdle();
5474 : CHECK_REQUEST(cx);
5475 0 : assertSameCompartment(cx, streamObj);
5476 : assertSameCompartment(cx, reason);
5477 :
5478 : Rooted<ReadableStream*> stream(cx, &streamObj->as<ReadableStream>());
5479 0 : return ReadableStream::cancel(cx, stream, reason);
5480 : }
5481 0 :
5482 : JS_PUBLIC_API(JS::ReadableStreamMode)
5483 : JS::ReadableStreamGetMode(const JSObject* stream)
5484 : {
5485 0 : return stream->as<ReadableStream>().mode();
5486 : }
5487 0 :
5488 : JS_PUBLIC_API(JSObject*)
5489 : JS::ReadableStreamGetReader(JSContext* cx, HandleObject streamObj, ReadableStreamReaderMode mode)
5490 : {
5491 0 : AssertHeapIsIdle();
5492 : CHECK_REQUEST(cx);
5493 0 : assertSameCompartment(cx, streamObj);
5494 :
5495 : Rooted<ReadableStream*> stream(cx, &streamObj->as<ReadableStream>());
5496 : return ReadableStream::getReader(cx, stream, mode);
5497 0 : }
5498 :
5499 0 : JS_PUBLIC_API(bool)
5500 : JS::ReadableStreamGetExternalUnderlyingSource(JSContext* cx, HandleObject streamObj, void** source)
5501 : {
5502 : AssertHeapIsIdle();
5503 0 : CHECK_REQUEST(cx);
5504 : assertSameCompartment(cx, streamObj);
5505 0 :
5506 : Rooted<ReadableStream*> stream(cx, &streamObj->as<ReadableStream>());
5507 : return ReadableStream::getExternalSource(cx, stream, source);
5508 : }
5509 0 :
5510 : JS_PUBLIC_API(void)
5511 0 : JS::ReadableStreamReleaseExternalUnderlyingSource(JSObject* stream)
5512 : {
5513 : stream->as<ReadableStream>().releaseExternalSource();
5514 : }
5515 0 :
5516 : JS_PUBLIC_API(bool)
5517 0 : JS::ReadableStreamUpdateDataAvailableFromSource(JSContext* cx, JS::HandleObject streamObj,
5518 : uint32_t availableData)
5519 : {
5520 : AssertHeapIsIdle();
5521 0 : CHECK_REQUEST(cx);
5522 : assertSameCompartment(cx, streamObj);
5523 0 :
5524 : Rooted<ReadableStream*> stream(cx, &streamObj->as<ReadableStream>());
5525 : return ReadableStream::updateDataAvailableFromSource(cx, stream, availableData);
5526 : }
5527 0 :
5528 : JS_PUBLIC_API(bool)
5529 0 : JS::ReadableStreamTee(JSContext* cx, HandleObject streamObj,
5530 0 : MutableHandleObject branch1Obj, MutableHandleObject branch2Obj)
5531 0 : {
5532 0 : AssertHeapIsIdle();
5533 : CHECK_REQUEST(cx);
5534 0 : assertSameCompartment(cx, streamObj);
5535 0 :
5536 : Rooted<ReadableStream*> stream(cx, &streamObj->as<ReadableStream>());
5537 : Rooted<ReadableStream*> branch1Stream(cx);
5538 : Rooted<ReadableStream*> branch2Stream(cx);
5539 0 :
5540 : if (!ReadableStream::tee(cx, stream, false, &branch1Stream, &branch2Stream))
5541 0 : return false;
5542 :
5543 : branch1Obj.set(branch1Stream);
5544 : branch2Obj.set(branch2Stream);
5545 0 :
5546 : return true;
5547 0 : }
5548 0 :
5549 0 : JS_PUBLIC_API(void)
5550 : JS::ReadableStreamGetDesiredSize(JSObject* streamObj, bool* hasValue, double* value)
5551 0 : {
5552 0 : streamObj->as<ReadableStream>().desiredSize(hasValue, value);
5553 : }
5554 :
5555 : JS_PUBLIC_API(bool)
5556 0 : JS::ReadableStreamClose(JSContext* cx, HandleObject streamObj)
5557 : {
5558 0 : AssertHeapIsIdle();
5559 0 : CHECK_REQUEST(cx);
5560 0 : assertSameCompartment(cx, streamObj);
5561 :
5562 0 : Rooted<ReadableStream*> stream(cx, &streamObj->as<ReadableStream>());
5563 0 : return ReadableStream::close(cx, stream);
5564 : }
5565 :
5566 : JS_PUBLIC_API(bool)
5567 0 : JS::ReadableStreamEnqueue(JSContext* cx, HandleObject streamObj, HandleValue chunk)
5568 : {
5569 0 : AssertHeapIsIdle();
5570 0 : CHECK_REQUEST(cx);
5571 : assertSameCompartment(cx, streamObj);
5572 : assertSameCompartment(cx, chunk);
5573 0 :
5574 : Rooted<ReadableStream*> stream(cx, &streamObj->as<ReadableStream>());
5575 : if (stream->mode() != JS::ReadableStreamMode::Default) {
5576 0 : JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
5577 0 : JSMSG_READABLESTREAM_NOT_DEFAULT_CONTROLLER,
5578 0 : "JS::ReadableStreamEnqueue");
5579 : return false;
5580 0 : }
5581 0 : return ReadableStream::enqueue(cx, stream, chunk);
5582 : }
5583 :
5584 : JS_PUBLIC_API(bool)
5585 0 : JS::ReadableByteStreamEnqueueBuffer(JSContext* cx, HandleObject streamObj, HandleObject chunkObj)
5586 : {
5587 : AssertHeapIsIdle();
5588 0 : CHECK_REQUEST(cx);
5589 0 : assertSameCompartment(cx, streamObj);
5590 0 : assertSameCompartment(cx, chunkObj);
5591 :
5592 0 : Rooted<ReadableStream*> stream(cx, &streamObj->as<ReadableStream>());
5593 0 : if (stream->mode() != JS::ReadableStreamMode::Byte) {
5594 0 : JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
5595 : JSMSG_READABLESTREAM_NOT_BYTE_STREAM_CONTROLLER,
5596 0 : "JS::ReadableByteStreamEnqueueBuffer");
5597 : return false;
5598 : }
5599 0 :
5600 0 : Rooted<ArrayBufferObject*> buffer(cx);
5601 : if (chunkObj->is<ArrayBufferViewObject>()) {
5602 0 : bool dummy;
5603 : buffer = &JS_GetArrayBufferViewBuffer(cx, chunkObj, &dummy)->as<ArrayBufferObject>();
5604 : } else if (chunkObj->is<ArrayBufferObject>()) {
5605 : buffer = &chunkObj->as<ArrayBufferObject>();
5606 0 : } else {
5607 : JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
5608 0 : JSMSG_READABLEBYTESTREAMCONTROLLER_BAD_CHUNK,
5609 0 : "JS::ReadableByteStreamEnqueueBuffer");
5610 : return false;
5611 : }
5612 0 :
5613 : return ReadableStream::enqueueBuffer(cx, stream, buffer);
5614 0 : }
5615 0 :
5616 0 : JS_PUBLIC_API(bool)
5617 : JS::ReadableStreamError(JSContext* cx, HandleObject streamObj, HandleValue error)
5618 0 : {
5619 0 : AssertHeapIsIdle();
5620 : CHECK_REQUEST(cx);
5621 : assertSameCompartment(cx, streamObj);
5622 : assertSameCompartment(cx, error);
5623 0 :
5624 : Rooted<ReadableStream*> stream(cx, &streamObj->as<ReadableStream>());
5625 0 : return js::ReadableStream::error(cx, stream, error);
5626 0 : }
5627 0 :
5628 0 : JS_PUBLIC_API(bool)
5629 : JS::ReadableStreamReaderIsClosed(const JSObject* reader)
5630 0 : {
5631 0 : return js::ReadableStreamReaderIsClosed(reader);
5632 : }
5633 :
5634 0 : JS_PUBLIC_API(bool)
5635 0 : JS::ReadableStreamReaderCancel(JSContext* cx, HandleObject reader, HandleValue reason)
5636 : {
5637 0 : AssertHeapIsIdle();
5638 : CHECK_REQUEST(cx);
5639 : assertSameCompartment(cx, reader);
5640 : assertSameCompartment(cx, reason);
5641 0 :
5642 : return js::ReadableStreamReaderCancel(cx, reader, reason);
5643 0 : }
5644 0 :
5645 0 : JS_PUBLIC_API(bool)
5646 0 : JS::ReadableStreamReaderReleaseLock(JSContext* cx, HandleObject reader)
5647 : {
5648 0 : AssertHeapIsIdle();
5649 0 : CHECK_REQUEST(cx);
5650 : assertSameCompartment(cx, reader);
5651 :
5652 0 : return js::ReadableStreamReaderReleaseLock(cx, reader);
5653 0 : }
5654 :
5655 : JS_PUBLIC_API(JSObject*)
5656 0 : JS::ReadableStreamDefaultReaderRead(JSContext* cx, HandleObject readerObj)
5657 0 : {
5658 : AssertHeapIsIdle();
5659 0 : CHECK_REQUEST(cx);
5660 0 : assertSameCompartment(cx, readerObj);
5661 0 :
5662 : Rooted<ReadableStreamDefaultReader*> reader(cx, &readerObj->as<ReadableStreamDefaultReader>());
5663 : return js::ReadableStreamDefaultReader::read(cx, reader);
5664 : }
5665 0 :
5666 0 : JS_PUBLIC_API(JSObject*)
5667 : JS::ReadableStreamBYOBReaderRead(JSContext* cx, HandleObject readerObj, HandleObject viewObj)
5668 : {
5669 0 : AssertHeapIsIdle();
5670 : CHECK_REQUEST(cx);
5671 : assertSameCompartment(cx, readerObj);
5672 : assertSameCompartment(cx, viewObj);
5673 0 :
5674 : Rooted<ReadableStreamBYOBReader*> reader(cx, &readerObj->as<ReadableStreamBYOBReader>());
5675 0 : Rooted<ArrayBufferViewObject*> view(cx, &viewObj->as<ArrayBufferViewObject>());
5676 0 : return js::ReadableStreamBYOBReader::read(cx, reader, view);
5677 0 : }
5678 0 :
5679 : JS_PUBLIC_API(void)
5680 0 : JS::InitDispatchToEventLoop(JSContext* cx, JS::DispatchToEventLoopCallback callback, void* closure)
5681 0 : {
5682 : cx->runtime()->offThreadPromiseState.ref().init(callback, closure);
5683 : }
5684 :
5685 0 : JS_PUBLIC_API(void)
5686 : JS::ShutdownAsyncTasks(JSContext* cx)
5687 0 : {
5688 : cx->runtime()->offThreadPromiseState.ref().shutdown(cx);
5689 : }
5690 :
5691 0 : JS_PUBLIC_API(void)
5692 : JS::InitConsumeStreamCallback(JSContext* cx, ConsumeStreamCallback callback)
5693 0 : {
5694 0 : cx->runtime()->consumeStreamCallback = callback;
5695 0 : }
5696 0 :
5697 : JS_PUBLIC_API(void)
5698 0 : JS_RequestInterruptCallback(JSContext* cx)
5699 : {
5700 : cx->requestInterrupt(InterruptReason::CallbackUrgent);
5701 : }
5702 0 :
5703 : JS_PUBLIC_API(void)
5704 0 : JS_RequestInterruptCallbackCanWait(JSContext* cx)
5705 0 : {
5706 0 : cx->requestInterrupt(InterruptReason::CallbackCanWait);
5707 : }
5708 0 :
5709 : JS::AutoSetAsyncStackForNewCalls::AutoSetAsyncStackForNewCalls(
5710 : JSContext* cx, HandleObject stack, const char* asyncCause,
5711 : JS::AutoSetAsyncStackForNewCalls::AsyncCallKind kind)
5712 0 : : cx(cx),
5713 : oldAsyncStack(cx, cx->asyncStackForNewActivations()),
5714 0 : oldAsyncCause(cx->asyncCauseForNewActivations),
5715 0 : oldAsyncCallIsExplicit(cx->asyncCallIsExplicit)
5716 0 : {
5717 : CHECK_REQUEST(cx);
5718 0 :
5719 0 : // The option determines whether we actually use the new values at this
5720 : // point. It will not affect restoring the previous values when the object
5721 : // is destroyed, so if the option changes it won't cause consistency issues.
5722 : if (!cx->options().asyncStack())
5723 0 : return;
5724 :
5725 0 : SavedFrame* asyncStack = &stack->as<SavedFrame>();
5726 0 :
5727 0 : cx->asyncStackForNewActivations() = asyncStack;
5728 0 : cx->asyncCauseForNewActivations = asyncCause;
5729 : cx->asyncCallIsExplicit = kind == AsyncCallKind::EXPLICIT;
5730 0 : }
5731 0 :
5732 0 : JS::AutoSetAsyncStackForNewCalls::~AutoSetAsyncStackForNewCalls()
5733 : {
5734 : cx->asyncCauseForNewActivations = oldAsyncCause;
5735 : cx->asyncStackForNewActivations() =
5736 1 : oldAsyncStack ? &oldAsyncStack->as<SavedFrame>() : nullptr;
5737 : cx->asyncCallIsExplicit = oldAsyncCallIsExplicit;
5738 8 : }
5739 4 :
5740 : /************************************************************************/
5741 : JS_PUBLIC_API(JSString*)
5742 0 : JS_NewStringCopyN(JSContext* cx, const char* s, size_t n)
5743 : {
5744 0 : AssertHeapIsIdle();
5745 0 : CHECK_REQUEST(cx);
5746 : return NewStringCopyN<CanGC>(cx, s, n);
5747 : }
5748 0 :
5749 : JS_PUBLIC_API(JSString*)
5750 8 : JS_NewStringCopyZ(JSContext* cx, const char* s)
5751 4 : {
5752 : AssertHeapIsIdle();
5753 : CHECK_REQUEST(cx);
5754 0 : if (!s)
5755 : return cx->runtime()->emptyString;
5756 0 : return NewStringCopyZ<CanGC>(cx, s);
5757 0 : }
5758 :
5759 : JS_PUBLIC_API(JSString*)
5760 0 : JS_NewStringCopyUTF8Z(JSContext* cx, const JS::ConstUTF8CharsZ s)
5761 : {
5762 0 : AssertHeapIsIdle();
5763 0 : CHECK_REQUEST(cx);
5764 : return NewStringCopyUTF8Z<CanGC>(cx, s);
5765 5219 : }
5766 :
5767 1 : JS_PUBLIC_API(JSString*)
5768 : JS_NewStringCopyUTF8N(JSContext* cx, const JS::UTF8Chars s)
5769 : {
5770 : AssertHeapIsIdle();
5771 0 : CHECK_REQUEST(cx);
5772 : return NewStringCopyUTF8N<CanGC>(cx, s);
5773 10438 : }
5774 :
5775 : JS_PUBLIC_API(bool)
5776 : JS_StringHasBeenPinned(JSContext* cx, JSString* str)
5777 : {
5778 15657 : AssertHeapIsIdle();
5779 0 : CHECK_REQUEST(cx);
5780 :
5781 5219 : if (!str->isAtom())
5782 : return false;
5783 0 :
5784 10438 : return str->asAtom().isPinned();
5785 0 : }
5786 :
5787 : JS_PUBLIC_API(jsid)
5788 0 : INTERNED_STRING_TO_JSID(JSContext* cx, JSString* str)
5789 : {
5790 10438 : MOZ_ASSERT(str);
5791 10438 : MOZ_ASSERT(((size_t)str & JSID_TYPE_MASK) == 0);
5792 0 : MOZ_ASSERT_IF(cx, JS_StringHasBeenPinned(cx, str));
5793 10438 : return AtomToId(&str->asAtom());
5794 0 : }
5795 :
5796 : JS_PUBLIC_API(JSString*)
5797 : JS_AtomizeAndPinJSString(JSContext* cx, HandleString str)
5798 0 : {
5799 : AssertHeapIsIdle();
5800 1447 : CHECK_REQUEST(cx);
5801 2894 : JSAtom* atom = AtomizeString(cx, str, PinAtom);
5802 0 : MOZ_ASSERT_IF(atom, JS_StringHasBeenPinned(cx, atom));
5803 : return atom;
5804 : }
5805 :
5806 0 : JS_PUBLIC_API(JSString*)
5807 : JS_AtomizeString(JSContext* cx, const char* s)
5808 181 : {
5809 362 : return JS_AtomizeStringN(cx, s, strlen(s));
5810 0 : }
5811 0 :
5812 0 : JS_PUBLIC_API(JSString*)
5813 : JS_AtomizeStringN(JSContext* cx, const char* s, size_t length)
5814 : {
5815 : AssertHeapIsIdle();
5816 0 : CHECK_REQUEST(cx);
5817 : return Atomize(cx, s, length, DoNotPinAtom);
5818 23 : }
5819 46 :
5820 0 : JS_PUBLIC_API(JSString*)
5821 : JS_AtomizeAndPinString(JSContext* cx, const char* s)
5822 : {
5823 : return JS_AtomizeAndPinStringN(cx, s, strlen(s));
5824 0 : }
5825 :
5826 0 : JS_PUBLIC_API(JSString*)
5827 0 : JS_AtomizeAndPinStringN(JSContext* cx, const char* s, size_t length)
5828 0 : {
5829 : AssertHeapIsIdle();
5830 : CHECK_REQUEST(cx);
5831 : JSAtom* atom = Atomize(cx, s, length, PinAtom);
5832 0 : MOZ_ASSERT_IF(atom, JS_StringHasBeenPinned(cx, atom));
5833 : return atom;
5834 10242 : }
5835 20484 :
5836 : JS_PUBLIC_API(JSString*)
5837 20484 : JS_NewLatin1String(JSContext* cx, JS::Latin1Char* chars, size_t length)
5838 : {
5839 : AssertHeapIsIdle();
5840 20484 : CHECK_REQUEST(cx);
5841 : return NewString<CanGC>(cx, chars, length);
5842 : }
5843 :
5844 0 : JS_PUBLIC_API(JSString*)
5845 : JS_NewUCString(JSContext* cx, char16_t* chars, size_t length)
5846 550615 : {
5847 550615 : AssertHeapIsIdle();
5848 0 : CHECK_REQUEST(cx);
5849 550615 : return NewString<CanGC>(cx, chars, length);
5850 : }
5851 :
5852 : JS_PUBLIC_API(JSString*)
5853 0 : JS_NewUCStringDontDeflate(JSContext* cx, char16_t* chars, size_t length)
5854 : {
5855 0 : AssertHeapIsIdle();
5856 0 : CHECK_REQUEST(cx);
5857 0 : return NewStringDontDeflate<CanGC>(cx, chars, length);
5858 0 : }
5859 0 :
5860 : JS_PUBLIC_API(JSString*)
5861 : JS_NewUCStringCopyN(JSContext* cx, const char16_t* s, size_t n)
5862 : {
5863 0 : AssertHeapIsIdle();
5864 : CHECK_REQUEST(cx);
5865 0 : if (!n)
5866 : return cx->names().empty;
5867 : return NewStringCopyN<CanGC>(cx, s, n);
5868 : }
5869 0 :
5870 : JS_PUBLIC_API(JSString*)
5871 0 : JS_NewUCStringCopyZ(JSContext* cx, const char16_t* s)
5872 0 : {
5873 0 : AssertHeapIsIdle();
5874 : CHECK_REQUEST(cx);
5875 : if (!s)
5876 : return cx->runtime()->emptyString;
5877 0 : return NewStringCopyZ<CanGC>(cx, s);
5878 : }
5879 5564 :
5880 : JS_PUBLIC_API(JSString*)
5881 : JS_AtomizeUCString(JSContext* cx, const char16_t* s)
5882 : {
5883 0 : return JS_AtomizeUCStringN(cx, s, js_strlen(s));
5884 : }
5885 5564 :
5886 11128 : JS_PUBLIC_API(JSString*)
5887 0 : JS_AtomizeUCStringN(JSContext* cx, const char16_t* s, size_t length)
5888 5564 : {
5889 0 : AssertHeapIsIdle();
5890 : CHECK_REQUEST(cx);
5891 : return AtomizeChars(cx, s, length, DoNotPinAtom);
5892 : }
5893 0 :
5894 : JS_PUBLIC_API(JSString*)
5895 0 : JS_AtomizeAndPinUCStringN(JSContext* cx, const char16_t* s, size_t length)
5896 0 : {
5897 0 : AssertHeapIsIdle();
5898 : CHECK_REQUEST(cx);
5899 : JSAtom* atom = AtomizeChars(cx, s, length, PinAtom);
5900 : MOZ_ASSERT_IF(atom, JS_StringHasBeenPinned(cx, atom));
5901 1 : return atom;
5902 : }
5903 226 :
5904 452 : JS_PUBLIC_API(JSString*)
5905 0 : JS_AtomizeAndPinUCString(JSContext* cx, const char16_t* s)
5906 : {
5907 : return JS_AtomizeAndPinUCStringN(cx, s, js_strlen(s));
5908 : }
5909 0 :
5910 : JS_PUBLIC_API(size_t)
5911 0 : JS_GetStringLength(JSString* str)
5912 0 : {
5913 0 : return str->length();
5914 : }
5915 :
5916 : JS_PUBLIC_API(bool)
5917 1 : JS_StringIsFlat(JSString* str)
5918 : {
5919 2015 : return str->isFlat();
5920 4030 : }
5921 0 :
5922 220 : JS_PUBLIC_API(bool)
5923 0 : JS_StringHasLatin1Chars(JSString* str)
5924 : {
5925 : return str->hasLatin1Chars();
5926 : }
5927 0 :
5928 : JS_PUBLIC_API(const JS::Latin1Char*)
5929 32 : JS_GetLatin1StringCharsAndLength(JSContext* cx, const JS::AutoRequireNoGC& nogc, JSString* str,
5930 64 : size_t* plength)
5931 0 : {
5932 0 : MOZ_ASSERT(plength);
5933 0 : AssertHeapIsIdleOrStringIsFlat(str);
5934 : CHECK_REQUEST(cx);
5935 : assertSameCompartment(cx, str);
5936 : JSLinearString* linear = str->ensureLinear(cx);
5937 0 : if (!linear)
5938 : return nullptr;
5939 0 : *plength = linear->length();
5940 : return linear->latin1Chars(nogc);
5941 : }
5942 :
5943 0 : JS_PUBLIC_API(const char16_t*)
5944 : JS_GetTwoByteStringCharsAndLength(JSContext* cx, const JS::AutoRequireNoGC& nogc, JSString* str,
5945 0 : size_t* plength)
5946 0 : {
5947 0 : MOZ_ASSERT(plength);
5948 : AssertHeapIsIdleOrStringIsFlat(str);
5949 : CHECK_REQUEST(cx);
5950 : assertSameCompartment(cx, str);
5951 0 : JSLinearString* linear = str->ensureLinear(cx);
5952 : if (!linear)
5953 0 : return nullptr;
5954 0 : *plength = linear->length();
5955 0 : return linear->twoByteChars(nogc);
5956 0 : }
5957 0 :
5958 : JS_PUBLIC_API(const char16_t*)
5959 : JS_GetTwoByteExternalStringChars(JSString* str)
5960 : {
5961 0 : return str->asExternal().twoByteChars();
5962 : }
5963 0 :
5964 : JS_PUBLIC_API(bool)
5965 : JS_GetStringCharAt(JSContext* cx, JSString* str, size_t index, char16_t* res)
5966 : {
5967 1 : AssertHeapIsIdleOrStringIsFlat(str);
5968 : CHECK_REQUEST(cx);
5969 2062 : assertSameCompartment(cx, str);
5970 :
5971 : JSLinearString* linear = str->ensureLinear(cx);
5972 : if (!linear)
5973 0 : return false;
5974 :
5975 0 : *res = linear->latin1OrTwoByteChar(index);
5976 : return true;
5977 : }
5978 :
5979 0 : JS_PUBLIC_API(char16_t)
5980 : JS_GetFlatStringCharAt(JSFlatString* str, size_t index)
5981 3074 : {
5982 : return str->latin1OrTwoByteChar(index);
5983 : }
5984 :
5985 0 : JS_PUBLIC_API(bool)
5986 : JS_CopyStringChars(JSContext* cx, mozilla::Range<char16_t> dest, JSString* str)
5987 : {
5988 1564 : AssertHeapIsIdleOrStringIsFlat(str);
5989 0 : CHECK_REQUEST(cx);
5990 3128 : assertSameCompartment(cx, str);
5991 1564 :
5992 0 : JSLinearString* linear = str->ensureLinear(cx);
5993 0 : if (!linear)
5994 : return false;
5995 0 :
5996 0 : MOZ_ASSERT(linear->length() <= dest.length());
5997 : CopyChars(dest.begin().get(), *linear);
5998 : return true;
5999 : }
6000 0 :
6001 : JS_PUBLIC_API(const Latin1Char*)
6002 : JS_GetLatin1InternedStringChars(const JS::AutoRequireNoGC& nogc, JSString* str)
6003 6 : {
6004 0 : MOZ_ASSERT(str->isAtom());
6005 12 : JSFlatString* flat = str->ensureFlat(nullptr);
6006 6 : if (!flat)
6007 0 : return nullptr;
6008 0 : return flat->latin1Chars(nogc);
6009 : }
6010 0 :
6011 0 : JS_PUBLIC_API(const char16_t*)
6012 : JS_GetTwoByteInternedStringChars(const JS::AutoRequireNoGC& nogc, JSString* str)
6013 : {
6014 : MOZ_ASSERT(str->isAtom());
6015 0 : JSFlatString* flat = str->ensureFlat(nullptr);
6016 : if (!flat)
6017 44 : return nullptr;
6018 : return flat->twoByteChars(nogc);
6019 : }
6020 :
6021 0 : extern JS_PUBLIC_API(JSFlatString*)
6022 : JS_FlattenString(JSContext* cx, JSString* str)
6023 0 : {
6024 0 : AssertHeapIsIdle();
6025 0 : CHECK_REQUEST(cx);
6026 : assertSameCompartment(cx, str);
6027 0 : JSFlatString* flat = str->ensureFlat(cx);
6028 0 : if (!flat)
6029 : return nullptr;
6030 : return flat;
6031 0 : }
6032 0 :
6033 : extern JS_PUBLIC_API(const Latin1Char*)
6034 : JS_GetLatin1FlatStringChars(const JS::AutoRequireNoGC& nogc, JSFlatString* str)
6035 : {
6036 0 : return str->latin1Chars(nogc);
6037 : }
6038 0 :
6039 : extern JS_PUBLIC_API(const char16_t*)
6040 : JS_GetTwoByteFlatStringChars(const JS::AutoRequireNoGC& nogc, JSFlatString* str)
6041 : {
6042 0 : return str->twoByteChars(nogc);
6043 : }
6044 128 :
6045 256 : JS_PUBLIC_API(bool)
6046 0 : JS_CompareStrings(JSContext* cx, JSString* str1, JSString* str2, int32_t* result)
6047 : {
6048 0 : AssertHeapIsIdle();
6049 0 : CHECK_REQUEST(cx);
6050 :
6051 : return CompareStrings(cx, str1, str2, result);
6052 0 : }
6053 0 :
6054 128 : JS_PUBLIC_API(bool)
6055 : JS_StringEqualsAscii(JSContext* cx, JSString* str, const char* asciiBytes, bool* match)
6056 : {
6057 : AssertHeapIsIdle();
6058 0 : CHECK_REQUEST(cx);
6059 :
6060 0 : JSLinearString* linearStr = str->ensureLinear(cx);
6061 0 : if (!linearStr)
6062 0 : return false;
6063 : *match = StringEqualsAscii(linearStr, asciiBytes);
6064 0 : return true;
6065 : }
6066 :
6067 : JS_PUBLIC_API(bool)
6068 0 : JS_FlatStringEqualsAscii(JSFlatString* str, const char* asciiBytes)
6069 : {
6070 0 : return StringEqualsAscii(str, asciiBytes);
6071 0 : }
6072 0 :
6073 : JS_PUBLIC_API(size_t)
6074 0 : JS_PutEscapedFlatString(char* buffer, size_t size, JSFlatString* str, char quote)
6075 : {
6076 : return PutEscapedString(buffer, size, str, quote);
6077 : }
6078 1 :
6079 : JS_PUBLIC_API(size_t)
6080 873 : JS_PutEscapedString(JSContext* cx, char* buffer, size_t size, JSString* str, char quote)
6081 1746 : {
6082 0 : AssertHeapIsIdle();
6083 873 : JSLinearString* linearStr = str->ensureLinear(cx);
6084 0 : if (!linearStr)
6085 : return size_t(-1);
6086 0 : return PutEscapedString(buffer, size, linearStr, quote);
6087 : }
6088 :
6089 : JS_PUBLIC_API(JSString*)
6090 0 : JS_NewDependentString(JSContext* cx, HandleString str, size_t start, size_t length)
6091 : {
6092 0 : AssertHeapIsIdle();
6093 : CHECK_REQUEST(cx);
6094 : return NewDependentString(cx, str, start, length);
6095 : }
6096 0 :
6097 : JS_PUBLIC_API(JSString*)
6098 0 : JS_ConcatStrings(JSContext* cx, HandleString left, HandleString right)
6099 : {
6100 : AssertHeapIsIdle();
6101 : CHECK_REQUEST(cx);
6102 0 : return ConcatStrings<CanGC>(cx, left, right);
6103 : }
6104 0 :
6105 0 : JS_PUBLIC_API(bool)
6106 : JS_DecodeBytes(JSContext* cx, const char* src, size_t srclen, char16_t* dst, size_t* dstlenp)
6107 0 : {
6108 : AssertHeapIsIdle();
6109 : CHECK_REQUEST(cx);
6110 :
6111 0 : if (!dst) {
6112 : *dstlenp = srclen;
6113 0 : return true;
6114 0 : }
6115 :
6116 0 : size_t dstlen = *dstlenp;
6117 0 :
6118 : if (srclen > dstlen) {
6119 0 : CopyAndInflateChars(dst, src, dstlen);
6120 0 :
6121 : AutoSuppressGC suppress(cx);
6122 : JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_BUFFER_TOO_SMALL);
6123 : return false;
6124 0 : }
6125 :
6126 1396 : CopyAndInflateChars(dst, src, srclen);
6127 : *dstlenp = srclen;
6128 : return true;
6129 : }
6130 0 :
6131 : static char*
6132 0 : EncodeLatin1(JSContext* cx, JSString* str)
6133 : {
6134 : JSLinearString* linear = str->ensureLinear(cx);
6135 : if (!linear)
6136 0 : return nullptr;
6137 :
6138 0 : JS::AutoCheckCannotGC nogc;
6139 0 : if (linear->hasTwoByteChars())
6140 0 : return JS::LossyTwoByteCharsToNewLatin1CharsZ(cx, linear->twoByteRange(nogc)).c_str();
6141 :
6142 0 : size_t len = str->length();
6143 : Latin1Char* buf = cx->pod_malloc<Latin1Char>(len + 1);
6144 : if (!buf) {
6145 : ReportOutOfMemory(cx);
6146 0 : return nullptr;
6147 : }
6148 0 :
6149 0 : mozilla::PodCopy(buf, linear->latin1Chars(nogc), len);
6150 0 : buf[len] = '\0';
6151 : return reinterpret_cast<char*>(buf);
6152 : }
6153 :
6154 0 : JS_PUBLIC_API(char*)
6155 : JS_EncodeString(JSContext* cx, JSString* str)
6156 0 : {
6157 0 : AssertHeapIsIdle();
6158 0 : CHECK_REQUEST(cx);
6159 :
6160 : return EncodeLatin1(cx, str);
6161 : }
6162 0 :
6163 : JS_PUBLIC_API(char*)
6164 0 : JS_EncodeStringToUTF8(JSContext* cx, HandleString str)
6165 0 : {
6166 : AssertHeapIsIdle();
6167 0 : CHECK_REQUEST(cx);
6168 0 :
6169 0 : return StringToNewUTF8CharsZ(cx, *str).release();
6170 : }
6171 :
6172 0 : JS_PUBLIC_API(size_t)
6173 : JS_GetStringEncodingLength(JSContext* cx, JSString* str)
6174 0 : {
6175 0 : AssertHeapIsIdle();
6176 : CHECK_REQUEST(cx);
6177 0 :
6178 0 : if (!str->ensureLinear(cx))
6179 0 : return size_t(-1);
6180 : return str->length();
6181 : }
6182 0 :
6183 0 : JS_PUBLIC_API(size_t)
6184 0 : JS_EncodeStringToBuffer(JSContext* cx, JSString* str, char* buffer, size_t length)
6185 : {
6186 : AssertHeapIsIdle();
6187 : CHECK_REQUEST(cx);
6188 1 :
6189 : /*
6190 842 : * FIXME bug 612141 - fix DeflateStringToBuffer interface so the result
6191 842 : * would allow to distinguish between insufficient buffer and encoding
6192 : * error.
6193 : */
6194 0 : size_t writtenLength = length;
6195 0 : JSLinearString* linear = str->ensureLinear(cx);
6196 0 : if (!linear)
6197 : return size_t(-1);
6198 0 :
6199 0 : bool res;
6200 0 : if (linear->hasLatin1Chars()) {
6201 0 : JS::AutoCheckCannotGC nogc;
6202 0 : res = DeflateStringToBuffer(nullptr, linear->latin1Chars(nogc), linear->length(), buffer,
6203 : &writtenLength);
6204 : } else {
6205 0 : JS::AutoCheckCannotGC nogc;
6206 0 : res = DeflateStringToBuffer(nullptr, linear->twoByteChars(nogc), linear->length(), buffer,
6207 842 : &writtenLength);
6208 : }
6209 : if (res) {
6210 : MOZ_ASSERT(writtenLength <= length);
6211 0 : return writtenLength;
6212 : }
6213 842 : MOZ_ASSERT(writtenLength <= length);
6214 1684 : size_t necessaryLength = str->length();
6215 : if (necessaryLength == size_t(-1))
6216 1684 : return size_t(-1);
6217 : MOZ_ASSERT(writtenLength == length); // C strings are NOT encoded.
6218 : return necessaryLength;
6219 : }
6220 0 :
6221 : JS_PUBLIC_API(JS::Symbol*)
6222 280 : JS::NewSymbol(JSContext* cx, HandleString description)
6223 560 : {
6224 : AssertHeapIsIdle();
6225 1120 : CHECK_REQUEST(cx);
6226 : if (description)
6227 : assertSameCompartment(cx, description);
6228 :
6229 0 : return Symbol::new_(cx, SymbolCode::UniqueSymbol, description);
6230 : }
6231 1670 :
6232 3340 : JS_PUBLIC_API(JS::Symbol*)
6233 : JS::GetSymbolFor(JSContext* cx, HandleString key)
6234 1670 : {
6235 : AssertHeapIsIdle();
6236 0 : CHECK_REQUEST(cx);
6237 : assertSameCompartment(cx, key);
6238 :
6239 : return Symbol::for_(cx, key);
6240 0 : }
6241 :
6242 1693 : JS_PUBLIC_API(JSString*)
6243 3386 : JS::GetSymbolDescription(HandleSymbol symbol)
6244 : {
6245 : return symbol->description();
6246 : }
6247 :
6248 : JS_PUBLIC_API(JS::SymbolCode)
6249 : JS::GetSymbolCode(Handle<Symbol*> symbol)
6250 1693 : {
6251 1693 : return symbol->code();
6252 1693 : }
6253 :
6254 : JS_PUBLIC_API(JS::Symbol*)
6255 : JS::GetWellKnownSymbol(JSContext* cx, JS::SymbolCode which)
6256 0 : {
6257 3374 : return cx->wellKnownSymbols().get(which);
6258 5061 : }
6259 1687 :
6260 : #ifdef DEBUG
6261 0 : static bool
6262 0 : PropertySpecNameIsDigits(const char* s) {
6263 0 : if (JS::PropertySpecNameIsSymbol(s))
6264 : return false;
6265 0 : if (!*s)
6266 0 : return false;
6267 : for (; *s; s++) {
6268 : if (*s < '0' || *s > '9')
6269 0 : return false;
6270 0 : }
6271 : return true;
6272 : }
6273 0 : #endif // DEBUG
6274 :
6275 : JS_PUBLIC_API(bool)
6276 : JS::PropertySpecNameEqualsId(const char* name, HandleId id)
6277 : {
6278 0 : if (JS::PropertySpecNameIsSymbol(name)) {
6279 : if (!JSID_IS_SYMBOL(id))
6280 0 : return false;
6281 0 : Symbol* sym = JSID_TO_SYMBOL(id);
6282 0 : return sym->isWellKnownSymbol() && sym->code() == PropertySpecNameToSymbolCode(name);
6283 0 : }
6284 :
6285 0 : MOZ_ASSERT(!PropertySpecNameIsDigits(name));
6286 : return JSID_IS_ATOM(id) && JS_FlatStringEqualsAscii(JSID_TO_ATOM(id), name);
6287 : }
6288 :
6289 0 : JS_PUBLIC_API(bool)
6290 : JS_Stringify(JSContext* cx, MutableHandleValue vp, HandleObject replacer,
6291 0 : HandleValue space, JSONWriteCallback callback, void* data)
6292 0 : {
6293 0 : AssertHeapIsIdle();
6294 : CHECK_REQUEST(cx);
6295 0 : assertSameCompartment(cx, replacer, space);
6296 : StringBuffer sb(cx);
6297 : if (!sb.ensureTwoByteChars())
6298 : return false;
6299 0 : if (!Stringify(cx, vp, replacer, space, sb, StringifyBehavior::Normal))
6300 : return false;
6301 0 : if (sb.empty() && !sb.append(cx->names().null))
6302 : return false;
6303 : return callback(sb.rawTwoByteBegin(), sb.length(), data);
6304 : }
6305 0 :
6306 : JS_PUBLIC_API(bool)
6307 0 : JS::ToJSONMaybeSafely(JSContext* cx, JS::HandleObject input,
6308 : JSONWriteCallback callback, void* data)
6309 : {
6310 : AssertHeapIsIdle();
6311 0 : CHECK_REQUEST(cx);
6312 : assertSameCompartment(cx, input);
6313 1803 :
6314 : StringBuffer sb(cx);
6315 : if (!sb.ensureTwoByteChars())
6316 : return false;
6317 :
6318 : RootedValue inputValue(cx, ObjectValue(*input));
6319 1829 : if (!Stringify(cx, &inputValue, nullptr, NullHandleValue, sb,
6320 : StringifyBehavior::RestrictedSafe))
6321 1829 : return false;
6322 :
6323 0 : if (sb.empty() && !sb.append(cx->names().null))
6324 1829 : return false;
6325 :
6326 : return callback(sb.rawTwoByteBegin(), sb.length(), data);
6327 : }
6328 :
6329 : JS_PUBLIC_API(bool)
6330 : JS_ParseJSON(JSContext* cx, const char16_t* chars, uint32_t len, MutableHandleValue vp)
6331 : {
6332 1872 : AssertHeapIsIdle();
6333 : CHECK_REQUEST(cx);
6334 1872 : return ParseJSONWithReviver(cx, mozilla::Range<const char16_t>(chars, len), NullHandleValue, vp);
6335 86 : }
6336 :
6337 3 : JS_PUBLIC_API(bool)
6338 0 : JS_ParseJSON(JSContext* cx, HandleString str, MutableHandleValue vp)
6339 : {
6340 : return JS_ParseJSONWithReviver(cx, str, NullHandleValue, vp);
6341 0 : }
6342 0 :
6343 : JS_PUBLIC_API(bool)
6344 : JS_ParseJSONWithReviver(JSContext* cx, const char16_t* chars, uint32_t len, HandleValue reviver, MutableHandleValue vp)
6345 : {
6346 0 : AssertHeapIsIdle();
6347 : CHECK_REQUEST(cx);
6348 : return ParseJSONWithReviver(cx, mozilla::Range<const char16_t>(chars, len), reviver, vp);
6349 0 : }
6350 0 :
6351 0 : JS_PUBLIC_API(bool)
6352 0 : JS_ParseJSONWithReviver(JSContext* cx, HandleString str, HandleValue reviver, MutableHandleValue vp)
6353 0 : {
6354 : AssertHeapIsIdle();
6355 0 : CHECK_REQUEST(cx);
6356 : assertSameCompartment(cx, str);
6357 0 :
6358 : AutoStableStringChars stableChars(cx);
6359 0 : if (!stableChars.init(cx, str))
6360 : return false;
6361 :
6362 : return stableChars.isLatin1()
6363 0 : ? ParseJSONWithReviver(cx, stableChars.latin1Range(), reviver, vp)
6364 : : ParseJSONWithReviver(cx, stableChars.twoByteRange(), reviver, vp);
6365 : }
6366 0 :
6367 0 : /************************************************************************/
6368 0 :
6369 : JS_PUBLIC_API(void)
6370 0 : JS_ReportErrorASCII(JSContext* cx, const char* format, ...)
6371 0 : {
6372 : va_list ap;
6373 :
6374 0 : AssertHeapIsIdle();
6375 0 : va_start(ap, format);
6376 : ReportErrorVA(cx, JSREPORT_ERROR, format, ArgumentsAreASCII, ap);
6377 : va_end(ap);
6378 : }
6379 0 :
6380 : JS_PUBLIC_API(void)
6381 : JS_ReportErrorLatin1(JSContext* cx, const char* format, ...)
6382 0 : {
6383 : va_list ap;
6384 :
6385 : AssertHeapIsIdle();
6386 0 : va_start(ap, format);
6387 : ReportErrorVA(cx, JSREPORT_ERROR, format, ArgumentsAreLatin1, ap);
6388 3 : va_end(ap);
6389 6 : }
6390 0 :
6391 : JS_PUBLIC_API(void)
6392 : JS_ReportErrorUTF8(JSContext* cx, const char* format, ...)
6393 : {
6394 0 : va_list ap;
6395 :
6396 0 : AssertHeapIsIdle();
6397 : va_start(ap, format);
6398 : ReportErrorVA(cx, JSREPORT_ERROR, format, ArgumentsAreUTF8, ap);
6399 : va_end(ap);
6400 0 : }
6401 :
6402 0 : JS_PUBLIC_API(void)
6403 0 : JS_ReportErrorNumberASCII(JSContext* cx, JSErrorCallback errorCallback,
6404 0 : void* userRef, const unsigned errorNumber, ...)
6405 : {
6406 : va_list ap;
6407 : va_start(ap, errorNumber);
6408 0 : JS_ReportErrorNumberASCIIVA(cx, errorCallback, userRef, errorNumber, ap);
6409 : va_end(ap);
6410 0 : }
6411 0 :
6412 0 : JS_PUBLIC_API(void)
6413 : JS_ReportErrorNumberASCIIVA(JSContext* cx, JSErrorCallback errorCallback,
6414 0 : void* userRef, const unsigned errorNumber,
6415 0 : va_list ap)
6416 : {
6417 : AssertHeapIsIdle();
6418 0 : ReportErrorNumberVA(cx, JSREPORT_ERROR, errorCallback, userRef,
6419 0 : errorNumber, ArgumentsAreASCII, ap);
6420 0 : }
6421 :
6422 : JS_PUBLIC_API(void)
6423 : JS_ReportErrorNumberLatin1(JSContext* cx, JSErrorCallback errorCallback,
6424 : void* userRef, const unsigned errorNumber, ...)
6425 : {
6426 2 : va_list ap;
6427 : va_start(ap, errorNumber);
6428 : JS_ReportErrorNumberLatin1VA(cx, errorCallback, userRef, errorNumber, ap);
6429 : va_end(ap);
6430 0 : }
6431 2 :
6432 2 : JS_PUBLIC_API(void)
6433 2 : JS_ReportErrorNumberLatin1VA(JSContext* cx, JSErrorCallback errorCallback,
6434 0 : void* userRef, const unsigned errorNumber,
6435 : va_list ap)
6436 : {
6437 0 : AssertHeapIsIdle();
6438 : ReportErrorNumberVA(cx, JSREPORT_ERROR, errorCallback, userRef,
6439 : errorNumber, ArgumentsAreLatin1, ap);
6440 : }
6441 0 :
6442 0 : JS_PUBLIC_API(void)
6443 0 : JS_ReportErrorNumberUTF8(JSContext* cx, JSErrorCallback errorCallback,
6444 0 : void* userRef, const unsigned errorNumber, ...)
6445 0 : {
6446 : va_list ap;
6447 : va_start(ap, errorNumber);
6448 1 : JS_ReportErrorNumberUTF8VA(cx, errorCallback, userRef, errorNumber, ap);
6449 : va_end(ap);
6450 : }
6451 :
6452 0 : JS_PUBLIC_API(void)
6453 6 : JS_ReportErrorNumberUTF8VA(JSContext* cx, JSErrorCallback errorCallback,
6454 6 : void* userRef, const unsigned errorNumber,
6455 6 : va_list ap)
6456 0 : {
6457 : AssertHeapIsIdle();
6458 : ReportErrorNumberVA(cx, JSREPORT_ERROR, errorCallback, userRef,
6459 0 : errorNumber, ArgumentsAreUTF8, ap);
6460 : }
6461 :
6462 : JS_PUBLIC_API(void)
6463 0 : JS_ReportErrorNumberUC(JSContext* cx, JSErrorCallback errorCallback,
6464 0 : void* userRef, const unsigned errorNumber, ...)
6465 0 : {
6466 0 : va_list ap;
6467 :
6468 : AssertHeapIsIdle();
6469 0 : va_start(ap, errorNumber);
6470 : ReportErrorNumberVA(cx, JSREPORT_ERROR, errorCallback, userRef,
6471 : errorNumber, ArgumentsAreUnicode, ap);
6472 : va_end(ap);
6473 0 : }
6474 :
6475 0 : JS_PUBLIC_API(void)
6476 0 : JS_ReportErrorNumberUCArray(JSContext* cx, JSErrorCallback errorCallback,
6477 : void* userRef, const unsigned errorNumber,
6478 : const char16_t** args)
6479 0 : {
6480 : AssertHeapIsIdle();
6481 : ReportErrorNumberUCArray(cx, JSREPORT_ERROR, errorCallback, userRef,
6482 : errorNumber, args);
6483 0 : }
6484 0 :
6485 0 : JS_PUBLIC_API(bool)
6486 0 : JS_ReportWarningASCII(JSContext* cx, const char* format, ...)
6487 : {
6488 : va_list ap;
6489 0 : bool ok;
6490 :
6491 : AssertHeapIsIdle();
6492 : va_start(ap, format);
6493 0 : ok = ReportErrorVA(cx, JSREPORT_WARNING, format, ArgumentsAreASCII, ap);
6494 : va_end(ap);
6495 0 : return ok;
6496 0 : }
6497 :
6498 : JS_PUBLIC_API(bool)
6499 0 : JS_ReportWarningLatin1(JSContext* cx, const char* format, ...)
6500 : {
6501 : va_list ap;
6502 : bool ok;
6503 0 :
6504 0 : AssertHeapIsIdle();
6505 0 : va_start(ap, format);
6506 0 : ok = ReportErrorVA(cx, JSREPORT_WARNING, format, ArgumentsAreLatin1, ap);
6507 : va_end(ap);
6508 : return ok;
6509 0 : }
6510 :
6511 : JS_PUBLIC_API(bool)
6512 : JS_ReportWarningUTF8(JSContext* cx, const char* format, ...)
6513 0 : {
6514 : va_list ap;
6515 0 : bool ok;
6516 0 :
6517 : AssertHeapIsIdle();
6518 : va_start(ap, format);
6519 0 : ok = ReportErrorVA(cx, JSREPORT_WARNING, format, ArgumentsAreUTF8, ap);
6520 : va_end(ap);
6521 : return ok;
6522 : }
6523 :
6524 0 : JS_PUBLIC_API(bool)
6525 0 : JS_ReportErrorFlagsAndNumberASCII(JSContext* cx, unsigned flags,
6526 : JSErrorCallback errorCallback, void* userRef,
6527 0 : const unsigned errorNumber, ...)
6528 0 : {
6529 0 : va_list ap;
6530 : bool ok;
6531 :
6532 0 : AssertHeapIsIdle();
6533 : va_start(ap, errorNumber);
6534 : ok = ReportErrorNumberVA(cx, flags, errorCallback, userRef,
6535 : errorNumber, ArgumentsAreASCII, ap);
6536 0 : va_end(ap);
6537 : return ok;
6538 12 : }
6539 12 :
6540 : JS_PUBLIC_API(bool)
6541 : JS_ReportErrorFlagsAndNumberLatin1(JSContext* cx, unsigned flags,
6542 0 : JSErrorCallback errorCallback, void* userRef,
6543 : const unsigned errorNumber, ...)
6544 : {
6545 : va_list ap;
6546 : bool ok;
6547 0 :
6548 0 : AssertHeapIsIdle();
6549 0 : va_start(ap, errorNumber);
6550 0 : ok = ReportErrorNumberVA(cx, flags, errorCallback, userRef,
6551 0 : errorNumber, ArgumentsAreLatin1, ap);
6552 : va_end(ap);
6553 : return ok;
6554 : }
6555 0 :
6556 : JS_PUBLIC_API(bool)
6557 : JS_ReportErrorFlagsAndNumberUTF8(JSContext* cx, unsigned flags,
6558 : JSErrorCallback errorCallback, void* userRef,
6559 : const unsigned errorNumber, ...)
6560 0 : {
6561 0 : va_list ap;
6562 0 : bool ok;
6563 0 :
6564 0 : AssertHeapIsIdle();
6565 : va_start(ap, errorNumber);
6566 : ok = ReportErrorNumberVA(cx, flags, errorCallback, userRef,
6567 : errorNumber, ArgumentsAreUTF8, ap);
6568 0 : va_end(ap);
6569 : return ok;
6570 : }
6571 :
6572 : JS_PUBLIC_API(bool)
6573 0 : JS_ReportErrorFlagsAndNumberUC(JSContext* cx, unsigned flags,
6574 0 : JSErrorCallback errorCallback, void* userRef,
6575 0 : const unsigned errorNumber, ...)
6576 0 : {
6577 0 : va_list ap;
6578 : bool ok;
6579 :
6580 : AssertHeapIsIdle();
6581 0 : va_start(ap, errorNumber);
6582 : ok = ReportErrorNumberVA(cx, flags, errorCallback, userRef,
6583 : errorNumber, ArgumentsAreUnicode, ap);
6584 : va_end(ap);
6585 : return ok;
6586 : }
6587 :
6588 0 : JS_PUBLIC_API(void)
6589 0 : JS_ReportOutOfMemory(JSContext* cx)
6590 : {
6591 0 : ReportOutOfMemory(cx);
6592 0 : }
6593 0 :
6594 : JS_PUBLIC_API(void)
6595 : JS_ReportAllocationOverflow(JSContext* cx)
6596 : {
6597 0 : ReportAllocationOverflow(cx);
6598 : }
6599 :
6600 : JS_PUBLIC_API(JS::WarningReporter)
6601 : JS::GetWarningReporter(JSContext* cx)
6602 : {
6603 : return cx->runtime()->warningReporter;
6604 2 : }
6605 2 :
6606 : JS_PUBLIC_API(JS::WarningReporter)
6607 2 : JS::SetWarningReporter(JSContext* cx, JS::WarningReporter reporter)
6608 0 : {
6609 0 : WarningReporter older = cx->runtime()->warningReporter;
6610 : cx->runtime()->warningReporter = reporter;
6611 : return older;
6612 : }
6613 0 :
6614 : /************************************************************************/
6615 :
6616 : /*
6617 : * Dates.
6618 : */
6619 : JS_PUBLIC_API(JSObject*)
6620 0 : JS_NewDateObject(JSContext* cx, int year, int mon, int mday, int hour, int min, int sec)
6621 0 : {
6622 : AssertHeapIsIdle();
6623 0 : CHECK_REQUEST(cx);
6624 0 : return NewDateObject(cx, year, mon, mday, hour, min, sec);
6625 0 : }
6626 :
6627 : JS_PUBLIC_API(JSObject*)
6628 : JS::NewDateObject(JSContext* cx, JS::ClippedTime time)
6629 0 : {
6630 : AssertHeapIsIdle();
6631 : CHECK_REQUEST(cx);
6632 : return NewDateObjectMsec(cx, time);
6633 : }
6634 :
6635 : JS_PUBLIC_API(bool)
6636 0 : JS_ObjectIsDate(JSContext* cx, HandleObject obj, bool* isDate)
6637 0 : {
6638 : assertSameCompartment(cx, obj);
6639 0 :
6640 0 : ESClass cls;
6641 0 : if (!GetBuiltinClass(cx, obj, &cls))
6642 : return false;
6643 :
6644 : *isDate = cls == ESClass::Date;
6645 0 : return true;
6646 : }
6647 0 :
6648 0 : /************************************************************************/
6649 :
6650 : /*
6651 0 : * Regular Expressions.
6652 : */
6653 0 : JS_PUBLIC_API(JSObject*)
6654 0 : JS_NewRegExpObject(JSContext* cx, const char* bytes, size_t length, unsigned flags)
6655 : {
6656 : AssertHeapIsIdle();
6657 1 : CHECK_REQUEST(cx);
6658 :
6659 19542 : ScopedJSFreePtr<char16_t> chars(InflateString(cx, bytes, length));
6660 : if (!chars)
6661 : return nullptr;
6662 :
6663 0 : return RegExpObject::create(cx, chars.get(), length, RegExpFlag(flags), cx->tempLifoAlloc(),
6664 : GenericObject);
6665 39082 : }
6666 39082 :
6667 0 : JS_PUBLIC_API(JSObject*)
6668 : JS_NewUCRegExpObject(JSContext* cx, const char16_t* chars, size_t length, unsigned flags)
6669 : {
6670 : AssertHeapIsIdle();
6671 : CHECK_REQUEST(cx);
6672 :
6673 : return RegExpObject::create(cx, chars, length, RegExpFlag(flags), cx->tempLifoAlloc(),
6674 : GenericObject);
6675 : }
6676 0 :
6677 : JS_PUBLIC_API(bool)
6678 0 : JS_SetRegExpInput(JSContext* cx, HandleObject obj, HandleString input)
6679 0 : {
6680 0 : AssertHeapIsIdle();
6681 : CHECK_REQUEST(cx);
6682 : assertSameCompartment(cx, input);
6683 :
6684 1 : Handle<GlobalObject*> global = obj.as<GlobalObject>();
6685 : RegExpStatics* res = GlobalObject::getRegExpStatics(cx, global);
6686 8 : if (!res)
6687 16 : return false;
6688 0 :
6689 : res->reset(input);
6690 : return true;
6691 : }
6692 0 :
6693 : JS_PUBLIC_API(bool)
6694 0 : JS_ClearRegExpStatics(JSContext* cx, HandleObject obj)
6695 : {
6696 : AssertHeapIsIdle();
6697 0 : CHECK_REQUEST(cx);
6698 : MOZ_ASSERT(obj);
6699 :
6700 0 : Handle<GlobalObject*> global = obj.as<GlobalObject>();
6701 0 : RegExpStatics* res = GlobalObject::getRegExpStatics(cx, global);
6702 : if (!res)
6703 : return false;
6704 :
6705 : res->clear();
6706 : return true;
6707 : }
6708 :
6709 : JS_PUBLIC_API(bool)
6710 0 : JS_ExecuteRegExp(JSContext* cx, HandleObject obj, HandleObject reobj, char16_t* chars,
6711 : size_t length, size_t* indexp, bool test, MutableHandleValue rval)
6712 0 : {
6713 0 : AssertHeapIsIdle();
6714 : CHECK_REQUEST(cx);
6715 0 :
6716 0 : Handle<GlobalObject*> global = obj.as<GlobalObject>();
6717 : RegExpStatics* res = GlobalObject::getRegExpStatics(cx, global);
6718 : if (!res)
6719 0 : return false;
6720 0 :
6721 : RootedLinearString input(cx, NewStringCopyN<CanGC>(cx, chars, length));
6722 : if (!input)
6723 : return false;
6724 0 :
6725 : return ExecuteRegExpLegacy(cx, res, reobj.as<RegExpObject>(), input, indexp, test, rval);
6726 0 : }
6727 0 :
6728 : JS_PUBLIC_API(bool)
6729 0 : JS_ExecuteRegExpNoStatics(JSContext* cx, HandleObject obj, char16_t* chars, size_t length,
6730 0 : size_t* indexp, bool test, MutableHandleValue rval)
6731 : {
6732 : AssertHeapIsIdle();
6733 : CHECK_REQUEST(cx);
6734 0 :
6735 : RootedLinearString input(cx, NewStringCopyN<CanGC>(cx, chars, length));
6736 0 : if (!input)
6737 0 : return false;
6738 0 :
6739 : return ExecuteRegExpLegacy(cx, nullptr, obj.as<RegExpObject>(), input, indexp, test,
6740 0 : rval);
6741 0 : }
6742 0 :
6743 : JS_PUBLIC_API(bool)
6744 : JS_ObjectIsRegExp(JSContext* cx, HandleObject obj, bool* isRegExp)
6745 0 : {
6746 0 : assertSameCompartment(cx, obj);
6747 :
6748 : ESClass cls;
6749 : if (!GetBuiltinClass(cx, obj, &cls))
6750 0 : return false;
6751 :
6752 0 : *isRegExp = cls == ESClass::RegExp;
6753 0 : return true;
6754 0 : }
6755 :
6756 0 : JS_PUBLIC_API(unsigned)
6757 0 : JS_GetRegExpFlags(JSContext* cx, HandleObject obj)
6758 0 : {
6759 : AssertHeapIsIdle();
6760 : CHECK_REQUEST(cx);
6761 0 :
6762 0 : RegExpShared* shared = RegExpToShared(cx, obj);
6763 : if (!shared)
6764 : return false;
6765 : return shared->getFlags();
6766 0 : }
6767 :
6768 : JS_PUBLIC_API(JSString*)
6769 0 : JS_GetRegExpSource(JSContext* cx, HandleObject obj)
6770 0 : {
6771 : AssertHeapIsIdle();
6772 0 : CHECK_REQUEST(cx);
6773 0 :
6774 0 : RegExpShared* shared = RegExpToShared(cx, obj);
6775 : if (!shared)
6776 : return nullptr;
6777 0 : return shared->getSource();
6778 0 : }
6779 :
6780 : /************************************************************************/
6781 0 :
6782 : JS_PUBLIC_API(bool)
6783 : JS_SetDefaultLocale(JSRuntime* rt, const char* locale)
6784 : {
6785 0 : AssertHeapIsIdle();
6786 : return rt->setDefaultLocale(locale);
6787 : }
6788 0 :
6789 0 : JS_PUBLIC_API(UniqueChars)
6790 : JS_GetDefaultLocale(JSContext* cx)
6791 0 : {
6792 0 : AssertHeapIsIdle();
6793 : if (const char* locale = cx->runtime()->getDefaultLocale())
6794 : return DuplicateString(cx, locale);
6795 0 :
6796 0 : return nullptr;
6797 : }
6798 :
6799 : JS_PUBLIC_API(void)
6800 0 : JS_ResetDefaultLocale(JSRuntime* rt)
6801 : {
6802 0 : AssertHeapIsIdle();
6803 : rt->resetDefaultLocale();
6804 : }
6805 0 :
6806 : JS_PUBLIC_API(void)
6807 : JS_SetLocaleCallbacks(JSRuntime* rt, const JSLocaleCallbacks* callbacks)
6808 0 : {
6809 0 : AssertHeapIsIdle();
6810 : rt->localeCallbacks = callbacks;
6811 : }
6812 :
6813 0 : JS_PUBLIC_API(const JSLocaleCallbacks*)
6814 : JS_GetLocaleCallbacks(JSRuntime* rt)
6815 0 : {
6816 0 : /* This function can be called by a finalizer. */
6817 : return rt->localeCallbacks;
6818 0 : }
6819 0 :
6820 : /************************************************************************/
6821 0 :
6822 : JS_PUBLIC_API(bool)
6823 : JS_IsExceptionPending(JSContext* cx)
6824 : {
6825 0 : /* This function can be called by a finalizer. */
6826 : return (bool) cx->isExceptionPending();
6827 0 : }
6828 0 :
6829 : JS_PUBLIC_API(bool)
6830 0 : JS_GetPendingException(JSContext* cx, MutableHandleValue vp)
6831 0 : {
6832 : AssertHeapIsIdle();
6833 0 : CHECK_REQUEST(cx);
6834 : if (!cx->isExceptionPending())
6835 : return false;
6836 : return cx->getPendingException(vp);
6837 : }
6838 :
6839 4 : JS_PUBLIC_API(void)
6840 : JS_SetPendingException(JSContext* cx, HandleValue value)
6841 4 : {
6842 4 : AssertHeapIsIdle();
6843 : CHECK_REQUEST(cx);
6844 : assertSameCompartment(cx, value);
6845 : cx->setPendingException(value);
6846 0 : }
6847 :
6848 3 : JS_PUBLIC_API(void)
6849 3 : JS_ClearPendingException(JSContext* cx)
6850 0 : {
6851 : AssertHeapIsIdle();
6852 : cx->clearPendingException();
6853 : }
6854 :
6855 : JS::AutoSaveExceptionState::AutoSaveExceptionState(JSContext* cx)
6856 0 : : context(cx),
6857 : wasPropagatingForcedReturn(cx->propagatingForcedReturn_),
6858 0 : wasOverRecursed(cx->overRecursed_),
6859 0 : wasThrowing(cx->throwing),
6860 0 : exceptionValue(cx)
6861 : {
6862 : AssertHeapIsIdle();
6863 0 : CHECK_REQUEST(cx);
6864 : if (wasPropagatingForcedReturn)
6865 1 : cx->clearPropagatingForcedReturn();
6866 2 : if (wasOverRecursed)
6867 0 : cx->overRecursed_ = false;
6868 : if (wasThrowing) {
6869 : exceptionValue = cx->unwrappedException();
6870 0 : cx->clearPendingException();
6871 : }
6872 : }
6873 2 :
6874 : void
6875 : JS::AutoSaveExceptionState::restore()
6876 : {
6877 : context->propagatingForcedReturn_ = wasPropagatingForcedReturn;
6878 : context->overRecursed_ = wasOverRecursed;
6879 103785 : context->throwing = wasThrowing;
6880 : context->unwrappedException() = exceptionValue;
6881 : drop();
6882 103783 : }
6883 :
6884 : JS::AutoSaveExceptionState::~AutoSaveExceptionState()
6885 : {
6886 0 : if (!context->isExceptionPending()) {
6887 : if (wasPropagatingForcedReturn)
6888 4 : context->setPropagatingForcedReturn();
6889 8 : if (wasThrowing) {
6890 0 : context->overRecursed_ = wasOverRecursed;
6891 : context->throwing = true;
6892 0 : context->unwrappedException() = exceptionValue;
6893 : }
6894 : }
6895 : }
6896 0 :
6897 : struct JSExceptionState {
6898 42 : explicit JSExceptionState(JSContext* cx) : exception(cx) {}
6899 84 : bool throwing;
6900 0 : PersistentRootedValue exception;
6901 42 : };
6902 0 :
6903 : JS_PUBLIC_API(JSExceptionState*)
6904 : JS_SaveExceptionState(JSContext* cx)
6905 0 : {
6906 : JSExceptionState* state;
6907 269 :
6908 269 : AssertHeapIsIdle();
6909 0 : CHECK_REQUEST(cx);
6910 : state = cx->new_<JSExceptionState>(cx);
6911 0 : if (state)
6912 : state->throwing = JS_GetPendingException(cx, &state->exception);
6913 : return state;
6914 : }
6915 :
6916 10700 : JS_PUBLIC_API(void)
6917 : JS_RestoreExceptionState(JSContext* cx, JSExceptionState* state)
6918 2140 : {
6919 4280 : AssertHeapIsIdle();
6920 0 : CHECK_REQUEST(cx);
6921 0 : if (state) {
6922 0 : if (state->throwing)
6923 0 : JS_SetPendingException(cx, state->exception);
6924 0 : else
6925 0 : JS_ClearPendingException(cx);
6926 0 : JS_DropExceptionState(cx, state);
6927 : }
6928 0 : }
6929 :
6930 : JS_PUBLIC_API(void)
6931 2140 : JS_DropExceptionState(JSContext* cx, JSExceptionState* state)
6932 : {
6933 4280 : AssertHeapIsIdle();
6934 4280 : CHECK_REQUEST(cx);
6935 0 : js_delete(state);
6936 4280 : }
6937 0 :
6938 0 : JS_PUBLIC_API(JSErrorReport*)
6939 : JS_ErrorFromException(JSContext* cx, HandleObject obj)
6940 0 : {
6941 : AssertHeapIsIdle();
6942 0 : CHECK_REQUEST(cx);
6943 2140 : assertSameCompartment(cx, obj);
6944 0 : return ErrorFromException(cx, obj);
6945 2140 : }
6946 0 :
6947 0 : void
6948 0 : JSErrorReport::initBorrowedLinebuf(const char16_t* linebufArg, size_t linebufLengthArg,
6949 : size_t tokenOffsetArg)
6950 : {
6951 0 : MOZ_ASSERT(linebufArg);
6952 : MOZ_ASSERT(tokenOffsetArg <= linebufLengthArg);
6953 0 : MOZ_ASSERT(linebufArg[linebufLengthArg] == '\0');
6954 0 :
6955 : linebuf_ = linebufArg;
6956 : linebufLength_ = linebufLengthArg;
6957 : tokenOffset_ = tokenOffsetArg;
6958 : }
6959 :
6960 0 : void
6961 : JSErrorReport::freeLinebuf()
6962 : {
6963 : if (ownsLinebuf_ && linebuf_) {
6964 0 : js_free((void*)linebuf_);
6965 0 : ownsLinebuf_ = false;
6966 0 : }
6967 0 : linebuf_ = nullptr;
6968 0 : }
6969 0 :
6970 : JSString*
6971 : JSErrorBase::newMessageString(JSContext* cx)
6972 : {
6973 0 : if (!message_)
6974 : return cx->runtime()->emptyString;
6975 0 :
6976 0 : return JS_NewStringCopyUTF8Z(cx, message_);
6977 0 : }
6978 0 :
6979 0 : void
6980 : JSErrorBase::freeMessage()
6981 : {
6982 0 : if (ownsMessage_) {
6983 : js_free((void*)message_.get());
6984 0 : ownsMessage_ = false;
6985 : }
6986 : message_ = JS::ConstUTF8CharsZ();
6987 0 : }
6988 :
6989 0 : JSErrorNotes::JSErrorNotes()
6990 0 : : notes_()
6991 0 : {}
6992 0 :
6993 : JSErrorNotes::~JSErrorNotes()
6994 : {
6995 1 : }
6996 :
6997 1 : static UniquePtr<JSErrorNotes::Note>
6998 2 : CreateErrorNoteVA(JSContext* cx,
6999 0 : const char* filename, unsigned lineno, unsigned column,
7000 2 : JSErrorCallback errorCallback, void* userRef,
7001 : const unsigned errorNumber,
7002 : ErrorArgumentsType argumentsType, va_list ap)
7003 : {
7004 0 : auto note = MakeUnique<JSErrorNotes::Note>();
7005 : if (!note) {
7006 : ReportOutOfMemory(cx);
7007 0 : return nullptr;
7008 0 : }
7009 0 :
7010 : note->errorNumber = errorNumber;
7011 0 : note->filename = filename;
7012 0 : note->lineno = lineno;
7013 0 : note->column = column;
7014 0 :
7015 : if (!ExpandErrorArgumentsVA(cx, errorCallback, userRef, errorNumber,
7016 : nullptr, argumentsType, note.get(), ap)) {
7017 0 : return nullptr;
7018 : }
7019 23 :
7020 0 : return note;
7021 0 : }
7022 :
7023 0 : bool
7024 0 : JSErrorNotes::addNoteASCII(JSContext* cx,
7025 : const char* filename, unsigned lineno, unsigned column,
7026 : JSErrorCallback errorCallback, void* userRef,
7027 0 : const unsigned errorNumber, ...)
7028 : {
7029 46 : va_list ap;
7030 0 : va_start(ap, errorNumber);
7031 : auto note = CreateErrorNoteVA(cx, filename, lineno, column, errorCallback, userRef,
7032 23 : errorNumber, ArgumentsAreASCII, ap);
7033 : va_end(ap);
7034 :
7035 : if (!note)
7036 0 : return false;
7037 : if (!notes_.append(std::move(note)))
7038 23 : return false;
7039 66 : return true;
7040 0 : }
7041 :
7042 0 : bool
7043 0 : JSErrorNotes::addNoteLatin1(JSContext* cx,
7044 : const char* filename, unsigned lineno, unsigned column,
7045 0 : JSErrorCallback errorCallback, void* userRef,
7046 0 : const unsigned errorNumber, ...)
7047 0 : {
7048 : va_list ap;
7049 0 : va_start(ap, errorNumber);
7050 : auto note = CreateErrorNoteVA(cx, filename, lineno, column, errorCallback, userRef,
7051 0 : errorNumber, ArgumentsAreLatin1, ap);
7052 : va_end(ap);
7053 :
7054 0 : if (!note)
7055 : return false;
7056 : if (!notes_.append(std::move(note)))
7057 : return false;
7058 : return true;
7059 : }
7060 0 :
7061 0 : bool
7062 0 : JSErrorNotes::addNoteUTF8(JSContext* cx,
7063 : const char* filename, unsigned lineno, unsigned column,
7064 : JSErrorCallback errorCallback, void* userRef,
7065 : const unsigned errorNumber, ...)
7066 0 : {
7067 0 : va_list ap;
7068 0 : va_start(ap, errorNumber);
7069 0 : auto note = CreateErrorNoteVA(cx, filename, lineno, column, errorCallback, userRef,
7070 : errorNumber, ArgumentsAreUTF8, ap);
7071 0 : va_end(ap);
7072 :
7073 : if (!note)
7074 : return false;
7075 : if (!notes_.append(std::move(note)))
7076 : return false;
7077 : return true;
7078 : }
7079 :
7080 0 : JS_PUBLIC_API(size_t)
7081 : JSErrorNotes::length()
7082 : {
7083 : return notes_.length();
7084 : }
7085 :
7086 0 : UniquePtr<JSErrorNotes>
7087 : JSErrorNotes::copy(JSContext* cx)
7088 0 : {
7089 0 : auto copiedNotes = MakeUnique<JSErrorNotes>();
7090 : if (!copiedNotes) {
7091 0 : ReportOutOfMemory(cx);
7092 : return nullptr;
7093 0 : }
7094 :
7095 0 : for (auto&& note : *this) {
7096 : UniquePtr<JSErrorNotes::Note> copied = CopyErrorNote(cx, note.get());
7097 : if (!copied)
7098 : return nullptr;
7099 0 :
7100 : if (!copiedNotes->notes_.append(std::move(copied)))
7101 : return nullptr;
7102 : }
7103 :
7104 : return copiedNotes;
7105 0 : }
7106 :
7107 0 : JS_PUBLIC_API(JSErrorNotes::iterator)
7108 0 : JSErrorNotes::begin()
7109 : {
7110 0 : return iterator(notes_.begin());
7111 : }
7112 0 :
7113 : JS_PUBLIC_API(JSErrorNotes::iterator)
7114 0 : JSErrorNotes::end()
7115 : {
7116 : return iterator(notes_.end());
7117 : }
7118 0 :
7119 : extern MOZ_NEVER_INLINE JS_PUBLIC_API(void)
7120 : JS_AbortIfWrongThread(JSContext* cx)
7121 : {
7122 : if (!CurrentThreadCanAccessRuntime(cx->runtime()))
7123 : MOZ_CRASH();
7124 0 : if (TlsContext.get() != cx)
7125 : MOZ_CRASH();
7126 0 : }
7127 0 :
7128 : #ifdef JS_GC_ZEAL
7129 0 : JS_PUBLIC_API(void)
7130 : JS_GetGCZealBits(JSContext* cx, uint32_t* zealBits, uint32_t* frequency, uint32_t* nextScheduled)
7131 0 : {
7132 : cx->runtime()->gc.getZealBits(zealBits, frequency, nextScheduled);
7133 0 : }
7134 :
7135 : JS_PUBLIC_API(void)
7136 : JS_SetGCZeal(JSContext* cx, uint8_t zeal, uint32_t frequency)
7137 0 : {
7138 : cx->runtime()->gc.setZeal(zeal, frequency);
7139 0 : }
7140 :
7141 : JS_PUBLIC_API(void)
7142 : JS_ScheduleGC(JSContext* cx, uint32_t count)
7143 0 : {
7144 : cx->runtime()->gc.setNextScheduled(count);
7145 0 : }
7146 0 : #endif
7147 0 :
7148 : JS_PUBLIC_API(void)
7149 : JS_SetParallelParsingEnabled(JSContext* cx, bool enabled)
7150 : {
7151 0 : cx->runtime()->setParallelParsingEnabled(enabled);
7152 0 : }
7153 0 :
7154 0 : JS_PUBLIC_API(void)
7155 : JS_SetOffthreadIonCompilationEnabled(JSContext* cx, bool enabled)
7156 0 : {
7157 : cx->runtime()->setOffthreadIonCompilationEnabled(enabled);
7158 : }
7159 :
7160 : JS_PUBLIC_API(void)
7161 : JS_SetGlobalJitCompilerOption(JSContext* cx, JSJitCompilerOption opt, uint32_t value)
7162 : {
7163 : JSRuntime* rt = cx->runtime();
7164 0 : switch (opt) {
7165 : case JSJITCOMPILER_BASELINE_WARMUP_TRIGGER:
7166 0 : if (value == uint32_t(-1)) {
7167 : jit::DefaultJitOptions defaultValues;
7168 : value = defaultValues.baselineWarmUpThreshold;
7169 : }
7170 0 : jit::JitOptions.baselineWarmUpThreshold = value;
7171 : break;
7172 0 : case JSJITCOMPILER_ION_WARMUP_TRIGGER:
7173 : if (value == uint32_t(-1)) {
7174 : jit::JitOptions.resetCompilerWarmUpThreshold();
7175 : break;
7176 0 : }
7177 : jit::JitOptions.setCompilerWarmUpThreshold(value);
7178 47 : if (value == 0)
7179 0 : jit::JitOptions.setEagerCompilation();
7180 0 : break;
7181 0 : case JSJITCOMPILER_ION_GVN_ENABLE:
7182 0 : if (value == 0) {
7183 : jit::JitOptions.enableGvn(false);
7184 : JitSpew(js::jit::JitSpew_IonScripts, "Disable ion's GVN");
7185 : } else {
7186 0 : jit::JitOptions.enableGvn(true);
7187 : JitSpew(js::jit::JitSpew_IonScripts, "Enable ion's GVN");
7188 0 : }
7189 0 : break;
7190 : case JSJITCOMPILER_ION_FORCE_IC:
7191 : if (value == 0) {
7192 0 : jit::JitOptions.forceInlineCaches = false;
7193 : JitSpew(js::jit::JitSpew_IonScripts, "IonBuilder: Enable non-IC optimizations.");
7194 6 : } else {
7195 3 : jit::JitOptions.forceInlineCaches = true;
7196 : JitSpew(js::jit::JitSpew_IonScripts, "IonBuilder: Disable non-IC optimizations.");
7197 : }
7198 0 : break;
7199 : case JSJITCOMPILER_ION_CHECK_RANGE_ANALYSIS:
7200 0 : if (value == 0) {
7201 0 : jit::JitOptions.checkRangeAnalysis = false;
7202 : JitSpew(js::jit::JitSpew_IonScripts, "IonBuilder: Enable range analysis checks.");
7203 : } else {
7204 : jit::JitOptions.checkRangeAnalysis = true;
7205 0 : JitSpew(js::jit::JitSpew_IonScripts, "IonBuilder: Disable range analysis checks.");
7206 : }
7207 6 : break;
7208 2 : case JSJITCOMPILER_ION_ENABLE:
7209 : if (value == 1) {
7210 : JS::ContextOptionsRef(cx).setIon(true);
7211 0 : JitSpew(js::jit::JitSpew_IonScripts, "Enable ion");
7212 : } else if (value == 0) {
7213 6 : JS::ContextOptionsRef(cx).setIon(false);
7214 2 : JitSpew(js::jit::JitSpew_IonScripts, "Disable ion");
7215 : }
7216 : break;
7217 0 : case JSJITCOMPILER_BASELINE_ENABLE:
7218 : if (value == 1) {
7219 18 : JS::ContextOptionsRef(cx).setBaseline(true);
7220 18 : ReleaseAllJITCode(rt->defaultFreeOp());
7221 : JitSpew(js::jit::JitSpew_BaselineScripts, "Enable baseline");
7222 2 : } else if (value == 0) {
7223 0 : JS::ContextOptionsRef(cx).setBaseline(false);
7224 0 : ReleaseAllJITCode(rt->defaultFreeOp());
7225 : JitSpew(js::jit::JitSpew_BaselineScripts, "Disable baseline");
7226 0 : }
7227 0 : break;
7228 : case JSJITCOMPILER_OFFTHREAD_COMPILATION_ENABLE:
7229 2 : if (value == 1) {
7230 0 : rt->setOffthreadIonCompilationEnabled(true);
7231 0 : JitSpew(js::jit::JitSpew_IonScripts, "Enable offthread compilation");
7232 : } else if (value == 0) {
7233 0 : rt->setOffthreadIonCompilationEnabled(false);
7234 0 : JitSpew(js::jit::JitSpew_IonScripts, "Disable offthread compilation");
7235 0 : }
7236 : break;
7237 : case JSJITCOMPILER_JUMP_THRESHOLD:
7238 0 : if (value == uint32_t(-1)) {
7239 0 : jit::DefaultJitOptions defaultValues;
7240 0 : value = defaultValues.jumpThreshold;
7241 : }
7242 0 : jit::JitOptions.jumpThreshold = value;
7243 0 : break;
7244 : case JSJITCOMPILER_TRACK_OPTIMIZATIONS:
7245 : jit::JitOptions.disableOptimizationTracking = !value;
7246 : break;
7247 0 : case JSJITCOMPILER_SPECTRE_INDEX_MASKING:
7248 0 : jit::JitOptions.spectreIndexMasking = !!value;
7249 0 : break;
7250 : case JSJITCOMPILER_SPECTRE_OBJECT_MITIGATIONS_BARRIERS:
7251 0 : jit::JitOptions.spectreObjectMitigationsBarriers = !!value;
7252 0 : break;
7253 : case JSJITCOMPILER_SPECTRE_OBJECT_MITIGATIONS_MISC:
7254 : jit::JitOptions.spectreObjectMitigationsMisc = !!value;
7255 : break;
7256 0 : case JSJITCOMPILER_SPECTRE_STRING_MITIGATIONS:
7257 0 : jit::JitOptions.spectreStringMitigations = !!value;
7258 0 : break;
7259 : case JSJITCOMPILER_SPECTRE_VALUE_MASKING:
7260 0 : jit::JitOptions.spectreValueMasking = !!value;
7261 0 : break;
7262 : case JSJITCOMPILER_SPECTRE_JIT_TO_CXX_CALLS:
7263 : jit::JitOptions.spectreJitToCxxCalls = !!value;
7264 : break;
7265 0 : case JSJITCOMPILER_ASMJS_ATOMICS_ENABLE:
7266 0 : jit::JitOptions.asmJSAtomicsEnable = !!value;
7267 0 : break;
7268 0 : case JSJITCOMPILER_WASM_FOLD_OFFSETS:
7269 0 : jit::JitOptions.wasmFoldOffsets = !!value;
7270 0 : break;
7271 : case JSJITCOMPILER_WASM_DELAY_TIER2:
7272 : jit::JitOptions.wasmDelayTier2 = !!value;
7273 : break;
7274 0 : #ifdef DEBUG
7275 0 : case JSJITCOMPILER_FULL_DEBUG_CHECKS:
7276 0 : jit::JitOptions.fullDebugChecks = !!value;
7277 0 : break;
7278 0 : #endif
7279 0 : default:
7280 0 : break;
7281 0 : }
7282 : }
7283 :
7284 : JS_PUBLIC_API(bool)
7285 0 : JS_GetGlobalJitCompilerOption(JSContext* cx, JSJitCompilerOption opt, uint32_t* valueOut)
7286 0 : {
7287 0 : MOZ_ASSERT(valueOut);
7288 0 : #ifndef JS_CODEGEN_NONE
7289 0 : JSRuntime* rt = cx->runtime();
7290 0 : switch (opt) {
7291 : case JSJITCOMPILER_BASELINE_WARMUP_TRIGGER:
7292 : *valueOut = jit::JitOptions.baselineWarmUpThreshold;
7293 : break;
7294 0 : case JSJITCOMPILER_ION_WARMUP_TRIGGER:
7295 0 : *valueOut = jit::JitOptions.forcedDefaultIonWarmUpThreshold
7296 0 : .valueOr(jit::OptimizationInfo::CompilerWarmupThreshold);
7297 : break;
7298 0 : case JSJITCOMPILER_ION_FORCE_IC:
7299 0 : *valueOut = jit::JitOptions.forceInlineCaches;
7300 : break;
7301 0 : case JSJITCOMPILER_ION_CHECK_RANGE_ANALYSIS:
7302 0 : *valueOut = jit::JitOptions.checkRangeAnalysis;
7303 : break;
7304 2 : case JSJITCOMPILER_ION_ENABLE:
7305 0 : *valueOut = JS::ContextOptionsRef(cx).ion();
7306 : break;
7307 2 : case JSJITCOMPILER_BASELINE_ENABLE:
7308 0 : *valueOut = JS::ContextOptionsRef(cx).baseline();
7309 : break;
7310 2 : case JSJITCOMPILER_OFFTHREAD_COMPILATION_ENABLE:
7311 0 : *valueOut = rt->canUseOffthreadIonCompilation();
7312 : break;
7313 2 : case JSJITCOMPILER_ASMJS_ATOMICS_ENABLE:
7314 0 : *valueOut = jit::JitOptions.asmJSAtomicsEnable ? 1 : 0;
7315 : break;
7316 2 : case JSJITCOMPILER_WASM_FOLD_OFFSETS:
7317 0 : *valueOut = jit::JitOptions.wasmFoldOffsets ? 1 : 0;
7318 : break;
7319 2 : #ifdef DEBUG
7320 0 : case JSJITCOMPILER_FULL_DEBUG_CHECKS:
7321 : *valueOut = jit::JitOptions.fullDebugChecks ? 1 : 0;
7322 0 : break;
7323 0 : #endif
7324 : default:
7325 0 : return false;
7326 0 : }
7327 : #else
7328 0 : *valueOut = 0;
7329 0 : #endif
7330 : return true;
7331 : }
7332 0 :
7333 0 : /************************************************************************/
7334 :
7335 : #if !defined(STATIC_EXPORTABLE_JS_API) && !defined(STATIC_JS_API) && defined(XP_WIN)
7336 :
7337 : #include "util/Windows.h"
7338 18 :
7339 : /*
7340 : * Initialization routine for the JS DLL.
7341 0 : */
7342 : BOOL WINAPI DllMain (HINSTANCE hDLL, DWORD dwReason, LPVOID lpReserved)
7343 0 : {
7344 : return TRUE;
7345 0 : }
7346 0 :
7347 : #endif
7348 0 :
7349 0 : JS_PUBLIC_API(bool)
7350 : JS_IndexToId(JSContext* cx, uint32_t index, MutableHandleId id)
7351 0 : {
7352 0 : return IndexToId(cx, index, id);
7353 0 : }
7354 :
7355 0 : JS_PUBLIC_API(bool)
7356 0 : JS_CharsToId(JSContext* cx, JS::TwoByteChars chars, MutableHandleId idp)
7357 : {
7358 0 : RootedAtom atom(cx, AtomizeChars(cx, chars.begin().get(), chars.length()));
7359 0 : if (!atom)
7360 : return false;
7361 0 : #ifdef DEBUG
7362 0 : uint32_t dummy;
7363 : MOZ_ASSERT(!atom->isIndex(&dummy), "API misuse: |chars| must not encode an index");
7364 0 : #endif
7365 0 : idp.set(AtomToId(atom));
7366 : return true;
7367 0 : }
7368 0 :
7369 : JS_PUBLIC_API(bool)
7370 0 : JS_IsIdentifier(JSContext* cx, HandleString str, bool* isIdentifier)
7371 0 : {
7372 : assertSameCompartment(cx, str);
7373 0 :
7374 0 : JSLinearString* linearStr = str->ensureLinear(cx);
7375 : if (!linearStr)
7376 : return false;
7377 0 :
7378 0 : *isIdentifier = js::frontend::IsIdentifier(linearStr);
7379 : return true;
7380 : }
7381 :
7382 : JS_PUBLIC_API(bool)
7383 : JS_IsIdentifier(const char16_t* chars, size_t length)
7384 : {
7385 : return js::frontend::IsIdentifier(chars, length);
7386 : }
7387 :
7388 : namespace JS {
7389 :
7390 : void AutoFilename::reset()
7391 : {
7392 : if (ss_) {
7393 : ss_->decref();
7394 : ss_ = nullptr;
7395 : }
7396 : if (filename_.is<const char*>())
7397 : filename_.as<const char*>() = nullptr;
7398 : else
7399 : filename_.as<UniqueChars>().reset();
7400 : }
7401 :
7402 : void AutoFilename::setScriptSource(js::ScriptSource* p)
7403 : {
7404 : MOZ_ASSERT(!ss_);
7405 : MOZ_ASSERT(!get());
7406 0 : ss_ = p;
7407 : if (p) {
7408 0 : p->incref();
7409 : setUnowned(p->filename());
7410 : }
7411 : }
7412 0 :
7413 : void AutoFilename::setUnowned(const char* filename)
7414 542 : {
7415 271 : MOZ_ASSERT(!get());
7416 : filename_.as<const char*>() = filename ? filename : "";
7417 : }
7418 :
7419 0 : void AutoFilename::setOwned(UniqueChars&& filename)
7420 : {
7421 271 : MOZ_ASSERT(!get());
7422 271 : filename_ = AsVariant(std::move(filename));
7423 : }
7424 :
7425 : const char* AutoFilename::get() const
7426 0 : {
7427 : if (filename_.is<const char*>())
7428 0 : return filename_.as<const char*>();
7429 : return filename_.as<UniqueChars>().get();
7430 0 : }
7431 0 :
7432 : JS_PUBLIC_API(bool)
7433 : DescribeScriptedCaller(JSContext* cx, AutoFilename* filename, unsigned* lineno,
7434 0 : unsigned* column)
7435 0 : {
7436 : if (filename)
7437 : filename->reset();
7438 : if (lineno)
7439 0 : *lineno = 0;
7440 : if (column)
7441 0 : *column = 0;
7442 :
7443 : if (!cx->compartment())
7444 : return false;
7445 :
7446 122 : NonBuiltinFrameIter i(cx, cx->realm()->principals());
7447 : if (i.done())
7448 122 : return false;
7449 61 :
7450 0 : // If the caller is hidden, the embedding wants us to return false here so
7451 : // that it can check its own stack (see HideScriptedCaller).
7452 0 : if (i.activation()->scriptedCallerIsHidden())
7453 0 : return false;
7454 :
7455 0 : if (filename) {
7456 0 : if (i.isWasm()) {
7457 : // For Wasm, copy out the filename, there is no script source.
7458 61 : UniqueChars copy = DuplicateString(i.filename() ? i.filename() : "");
7459 : if (!copy)
7460 0 : filename->setUnowned("out of memory");
7461 61 : else
7462 0 : filename->setOwned(std::move(copy));
7463 61 : } else {
7464 0 : // All other frames have a script source to read the filename from.
7465 0 : filename->setScriptSource(i.scriptSource());
7466 : }
7467 0 : }
7468 :
7469 0 : if (lineno)
7470 : *lineno = i.computeLine(column);
7471 0 : else if (column)
7472 61 : i.computeLine(column);
7473 0 :
7474 : return true;
7475 0 : }
7476 :
7477 0 : // Fast path to get the activation and realm to use for GetScriptedCallerGlobal.
7478 0 : // If this returns false, the fast path didn't work out and the caller has to
7479 0 : // use the (much slower) NonBuiltinFrameIter path.
7480 : //
7481 0 : // The optimization here is that we skip Ion-inlined frames and only look at
7482 : // 'outer' frames. That's fine because Ion doesn't inline cross-realm calls.
7483 0 : // However, GetScriptedCallerGlobal has to skip self-hosted frames and Ion
7484 146 : // can inline self-hosted scripts, so we have to be careful:
7485 0 : //
7486 : // * When we see a non-self-hosted outer script, it's possible we inlined
7487 : // self-hosted scripts into it but that doesn't matter because these scripts
7488 : // all have the same realm/global anyway.
7489 0 : //
7490 : // * When we see a self-hosted outer script, it's possible we inlined
7491 : // non-self-hosted scripts into it, so we have to give up because in this
7492 61 : // case, whether or not to skip the self-hosted frame (to the possibly
7493 0 : // different-realm caller) requires the slow path to handle inlining. Baseline
7494 61 : // and the interpreter don't inline so this only affects Ion.
7495 4 : static bool
7496 0 : GetScriptedCallerActivationRealmFast(JSContext* cx, Activation** activation, Realm** realm)
7497 0 : {
7498 : ActivationIterator activationIter(cx);
7499 0 :
7500 : if (activationIter.done()) {
7501 : *activation = nullptr;
7502 122 : *realm = nullptr;
7503 0 : return true;
7504 : }
7505 :
7506 : if (activationIter->isJit()) {
7507 : jit::JitActivation* act = activationIter->asJit();
7508 61 : JitFrameIter iter(act);
7509 : while (true) {
7510 : iter.skipNonScriptedJSFrames();
7511 61 : if (iter.done())
7512 0 : break;
7513 :
7514 0 : if (!iter.isSelfHostedIgnoringInlining()) {
7515 0 : *activation = act;
7516 0 : *realm = iter.realm();
7517 : return true;
7518 0 : }
7519 :
7520 : if (iter.isJSJit() && iter.asJSJit().isIonScripted()) {
7521 61 : // Ion might have inlined non-self-hosted scripts in this
7522 : // self-hosted script.
7523 : return false;
7524 : }
7525 0 :
7526 4 : ++iter;
7527 57 : }
7528 0 : } else if (activationIter->isInterpreter()) {
7529 : InterpreterActivation* act = activationIter->asInterpreter();
7530 : for (InterpreterFrameIterator iter(act); !iter.done(); ++iter) {
7531 : if (!iter.frame()->script()->selfHosted()) {
7532 : *activation = act;
7533 : *realm = iter.frame()->script()->realm();
7534 : return true;
7535 : }
7536 : }
7537 : }
7538 :
7539 : return false;
7540 : }
7541 :
7542 : JS_PUBLIC_API(JSObject*)
7543 : GetScriptedCallerGlobal(JSContext* cx)
7544 : {
7545 : Activation* activation;
7546 : Realm* realm;
7547 : if (GetScriptedCallerActivationRealmFast(cx, &activation, &realm)) {
7548 : if (!activation)
7549 : return nullptr;
7550 : } else {
7551 : NonBuiltinFrameIter i(cx);
7552 4985 : if (i.done())
7553 : return nullptr;
7554 4985 : activation = i.activation();
7555 : realm = i.realm();
7556 0 : }
7557 1270 :
7558 0 : MOZ_ASSERT(realm->compartment() == activation->compartment());
7559 1270 :
7560 : // If the caller is hidden, the embedding wants us to return null here so
7561 : // that it can check its own stack (see HideScriptedCaller).
7562 0 : if (activation->scriptedCallerIsHidden())
7563 0 : return nullptr;
7564 1149 :
7565 : GlobalObject* global = realm->maybeGlobal();
7566 0 :
7567 0 : // No one should be running code in a realm without any live objects, so
7568 : // there should definitely be a live global.
7569 : MOZ_ASSERT(global);
7570 0 :
7571 0 : return global;
7572 1071 : }
7573 2142 :
7574 : JS_PUBLIC_API(void)
7575 : HideScriptedCaller(JSContext* cx)
7576 0 : {
7577 : MOZ_ASSERT(cx);
7578 :
7579 : // If there's no accessible activation on the stack, we'll return null from
7580 : // DescribeScriptedCaller anyway, so there's no need to annotate anything.
7581 : Activation* act = cx->activation();
7582 109 : if (!act)
7583 : return;
7584 2605 : act->hideScriptedCaller();
7585 2605 : }
7586 0 :
7587 5238 : JS_PUBLIC_API(void)
7588 0 : UnhideScriptedCaller(JSContext* cx)
7589 0 : {
7590 0 : Activation* act = cx->activation();
7591 : if (!act)
7592 : return;
7593 : act->unhideScriptedCaller();
7594 : }
7595 :
7596 : } /* namespace JS */
7597 :
7598 : #ifdef JS_DEBUG
7599 4985 : JS_PUBLIC_API(void)
7600 : JS::detail::AssertArgumentsAreSane(JSContext* cx, HandleValue value)
7601 : {
7602 : AssertHeapIsIdle();
7603 0 : CHECK_REQUEST(cx);
7604 4944 : assertSameCompartment(cx, value);
7605 : }
7606 : #endif /* JS_DEBUG */
7607 0 :
7608 0 : JS_PUBLIC_API(JS::TranscodeResult)
7609 0 : JS::EncodeScript(JSContext* cx, TranscodeBuffer& buffer, HandleScript scriptArg)
7610 41 : {
7611 0 : XDREncoder encoder(cx, buffer, buffer.length());
7612 : RootedScript script(cx, scriptArg);
7613 : XDRResult res = encoder.codeScript(&script);
7614 0 : if (res.isErr()) {
7615 : buffer.clearAndFree();
7616 : return res.unwrapErr();
7617 : }
7618 0 : MOZ_ASSERT(!buffer.empty());
7619 : return JS::TranscodeResult_Ok;
7620 : }
7621 2773 :
7622 : JS_PUBLIC_API(JS::TranscodeResult)
7623 : JS::EncodeInterpretedFunction(JSContext* cx, TranscodeBuffer& buffer, HandleObject funobjArg)
7624 : {
7625 0 : XDREncoder encoder(cx, buffer, buffer.length());
7626 : RootedFunction funobj(cx, &funobjArg->as<JSFunction>());
7627 : XDRResult res = encoder.codeFunction(&funobj);
7628 : if (res.isErr()) {
7629 : buffer.clearAndFree();
7630 : return res.unwrapErr();
7631 11975 : }
7632 : MOZ_ASSERT(!buffer.empty());
7633 11975 : return JS::TranscodeResult_Ok;
7634 : }
7635 :
7636 : JS_PUBLIC_API(JS::TranscodeResult)
7637 0 : JS::DecodeScript(JSContext* cx, TranscodeBuffer& buffer, JS::MutableHandleScript scriptp,
7638 11975 : size_t cursorIndex)
7639 : {
7640 : XDRDecoder decoder(cx, buffer, cursorIndex);
7641 : XDRResult res = decoder.codeScript(scriptp);
7642 : MOZ_ASSERT(bool(scriptp) == res.isOk());
7643 : if (res.isErr())
7644 11972 : return res.unwrapErr();
7645 : return JS::TranscodeResult_Ok;
7646 11972 : }
7647 11972 :
7648 : JS_PUBLIC_API(JS::TranscodeResult)
7649 5982 : JS::DecodeScript(JSContext* cx, const TranscodeRange& range, JS::MutableHandleScript scriptp)
7650 : {
7651 : XDRDecoder decoder(cx, range);
7652 : XDRResult res = decoder.codeScript(scriptp);
7653 : MOZ_ASSERT(bool(scriptp) == res.isOk());
7654 : if (res.isErr())
7655 : return res.unwrapErr();
7656 54807 : return JS::TranscodeResult_Ok;
7657 : }
7658 54807 :
7659 109612 : JS_PUBLIC_API(JS::TranscodeResult)
7660 0 : JS::DecodeInterpretedFunction(JSContext* cx, TranscodeBuffer& buffer,
7661 54806 : JS::MutableHandleFunction funp,
7662 : size_t cursorIndex)
7663 : {
7664 : XDRDecoder decoder(cx, buffer, cursorIndex);
7665 0 : XDRResult res = decoder.codeFunction(funp);
7666 : MOZ_ASSERT(bool(funp) == res.isOk());
7667 1470 : if (res.isErr())
7668 980 : return res.unwrapErr();
7669 0 : return JS::TranscodeResult_Ok;
7670 490 : }
7671 0 :
7672 0 : JS_PUBLIC_API(bool)
7673 : JS::StartIncrementalEncoding(JSContext* cx, JS::HandleScript script)
7674 0 : {
7675 : if (!script)
7676 : return false;
7677 : if (!script->scriptSource()->xdrEncodeTopLevel(cx, script))
7678 : return false;
7679 783 : return true;
7680 : }
7681 2349 :
7682 1566 : JS_PUBLIC_API(bool)
7683 0 : JS::FinishIncrementalEncoding(JSContext* cx, JS::HandleScript script, TranscodeBuffer& buffer)
7684 783 : {
7685 0 : if (!script)
7686 0 : return false;
7687 : if (!script->scriptSource()->xdrFinalizeEncoder(buffer))
7688 0 : return false;
7689 : return true;
7690 : }
7691 :
7692 : JS_PUBLIC_API(void)
7693 0 : JS::SetBuildIdOp(JSContext* cx, JS::BuildIdOp buildIdOp)
7694 : {
7695 : cx->runtime()->buildIdOp = buildIdOp;
7696 0 : }
7697 0 :
7698 0 : JS_PUBLIC_API(void)
7699 0 : JS::SetAsmJSCacheOps(JSContext* cx, const JS::AsmJSCacheOps* ops)
7700 0 : {
7701 : cx->runtime()->asmJSCacheOps = *ops;
7702 : }
7703 :
7704 : bool
7705 0 : JS::IsWasmModuleObject(HandleObject obj)
7706 : {
7707 0 : JSObject* unwrapped = CheckedUnwrap(obj);
7708 0 : if (!unwrapped)
7709 0 : return false;
7710 0 : return unwrapped->is<WasmModuleObject>();
7711 0 : }
7712 :
7713 : JS_PUBLIC_API(RefPtr<JS::WasmModule>)
7714 : JS::GetWasmModule(HandleObject obj)
7715 : {
7716 0 : MOZ_ASSERT(JS::IsWasmModuleObject(obj));
7717 : return &CheckedUnwrap(obj)->as<WasmModuleObject>().module();
7718 : }
7719 :
7720 0 : JS_PUBLIC_API(bool)
7721 0 : JS::CompiledWasmModuleAssumptionsMatch(PRFileDesc* compiled, JS::BuildIdCharVector&& buildId)
7722 0 : {
7723 0 : return wasm::CompiledModuleAssumptionsMatch(compiled, std::move(buildId));
7724 0 : }
7725 :
7726 : JS_PUBLIC_API(RefPtr<JS::WasmModule>)
7727 : JS::DeserializeWasmModule(PRFileDesc* bytecode, PRFileDesc* maybeCompiled,
7728 : JS::BuildIdCharVector&& buildId, UniqueChars file,
7729 0 : unsigned line)
7730 : {
7731 0 : return wasm::DeserializeModule(bytecode, maybeCompiled, std::move(buildId), std::move(file), line);
7732 : }
7733 0 :
7734 : JS_PUBLIC_API(void)
7735 0 : JS::SetProcessLargeAllocationFailureCallback(JS::LargeAllocationFailureCallback lafc)
7736 : {
7737 : MOZ_ASSERT(!OnLargeAllocationFailure);
7738 : OnLargeAllocationFailure = lafc;
7739 0 : }
7740 :
7741 0 : JS_PUBLIC_API(void)
7742 : JS::SetOutOfMemoryCallback(JSContext* cx, OutOfMemoryCallback cb, void* data)
7743 0 : {
7744 : cx->runtime()->oomCallback = cb;
7745 0 : cx->runtime()->oomCallbackData = data;
7746 : }
7747 :
7748 : JS::FirstSubsumedFrame::FirstSubsumedFrame(JSContext* cx,
7749 0 : bool ignoreSelfHostedFrames /* = true */)
7750 : : JS::FirstSubsumedFrame(cx, cx->realm()->principals(), ignoreSelfHostedFrames)
7751 8 : { }
7752 4 :
7753 : JS_PUBLIC_API(bool)
7754 : JS::CaptureCurrentStack(JSContext* cx, JS::MutableHandleObject stackp,
7755 0 : JS::StackCapture&& capture /* = JS::StackCapture(JS::AllFrames()) */)
7756 : {
7757 8 : AssertHeapIsIdle();
7758 4 : CHECK_REQUEST(cx);
7759 : MOZ_RELEASE_ASSERT(cx->realm());
7760 :
7761 0 : Realm* realm = cx->realm();
7762 : Rooted<SavedFrame*> frame(cx);
7763 0 : if (!realm->savedStacks().saveCurrentStack(cx, &frame, std::move(capture)))
7764 0 : return false;
7765 : stackp.set(frame.get());
7766 0 : return true;
7767 : }
7768 :
7769 : JS_PUBLIC_API(bool)
7770 0 : JS::CopyAsyncStack(JSContext* cx, JS::HandleObject asyncStack,
7771 : JS::HandleString asyncCause, JS::MutableHandleObject stackp,
7772 0 : const Maybe<size_t>& maxFrameCount)
7773 0 : {
7774 : AssertHeapIsIdle();
7775 : CHECK_REQUEST(cx);
7776 : MOZ_RELEASE_ASSERT(cx->realm());
7777 0 :
7778 : js::AssertObjectIsSavedFrameOrWrapper(cx, asyncStack);
7779 0 : Realm* realm = cx->realm();
7780 : Rooted<SavedFrame*> frame(cx);
7781 : if (!realm->savedStacks().copyAsyncStack(cx, asyncStack, asyncCause, &frame, maxFrameCount))
7782 : return false;
7783 0 : stackp.set(frame.get());
7784 : return true;
7785 : }
7786 :
7787 0 : JS_PUBLIC_API(Zone*)
7788 : JS::GetObjectZone(JSObject* obj)
7789 : {
7790 : return obj->zone();
7791 0 : }
7792 :
7793 1 : JS_PUBLIC_API(Zone*)
7794 1 : JS::GetNurseryStringZone(JSString* str)
7795 0 : {
7796 : MOZ_ASSERT(!str->isTenured());
7797 : return str->zone();
7798 0 : }
7799 :
7800 8 : JS_PUBLIC_API(JS::TraceKind)
7801 8 : JS::GCThingTraceKind(void* thing)
7802 0 : {
7803 : MOZ_ASSERT(thing);
7804 0 : return static_cast<js::gc::Cell*>(thing)->getTraceKind();
7805 0 : }
7806 0 :
7807 0 : JS_PUBLIC_API(void)
7808 : js::SetStackFormat(JSContext* cx, js::StackFormat format)
7809 : {
7810 0 : cx->runtime()->setStackFormat(format);
7811 : }
7812 :
7813 9276 : JS_PUBLIC_API(js::StackFormat)
7814 0 : js::GetStackFormat(JSContext* cx)
7815 18552 : {
7816 : return cx->runtime()->stackFormat();
7817 0 : }
7818 0 :
7819 0 : namespace js {
7820 :
7821 0 : JS_PUBLIC_API(void)
7822 0 : NoteIntentionalCrash()
7823 : {
7824 : #ifdef __linux__
7825 : static bool* addr = reinterpret_cast<bool*>(dlsym(RTLD_DEFAULT, "gBreakpadInjectorEnabled"));
7826 0 : if (addr)
7827 : *addr = false;
7828 : #endif
7829 : }
7830 0 :
7831 0 : } // namespace js
|