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