1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: set ts=8 sts=2 et sw=2 tw=80:
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 #include "vm/SelfHosting.h"
8
9 #include "mozilla/BinarySearch.h"
10 #include "mozilla/Casting.h"
11 #include "mozilla/DebugOnly.h"
12 #include "mozilla/Maybe.h"
13 #include "mozilla/ScopeExit.h" // mozilla::MakeScopeExit
14 #include "mozilla/Utf8.h" // mozilla::Utf8Unit
15
16 #include <algorithm>
17 #include <iterator>
18
19 #include "jsdate.h"
20 #include "jsfriendapi.h"
21 #include "jsmath.h"
22 #include "jsnum.h"
23 #include "selfhosted.out.h"
24
25 #include "builtin/Array.h"
26 #include "builtin/BigInt.h"
27 #ifdef JS_HAS_INTL_API
28 # include "builtin/intl/Collator.h"
29 # include "builtin/intl/DateTimeFormat.h"
30 # include "builtin/intl/DisplayNames.h"
31 # include "builtin/intl/IntlObject.h"
32 # include "builtin/intl/ListFormat.h"
33 # include "builtin/intl/Locale.h"
34 # include "builtin/intl/NumberFormat.h"
35 # include "builtin/intl/PluralRules.h"
36 # include "builtin/intl/RelativeTimeFormat.h"
37 #endif
38 #include "builtin/MapObject.h"
39 #include "builtin/ModuleObject.h"
40 #include "builtin/Object.h"
41 #include "builtin/Promise.h"
42 #include "builtin/Reflect.h"
43 #include "builtin/RegExp.h"
44 #include "builtin/SelfHostingDefines.h"
45 #include "builtin/String.h"
46 #include "builtin/Symbol.h"
47 #ifdef ENABLE_RECORD_TUPLE
48 # include "builtin/TupleObject.h"
49 #endif
50 #include "builtin/WeakMapObject.h"
51 #include "frontend/BytecodeCompilation.h" // CompileGlobalScriptToStencil
52 #include "frontend/CompilationStencil.h" // js::frontend::CompilationStencil
53 #include "gc/Marking.h"
54 #include "gc/Policy.h"
55 #include "jit/AtomicOperations.h"
56 #include "jit/InlinableNatives.h"
57 #include "js/CallAndConstruct.h" // JS::Construct, JS::IsCallable, JS::IsConstructor
58 #include "js/CharacterEncoding.h"
59 #include "js/CompilationAndEvaluation.h"
60 #include "js/Conversions.h"
61 #include "js/Date.h"
62 #include "js/ErrorReport.h" // JS::PrintError
63 #include "js/Exception.h"
64 #include "js/experimental/JSStencil.h" // RefPtrTraits<JS::Stencil>
65 #include "js/experimental/TypedData.h" // JS_GetArrayBufferViewType
66 #include "js/friend/ErrorMessages.h" // js::GetErrorMessage, JSMSG_*
67 #include "js/Modules.h" // JS::GetModulePrivate
68 #include "js/PropertyAndElement.h" // JS_DefineProperty, JS_DefinePropertyById
69 #include "js/PropertySpec.h"
70 #include "js/ScalarType.h" // js::Scalar::Type
71 #include "js/SourceText.h" // JS::SourceText
72 #include "js/StableStringChars.h"
73 #include "js/Transcoding.h"
74 #include "js/Warnings.h" // JS::{,Set}WarningReporter
75 #include "js/Wrapper.h"
76 #include "util/StringBuffer.h"
77 #include "vm/ArgumentsObject.h"
78 #include "vm/AsyncFunction.h"
79 #include "vm/AsyncIteration.h"
80 #include "vm/BigIntType.h"
81 #include "vm/BytecodeIterator.h"
82 #include "vm/BytecodeLocation.h"
83 #include "vm/Compression.h"
84 #include "vm/DateObject.h"
85 #include "vm/ErrorReporting.h" // js::MaybePrintAndClearPendingException
86 #include "vm/FrameIter.h" // js::ScriptFrameIter
87 #include "vm/FunctionFlags.h" // js::FunctionFlags
88 #include "vm/GeneratorObject.h"
89 #include "vm/Interpreter.h"
90 #include "vm/Iteration.h"
91 #include "vm/JSContext.h"
92 #include "vm/JSFunction.h"
93 #include "vm/JSObject.h"
94 #include "vm/PIC.h"
95 #include "vm/PlainObject.h" // js::PlainObject
96 #include "vm/Printer.h"
97 #include "vm/Realm.h"
98 #include "vm/RegExpObject.h"
99 #include "vm/StringType.h"
100 #include "vm/ToSource.h" // js::ValueToSource
101 #include "vm/TypedArrayObject.h"
102 #include "vm/Uint8Clamped.h"
103 #include "vm/WrapperObject.h"
104
105 #include "gc/GC-inl.h"
106 #include "vm/BooleanObject-inl.h"
107 #include "vm/BytecodeIterator-inl.h"
108 #include "vm/BytecodeLocation-inl.h"
109 #include "vm/Compartment-inl.h"
110 #include "vm/JSAtom-inl.h"
111 #include "vm/JSFunction-inl.h"
112 #include "vm/JSObject-inl.h"
113 #include "vm/JSScript-inl.h"
114 #include "vm/NativeObject-inl.h"
115 #include "vm/NumberObject-inl.h"
116 #include "vm/StringObject-inl.h"
117 #include "vm/TypedArrayObject-inl.h"
118
119 using namespace js;
120 using namespace js::selfhosted;
121
122 using JS::AutoCheckCannotGC;
123 using JS::AutoStableStringChars;
124 using JS::CompileOptions;
125 using mozilla::Maybe;
126
selfHosting_WarningReporter(JSContext * cx,JSErrorReport * report)127 static void selfHosting_WarningReporter(JSContext* cx, JSErrorReport* report) {
128 MOZ_ASSERT(report->isWarning());
129
130 JS::PrintError(stderr, report, true);
131 }
132
intrinsic_ToObject(JSContext * cx,unsigned argc,Value * vp)133 static bool intrinsic_ToObject(JSContext* cx, unsigned argc, Value* vp) {
134 CallArgs args = CallArgsFromVp(argc, vp);
135 JSObject* obj = ToObject(cx, args[0]);
136 if (!obj) {
137 return false;
138 }
139 args.rval().setObject(*obj);
140 return true;
141 }
142
143 #ifdef ENABLE_RECORD_TUPLE
144
intrinsic_ThisTupleValue(JSContext * cx,unsigned argc,Value * vp)145 bool intrinsic_ThisTupleValue(JSContext* cx, unsigned argc, Value* vp) {
146 CallArgs args = CallArgsFromVp(argc, vp);
147 MOZ_ASSERT(args.length() == 1);
148 mozilla::Maybe<TupleType&> result = js::ThisTupleValue(cx, args[0]);
149 if (!result) {
150 return false;
151 }
152 args.rval().setExtendedPrimitive(*result);
153 return true;
154 }
155
intrinsic_TupleLength(JSContext * cx,unsigned argc,Value * vp)156 bool intrinsic_TupleLength(JSContext* cx, unsigned argc, Value* vp) {
157 CallArgs args = CallArgsFromVp(argc, vp);
158 MOZ_ASSERT(args.length() == 1);
159 mozilla::Maybe<TupleType&> result = js::ThisTupleValue(cx, args[0]);
160 if (!result) {
161 return false;
162 }
163 args.rval().setInt32((*result).getDenseInitializedLength());
164 return true;
165 }
166 #endif
167
intrinsic_IsObject(JSContext * cx,unsigned argc,Value * vp)168 static bool intrinsic_IsObject(JSContext* cx, unsigned argc, Value* vp) {
169 CallArgs args = CallArgsFromVp(argc, vp);
170 Value val = args[0];
171 bool isObject = val.isObject();
172 args.rval().setBoolean(isObject);
173 return true;
174 }
175
intrinsic_IsArray(JSContext * cx,unsigned argc,Value * vp)176 static bool intrinsic_IsArray(JSContext* cx, unsigned argc, Value* vp) {
177 CallArgs args = CallArgsFromVp(argc, vp);
178 MOZ_ASSERT(args.length() == 1);
179 RootedValue val(cx, args[0]);
180 if (val.isObject()) {
181 RootedObject obj(cx, &val.toObject());
182 bool isArray = false;
183 if (!IsArray(cx, obj, &isArray)) {
184 return false;
185 }
186 args.rval().setBoolean(isArray);
187 } else {
188 args.rval().setBoolean(false);
189 }
190 return true;
191 }
192
193 #ifdef ENABLE_RECORD_TUPLE
194 // returns true for TupleTypes and TupleObjects
IsTupleUnchecked(JSContext * cx,const CallArgs & args)195 bool js::IsTupleUnchecked(JSContext* cx, const CallArgs& args) {
196 args.rval().setBoolean(IsTuple(args.get(0)));
197 return true;
198 }
199
200 /* Identical to Tuple.prototype.isTuple, but with an
201 * added check that args.length() is 1
202 */
intrinsic_IsTuple(JSContext * cx,unsigned argc,JS::Value * vp)203 bool js::intrinsic_IsTuple(JSContext* cx, unsigned argc, JS::Value* vp) {
204 CallArgs args = CallArgsFromVp(argc, vp);
205 MOZ_ASSERT(args.length() == 1);
206 return js::IsTupleUnchecked(cx, args);
207 }
208 #endif
209
intrinsic_IsCrossRealmArrayConstructor(JSContext * cx,unsigned argc,Value * vp)210 static bool intrinsic_IsCrossRealmArrayConstructor(JSContext* cx, unsigned argc,
211 Value* vp) {
212 CallArgs args = CallArgsFromVp(argc, vp);
213 MOZ_ASSERT(args.length() == 1);
214 MOZ_ASSERT(args[0].isObject());
215
216 bool result = false;
217 if (!IsCrossRealmArrayConstructor(cx, &args[0].toObject(), &result)) {
218 return false;
219 }
220 args.rval().setBoolean(result);
221 return true;
222 }
223
intrinsic_ToLength(JSContext * cx,unsigned argc,Value * vp)224 static bool intrinsic_ToLength(JSContext* cx, unsigned argc, Value* vp) {
225 CallArgs args = CallArgsFromVp(argc, vp);
226 MOZ_ASSERT(args.length() == 1);
227
228 // Inline fast path for the common case.
229 if (args[0].isInt32()) {
230 int32_t i = args[0].toInt32();
231 args.rval().setInt32(i < 0 ? 0 : i);
232 return true;
233 }
234
235 uint64_t length = 0;
236 if (!ToLength(cx, args[0], &length)) {
237 return false;
238 }
239
240 args.rval().setNumber(double(length));
241 return true;
242 }
243
intrinsic_ToInteger(JSContext * cx,unsigned argc,Value * vp)244 static bool intrinsic_ToInteger(JSContext* cx, unsigned argc, Value* vp) {
245 CallArgs args = CallArgsFromVp(argc, vp);
246 double result;
247 if (!ToInteger(cx, args[0], &result)) {
248 return false;
249 }
250 args.rval().setNumber(result);
251 return true;
252 }
253
intrinsic_ToSource(JSContext * cx,unsigned argc,Value * vp)254 static bool intrinsic_ToSource(JSContext* cx, unsigned argc, Value* vp) {
255 CallArgs args = CallArgsFromVp(argc, vp);
256 JSString* str = ValueToSource(cx, args[0]);
257 if (!str) {
258 return false;
259 }
260 args.rval().setString(str);
261 return true;
262 }
263
intrinsic_ToPropertyKey(JSContext * cx,unsigned argc,Value * vp)264 static bool intrinsic_ToPropertyKey(JSContext* cx, unsigned argc, Value* vp) {
265 CallArgs args = CallArgsFromVp(argc, vp);
266 RootedId id(cx);
267 if (!ToPropertyKey(cx, args[0], &id)) {
268 return false;
269 }
270
271 args.rval().set(IdToValue(id));
272 return true;
273 }
274
intrinsic_IsCallable(JSContext * cx,unsigned argc,Value * vp)275 static bool intrinsic_IsCallable(JSContext* cx, unsigned argc, Value* vp) {
276 CallArgs args = CallArgsFromVp(argc, vp);
277 args.rval().setBoolean(IsCallable(args[0]));
278 return true;
279 }
280
intrinsic_IsConstructor(JSContext * cx,unsigned argc,Value * vp)281 static bool intrinsic_IsConstructor(JSContext* cx, unsigned argc, Value* vp) {
282 CallArgs args = CallArgsFromVp(argc, vp);
283 MOZ_ASSERT(args.length() == 1);
284 args.rval().setBoolean(IsConstructor(args[0]));
285 return true;
286 }
287
288 template <typename T>
intrinsic_IsInstanceOfBuiltin(JSContext * cx,unsigned argc,Value * vp)289 static bool intrinsic_IsInstanceOfBuiltin(JSContext* cx, unsigned argc,
290 Value* vp) {
291 CallArgs args = CallArgsFromVp(argc, vp);
292 MOZ_ASSERT(args.length() == 1);
293 MOZ_ASSERT(args[0].isObject());
294
295 args.rval().setBoolean(args[0].toObject().is<T>());
296 return true;
297 }
298
299 template <typename T>
intrinsic_GuardToBuiltin(JSContext * cx,unsigned argc,Value * vp)300 static bool intrinsic_GuardToBuiltin(JSContext* cx, unsigned argc, Value* vp) {
301 CallArgs args = CallArgsFromVp(argc, vp);
302 MOZ_ASSERT(args.length() == 1);
303 MOZ_ASSERT(args[0].isObject());
304
305 if (args[0].toObject().is<T>()) {
306 args.rval().setObject(args[0].toObject());
307 return true;
308 }
309 args.rval().setNull();
310 return true;
311 }
312
313 template <typename T>
intrinsic_IsWrappedInstanceOfBuiltin(JSContext * cx,unsigned argc,Value * vp)314 static bool intrinsic_IsWrappedInstanceOfBuiltin(JSContext* cx, unsigned argc,
315 Value* vp) {
316 CallArgs args = CallArgsFromVp(argc, vp);
317 MOZ_ASSERT(args.length() == 1);
318 MOZ_ASSERT(args[0].isObject());
319
320 JSObject* obj = &args[0].toObject();
321 if (!obj->is<WrapperObject>()) {
322 args.rval().setBoolean(false);
323 return true;
324 }
325
326 JSObject* unwrapped = CheckedUnwrapDynamic(obj, cx);
327 if (!unwrapped) {
328 ReportAccessDenied(cx);
329 return false;
330 }
331
332 args.rval().setBoolean(unwrapped->is<T>());
333 return true;
334 }
335
336 template <typename T>
intrinsic_IsPossiblyWrappedInstanceOfBuiltin(JSContext * cx,unsigned argc,Value * vp)337 static bool intrinsic_IsPossiblyWrappedInstanceOfBuiltin(JSContext* cx,
338 unsigned argc,
339 Value* vp) {
340 CallArgs args = CallArgsFromVp(argc, vp);
341 MOZ_ASSERT(args.length() == 1);
342 MOZ_ASSERT(args[0].isObject());
343
344 JSObject* obj = CheckedUnwrapDynamic(&args[0].toObject(), cx);
345 if (!obj) {
346 ReportAccessDenied(cx);
347 return false;
348 }
349
350 args.rval().setBoolean(obj->is<T>());
351 return true;
352 }
353
intrinsic_SubstringKernel(JSContext * cx,unsigned argc,Value * vp)354 static bool intrinsic_SubstringKernel(JSContext* cx, unsigned argc, Value* vp) {
355 CallArgs args = CallArgsFromVp(argc, vp);
356 MOZ_ASSERT(args[0].isString());
357 MOZ_RELEASE_ASSERT(args[1].isInt32());
358 MOZ_RELEASE_ASSERT(args[2].isInt32());
359
360 RootedString str(cx, args[0].toString());
361 int32_t begin = args[1].toInt32();
362 int32_t length = args[2].toInt32();
363
364 JSString* substr = SubstringKernel(cx, str, begin, length);
365 if (!substr) {
366 return false;
367 }
368
369 args.rval().setString(substr);
370 return true;
371 }
372
ThrowErrorWithType(JSContext * cx,JSExnType type,const CallArgs & args)373 static void ThrowErrorWithType(JSContext* cx, JSExnType type,
374 const CallArgs& args) {
375 MOZ_RELEASE_ASSERT(args[0].isInt32());
376 uint32_t errorNumber = args[0].toInt32();
377
378 #ifdef DEBUG
379 const JSErrorFormatString* efs = GetErrorMessage(nullptr, errorNumber);
380 MOZ_ASSERT(efs->argCount == args.length() - 1);
381 MOZ_ASSERT(efs->exnType == type,
382 "error-throwing intrinsic and error number are inconsistent");
383 #endif
384
385 UniqueChars errorArgs[3];
386 for (unsigned i = 1; i < 4 && i < args.length(); i++) {
387 HandleValue val = args[i];
388 if (val.isInt32() || val.isString()) {
389 JSString* str = ToString<CanGC>(cx, val);
390 if (!str) {
391 return;
392 }
393 errorArgs[i - 1] = QuoteString(cx, str);
394 } else {
395 errorArgs[i - 1] =
396 DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, val, nullptr);
397 }
398 if (!errorArgs[i - 1]) {
399 return;
400 }
401 }
402
403 JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, errorNumber,
404 errorArgs[0].get(), errorArgs[1].get(),
405 errorArgs[2].get());
406 }
407
intrinsic_ThrowRangeError(JSContext * cx,unsigned argc,Value * vp)408 static bool intrinsic_ThrowRangeError(JSContext* cx, unsigned argc, Value* vp) {
409 CallArgs args = CallArgsFromVp(argc, vp);
410 MOZ_ASSERT(args.length() >= 1);
411
412 ThrowErrorWithType(cx, JSEXN_RANGEERR, args);
413 return false;
414 }
415
intrinsic_ThrowTypeError(JSContext * cx,unsigned argc,Value * vp)416 static bool intrinsic_ThrowTypeError(JSContext* cx, unsigned argc, Value* vp) {
417 CallArgs args = CallArgsFromVp(argc, vp);
418 MOZ_ASSERT(args.length() >= 1);
419
420 ThrowErrorWithType(cx, JSEXN_TYPEERR, args);
421 return false;
422 }
423
intrinsic_ThrowSyntaxError(JSContext * cx,unsigned argc,Value * vp)424 static bool intrinsic_ThrowSyntaxError(JSContext* cx, unsigned argc,
425 Value* vp) {
426 CallArgs args = CallArgsFromVp(argc, vp);
427 MOZ_ASSERT(args.length() >= 1);
428
429 ThrowErrorWithType(cx, JSEXN_SYNTAXERR, args);
430 return false;
431 }
432
intrinsic_ThrowAggregateError(JSContext * cx,unsigned argc,Value * vp)433 static bool intrinsic_ThrowAggregateError(JSContext* cx, unsigned argc,
434 Value* vp) {
435 CallArgs args = CallArgsFromVp(argc, vp);
436 MOZ_ASSERT(args.length() >= 1);
437
438 ThrowErrorWithType(cx, JSEXN_AGGREGATEERR, args);
439 return false;
440 }
441
intrinsic_ThrowInternalError(JSContext * cx,unsigned argc,Value * vp)442 static bool intrinsic_ThrowInternalError(JSContext* cx, unsigned argc,
443 Value* vp) {
444 CallArgs args = CallArgsFromVp(argc, vp);
445 MOZ_ASSERT(args.length() >= 1);
446
447 ThrowErrorWithType(cx, JSEXN_INTERNALERR, args);
448 return false;
449 }
450
intrinsic_GetErrorMessage(JSContext * cx,unsigned argc,Value * vp)451 static bool intrinsic_GetErrorMessage(JSContext* cx, unsigned argc, Value* vp) {
452 CallArgs args = CallArgsFromVp(argc, vp);
453 MOZ_ASSERT(args.length() == 1);
454 MOZ_RELEASE_ASSERT(args[0].isInt32());
455
456 const JSErrorFormatString* errorString =
457 GetErrorMessage(nullptr, args[0].toInt32());
458 MOZ_ASSERT(errorString);
459
460 MOZ_ASSERT(errorString->argCount == 0);
461 RootedString message(cx, JS_NewStringCopyZ(cx, errorString->format));
462 if (!message) {
463 return false;
464 }
465
466 args.rval().setString(message);
467 return true;
468 }
469
intrinsic_CreateModuleSyntaxError(JSContext * cx,unsigned argc,Value * vp)470 static bool intrinsic_CreateModuleSyntaxError(JSContext* cx, unsigned argc,
471 Value* vp) {
472 CallArgs args = CallArgsFromVp(argc, vp);
473 MOZ_ASSERT(args.length() == 4);
474 MOZ_ASSERT(args[0].isObject());
475 MOZ_RELEASE_ASSERT(args[1].isInt32());
476 MOZ_RELEASE_ASSERT(args[2].isInt32());
477 MOZ_ASSERT(args[3].isString());
478
479 RootedModuleObject module(cx, &args[0].toObject().as<ModuleObject>());
480 RootedString filename(cx,
481 JS_NewStringCopyZ(cx, module->script()->filename()));
482 if (!filename) {
483 return false;
484 }
485
486 RootedString message(cx, args[3].toString());
487
488 RootedValue error(cx);
489 if (!JS::CreateError(cx, JSEXN_SYNTAXERR, nullptr, filename,
490 args[1].toInt32(), args[2].toInt32(), nullptr, message,
491 JS::NothingHandleValue, &error)) {
492 return false;
493 }
494
495 args.rval().set(error);
496 return true;
497 }
498
499 /**
500 * Handles an assertion failure in self-hosted code just like an assertion
501 * failure in C++ code. Information about the failure can be provided in
502 * args[0].
503 */
intrinsic_AssertionFailed(JSContext * cx,unsigned argc,Value * vp)504 static bool intrinsic_AssertionFailed(JSContext* cx, unsigned argc, Value* vp) {
505 #ifdef DEBUG
506 CallArgs args = CallArgsFromVp(argc, vp);
507 if (args.length() > 0) {
508 // try to dump the informative string
509 JSString* str = ToString<CanGC>(cx, args[0]);
510 if (str) {
511 js::Fprinter out(stderr);
512 out.put("Self-hosted JavaScript assertion info: ");
513 str->dumpCharsNoNewline(out);
514 out.putChar('\n');
515 }
516 }
517 #endif
518 MOZ_ASSERT(false);
519 return false;
520 }
521
522 /**
523 * Dumps a message to stderr, after stringifying it. Doesn't append a newline.
524 */
intrinsic_DumpMessage(JSContext * cx,unsigned argc,Value * vp)525 static bool intrinsic_DumpMessage(JSContext* cx, unsigned argc, Value* vp) {
526 CallArgs args = CallArgsFromVp(argc, vp);
527 #ifdef DEBUG
528 if (args.length() > 0) {
529 // try to dump the informative string
530 js::Fprinter out(stderr);
531 JSString* str = ToString<CanGC>(cx, args[0]);
532 if (str) {
533 str->dumpCharsNoNewline(out);
534 out.putChar('\n');
535 } else {
536 cx->recoverFromOutOfMemory();
537 }
538 }
539 #endif
540 args.rval().setUndefined();
541 return true;
542 }
543
intrinsic_FinishBoundFunctionInit(JSContext * cx,unsigned argc,Value * vp)544 static bool intrinsic_FinishBoundFunctionInit(JSContext* cx, unsigned argc,
545 Value* vp) {
546 CallArgs args = CallArgsFromVp(argc, vp);
547 MOZ_ASSERT(args.length() == 3);
548 MOZ_ASSERT(IsCallable(args[1]));
549 MOZ_RELEASE_ASSERT(args[2].isInt32());
550
551 RootedFunction bound(cx, &args[0].toObject().as<JSFunction>());
552 RootedObject targetObj(cx, &args[1].toObject());
553 int32_t argCount = args[2].toInt32();
554
555 args.rval().setUndefined();
556 return JSFunction::finishBoundFunctionInit(cx, bound, targetObj, argCount);
557 }
558
559 /*
560 * Used to decompile values in the nearest non-builtin stack frame, falling
561 * back to decompiling in the current frame. Helpful for printing higher-order
562 * function arguments.
563 *
564 * The user must supply the argument number of the value in question; it
565 * _cannot_ be automatically determined.
566 */
intrinsic_DecompileArg(JSContext * cx,unsigned argc,Value * vp)567 static bool intrinsic_DecompileArg(JSContext* cx, unsigned argc, Value* vp) {
568 CallArgs args = CallArgsFromVp(argc, vp);
569 MOZ_ASSERT(args.length() == 2);
570 MOZ_RELEASE_ASSERT(args[0].isInt32());
571
572 HandleValue value = args[1];
573 JSString* str = DecompileArgument(cx, args[0].toInt32(), value);
574 if (!str) {
575 return false;
576 }
577 args.rval().setString(str);
578 return true;
579 }
580
intrinsic_DefineDataProperty(JSContext * cx,unsigned argc,Value * vp)581 static bool intrinsic_DefineDataProperty(JSContext* cx, unsigned argc,
582 Value* vp) {
583 CallArgs args = CallArgsFromVp(argc, vp);
584
585 // When DefineDataProperty is called with 3 arguments, it's compiled to
586 // JSOp::InitElem in the bytecode emitter so we shouldn't get here.
587 MOZ_ASSERT(args.length() == 4);
588 MOZ_ASSERT(args[0].isObject());
589 MOZ_RELEASE_ASSERT(args[3].isInt32());
590
591 RootedObject obj(cx, &args[0].toObject());
592 RootedId id(cx);
593 if (!ToPropertyKey(cx, args[1], &id)) {
594 return false;
595 }
596 RootedValue value(cx, args[2]);
597
598 JS::PropertyAttributes attrs;
599 unsigned attributes = args[3].toInt32();
600
601 MOZ_ASSERT(bool(attributes & ATTR_ENUMERABLE) !=
602 bool(attributes & ATTR_NONENUMERABLE),
603 "DefineDataProperty must receive either ATTR_ENUMERABLE xor "
604 "ATTR_NONENUMERABLE");
605 if (attributes & ATTR_ENUMERABLE) {
606 attrs += JS::PropertyAttribute::Enumerable;
607 }
608
609 MOZ_ASSERT(bool(attributes & ATTR_CONFIGURABLE) !=
610 bool(attributes & ATTR_NONCONFIGURABLE),
611 "DefineDataProperty must receive either ATTR_CONFIGURABLE xor "
612 "ATTR_NONCONFIGURABLE");
613 if (attributes & ATTR_CONFIGURABLE) {
614 attrs += JS::PropertyAttribute::Configurable;
615 }
616
617 MOZ_ASSERT(
618 bool(attributes & ATTR_WRITABLE) != bool(attributes & ATTR_NONWRITABLE),
619 "DefineDataProperty must receive either ATTR_WRITABLE xor "
620 "ATTR_NONWRITABLE");
621 if (attributes & ATTR_WRITABLE) {
622 attrs += JS::PropertyAttribute::Writable;
623 }
624
625 Rooted<PropertyDescriptor> desc(cx, PropertyDescriptor::Data(value, attrs));
626 if (!DefineProperty(cx, obj, id, desc)) {
627 return false;
628 }
629
630 args.rval().setUndefined();
631 return true;
632 }
633
intrinsic_DefineProperty(JSContext * cx,unsigned argc,Value * vp)634 static bool intrinsic_DefineProperty(JSContext* cx, unsigned argc, Value* vp) {
635 // _DefineProperty(object, propertyKey, attributes,
636 // valueOrGetter, setter, strict)
637 CallArgs args = CallArgsFromVp(argc, vp);
638 MOZ_ASSERT(args.length() == 6);
639 MOZ_ASSERT(args[0].isObject());
640 MOZ_ASSERT(args[1].isString() || args[1].isNumber() || args[1].isSymbol());
641 MOZ_RELEASE_ASSERT(args[2].isInt32());
642 MOZ_ASSERT(args[5].isBoolean());
643
644 RootedObject obj(cx, &args[0].toObject());
645 RootedId id(cx);
646 if (!PrimitiveValueToId<CanGC>(cx, args[1], &id)) {
647 return false;
648 }
649
650 Rooted<PropertyDescriptor> desc(cx, PropertyDescriptor::Empty());
651
652 unsigned attributes = args[2].toInt32();
653 if (attributes & (ATTR_ENUMERABLE | ATTR_NONENUMERABLE)) {
654 desc.setEnumerable(attributes & ATTR_ENUMERABLE);
655 }
656
657 if (attributes & (ATTR_CONFIGURABLE | ATTR_NONCONFIGURABLE)) {
658 desc.setConfigurable(attributes & ATTR_CONFIGURABLE);
659 }
660
661 if (attributes & (ATTR_WRITABLE | ATTR_NONWRITABLE)) {
662 desc.setWritable(attributes & ATTR_WRITABLE);
663 }
664
665 // When args[4] is |null|, the data descriptor has a value component.
666 if ((attributes & DATA_DESCRIPTOR_KIND) && args[4].isNull()) {
667 desc.setValue(args[3]);
668 }
669
670 if (attributes & ACCESSOR_DESCRIPTOR_KIND) {
671 Value getter = args[3];
672 if (getter.isObject()) {
673 desc.setGetter(&getter.toObject());
674 } else if (getter.isUndefined()) {
675 desc.setGetter(nullptr);
676 } else {
677 MOZ_ASSERT(getter.isNull());
678 }
679
680 Value setter = args[4];
681 if (setter.isObject()) {
682 desc.setSetter(&setter.toObject());
683 } else if (setter.isUndefined()) {
684 desc.setSetter(nullptr);
685 } else {
686 MOZ_ASSERT(setter.isNull());
687 }
688 }
689
690 desc.assertValid();
691
692 ObjectOpResult result;
693 if (!DefineProperty(cx, obj, id, desc, result)) {
694 return false;
695 }
696
697 bool strict = args[5].toBoolean();
698 if (strict && !result.ok()) {
699 // We need to tell our caller Object.defineProperty,
700 // that this operation failed, without actually throwing
701 // for web-compatibility reasons.
702 if (result.failureCode() == JSMSG_CANT_DEFINE_WINDOW_NC) {
703 args.rval().setBoolean(false);
704 return true;
705 }
706
707 return result.reportError(cx, obj, id);
708 }
709
710 args.rval().setBoolean(result.ok());
711 return true;
712 }
713
intrinsic_ObjectHasPrototype(JSContext * cx,unsigned argc,Value * vp)714 static bool intrinsic_ObjectHasPrototype(JSContext* cx, unsigned argc,
715 Value* vp) {
716 CallArgs args = CallArgsFromVp(argc, vp);
717 MOZ_ASSERT(args.length() == 2);
718
719 // Self-hosted code calls this intrinsic with builtin prototypes. These are
720 // always native objects.
721 auto* obj = &args[0].toObject().as<NativeObject>();
722 auto* proto = &args[1].toObject().as<NativeObject>();
723
724 JSObject* actualProto = obj->staticPrototype();
725 args.rval().setBoolean(actualProto == proto);
726 return true;
727 }
728
intrinsic_UnsafeSetReservedSlot(JSContext * cx,unsigned argc,Value * vp)729 static bool intrinsic_UnsafeSetReservedSlot(JSContext* cx, unsigned argc,
730 Value* vp) {
731 CallArgs args = CallArgsFromVp(argc, vp);
732 MOZ_ASSERT(args.length() == 3);
733 MOZ_ASSERT(args[0].isObject());
734 MOZ_RELEASE_ASSERT(args[1].isInt32());
735 MOZ_ASSERT(args[1].toInt32() >= 0);
736
737 uint32_t slot = uint32_t(args[1].toInt32());
738 args[0].toObject().as<NativeObject>().setReservedSlot(slot, args[2]);
739 args.rval().setUndefined();
740 return true;
741 }
742
intrinsic_UnsafeGetReservedSlot(JSContext * cx,unsigned argc,Value * vp)743 static bool intrinsic_UnsafeGetReservedSlot(JSContext* cx, unsigned argc,
744 Value* vp) {
745 CallArgs args = CallArgsFromVp(argc, vp);
746 MOZ_ASSERT(args.length() == 2);
747 MOZ_ASSERT(args[0].isObject());
748 MOZ_RELEASE_ASSERT(args[1].isInt32());
749 MOZ_ASSERT(args[1].toInt32() >= 0);
750
751 uint32_t slot = uint32_t(args[1].toInt32());
752 args.rval().set(args[0].toObject().as<NativeObject>().getReservedSlot(slot));
753 return true;
754 }
755
intrinsic_UnsafeGetObjectFromReservedSlot(JSContext * cx,unsigned argc,Value * vp)756 static bool intrinsic_UnsafeGetObjectFromReservedSlot(JSContext* cx,
757 unsigned argc,
758 Value* vp) {
759 if (!intrinsic_UnsafeGetReservedSlot(cx, argc, vp)) {
760 return false;
761 }
762 MOZ_ASSERT(vp->isObject());
763 return true;
764 }
765
intrinsic_UnsafeGetInt32FromReservedSlot(JSContext * cx,unsigned argc,Value * vp)766 static bool intrinsic_UnsafeGetInt32FromReservedSlot(JSContext* cx,
767 unsigned argc, Value* vp) {
768 if (!intrinsic_UnsafeGetReservedSlot(cx, argc, vp)) {
769 return false;
770 }
771 MOZ_ASSERT(vp->isInt32());
772 return true;
773 }
774
intrinsic_UnsafeGetStringFromReservedSlot(JSContext * cx,unsigned argc,Value * vp)775 static bool intrinsic_UnsafeGetStringFromReservedSlot(JSContext* cx,
776 unsigned argc,
777 Value* vp) {
778 if (!intrinsic_UnsafeGetReservedSlot(cx, argc, vp)) {
779 return false;
780 }
781 MOZ_ASSERT(vp->isString());
782 return true;
783 }
784
intrinsic_UnsafeGetBooleanFromReservedSlot(JSContext * cx,unsigned argc,Value * vp)785 static bool intrinsic_UnsafeGetBooleanFromReservedSlot(JSContext* cx,
786 unsigned argc,
787 Value* vp) {
788 if (!intrinsic_UnsafeGetReservedSlot(cx, argc, vp)) {
789 return false;
790 }
791 MOZ_ASSERT(vp->isBoolean());
792 return true;
793 }
794
intrinsic_ThisTimeValue(JSContext * cx,unsigned argc,Value * vp)795 static bool intrinsic_ThisTimeValue(JSContext* cx, unsigned argc, Value* vp) {
796 CallArgs args = CallArgsFromVp(argc, vp);
797 MOZ_ASSERT(args.length() == 1);
798 MOZ_ASSERT(args[0].isInt32());
799
800 const char* name = nullptr;
801
802 int32_t method = args[0].toInt32();
803 if (method == DATE_METHOD_LOCALE_TIME_STRING) {
804 name = "toLocaleTimeString";
805 } else if (method == DATE_METHOD_LOCALE_DATE_STRING) {
806 name = "toLocaleDateString";
807 } else {
808 MOZ_ASSERT(method == DATE_METHOD_LOCALE_STRING);
809 name = "toLocaleString";
810 }
811
812 auto* unwrapped = UnwrapAndTypeCheckThis<DateObject>(cx, args, name);
813 if (!unwrapped) {
814 return false;
815 }
816
817 args.rval().set(unwrapped->UTCTime());
818 return true;
819 }
820
intrinsic_IsPackedArray(JSContext * cx,unsigned argc,Value * vp)821 static bool intrinsic_IsPackedArray(JSContext* cx, unsigned argc, Value* vp) {
822 CallArgs args = CallArgsFromVp(argc, vp);
823 MOZ_ASSERT(args.length() == 1);
824 MOZ_ASSERT(args[0].hasObjectPayload());
825 args.rval().setBoolean(
826 (args[0].isObject() && IsPackedArray(&args[0].toObject())) ||
827 IF_RECORD_TUPLE(IsTuple(args[0]), false));
828 return true;
829 }
830
intrinsic_NewArrayIterator(JSContext * cx,unsigned argc,Value * vp)831 bool js::intrinsic_NewArrayIterator(JSContext* cx, unsigned argc, Value* vp) {
832 CallArgs args = CallArgsFromVp(argc, vp);
833 MOZ_ASSERT(args.length() == 0);
834
835 JSObject* obj = NewArrayIterator(cx);
836 if (!obj) {
837 return false;
838 }
839
840 args.rval().setObject(*obj);
841 return true;
842 }
843
intrinsic_ArrayIteratorPrototypeOptimizable(JSContext * cx,unsigned argc,Value * vp)844 static bool intrinsic_ArrayIteratorPrototypeOptimizable(JSContext* cx,
845 unsigned argc,
846 Value* vp) {
847 CallArgs args = CallArgsFromVp(argc, vp);
848 MOZ_ASSERT(args.length() == 0);
849
850 ForOfPIC::Chain* stubChain = ForOfPIC::getOrCreate(cx);
851 if (!stubChain) {
852 return false;
853 }
854
855 bool optimized;
856 if (!stubChain->tryOptimizeArrayIteratorNext(cx, &optimized)) {
857 return false;
858 }
859 args.rval().setBoolean(optimized);
860 return true;
861 }
862
intrinsic_GetNextMapEntryForIterator(JSContext * cx,unsigned argc,Value * vp)863 static bool intrinsic_GetNextMapEntryForIterator(JSContext* cx, unsigned argc,
864 Value* vp) {
865 CallArgs args = CallArgsFromVp(argc, vp);
866 MOZ_ASSERT(args.length() == 2);
867 MOZ_ASSERT(args[0].toObject().is<MapIteratorObject>());
868 MOZ_ASSERT(args[1].isObject());
869
870 MapIteratorObject* mapIterator = &args[0].toObject().as<MapIteratorObject>();
871 ArrayObject* result = &args[1].toObject().as<ArrayObject>();
872
873 args.rval().setBoolean(MapIteratorObject::next(mapIterator, result));
874 return true;
875 }
876
intrinsic_CreateMapIterationResultPair(JSContext * cx,unsigned argc,Value * vp)877 static bool intrinsic_CreateMapIterationResultPair(JSContext* cx, unsigned argc,
878 Value* vp) {
879 CallArgs args = CallArgsFromVp(argc, vp);
880 MOZ_ASSERT(args.length() == 0);
881
882 JSObject* result = MapIteratorObject::createResultPair(cx);
883 if (!result) {
884 return false;
885 }
886
887 args.rval().setObject(*result);
888 return true;
889 }
890
intrinsic_GetNextSetEntryForIterator(JSContext * cx,unsigned argc,Value * vp)891 static bool intrinsic_GetNextSetEntryForIterator(JSContext* cx, unsigned argc,
892 Value* vp) {
893 CallArgs args = CallArgsFromVp(argc, vp);
894 MOZ_ASSERT(args.length() == 2);
895 MOZ_ASSERT(args[0].toObject().is<SetIteratorObject>());
896 MOZ_ASSERT(args[1].isObject());
897
898 SetIteratorObject* setIterator = &args[0].toObject().as<SetIteratorObject>();
899 ArrayObject* result = &args[1].toObject().as<ArrayObject>();
900
901 args.rval().setBoolean(SetIteratorObject::next(setIterator, result));
902 return true;
903 }
904
intrinsic_CreateSetIterationResult(JSContext * cx,unsigned argc,Value * vp)905 static bool intrinsic_CreateSetIterationResult(JSContext* cx, unsigned argc,
906 Value* vp) {
907 CallArgs args = CallArgsFromVp(argc, vp);
908 MOZ_ASSERT(args.length() == 0);
909
910 JSObject* result = SetIteratorObject::createResult(cx);
911 if (!result) {
912 return false;
913 }
914
915 args.rval().setObject(*result);
916 return true;
917 }
918
intrinsic_NewStringIterator(JSContext * cx,unsigned argc,Value * vp)919 bool js::intrinsic_NewStringIterator(JSContext* cx, unsigned argc, Value* vp) {
920 CallArgs args = CallArgsFromVp(argc, vp);
921 MOZ_ASSERT(args.length() == 0);
922
923 JSObject* obj = NewStringIterator(cx);
924 if (!obj) {
925 return false;
926 }
927
928 args.rval().setObject(*obj);
929 return true;
930 }
931
intrinsic_NewRegExpStringIterator(JSContext * cx,unsigned argc,Value * vp)932 bool js::intrinsic_NewRegExpStringIterator(JSContext* cx, unsigned argc,
933 Value* vp) {
934 CallArgs args = CallArgsFromVp(argc, vp);
935 MOZ_ASSERT(args.length() == 0);
936
937 JSObject* obj = NewRegExpStringIterator(cx);
938 if (!obj) {
939 return false;
940 }
941
942 args.rval().setObject(*obj);
943 return true;
944 }
945
GetClonedSelfHostedFunctionName(const JSFunction * fun)946 js::PropertyName* js::GetClonedSelfHostedFunctionName(const JSFunction* fun) {
947 if (!fun->isExtended()) {
948 return nullptr;
949 }
950 Value name = fun->getExtendedSlot(LAZY_FUNCTION_NAME_SLOT);
951 if (!name.isString()) {
952 return nullptr;
953 }
954 return name.toString()->asAtom().asPropertyName();
955 }
956
IsExtendedUnclonedSelfHostedFunctionName(JSAtom * name)957 bool js::IsExtendedUnclonedSelfHostedFunctionName(JSAtom* name) {
958 if (name->length() < 2) {
959 return false;
960 }
961 return name->latin1OrTwoByteChar(0) ==
962 ExtendedUnclonedSelfHostedFunctionNamePrefix;
963 }
964
SetClonedSelfHostedFunctionName(JSFunction * fun,js::PropertyName * name)965 void js::SetClonedSelfHostedFunctionName(JSFunction* fun,
966 js::PropertyName* name) {
967 fun->setExtendedSlot(LAZY_FUNCTION_NAME_SLOT, StringValue(name));
968 }
969
intrinsic_GeneratorObjectIsClosed(JSContext * cx,unsigned argc,Value * vp)970 static bool intrinsic_GeneratorObjectIsClosed(JSContext* cx, unsigned argc,
971 Value* vp) {
972 CallArgs args = CallArgsFromVp(argc, vp);
973 MOZ_ASSERT(args.length() == 1);
974 MOZ_ASSERT(args[0].isObject());
975
976 GeneratorObject* genObj = &args[0].toObject().as<GeneratorObject>();
977 args.rval().setBoolean(genObj->isClosed());
978 return true;
979 }
980
intrinsic_IsSuspendedGenerator(JSContext * cx,unsigned argc,Value * vp)981 static bool intrinsic_IsSuspendedGenerator(JSContext* cx, unsigned argc,
982 Value* vp) {
983 CallArgs args = CallArgsFromVp(argc, vp);
984 MOZ_ASSERT(args.length() == 1);
985
986 if (!args[0].isObject() || !args[0].toObject().is<GeneratorObject>()) {
987 args.rval().setBoolean(false);
988 return true;
989 }
990
991 GeneratorObject& genObj = args[0].toObject().as<GeneratorObject>();
992 args.rval().setBoolean(!genObj.isClosed() && genObj.isSuspended());
993 return true;
994 }
995
intrinsic_GeneratorIsRunning(JSContext * cx,unsigned argc,Value * vp)996 static bool intrinsic_GeneratorIsRunning(JSContext* cx, unsigned argc,
997 Value* vp) {
998 CallArgs args = CallArgsFromVp(argc, vp);
999 MOZ_ASSERT(args.length() == 1);
1000 MOZ_ASSERT(args[0].isObject());
1001
1002 GeneratorObject* genObj = &args[0].toObject().as<GeneratorObject>();
1003 args.rval().setBoolean(genObj->isRunning());
1004 return true;
1005 }
1006
intrinsic_GeneratorSetClosed(JSContext * cx,unsigned argc,Value * vp)1007 static bool intrinsic_GeneratorSetClosed(JSContext* cx, unsigned argc,
1008 Value* vp) {
1009 CallArgs args = CallArgsFromVp(argc, vp);
1010 MOZ_ASSERT(args.length() == 1);
1011 MOZ_ASSERT(args[0].isObject());
1012
1013 GeneratorObject* genObj = &args[0].toObject().as<GeneratorObject>();
1014 genObj->setClosed();
1015 return true;
1016 }
1017
1018 template <typename T>
intrinsic_ArrayBufferByteLength(JSContext * cx,unsigned argc,Value * vp)1019 static bool intrinsic_ArrayBufferByteLength(JSContext* cx, unsigned argc,
1020 Value* vp) {
1021 CallArgs args = CallArgsFromVp(argc, vp);
1022 MOZ_ASSERT(args.length() == 1);
1023 MOZ_ASSERT(args[0].isObject());
1024 MOZ_ASSERT(args[0].toObject().is<T>());
1025
1026 size_t byteLength = args[0].toObject().as<T>().byteLength();
1027 args.rval().setNumber(byteLength);
1028 return true;
1029 }
1030
1031 template <typename T>
intrinsic_PossiblyWrappedArrayBufferByteLength(JSContext * cx,unsigned argc,Value * vp)1032 static bool intrinsic_PossiblyWrappedArrayBufferByteLength(JSContext* cx,
1033 unsigned argc,
1034 Value* vp) {
1035 CallArgs args = CallArgsFromVp(argc, vp);
1036 MOZ_ASSERT(args.length() == 1);
1037
1038 T* obj = args[0].toObject().maybeUnwrapAs<T>();
1039 if (!obj) {
1040 ReportAccessDenied(cx);
1041 return false;
1042 }
1043
1044 size_t byteLength = obj->byteLength();
1045 args.rval().setNumber(byteLength);
1046 return true;
1047 }
1048
AssertNonNegativeInteger(const Value & v)1049 static void AssertNonNegativeInteger(const Value& v) {
1050 MOZ_ASSERT(v.isNumber());
1051 MOZ_ASSERT(v.toNumber() >= 0);
1052 MOZ_ASSERT(v.toNumber() < DOUBLE_INTEGRAL_PRECISION_LIMIT);
1053 MOZ_ASSERT(JS::ToInteger(v.toNumber()) == v.toNumber());
1054 }
1055
1056 template <typename T>
intrinsic_ArrayBufferCopyData(JSContext * cx,unsigned argc,Value * vp)1057 static bool intrinsic_ArrayBufferCopyData(JSContext* cx, unsigned argc,
1058 Value* vp) {
1059 CallArgs args = CallArgsFromVp(argc, vp);
1060 MOZ_ASSERT(args.length() == 6);
1061 AssertNonNegativeInteger(args[1]);
1062 AssertNonNegativeInteger(args[3]);
1063 AssertNonNegativeInteger(args[4]);
1064
1065 bool isWrapped = args[5].toBoolean();
1066 Rooted<T*> toBuffer(cx);
1067 if (!isWrapped) {
1068 toBuffer = &args[0].toObject().as<T>();
1069 } else {
1070 JSObject* wrapped = &args[0].toObject();
1071 MOZ_ASSERT(wrapped->is<WrapperObject>());
1072 toBuffer = wrapped->maybeUnwrapAs<T>();
1073 if (!toBuffer) {
1074 ReportAccessDenied(cx);
1075 return false;
1076 }
1077 }
1078 size_t toIndex = size_t(args[1].toNumber());
1079 Rooted<T*> fromBuffer(cx, &args[2].toObject().as<T>());
1080 size_t fromIndex = size_t(args[3].toNumber());
1081 size_t count = size_t(args[4].toNumber());
1082
1083 T::copyData(toBuffer, toIndex, fromBuffer, fromIndex, count);
1084
1085 args.rval().setUndefined();
1086 return true;
1087 }
1088
1089 // Arguments must both be SharedArrayBuffer or wrapped SharedArrayBuffer.
intrinsic_SharedArrayBuffersMemorySame(JSContext * cx,unsigned argc,Value * vp)1090 static bool intrinsic_SharedArrayBuffersMemorySame(JSContext* cx, unsigned argc,
1091 Value* vp) {
1092 CallArgs args = CallArgsFromVp(argc, vp);
1093 MOZ_ASSERT(args.length() == 2);
1094
1095 auto* lhs = args[0].toObject().maybeUnwrapAs<SharedArrayBufferObject>();
1096 if (!lhs) {
1097 ReportAccessDenied(cx);
1098 return false;
1099 }
1100 auto* rhs = args[1].toObject().maybeUnwrapAs<SharedArrayBufferObject>();
1101 if (!rhs) {
1102 ReportAccessDenied(cx);
1103 return false;
1104 }
1105
1106 args.rval().setBoolean(lhs->rawBufferObject() == rhs->rawBufferObject());
1107 return true;
1108 }
1109
intrinsic_GetTypedArrayKind(JSContext * cx,unsigned argc,Value * vp)1110 static bool intrinsic_GetTypedArrayKind(JSContext* cx, unsigned argc,
1111 Value* vp) {
1112 CallArgs args = CallArgsFromVp(argc, vp);
1113 MOZ_ASSERT(args.length() == 1);
1114 MOZ_ASSERT(args[0].isObject());
1115
1116 static_assert(TYPEDARRAY_KIND_INT8 == Scalar::Type::Int8,
1117 "TYPEDARRAY_KIND_INT8 doesn't match the scalar type");
1118 static_assert(TYPEDARRAY_KIND_UINT8 == Scalar::Type::Uint8,
1119 "TYPEDARRAY_KIND_UINT8 doesn't match the scalar type");
1120 static_assert(TYPEDARRAY_KIND_INT16 == Scalar::Type::Int16,
1121 "TYPEDARRAY_KIND_INT16 doesn't match the scalar type");
1122 static_assert(TYPEDARRAY_KIND_UINT16 == Scalar::Type::Uint16,
1123 "TYPEDARRAY_KIND_UINT16 doesn't match the scalar type");
1124 static_assert(TYPEDARRAY_KIND_INT32 == Scalar::Type::Int32,
1125 "TYPEDARRAY_KIND_INT32 doesn't match the scalar type");
1126 static_assert(TYPEDARRAY_KIND_UINT32 == Scalar::Type::Uint32,
1127 "TYPEDARRAY_KIND_UINT32 doesn't match the scalar type");
1128 static_assert(TYPEDARRAY_KIND_FLOAT32 == Scalar::Type::Float32,
1129 "TYPEDARRAY_KIND_FLOAT32 doesn't match the scalar type");
1130 static_assert(TYPEDARRAY_KIND_FLOAT64 == Scalar::Type::Float64,
1131 "TYPEDARRAY_KIND_FLOAT64 doesn't match the scalar type");
1132 static_assert(TYPEDARRAY_KIND_UINT8CLAMPED == Scalar::Type::Uint8Clamped,
1133 "TYPEDARRAY_KIND_UINT8CLAMPED doesn't match the scalar type");
1134 static_assert(TYPEDARRAY_KIND_BIGINT64 == Scalar::Type::BigInt64,
1135 "TYPEDARRAY_KIND_BIGINT64 doesn't match the scalar type");
1136 static_assert(TYPEDARRAY_KIND_BIGUINT64 == Scalar::Type::BigUint64,
1137 "TYPEDARRAY_KIND_BIGUINT64 doesn't match the scalar type");
1138
1139 JSObject* obj = &args[0].toObject();
1140 Scalar::Type type = JS_GetArrayBufferViewType(obj);
1141
1142 args.rval().setInt32(static_cast<int32_t>(type));
1143 return true;
1144 }
1145
intrinsic_IsTypedArrayConstructor(JSContext * cx,unsigned argc,Value * vp)1146 static bool intrinsic_IsTypedArrayConstructor(JSContext* cx, unsigned argc,
1147 Value* vp) {
1148 CallArgs args = CallArgsFromVp(argc, vp);
1149 MOZ_ASSERT(args.length() == 1);
1150 MOZ_ASSERT(args[0].isObject());
1151
1152 args.rval().setBoolean(js::IsTypedArrayConstructor(&args[0].toObject()));
1153 return true;
1154 }
1155
intrinsic_TypedArrayBuffer(JSContext * cx,unsigned argc,Value * vp)1156 static bool intrinsic_TypedArrayBuffer(JSContext* cx, unsigned argc,
1157 Value* vp) {
1158 CallArgs args = CallArgsFromVp(argc, vp);
1159 MOZ_ASSERT(args.length() == 1);
1160 MOZ_ASSERT(TypedArrayObject::is(args[0]));
1161
1162 Rooted<TypedArrayObject*> tarray(cx,
1163 &args[0].toObject().as<TypedArrayObject>());
1164 if (!TypedArrayObject::ensureHasBuffer(cx, tarray)) {
1165 return false;
1166 }
1167
1168 args.rval().set(tarray->bufferValue());
1169 return true;
1170 }
1171
intrinsic_TypedArrayByteOffset(JSContext * cx,unsigned argc,Value * vp)1172 static bool intrinsic_TypedArrayByteOffset(JSContext* cx, unsigned argc,
1173 Value* vp) {
1174 CallArgs args = CallArgsFromVp(argc, vp);
1175 MOZ_ASSERT(args.length() == 1);
1176 MOZ_ASSERT(TypedArrayObject::is(args[0]));
1177
1178 auto* tarr = &args[0].toObject().as<TypedArrayObject>();
1179 args.rval().set(tarr->byteOffsetValue());
1180 return true;
1181 }
1182
intrinsic_TypedArrayElementSize(JSContext * cx,unsigned argc,Value * vp)1183 static bool intrinsic_TypedArrayElementSize(JSContext* cx, unsigned argc,
1184 Value* vp) {
1185 CallArgs args = CallArgsFromVp(argc, vp);
1186 MOZ_ASSERT(args.length() == 1);
1187 MOZ_ASSERT(TypedArrayObject::is(args[0]));
1188
1189 unsigned size =
1190 TypedArrayElemSize(args[0].toObject().as<TypedArrayObject>().type());
1191 MOZ_ASSERT(size == 1 || size == 2 || size == 4 || size == 8);
1192
1193 args.rval().setInt32(mozilla::AssertedCast<int32_t>(size));
1194 return true;
1195 }
1196
1197 // Return the value of [[ArrayLength]] internal slot of the TypedArray
intrinsic_TypedArrayLength(JSContext * cx,unsigned argc,Value * vp)1198 static bool intrinsic_TypedArrayLength(JSContext* cx, unsigned argc,
1199 Value* vp) {
1200 CallArgs args = CallArgsFromVp(argc, vp);
1201 MOZ_ASSERT(args.length() == 1);
1202 MOZ_ASSERT(TypedArrayObject::is(args[0]));
1203
1204 auto* tarr = &args[0].toObject().as<TypedArrayObject>();
1205 args.rval().set(tarr->lengthValue());
1206 return true;
1207 }
1208
intrinsic_PossiblyWrappedTypedArrayLength(JSContext * cx,unsigned argc,Value * vp)1209 static bool intrinsic_PossiblyWrappedTypedArrayLength(JSContext* cx,
1210 unsigned argc,
1211 Value* vp) {
1212 CallArgs args = CallArgsFromVp(argc, vp);
1213 MOZ_ASSERT(args.length() == 1);
1214 MOZ_ASSERT(args[0].isObject());
1215
1216 TypedArrayObject* obj = args[0].toObject().maybeUnwrapAs<TypedArrayObject>();
1217 if (!obj) {
1218 ReportAccessDenied(cx);
1219 return false;
1220 }
1221
1222 args.rval().set(obj->lengthValue());
1223 return true;
1224 }
1225
intrinsic_PossiblyWrappedTypedArrayHasDetachedBuffer(JSContext * cx,unsigned argc,Value * vp)1226 static bool intrinsic_PossiblyWrappedTypedArrayHasDetachedBuffer(JSContext* cx,
1227 unsigned argc,
1228 Value* vp) {
1229 CallArgs args = CallArgsFromVp(argc, vp);
1230 MOZ_ASSERT(args.length() == 1);
1231 MOZ_ASSERT(args[0].isObject());
1232
1233 TypedArrayObject* obj = args[0].toObject().maybeUnwrapAs<TypedArrayObject>();
1234 if (!obj) {
1235 ReportAccessDenied(cx);
1236 return false;
1237 }
1238
1239 bool detached = obj->hasDetachedBuffer();
1240 args.rval().setBoolean(detached);
1241 return true;
1242 }
1243
1244 // Extract the TypedArrayObject* underlying |obj| and return it. This method,
1245 // in a TOTALLY UNSAFE manner, completely violates the normal compartment
1246 // boundaries, returning an object not necessarily in the current compartment
1247 // or in |obj|'s compartment.
1248 //
1249 // All callers of this method are expected to sigil this TypedArrayObject*, and
1250 // all values and information derived from it, with an "unsafe" prefix, to
1251 // indicate the extreme caution required when dealing with such values.
1252 //
1253 // If calling code discipline ever fails to be maintained, it's gonna have a
1254 // bad time.
DangerouslyUnwrapTypedArray(JSContext * cx,JSObject * obj)1255 static TypedArrayObject* DangerouslyUnwrapTypedArray(JSContext* cx,
1256 JSObject* obj) {
1257 // An unwrapped pointer to an object potentially on the other side of a
1258 // compartment boundary! Isn't this such fun?
1259 TypedArrayObject* unwrapped = obj->maybeUnwrapAs<TypedArrayObject>();
1260 if (!unwrapped) {
1261 ReportAccessDenied(cx);
1262 return nullptr;
1263 }
1264
1265 // Be super-duper careful using this, as we've just punched through
1266 // the compartment boundary, and things like buffer() on this aren't
1267 // same-compartment with anything else in the calling method.
1268 return unwrapped;
1269 }
1270
1271 // The specification requires us to perform bitwise copying when |sourceType|
1272 // and |targetType| are the same (ES2017, §22.2.3.24, step 15). Additionally,
1273 // as an optimization, we can also perform bitwise copying when |sourceType|
1274 // and |targetType| have compatible bit-level representations.
IsTypedArrayBitwiseSlice(Scalar::Type sourceType,Scalar::Type targetType)1275 static bool IsTypedArrayBitwiseSlice(Scalar::Type sourceType,
1276 Scalar::Type targetType) {
1277 switch (sourceType) {
1278 case Scalar::Int8:
1279 return targetType == Scalar::Int8 || targetType == Scalar::Uint8;
1280
1281 case Scalar::Uint8:
1282 case Scalar::Uint8Clamped:
1283 return targetType == Scalar::Int8 || targetType == Scalar::Uint8 ||
1284 targetType == Scalar::Uint8Clamped;
1285
1286 case Scalar::Int16:
1287 case Scalar::Uint16:
1288 return targetType == Scalar::Int16 || targetType == Scalar::Uint16;
1289
1290 case Scalar::Int32:
1291 case Scalar::Uint32:
1292 return targetType == Scalar::Int32 || targetType == Scalar::Uint32;
1293
1294 case Scalar::Float32:
1295 return targetType == Scalar::Float32;
1296
1297 case Scalar::Float64:
1298 return targetType == Scalar::Float64;
1299
1300 case Scalar::BigInt64:
1301 case Scalar::BigUint64:
1302 return targetType == Scalar::BigInt64 || targetType == Scalar::BigUint64;
1303
1304 default:
1305 MOZ_CRASH("IsTypedArrayBitwiseSlice with a bogus typed array type");
1306 }
1307 }
1308
intrinsic_TypedArrayBitwiseSlice(JSContext * cx,unsigned argc,Value * vp)1309 static bool intrinsic_TypedArrayBitwiseSlice(JSContext* cx, unsigned argc,
1310 Value* vp) {
1311 CallArgs args = CallArgsFromVp(argc, vp);
1312 MOZ_ASSERT(args.length() == 4);
1313 MOZ_ASSERT(args[0].isObject());
1314 MOZ_ASSERT(args[1].isObject());
1315 AssertNonNegativeInteger(args[2]);
1316 AssertNonNegativeInteger(args[3]);
1317
1318 Rooted<TypedArrayObject*> source(cx,
1319 &args[0].toObject().as<TypedArrayObject>());
1320 MOZ_ASSERT(!source->hasDetachedBuffer());
1321
1322 // As directed by |DangerouslyUnwrapTypedArray|, sigil this pointer and all
1323 // variables derived from it to counsel extreme caution here.
1324 Rooted<TypedArrayObject*> unsafeTypedArrayCrossCompartment(cx);
1325 unsafeTypedArrayCrossCompartment =
1326 DangerouslyUnwrapTypedArray(cx, &args[1].toObject());
1327 if (!unsafeTypedArrayCrossCompartment) {
1328 return false;
1329 }
1330 MOZ_ASSERT(!unsafeTypedArrayCrossCompartment->hasDetachedBuffer());
1331
1332 Scalar::Type sourceType = source->type();
1333 if (!IsTypedArrayBitwiseSlice(sourceType,
1334 unsafeTypedArrayCrossCompartment->type())) {
1335 args.rval().setBoolean(false);
1336 return true;
1337 }
1338
1339 size_t sourceOffset = size_t(args[2].toNumber());
1340 size_t count = size_t(args[3].toNumber());
1341
1342 MOZ_ASSERT(count > 0 && count <= source->length());
1343 MOZ_ASSERT(sourceOffset <= source->length() - count);
1344 MOZ_ASSERT(count <= unsafeTypedArrayCrossCompartment->length());
1345
1346 size_t elementSize = TypedArrayElemSize(sourceType);
1347 MOZ_ASSERT(elementSize ==
1348 TypedArrayElemSize(unsafeTypedArrayCrossCompartment->type()));
1349
1350 SharedMem<uint8_t*> sourceData =
1351 source->dataPointerEither().cast<uint8_t*>() + sourceOffset * elementSize;
1352
1353 SharedMem<uint8_t*> unsafeTargetDataCrossCompartment =
1354 unsafeTypedArrayCrossCompartment->dataPointerEither().cast<uint8_t*>();
1355
1356 size_t byteLength = count * elementSize;
1357
1358 // The same-type case requires exact copying preserving the bit-level
1359 // encoding of the source data, so use memcpy if possible. If source and
1360 // target are the same buffer, we can't use memcpy (or memmove), because
1361 // the specification requires sequential copying of the values. This case
1362 // is only possible if a @@species constructor created a specifically
1363 // crafted typed array. It won't happen in normal code and hence doesn't
1364 // need to be optimized.
1365 if (!TypedArrayObject::sameBuffer(source, unsafeTypedArrayCrossCompartment)) {
1366 if (source->isSharedMemory() ||
1367 unsafeTypedArrayCrossCompartment->isSharedMemory()) {
1368 jit::AtomicOperations::memcpySafeWhenRacy(
1369 unsafeTargetDataCrossCompartment, sourceData, byteLength);
1370 } else {
1371 memcpy(unsafeTargetDataCrossCompartment.unwrapUnshared(),
1372 sourceData.unwrapUnshared(), byteLength);
1373 }
1374 } else {
1375 using namespace jit;
1376
1377 for (; byteLength > 0; byteLength--) {
1378 AtomicOperations::storeSafeWhenRacy(
1379 unsafeTargetDataCrossCompartment++,
1380 AtomicOperations::loadSafeWhenRacy(sourceData++));
1381 }
1382 }
1383
1384 args.rval().setBoolean(true);
1385 return true;
1386 }
1387
intrinsic_TypedArrayInitFromPackedArray(JSContext * cx,unsigned argc,Value * vp)1388 static bool intrinsic_TypedArrayInitFromPackedArray(JSContext* cx,
1389 unsigned argc, Value* vp) {
1390 CallArgs args = CallArgsFromVp(argc, vp);
1391 MOZ_ASSERT(args.length() == 2);
1392 MOZ_ASSERT(args[0].isObject());
1393 MOZ_ASSERT(args[1].isObject());
1394
1395 Rooted<TypedArrayObject*> target(cx,
1396 &args[0].toObject().as<TypedArrayObject>());
1397 MOZ_ASSERT(!target->hasDetachedBuffer());
1398 MOZ_ASSERT(!target->isSharedMemory());
1399
1400 RootedArrayObject source(cx, &args[1].toObject().as<ArrayObject>());
1401 MOZ_ASSERT(IsPackedArray(source));
1402 MOZ_ASSERT(source->length() == target->length());
1403
1404 switch (target->type()) {
1405 #define INIT_TYPED_ARRAY(_, T, N) \
1406 case Scalar::N: { \
1407 if (!ElementSpecific<T, UnsharedOps>::initFromIterablePackedArray( \
1408 cx, target, source)) { \
1409 return false; \
1410 } \
1411 break; \
1412 }
1413 JS_FOR_EACH_TYPED_ARRAY(INIT_TYPED_ARRAY)
1414 #undef INIT_TYPED_ARRAY
1415
1416 default:
1417 MOZ_CRASH(
1418 "TypedArrayInitFromPackedArray with a typed array with bogus type");
1419 }
1420
1421 args.rval().setUndefined();
1422 return true;
1423 }
1424
intrinsic_RegExpCreate(JSContext * cx,unsigned argc,Value * vp)1425 static bool intrinsic_RegExpCreate(JSContext* cx, unsigned argc, Value* vp) {
1426 CallArgs args = CallArgsFromVp(argc, vp);
1427
1428 MOZ_ASSERT(args.length() == 1 || args.length() == 2);
1429 MOZ_ASSERT_IF(args.length() == 2,
1430 args[1].isString() || args[1].isUndefined());
1431 MOZ_ASSERT(!args.isConstructing());
1432
1433 return RegExpCreate(cx, args[0], args.get(1), args.rval());
1434 }
1435
intrinsic_RegExpGetSubstitution(JSContext * cx,unsigned argc,Value * vp)1436 static bool intrinsic_RegExpGetSubstitution(JSContext* cx, unsigned argc,
1437 Value* vp) {
1438 CallArgs args = CallArgsFromVp(argc, vp);
1439 MOZ_ASSERT(args.length() == 6);
1440
1441 RootedArrayObject matchResult(cx, &args[0].toObject().as<ArrayObject>());
1442
1443 RootedLinearString string(cx, args[1].toString()->ensureLinear(cx));
1444 if (!string) {
1445 return false;
1446 }
1447
1448 int32_t position = int32_t(args[2].toNumber());
1449 MOZ_ASSERT(position >= 0);
1450
1451 RootedLinearString replacement(cx, args[3].toString()->ensureLinear(cx));
1452 if (!replacement) {
1453 return false;
1454 }
1455
1456 int32_t firstDollarIndex = int32_t(args[4].toNumber());
1457 MOZ_ASSERT(firstDollarIndex >= 0);
1458
1459 RootedValue namedCaptures(cx, args[5]);
1460 MOZ_ASSERT(namedCaptures.isUndefined() || namedCaptures.isObject());
1461
1462 return RegExpGetSubstitution(cx, matchResult, string, size_t(position),
1463 replacement, size_t(firstDollarIndex),
1464 namedCaptures, args.rval());
1465 }
1466
intrinsic_StringReplaceString(JSContext * cx,unsigned argc,Value * vp)1467 static bool intrinsic_StringReplaceString(JSContext* cx, unsigned argc,
1468 Value* vp) {
1469 CallArgs args = CallArgsFromVp(argc, vp);
1470 MOZ_ASSERT(args.length() == 3);
1471
1472 RootedString string(cx, args[0].toString());
1473 RootedString pattern(cx, args[1].toString());
1474 RootedString replacement(cx, args[2].toString());
1475 JSString* result = str_replace_string_raw(cx, string, pattern, replacement);
1476 if (!result) {
1477 return false;
1478 }
1479
1480 args.rval().setString(result);
1481 return true;
1482 }
1483
intrinsic_StringReplaceAllString(JSContext * cx,unsigned argc,Value * vp)1484 static bool intrinsic_StringReplaceAllString(JSContext* cx, unsigned argc,
1485 Value* vp) {
1486 CallArgs args = CallArgsFromVp(argc, vp);
1487 MOZ_ASSERT(args.length() == 3);
1488
1489 RootedString string(cx, args[0].toString());
1490 RootedString pattern(cx, args[1].toString());
1491 RootedString replacement(cx, args[2].toString());
1492 JSString* result =
1493 str_replaceAll_string_raw(cx, string, pattern, replacement);
1494 if (!result) {
1495 return false;
1496 }
1497
1498 args.rval().setString(result);
1499 return true;
1500 }
1501
intrinsic_StringSplitString(JSContext * cx,unsigned argc,Value * vp)1502 static bool intrinsic_StringSplitString(JSContext* cx, unsigned argc,
1503 Value* vp) {
1504 CallArgs args = CallArgsFromVp(argc, vp);
1505 MOZ_ASSERT(args.length() == 2);
1506
1507 RootedString string(cx, args[0].toString());
1508 RootedString sep(cx, args[1].toString());
1509
1510 JSObject* aobj = StringSplitString(cx, string, sep, INT32_MAX);
1511 if (!aobj) {
1512 return false;
1513 }
1514
1515 args.rval().setObject(*aobj);
1516 return true;
1517 }
1518
intrinsic_StringSplitStringLimit(JSContext * cx,unsigned argc,Value * vp)1519 static bool intrinsic_StringSplitStringLimit(JSContext* cx, unsigned argc,
1520 Value* vp) {
1521 CallArgs args = CallArgsFromVp(argc, vp);
1522 MOZ_ASSERT(args.length() == 3);
1523
1524 RootedString string(cx, args[0].toString());
1525 RootedString sep(cx, args[1].toString());
1526
1527 // args[2] should be already in UInt32 range, but it could be double typed,
1528 // because of Ion optimization.
1529 uint32_t limit = uint32_t(args[2].toNumber());
1530 MOZ_ASSERT(limit > 0,
1531 "Zero limit case is already handled in self-hosted code.");
1532
1533 JSObject* aobj = StringSplitString(cx, string, sep, limit);
1534 if (!aobj) {
1535 return false;
1536 }
1537
1538 args.rval().setObject(*aobj);
1539 return true;
1540 }
1541
CallSelfHostedNonGenericMethod(JSContext * cx,const CallArgs & args)1542 bool CallSelfHostedNonGenericMethod(JSContext* cx, const CallArgs& args) {
1543 // This function is called when a self-hosted method is invoked on a
1544 // wrapper object, like a CrossCompartmentWrapper. The last argument is
1545 // the name of the self-hosted function. The other arguments are the
1546 // arguments to pass to this function.
1547
1548 MOZ_ASSERT(args.length() > 0);
1549 RootedPropertyName name(
1550 cx, args[args.length() - 1].toString()->asAtom().asPropertyName());
1551
1552 InvokeArgs args2(cx);
1553 if (!args2.init(cx, args.length() - 1)) {
1554 return false;
1555 }
1556
1557 for (size_t i = 0; i < args.length() - 1; i++) {
1558 args2[i].set(args[i]);
1559 }
1560
1561 return CallSelfHostedFunction(cx, name, args.thisv(), args2, args.rval());
1562 }
1563
1564 #ifdef DEBUG
CallSelfHostedFunction(JSContext * cx,const char * name,HandleValue thisv,const AnyInvokeArgs & args,MutableHandleValue rval)1565 bool js::CallSelfHostedFunction(JSContext* cx, const char* name,
1566 HandleValue thisv, const AnyInvokeArgs& args,
1567 MutableHandleValue rval) {
1568 JSAtom* funAtom = Atomize(cx, name, strlen(name));
1569 if (!funAtom) {
1570 return false;
1571 }
1572 RootedPropertyName funName(cx, funAtom->asPropertyName());
1573 return CallSelfHostedFunction(cx, funName, thisv, args, rval);
1574 }
1575 #endif
1576
CallSelfHostedFunction(JSContext * cx,HandlePropertyName name,HandleValue thisv,const AnyInvokeArgs & args,MutableHandleValue rval)1577 bool js::CallSelfHostedFunction(JSContext* cx, HandlePropertyName name,
1578 HandleValue thisv, const AnyInvokeArgs& args,
1579 MutableHandleValue rval) {
1580 RootedValue fun(cx);
1581 if (!GlobalObject::getIntrinsicValue(cx, cx->global(), name, &fun)) {
1582 return false;
1583 }
1584 MOZ_ASSERT(fun.toObject().is<JSFunction>());
1585
1586 return Call(cx, fun, thisv, args, rval);
1587 }
1588
1589 template <typename T>
Is(HandleValue v)1590 bool Is(HandleValue v) {
1591 return v.isObject() && v.toObject().is<T>();
1592 }
1593
1594 template <IsAcceptableThis Test>
CallNonGenericSelfhostedMethod(JSContext * cx,unsigned argc,Value * vp)1595 static bool CallNonGenericSelfhostedMethod(JSContext* cx, unsigned argc,
1596 Value* vp) {
1597 CallArgs args = CallArgsFromVp(argc, vp);
1598 return CallNonGenericMethod<Test, CallSelfHostedNonGenericMethod>(cx, args);
1599 }
1600
IsCallSelfHostedNonGenericMethod(NativeImpl impl)1601 bool js::IsCallSelfHostedNonGenericMethod(NativeImpl impl) {
1602 return impl == CallSelfHostedNonGenericMethod;
1603 }
1604
ReportIncompatibleSelfHostedMethod(JSContext * cx,const CallArgs & args)1605 bool js::ReportIncompatibleSelfHostedMethod(JSContext* cx,
1606 const CallArgs& args) {
1607 // The contract for this function is the same as
1608 // CallSelfHostedNonGenericMethod. The normal ReportIncompatible function
1609 // doesn't work for selfhosted functions, because they always call the
1610 // different CallXXXMethodIfWrapped methods, which would be reported as the
1611 // called function instead.
1612
1613 // Lookup the selfhosted method that was invoked. But skip over
1614 // internal self-hosted function frames, because those are never the
1615 // actual self-hosted callee from external code. We can't just skip
1616 // self-hosted things until we find a non-self-hosted one because of cases
1617 // like array.sort(somethingSelfHosted), where we want to report the error
1618 // in the somethingSelfHosted, not in the sort() call.
1619
1620 static const char* const internalNames[] = {
1621 "IsTypedArrayEnsuringArrayBuffer",
1622 "UnwrapAndCallRegExpBuiltinExec",
1623 "RegExpBuiltinExec",
1624 "RegExpExec",
1625 "RegExpSearchSlowPath",
1626 "RegExpReplaceSlowPath",
1627 "RegExpMatchSlowPath",
1628 };
1629
1630 ScriptFrameIter iter(cx);
1631 MOZ_ASSERT(iter.isFunctionFrame());
1632
1633 while (!iter.done()) {
1634 MOZ_ASSERT(iter.callee(cx)->isSelfHostedOrIntrinsic() &&
1635 !iter.callee(cx)->isBoundFunction());
1636 UniqueChars funNameBytes;
1637 const char* funName =
1638 GetFunctionNameBytes(cx, iter.callee(cx), &funNameBytes);
1639 if (!funName) {
1640 return false;
1641 }
1642 if (std::all_of(
1643 std::begin(internalNames), std::end(internalNames),
1644 [funName](auto* name) { return strcmp(funName, name) != 0; })) {
1645 JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr,
1646 JSMSG_INCOMPATIBLE_METHOD, funName, "method",
1647 InformalValueTypeName(args.thisv()));
1648 return false;
1649 }
1650 ++iter;
1651 }
1652
1653 MOZ_ASSERT_UNREACHABLE("How did we not find a useful self-hosted frame?");
1654 return false;
1655 }
1656
1657 #ifdef JS_HAS_INTL_API
1658 /**
1659 * Returns the default locale as a well-formed, but not necessarily
1660 * canonicalized, BCP-47 language tag.
1661 */
intrinsic_RuntimeDefaultLocale(JSContext * cx,unsigned argc,Value * vp)1662 static bool intrinsic_RuntimeDefaultLocale(JSContext* cx, unsigned argc,
1663 Value* vp) {
1664 CallArgs args = CallArgsFromVp(argc, vp);
1665 MOZ_ASSERT(args.length() == 0);
1666
1667 const char* locale = cx->runtime()->getDefaultLocale();
1668 if (!locale) {
1669 JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
1670 JSMSG_DEFAULT_LOCALE_ERROR);
1671 return false;
1672 }
1673
1674 JSString* jslocale = NewStringCopyZ<CanGC>(cx, locale);
1675 if (!jslocale) {
1676 return false;
1677 }
1678
1679 args.rval().setString(jslocale);
1680 return true;
1681 }
1682
intrinsic_IsRuntimeDefaultLocale(JSContext * cx,unsigned argc,Value * vp)1683 static bool intrinsic_IsRuntimeDefaultLocale(JSContext* cx, unsigned argc,
1684 Value* vp) {
1685 CallArgs args = CallArgsFromVp(argc, vp);
1686 MOZ_ASSERT(args.length() == 1);
1687 MOZ_ASSERT(args[0].isString() || args[0].isUndefined());
1688
1689 // |undefined| is the default value when the Intl runtime caches haven't
1690 // yet been initialized. Handle it the same way as a cache miss.
1691 if (args[0].isUndefined()) {
1692 args.rval().setBoolean(false);
1693 return true;
1694 }
1695
1696 const char* locale = cx->runtime()->getDefaultLocale();
1697 if (!locale) {
1698 JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
1699 JSMSG_DEFAULT_LOCALE_ERROR);
1700 return false;
1701 }
1702
1703 JSLinearString* str = args[0].toString()->ensureLinear(cx);
1704 if (!str) {
1705 return false;
1706 }
1707
1708 bool equals = StringEqualsAscii(str, locale);
1709 args.rval().setBoolean(equals);
1710 return true;
1711 }
1712 #endif // JS_HAS_INTL_API
1713
intrinsic_ThrowArgTypeNotObject(JSContext * cx,unsigned argc,Value * vp)1714 static bool intrinsic_ThrowArgTypeNotObject(JSContext* cx, unsigned argc,
1715 Value* vp) {
1716 CallArgs args = CallArgsFromVp(argc, vp);
1717 MOZ_ASSERT(args.length() == 2);
1718 MOZ_ASSERT(args[0].isNumber());
1719 MOZ_ASSERT(!args[1].isObject());
1720 if (args[0].toNumber() == NOT_OBJECT_KIND_DESCRIPTOR) {
1721 ReportNotObject(cx, JSMSG_OBJECT_REQUIRED_PROP_DESC, args[1]);
1722 } else {
1723 MOZ_CRASH("unexpected kind");
1724 }
1725
1726 return false;
1727 }
1728
intrinsic_ConstructFunction(JSContext * cx,unsigned argc,Value * vp)1729 static bool intrinsic_ConstructFunction(JSContext* cx, unsigned argc,
1730 Value* vp) {
1731 CallArgs args = CallArgsFromVp(argc, vp);
1732 MOZ_ASSERT(args.length() == 3);
1733 MOZ_ASSERT(IsConstructor(args[0]));
1734 MOZ_ASSERT(IsConstructor(args[1]));
1735 MOZ_ASSERT(args[2].toObject().is<ArrayObject>());
1736
1737 RootedArrayObject argsList(cx, &args[2].toObject().as<ArrayObject>());
1738 uint32_t len = argsList->length();
1739 ConstructArgs constructArgs(cx);
1740 if (!constructArgs.init(cx, len)) {
1741 return false;
1742 }
1743 for (uint32_t index = 0; index < len; index++) {
1744 constructArgs[index].set(argsList->getDenseElement(index));
1745 }
1746
1747 RootedObject res(cx);
1748 if (!Construct(cx, args[0], constructArgs, args[1], &res)) {
1749 return false;
1750 }
1751
1752 args.rval().setObject(*res);
1753 return true;
1754 }
1755
intrinsic_IsConstructing(JSContext * cx,unsigned argc,Value * vp)1756 static bool intrinsic_IsConstructing(JSContext* cx, unsigned argc, Value* vp) {
1757 CallArgs args = CallArgsFromVp(argc, vp);
1758 MOZ_ASSERT(args.length() == 0);
1759
1760 ScriptFrameIter iter(cx);
1761 bool isConstructing = iter.isConstructing();
1762 args.rval().setBoolean(isConstructing);
1763 return true;
1764 }
1765
intrinsic_ConstructorForTypedArray(JSContext * cx,unsigned argc,Value * vp)1766 static bool intrinsic_ConstructorForTypedArray(JSContext* cx, unsigned argc,
1767 Value* vp) {
1768 CallArgs args = CallArgsFromVp(argc, vp);
1769 MOZ_ASSERT(args.length() == 1);
1770 MOZ_ASSERT(args[0].isObject());
1771
1772 auto* object = UnwrapAndDowncastValue<TypedArrayObject>(cx, args[0]);
1773 if (!object) {
1774 return false;
1775 }
1776
1777 JSProtoKey protoKey = StandardProtoKeyOrNull(object);
1778 MOZ_ASSERT(protoKey);
1779
1780 // While it may seem like an invariant that in any compartment,
1781 // seeing a typed array object implies that the TypedArray constructor
1782 // for that type is initialized on the compartment's global, this is not
1783 // the case. When we construct a typed array given a cross-compartment
1784 // ArrayBuffer, we put the constructed TypedArray in the same compartment
1785 // as the ArrayBuffer. Since we use the prototype from the initial
1786 // compartment, and never call the constructor in the ArrayBuffer's
1787 // compartment from script, we are not guaranteed to have initialized
1788 // the constructor.
1789 JSObject* ctor = GlobalObject::getOrCreateConstructor(cx, protoKey);
1790 if (!ctor) {
1791 return false;
1792 }
1793
1794 args.rval().setObject(*ctor);
1795 return true;
1796 }
1797
intrinsic_HostResolveImportedModule(JSContext * cx,unsigned argc,Value * vp)1798 static bool intrinsic_HostResolveImportedModule(JSContext* cx, unsigned argc,
1799 Value* vp) {
1800 CallArgs args = CallArgsFromVp(argc, vp);
1801 MOZ_ASSERT(args.length() == 2);
1802 RootedModuleObject module(cx, &args[0].toObject().as<ModuleObject>());
1803 RootedObject moduleRequest(cx, &args[1].toObject());
1804
1805 RootedValue referencingPrivate(cx, JS::GetModulePrivate(module));
1806 RootedObject result(
1807 cx, CallModuleResolveHook(cx, referencingPrivate, moduleRequest));
1808 if (!result) {
1809 return false;
1810 }
1811
1812 if (!result->is<ModuleObject>()) {
1813 JS_ReportErrorASCII(cx, "Module resolve hook did not return Module object");
1814 return false;
1815 }
1816
1817 args.rval().setObject(*result);
1818 return true;
1819 }
1820
intrinsic_CreateImportBinding(JSContext * cx,unsigned argc,Value * vp)1821 static bool intrinsic_CreateImportBinding(JSContext* cx, unsigned argc,
1822 Value* vp) {
1823 CallArgs args = CallArgsFromVp(argc, vp);
1824 MOZ_ASSERT(args.length() == 4);
1825 RootedModuleEnvironmentObject environment(
1826 cx, &args[0].toObject().as<ModuleEnvironmentObject>());
1827 RootedAtom importedName(cx, &args[1].toString()->asAtom());
1828 RootedModuleObject module(cx, &args[2].toObject().as<ModuleObject>());
1829 RootedAtom localName(cx, &args[3].toString()->asAtom());
1830 if (!environment->createImportBinding(cx, importedName, module, localName)) {
1831 return false;
1832 }
1833
1834 args.rval().setUndefined();
1835 return true;
1836 }
1837
intrinsic_CreateNamespaceBinding(JSContext * cx,unsigned argc,Value * vp)1838 static bool intrinsic_CreateNamespaceBinding(JSContext* cx, unsigned argc,
1839 Value* vp) {
1840 CallArgs args = CallArgsFromVp(argc, vp);
1841 MOZ_ASSERT(args.length() == 3);
1842 RootedModuleEnvironmentObject environment(
1843 cx, &args[0].toObject().as<ModuleEnvironmentObject>());
1844 RootedId name(cx, AtomToId(&args[1].toString()->asAtom()));
1845 MOZ_ASSERT(args[2].toObject().is<ModuleNamespaceObject>());
1846 // The property already exists in the evironment but is not writable, so set
1847 // the slot directly.
1848 mozilla::Maybe<PropertyInfo> prop = environment->lookup(cx, name);
1849 MOZ_ASSERT(prop.isSome());
1850 environment->setSlot(prop->slot(), args[2]);
1851 args.rval().setUndefined();
1852 return true;
1853 }
1854
intrinsic_EnsureModuleEnvironmentNamespace(JSContext * cx,unsigned argc,Value * vp)1855 static bool intrinsic_EnsureModuleEnvironmentNamespace(JSContext* cx,
1856 unsigned argc,
1857 Value* vp) {
1858 CallArgs args = CallArgsFromVp(argc, vp);
1859 MOZ_ASSERT(args.length() == 2);
1860 RootedModuleObject module(cx, &args[0].toObject().as<ModuleObject>());
1861 MOZ_ASSERT(args[1].toObject().is<ModuleNamespaceObject>());
1862 RootedModuleEnvironmentObject environment(cx, &module->initialEnvironment());
1863 // The property already exists in the evironment but is not writable, so set
1864 // the slot directly.
1865 mozilla::Maybe<PropertyInfo> prop =
1866 environment->lookup(cx, cx->names().starNamespaceStar);
1867 MOZ_ASSERT(prop.isSome());
1868 environment->setSlot(prop->slot(), args[1]);
1869 args.rval().setUndefined();
1870 return true;
1871 }
1872
intrinsic_InstantiateModuleFunctionDeclarations(JSContext * cx,unsigned argc,Value * vp)1873 static bool intrinsic_InstantiateModuleFunctionDeclarations(JSContext* cx,
1874 unsigned argc,
1875 Value* vp) {
1876 CallArgs args = CallArgsFromVp(argc, vp);
1877 MOZ_ASSERT(args.length() == 1);
1878 RootedModuleObject module(cx, &args[0].toObject().as<ModuleObject>());
1879 args.rval().setUndefined();
1880 return ModuleObject::instantiateFunctionDeclarations(cx, module);
1881 }
1882
intrinsic_ExecuteModule(JSContext * cx,unsigned argc,Value * vp)1883 static bool intrinsic_ExecuteModule(JSContext* cx, unsigned argc, Value* vp) {
1884 CallArgs args = CallArgsFromVp(argc, vp);
1885 MOZ_ASSERT(args.length() == 1);
1886 RootedModuleObject module(cx, &args[0].toObject().as<ModuleObject>());
1887 return ModuleObject::execute(cx, module, args.rval());
1888 }
1889
intrinsic_SetCycleRoot(JSContext * cx,unsigned argc,Value * vp)1890 static bool intrinsic_SetCycleRoot(JSContext* cx, unsigned argc, Value* vp) {
1891 CallArgs args = CallArgsFromVp(argc, vp);
1892 MOZ_ASSERT(args.length() == 2);
1893 RootedModuleObject module(cx, &args[0].toObject().as<ModuleObject>());
1894 RootedModuleObject cycleRoot(cx, &args[1].toObject().as<ModuleObject>());
1895 module->setCycleRoot(cycleRoot);
1896 args.rval().setUndefined();
1897 return true;
1898 }
1899
intrinsic_GetCycleRoot(JSContext * cx,unsigned argc,Value * vp)1900 static bool intrinsic_GetCycleRoot(JSContext* cx, unsigned argc, Value* vp) {
1901 CallArgs args = CallArgsFromVp(argc, vp);
1902 MOZ_ASSERT(args.length() == 1);
1903 RootedModuleObject module(cx, &args[0].toObject().as<ModuleObject>());
1904 JSObject* result = module->getCycleRoot();
1905 if (!result) {
1906 return false;
1907 }
1908 args.rval().setObject(*result);
1909 return true;
1910 }
1911
intrinsic_AppendAsyncParentModule(JSContext * cx,unsigned argc,Value * vp)1912 static bool intrinsic_AppendAsyncParentModule(JSContext* cx, unsigned argc,
1913 Value* vp) {
1914 CallArgs args = CallArgsFromVp(argc, vp);
1915 MOZ_ASSERT(args.length() == 2);
1916 RootedModuleObject self(cx, &args[0].toObject().as<ModuleObject>());
1917 RootedModuleObject parent(cx, &args[1].toObject().as<ModuleObject>());
1918 return ModuleObject::appendAsyncParentModule(cx, self, parent);
1919 }
1920
intrinsic_InitAsyncEvaluating(JSContext * cx,unsigned argc,Value * vp)1921 static bool intrinsic_InitAsyncEvaluating(JSContext* cx, unsigned argc,
1922 Value* vp) {
1923 CallArgs args = CallArgsFromVp(argc, vp);
1924 MOZ_ASSERT(args.length() == 1);
1925 RootedModuleObject module(cx, &args[0].toObject().as<ModuleObject>());
1926 if (!module->initAsyncEvaluatingSlot()) {
1927 return false;
1928 }
1929 args.rval().setUndefined();
1930 return true;
1931 }
1932
intrinsic_IsAsyncEvaluating(JSContext * cx,unsigned argc,Value * vp)1933 static bool intrinsic_IsAsyncEvaluating(JSContext* cx, unsigned argc,
1934 Value* vp) {
1935 CallArgs args = CallArgsFromVp(argc, vp);
1936 MOZ_ASSERT(args.length() == 1);
1937 RootedModuleObject module(cx, &args[0].toObject().as<ModuleObject>());
1938 bool isAsyncEvaluating = module->isAsyncEvaluating();
1939 args.rval().setBoolean(isAsyncEvaluating);
1940 return true;
1941 }
1942
intrinsic_CreateTopLevelCapability(JSContext * cx,unsigned argc,Value * vp)1943 static bool intrinsic_CreateTopLevelCapability(JSContext* cx, unsigned argc,
1944 Value* vp) {
1945 CallArgs args = CallArgsFromVp(argc, vp);
1946 MOZ_ASSERT(args.length() == 1);
1947 RootedModuleObject self(cx, &args[0].toObject().as<ModuleObject>());
1948 PromiseObject* result = ModuleObject::createTopLevelCapability(cx, self);
1949 if (!result) {
1950 return false;
1951 }
1952 args.rval().setObject(*result);
1953 return true;
1954 }
1955
intrinsic_ModuleTopLevelCapabilityResolve(JSContext * cx,unsigned argc,Value * vp)1956 static bool intrinsic_ModuleTopLevelCapabilityResolve(JSContext* cx,
1957 unsigned argc,
1958 Value* vp) {
1959 CallArgs args = CallArgsFromVp(argc, vp);
1960 MOZ_ASSERT(args.length() == 1);
1961 RootedModuleObject module(cx, &args[0].toObject().as<ModuleObject>());
1962 ModuleObject::topLevelCapabilityResolve(cx, module);
1963 args.rval().setUndefined();
1964 return true;
1965 }
1966
intrinsic_ModuleTopLevelCapabilityReject(JSContext * cx,unsigned argc,Value * vp)1967 static bool intrinsic_ModuleTopLevelCapabilityReject(JSContext* cx,
1968 unsigned argc, Value* vp) {
1969 CallArgs args = CallArgsFromVp(argc, vp);
1970 MOZ_ASSERT(args.length() == 2);
1971 RootedModuleObject module(cx, &args[0].toObject().as<ModuleObject>());
1972 HandleValue error = args[1];
1973 ModuleObject::topLevelCapabilityReject(cx, module, error);
1974 args.rval().setUndefined();
1975 return true;
1976 }
1977
intrinsic_NewModuleNamespace(JSContext * cx,unsigned argc,Value * vp)1978 static bool intrinsic_NewModuleNamespace(JSContext* cx, unsigned argc,
1979 Value* vp) {
1980 CallArgs args = CallArgsFromVp(argc, vp);
1981 MOZ_ASSERT(args.length() == 2);
1982 RootedModuleObject module(cx, &args[0].toObject().as<ModuleObject>());
1983 RootedObject exports(cx, &args[1].toObject());
1984 JSObject* namespace_ = ModuleObject::createNamespace(cx, module, exports);
1985 if (!namespace_) {
1986 return false;
1987 }
1988
1989 args.rval().setObject(*namespace_);
1990 return true;
1991 }
1992
intrinsic_AddModuleNamespaceBinding(JSContext * cx,unsigned argc,Value * vp)1993 static bool intrinsic_AddModuleNamespaceBinding(JSContext* cx, unsigned argc,
1994 Value* vp) {
1995 CallArgs args = CallArgsFromVp(argc, vp);
1996 MOZ_ASSERT(args.length() == 4);
1997 RootedModuleNamespaceObject namespace_(
1998 cx, &args[0].toObject().as<ModuleNamespaceObject>());
1999 RootedAtom exportedName(cx, &args[1].toString()->asAtom());
2000 RootedModuleObject targetModule(cx, &args[2].toObject().as<ModuleObject>());
2001 RootedAtom targetName(cx, &args[3].toString()->asAtom());
2002 if (!namespace_->addBinding(cx, exportedName, targetModule, targetName)) {
2003 return false;
2004 }
2005
2006 args.rval().setUndefined();
2007 return true;
2008 }
2009
intrinsic_PromiseResolve(JSContext * cx,unsigned argc,Value * vp)2010 static bool intrinsic_PromiseResolve(JSContext* cx, unsigned argc, Value* vp) {
2011 CallArgs args = CallArgsFromVp(argc, vp);
2012 MOZ_ASSERT(args.length() == 2);
2013
2014 RootedObject constructor(cx, &args[0].toObject());
2015 JSObject* promise = js::PromiseResolve(cx, constructor, args[1]);
2016 if (!promise) {
2017 return false;
2018 }
2019
2020 args.rval().setObject(*promise);
2021 return true;
2022 }
2023
intrinsic_CopyDataPropertiesOrGetOwnKeys(JSContext * cx,unsigned argc,Value * vp)2024 static bool intrinsic_CopyDataPropertiesOrGetOwnKeys(JSContext* cx,
2025 unsigned argc, Value* vp) {
2026 CallArgs args = CallArgsFromVp(argc, vp);
2027 MOZ_ASSERT(args.length() == 3);
2028 MOZ_ASSERT(args[0].isObject());
2029 MOZ_ASSERT(args[1].isObject());
2030 MOZ_ASSERT(args[2].isObjectOrNull());
2031
2032 RootedObject target(cx, &args[0].toObject());
2033 RootedObject from(cx, &args[1].toObject());
2034 RootedObject excludedItems(cx, args[2].toObjectOrNull());
2035
2036 if (from->is<NativeObject>() && target->is<PlainObject>() &&
2037 (!excludedItems || excludedItems->is<PlainObject>())) {
2038 bool optimized;
2039 if (!CopyDataPropertiesNative(
2040 cx, target.as<PlainObject>(), from.as<NativeObject>(),
2041 (excludedItems ? excludedItems.as<PlainObject>() : nullptr),
2042 &optimized)) {
2043 return false;
2044 }
2045
2046 if (optimized) {
2047 args.rval().setNull();
2048 return true;
2049 }
2050 }
2051
2052 return GetOwnPropertyKeys(
2053 cx, from, JSITER_OWNONLY | JSITER_HIDDEN | JSITER_SYMBOLS, args.rval());
2054 }
2055
intrinsic_ToBigInt(JSContext * cx,unsigned argc,Value * vp)2056 static bool intrinsic_ToBigInt(JSContext* cx, unsigned argc, Value* vp) {
2057 CallArgs args = CallArgsFromVp(argc, vp);
2058 MOZ_ASSERT(args.length() == 1);
2059 BigInt* res = ToBigInt(cx, args[0]);
2060 if (!res) {
2061 return false;
2062 }
2063 args.rval().setBigInt(res);
2064 return true;
2065 }
2066
intrinsic_NewWrapForValidIterator(JSContext * cx,unsigned argc,Value * vp)2067 static bool intrinsic_NewWrapForValidIterator(JSContext* cx, unsigned argc,
2068 Value* vp) {
2069 CallArgs args = CallArgsFromVp(argc, vp);
2070 MOZ_ASSERT(args.length() == 0);
2071
2072 JSObject* obj = NewWrapForValidIterator(cx);
2073 if (!obj) {
2074 return false;
2075 }
2076
2077 args.rval().setObject(*obj);
2078 return true;
2079 }
2080
intrinsic_NewIteratorHelper(JSContext * cx,unsigned argc,Value * vp)2081 static bool intrinsic_NewIteratorHelper(JSContext* cx, unsigned argc,
2082 Value* vp) {
2083 CallArgs args = CallArgsFromVp(argc, vp);
2084 MOZ_ASSERT(args.length() == 0);
2085
2086 JSObject* obj = NewIteratorHelper(cx);
2087 if (!obj) {
2088 return false;
2089 }
2090
2091 args.rval().setObject(*obj);
2092 return true;
2093 }
2094
intrinsic_NewAsyncIteratorHelper(JSContext * cx,unsigned argc,Value * vp)2095 static bool intrinsic_NewAsyncIteratorHelper(JSContext* cx, unsigned argc,
2096 Value* vp) {
2097 CallArgs args = CallArgsFromVp(argc, vp);
2098 MOZ_ASSERT(args.length() == 0);
2099
2100 JSObject* obj = NewAsyncIteratorHelper(cx);
2101 if (!obj) {
2102 return false;
2103 }
2104
2105 args.rval().setObject(*obj);
2106 return true;
2107 }
2108
intrinsic_NoPrivateGetter(JSContext * cx,unsigned argc,Value * vp)2109 static bool intrinsic_NoPrivateGetter(JSContext* cx, unsigned argc, Value* vp) {
2110 CallArgs args = CallArgsFromVp(argc, vp);
2111 MOZ_ASSERT(args.length() == 0);
2112
2113 JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
2114 JSMSG_PRIVATE_SETTER_ONLY);
2115
2116 args.rval().setUndefined();
2117 return false;
2118 }
2119
2120 static const JSFunctionSpec intrinsic_functions[] = {
2121 // Intrinsic helper functions
2122 JS_FN("AddModuleNamespaceBinding", intrinsic_AddModuleNamespaceBinding, 4,
2123 0),
2124 JS_FN("AppendAsyncParentModule", intrinsic_AppendAsyncParentModule, 2, 0),
2125 JS_INLINABLE_FN("ArrayBufferByteLength",
2126 intrinsic_ArrayBufferByteLength<ArrayBufferObject>, 1, 0,
2127 IntrinsicArrayBufferByteLength),
2128 JS_FN("ArrayBufferCopyData",
2129 intrinsic_ArrayBufferCopyData<ArrayBufferObject>, 6, 0),
2130 JS_INLINABLE_FN("ArrayIteratorPrototypeOptimizable",
2131 intrinsic_ArrayIteratorPrototypeOptimizable, 0, 0,
2132 IntrinsicArrayIteratorPrototypeOptimizable),
2133 JS_FN("ArrayNativeSort", intrinsic_ArrayNativeSort, 1, 0),
2134 JS_FN("AssertionFailed", intrinsic_AssertionFailed, 1, 0),
2135 JS_FN("CallArrayBufferMethodIfWrapped",
2136 CallNonGenericSelfhostedMethod<Is<ArrayBufferObject>>, 2, 0),
2137 JS_FN("CallArrayIteratorMethodIfWrapped",
2138 CallNonGenericSelfhostedMethod<Is<ArrayIteratorObject>>, 2, 0),
2139 JS_FN("CallAsyncIteratorHelperMethodIfWrapped",
2140 CallNonGenericSelfhostedMethod<Is<AsyncIteratorHelperObject>>, 2, 0),
2141 JS_FN("CallGeneratorMethodIfWrapped",
2142 CallNonGenericSelfhostedMethod<Is<GeneratorObject>>, 2, 0),
2143 JS_FN("CallIteratorHelperMethodIfWrapped",
2144 CallNonGenericSelfhostedMethod<Is<IteratorHelperObject>>, 2, 0),
2145 JS_FN("CallMapIteratorMethodIfWrapped",
2146 CallNonGenericSelfhostedMethod<Is<MapIteratorObject>>, 2, 0),
2147 JS_FN("CallMapMethodIfWrapped",
2148 CallNonGenericSelfhostedMethod<Is<MapObject>>, 2, 0),
2149 JS_FN("CallModuleMethodIfWrapped",
2150 CallNonGenericSelfhostedMethod<Is<ModuleObject>>, 2, 0),
2151 JS_FN("CallRegExpMethodIfWrapped",
2152 CallNonGenericSelfhostedMethod<Is<RegExpObject>>, 2, 0),
2153 JS_FN("CallRegExpStringIteratorMethodIfWrapped",
2154 CallNonGenericSelfhostedMethod<Is<RegExpStringIteratorObject>>, 2, 0),
2155 JS_FN("CallSetIteratorMethodIfWrapped",
2156 CallNonGenericSelfhostedMethod<Is<SetIteratorObject>>, 2, 0),
2157 JS_FN("CallSetMethodIfWrapped",
2158 CallNonGenericSelfhostedMethod<Is<SetObject>>, 2, 0),
2159 JS_FN("CallSharedArrayBufferMethodIfWrapped",
2160 CallNonGenericSelfhostedMethod<Is<SharedArrayBufferObject>>, 2, 0),
2161 JS_FN("CallStringIteratorMethodIfWrapped",
2162 CallNonGenericSelfhostedMethod<Is<StringIteratorObject>>, 2, 0),
2163 JS_FN("CallTypedArrayMethodIfWrapped",
2164 CallNonGenericSelfhostedMethod<Is<TypedArrayObject>>, 2, 0),
2165 JS_FN("CallWrapForValidIteratorMethodIfWrapped",
2166 CallNonGenericSelfhostedMethod<Is<WrapForValidIteratorObject>>, 2, 0),
2167 JS_FN("ConstructFunction", intrinsic_ConstructFunction, 2, 0),
2168 JS_FN("ConstructorForTypedArray", intrinsic_ConstructorForTypedArray, 1, 0),
2169 JS_FN("CopyDataPropertiesOrGetOwnKeys",
2170 intrinsic_CopyDataPropertiesOrGetOwnKeys, 3, 0),
2171 JS_FN("CreateImportBinding", intrinsic_CreateImportBinding, 4, 0),
2172 JS_FN("CreateMapIterationResultPair",
2173 intrinsic_CreateMapIterationResultPair, 0, 0),
2174 JS_FN("CreateModuleSyntaxError", intrinsic_CreateModuleSyntaxError, 4, 0),
2175 JS_FN("CreateNamespaceBinding", intrinsic_CreateNamespaceBinding, 3, 0),
2176 JS_FN("CreateSetIterationResult", intrinsic_CreateSetIterationResult, 0, 0),
2177 JS_FN("CreateTopLevelCapability", intrinsic_CreateTopLevelCapability, 1, 0),
2178 JS_FN("DecompileArg", intrinsic_DecompileArg, 2, 0),
2179 JS_FN("DefineDataProperty", intrinsic_DefineDataProperty, 4, 0),
2180 JS_FN("DefineProperty", intrinsic_DefineProperty, 6, 0),
2181 JS_FN("DumpMessage", intrinsic_DumpMessage, 1, 0),
2182 JS_FN("EnsureModuleEnvironmentNamespace",
2183 intrinsic_EnsureModuleEnvironmentNamespace, 1, 0),
2184 JS_FN("ExecuteModule", intrinsic_ExecuteModule, 1, 0),
2185 JS_INLINABLE_FN("FinishBoundFunctionInit",
2186 intrinsic_FinishBoundFunctionInit, 3, 0,
2187 IntrinsicFinishBoundFunctionInit),
2188 JS_FN("FlatStringMatch", FlatStringMatch, 2, 0),
2189 JS_FN("FlatStringSearch", FlatStringSearch, 2, 0),
2190 JS_FN("GeneratorIsRunning", intrinsic_GeneratorIsRunning, 1, 0),
2191 JS_FN("GeneratorObjectIsClosed", intrinsic_GeneratorObjectIsClosed, 1, 0),
2192 JS_FN("GeneratorSetClosed", intrinsic_GeneratorSetClosed, 1, 0),
2193 JS_FN("GetCycleRoot", intrinsic_GetCycleRoot, 1, 0),
2194 JS_FN("GetElemBaseForLambda", intrinsic_GetElemBaseForLambda, 1, 0),
2195 JS_FN("GetErrorMessage", intrinsic_GetErrorMessage, 1, 0),
2196 JS_INLINABLE_FN("GetFirstDollarIndex", GetFirstDollarIndex, 1, 0,
2197 GetFirstDollarIndex),
2198 JS_INLINABLE_FN("GetNextMapEntryForIterator",
2199 intrinsic_GetNextMapEntryForIterator, 2, 0,
2200 IntrinsicGetNextMapEntryForIterator),
2201 JS_INLINABLE_FN("GetNextSetEntryForIterator",
2202 intrinsic_GetNextSetEntryForIterator, 2, 0,
2203 IntrinsicGetNextSetEntryForIterator),
2204 JS_FN("GetOwnPropertyDescriptorToArray", GetOwnPropertyDescriptorToArray, 2,
2205 0),
2206 JS_FN("GetStringDataProperty", intrinsic_GetStringDataProperty, 2, 0),
2207 JS_FN("GetTypedArrayKind", intrinsic_GetTypedArrayKind, 1, 0),
2208 JS_INLINABLE_FN("GuardToArrayBuffer",
2209 intrinsic_GuardToBuiltin<ArrayBufferObject>, 1, 0,
2210 IntrinsicGuardToArrayBuffer),
2211 JS_INLINABLE_FN("GuardToArrayIterator",
2212 intrinsic_GuardToBuiltin<ArrayIteratorObject>, 1, 0,
2213 IntrinsicGuardToArrayIterator),
2214 JS_INLINABLE_FN("GuardToAsyncIteratorHelper",
2215 intrinsic_GuardToBuiltin<AsyncIteratorHelperObject>, 1, 0,
2216 IntrinsicGuardToAsyncIteratorHelper),
2217 JS_INLINABLE_FN("GuardToIteratorHelper",
2218 intrinsic_GuardToBuiltin<IteratorHelperObject>, 1, 0,
2219 IntrinsicGuardToIteratorHelper),
2220 JS_INLINABLE_FN("GuardToMapIterator",
2221 intrinsic_GuardToBuiltin<MapIteratorObject>, 1, 0,
2222 IntrinsicGuardToMapIterator),
2223 JS_INLINABLE_FN("GuardToMapObject", intrinsic_GuardToBuiltin<MapObject>, 1,
2224 0, IntrinsicGuardToMapObject),
2225 JS_INLINABLE_FN("GuardToRegExpStringIterator",
2226 intrinsic_GuardToBuiltin<RegExpStringIteratorObject>, 1, 0,
2227 IntrinsicGuardToRegExpStringIterator),
2228 JS_INLINABLE_FN("GuardToSetIterator",
2229 intrinsic_GuardToBuiltin<SetIteratorObject>, 1, 0,
2230 IntrinsicGuardToSetIterator),
2231 JS_INLINABLE_FN("GuardToSetObject", intrinsic_GuardToBuiltin<SetObject>, 1,
2232 0, IntrinsicGuardToSetObject),
2233 JS_INLINABLE_FN("GuardToSharedArrayBuffer",
2234 intrinsic_GuardToBuiltin<SharedArrayBufferObject>, 1, 0,
2235 IntrinsicGuardToSharedArrayBuffer),
2236 JS_INLINABLE_FN("GuardToStringIterator",
2237 intrinsic_GuardToBuiltin<StringIteratorObject>, 1, 0,
2238 IntrinsicGuardToStringIterator),
2239 JS_INLINABLE_FN("GuardToWrapForValidIterator",
2240 intrinsic_GuardToBuiltin<WrapForValidIteratorObject>, 1, 0,
2241 IntrinsicGuardToWrapForValidIterator),
2242 JS_FN("HostResolveImportedModule", intrinsic_HostResolveImportedModule, 2,
2243 0),
2244 JS_FN("InitAsyncEvaluating", intrinsic_InitAsyncEvaluating, 1, 0),
2245 JS_FN("InstantiateModuleFunctionDeclarations",
2246 intrinsic_InstantiateModuleFunctionDeclarations, 1, 0),
2247 JS_FN("IntrinsicAsyncGeneratorNext", AsyncGeneratorNext, 1, 0),
2248 JS_FN("IntrinsicAsyncGeneratorReturn", AsyncGeneratorReturn, 1, 0),
2249 JS_FN("IntrinsicAsyncGeneratorThrow", AsyncGeneratorThrow, 1, 0),
2250 JS_INLINABLE_FN("IsArray", intrinsic_IsArray, 1, 0, ArrayIsArray),
2251 JS_FN("IsAsyncEvaluating", intrinsic_IsAsyncEvaluating, 1, 0),
2252 JS_FN("IsAsyncFunctionGeneratorObject",
2253 intrinsic_IsInstanceOfBuiltin<AsyncFunctionGeneratorObject>, 1, 0),
2254 JS_FN("IsAsyncGeneratorObject",
2255 intrinsic_IsInstanceOfBuiltin<AsyncGeneratorObject>, 1, 0),
2256 JS_INLINABLE_FN("IsCallable", intrinsic_IsCallable, 1, 0,
2257 IntrinsicIsCallable),
2258 JS_INLINABLE_FN("IsConstructing", intrinsic_IsConstructing, 0, 0,
2259 IntrinsicIsConstructing),
2260 JS_INLINABLE_FN("IsConstructor", intrinsic_IsConstructor, 1, 0,
2261 IntrinsicIsConstructor),
2262 JS_INLINABLE_FN("IsCrossRealmArrayConstructor",
2263 intrinsic_IsCrossRealmArrayConstructor, 1, 0,
2264 IntrinsicIsCrossRealmArrayConstructor),
2265 JS_FN("IsGeneratorObject", intrinsic_IsInstanceOfBuiltin<GeneratorObject>,
2266 1, 0),
2267 JS_FN("IsModule", intrinsic_IsInstanceOfBuiltin<ModuleObject>, 1, 0),
2268 JS_FN("IsModuleEnvironment",
2269 intrinsic_IsInstanceOfBuiltin<ModuleEnvironmentObject>, 1, 0),
2270 JS_INLINABLE_FN("IsObject", intrinsic_IsObject, 1, 0, IntrinsicIsObject),
2271 JS_INLINABLE_FN("IsPackedArray", intrinsic_IsPackedArray, 1, 0,
2272 IntrinsicIsPackedArray),
2273 JS_INLINABLE_FN("IsPossiblyWrappedRegExpObject",
2274 intrinsic_IsPossiblyWrappedInstanceOfBuiltin<RegExpObject>,
2275 1, 0, IsPossiblyWrappedRegExpObject),
2276 JS_INLINABLE_FN(
2277 "IsPossiblyWrappedTypedArray",
2278 intrinsic_IsPossiblyWrappedInstanceOfBuiltin<TypedArrayObject>, 1, 0,
2279 IntrinsicIsPossiblyWrappedTypedArray),
2280 JS_INLINABLE_FN("IsRegExpObject",
2281 intrinsic_IsInstanceOfBuiltin<RegExpObject>, 1, 0,
2282 IsRegExpObject),
2283 JS_INLINABLE_FN("IsSuspendedGenerator", intrinsic_IsSuspendedGenerator, 1,
2284 0, IntrinsicIsSuspendedGenerator),
2285 #ifdef ENABLE_RECORD_TUPLE
2286 JS_FN("IsTuple", intrinsic_IsTuple, 1, 0),
2287 #endif
2288 JS_INLINABLE_FN("IsTypedArray",
2289 intrinsic_IsInstanceOfBuiltin<TypedArrayObject>, 1, 0,
2290 IntrinsicIsTypedArray),
2291 JS_INLINABLE_FN("IsTypedArrayConstructor",
2292 intrinsic_IsTypedArrayConstructor, 1, 0,
2293 IntrinsicIsTypedArrayConstructor),
2294 JS_FN("IsWrappedArrayBuffer",
2295 intrinsic_IsWrappedInstanceOfBuiltin<ArrayBufferObject>, 1, 0),
2296 JS_FN("IsWrappedSharedArrayBuffer",
2297 intrinsic_IsWrappedInstanceOfBuiltin<SharedArrayBufferObject>, 1, 0),
2298 JS_FN("ModuleTopLevelCapabilityReject",
2299 intrinsic_ModuleTopLevelCapabilityReject, 2, 0),
2300 JS_FN("ModuleTopLevelCapabilityResolve",
2301 intrinsic_ModuleTopLevelCapabilityResolve, 1, 0),
2302 JS_INLINABLE_FN("NewArrayIterator", intrinsic_NewArrayIterator, 0, 0,
2303 IntrinsicNewArrayIterator),
2304 JS_FN("NewAsyncIteratorHelper", intrinsic_NewAsyncIteratorHelper, 0, 0),
2305 JS_FN("NewIteratorHelper", intrinsic_NewIteratorHelper, 0, 0),
2306 JS_FN("NewModuleNamespace", intrinsic_NewModuleNamespace, 2, 0),
2307 JS_INLINABLE_FN("NewRegExpStringIterator",
2308 intrinsic_NewRegExpStringIterator, 0, 0,
2309 IntrinsicNewRegExpStringIterator),
2310 JS_INLINABLE_FN("NewStringIterator", intrinsic_NewStringIterator, 0, 0,
2311 IntrinsicNewStringIterator),
2312 JS_FN("NewWrapForValidIterator", intrinsic_NewWrapForValidIterator, 0, 0),
2313 JS_FN("NoPrivateGetter", intrinsic_NoPrivateGetter, 1, 0),
2314 JS_INLINABLE_FN("ObjectHasPrototype", intrinsic_ObjectHasPrototype, 2, 0,
2315 IntrinsicObjectHasPrototype),
2316 JS_INLINABLE_FN(
2317 "PossiblyWrappedArrayBufferByteLength",
2318 intrinsic_PossiblyWrappedArrayBufferByteLength<ArrayBufferObject>, 1, 0,
2319 IntrinsicPossiblyWrappedArrayBufferByteLength),
2320 JS_FN(
2321 "PossiblyWrappedSharedArrayBufferByteLength",
2322 intrinsic_PossiblyWrappedArrayBufferByteLength<SharedArrayBufferObject>,
2323 1, 0),
2324 JS_FN("PossiblyWrappedTypedArrayHasDetachedBuffer",
2325 intrinsic_PossiblyWrappedTypedArrayHasDetachedBuffer, 1, 0),
2326 JS_INLINABLE_FN("PossiblyWrappedTypedArrayLength",
2327 intrinsic_PossiblyWrappedTypedArrayLength, 1, 0,
2328 IntrinsicPossiblyWrappedTypedArrayLength),
2329 JS_FN("PromiseResolve", intrinsic_PromiseResolve, 2, 0),
2330 JS_FN("RegExpConstructRaw", regexp_construct_raw_flags, 2, 0),
2331 JS_FN("RegExpCreate", intrinsic_RegExpCreate, 2, 0),
2332 JS_FN("RegExpGetSubstitution", intrinsic_RegExpGetSubstitution, 5, 0),
2333 JS_INLINABLE_FN("RegExpInstanceOptimizable", RegExpInstanceOptimizable, 1,
2334 0, RegExpInstanceOptimizable),
2335 JS_INLINABLE_FN("RegExpMatcher", RegExpMatcher, 3, 0, RegExpMatcher),
2336 JS_INLINABLE_FN("RegExpPrototypeOptimizable", RegExpPrototypeOptimizable, 1,
2337 0, RegExpPrototypeOptimizable),
2338 JS_INLINABLE_FN("RegExpSearcher", RegExpSearcher, 3, 0, RegExpSearcher),
2339 JS_INLINABLE_FN("RegExpTester", RegExpTester, 3, 0, RegExpTester),
2340 JS_INLINABLE_FN("SameValue", js::obj_is, 2, 0, ObjectIs),
2341 JS_FN("SetCycleRoot", intrinsic_SetCycleRoot, 2, 0),
2342 JS_FN("SharedArrayBufferByteLength",
2343 intrinsic_ArrayBufferByteLength<SharedArrayBufferObject>, 1, 0),
2344 JS_FN("SharedArrayBufferCopyData",
2345 intrinsic_ArrayBufferCopyData<SharedArrayBufferObject>, 6, 0),
2346 JS_FN("SharedArrayBuffersMemorySame",
2347 intrinsic_SharedArrayBuffersMemorySame, 2, 0),
2348 JS_FN("StringReplaceAllString", intrinsic_StringReplaceAllString, 3, 0),
2349 JS_INLINABLE_FN("StringReplaceString", intrinsic_StringReplaceString, 3, 0,
2350 IntrinsicStringReplaceString),
2351 JS_INLINABLE_FN("StringSplitString", intrinsic_StringSplitString, 2, 0,
2352 IntrinsicStringSplitString),
2353 JS_FN("StringSplitStringLimit", intrinsic_StringSplitStringLimit, 3, 0),
2354 JS_INLINABLE_FN("SubstringKernel", intrinsic_SubstringKernel, 3, 0,
2355 IntrinsicSubstringKernel),
2356 JS_FN("ThisNumberValueForToLocaleString", ThisNumberValueForToLocaleString,
2357 0, 0),
2358 JS_FN("ThisTimeValue", intrinsic_ThisTimeValue, 1, 0),
2359 #ifdef ENABLE_RECORD_TUPLE
2360 JS_FN("ThisTupleValue", intrinsic_ThisTupleValue, 1, 0),
2361 #endif
2362 JS_FN("ThrowAggregateError", intrinsic_ThrowAggregateError, 4, 0),
2363 JS_FN("ThrowArgTypeNotObject", intrinsic_ThrowArgTypeNotObject, 2, 0),
2364 JS_FN("ThrowInternalError", intrinsic_ThrowInternalError, 4, 0),
2365 JS_FN("ThrowRangeError", intrinsic_ThrowRangeError, 4, 0),
2366 JS_FN("ThrowSyntaxError", intrinsic_ThrowSyntaxError, 4, 0),
2367 JS_FN("ThrowTypeError", intrinsic_ThrowTypeError, 4, 0),
2368 JS_FN("ToBigInt", intrinsic_ToBigInt, 1, 0),
2369 JS_INLINABLE_FN("ToInteger", intrinsic_ToInteger, 1, 0, IntrinsicToInteger),
2370 JS_INLINABLE_FN("ToLength", intrinsic_ToLength, 1, 0, IntrinsicToLength),
2371 JS_INLINABLE_FN("ToObject", intrinsic_ToObject, 1, 0, IntrinsicToObject),
2372 JS_FN("ToPropertyKey", intrinsic_ToPropertyKey, 1, 0),
2373 JS_FN("ToSource", intrinsic_ToSource, 1, 0),
2374 #ifdef ENABLE_RECORD_TUPLE
2375 JS_FN("TupleLength", intrinsic_TupleLength, 1, 0),
2376 #endif
2377 JS_FN("TypedArrayBitwiseSlice", intrinsic_TypedArrayBitwiseSlice, 4, 0),
2378 JS_FN("TypedArrayBuffer", intrinsic_TypedArrayBuffer, 1, 0),
2379 JS_INLINABLE_FN("TypedArrayByteOffset", intrinsic_TypedArrayByteOffset, 1,
2380 0, IntrinsicTypedArrayByteOffset),
2381 JS_INLINABLE_FN("TypedArrayElementSize", intrinsic_TypedArrayElementSize, 1,
2382 0, IntrinsicTypedArrayElementSize),
2383 JS_FN("TypedArrayInitFromPackedArray",
2384 intrinsic_TypedArrayInitFromPackedArray, 2, 0),
2385 JS_INLINABLE_FN("TypedArrayLength", intrinsic_TypedArrayLength, 1, 0,
2386 IntrinsicTypedArrayLength),
2387 JS_INLINABLE_FN("UnsafeGetBooleanFromReservedSlot",
2388 intrinsic_UnsafeGetBooleanFromReservedSlot, 2, 0,
2389 IntrinsicUnsafeGetBooleanFromReservedSlot),
2390 JS_INLINABLE_FN("UnsafeGetInt32FromReservedSlot",
2391 intrinsic_UnsafeGetInt32FromReservedSlot, 2, 0,
2392 IntrinsicUnsafeGetInt32FromReservedSlot),
2393 JS_INLINABLE_FN("UnsafeGetObjectFromReservedSlot",
2394 intrinsic_UnsafeGetObjectFromReservedSlot, 2, 0,
2395 IntrinsicUnsafeGetObjectFromReservedSlot),
2396 JS_INLINABLE_FN("UnsafeGetReservedSlot", intrinsic_UnsafeGetReservedSlot, 2,
2397 0, IntrinsicUnsafeGetReservedSlot),
2398 JS_INLINABLE_FN("UnsafeGetStringFromReservedSlot",
2399 intrinsic_UnsafeGetStringFromReservedSlot, 2, 0,
2400 IntrinsicUnsafeGetStringFromReservedSlot),
2401 JS_INLINABLE_FN("UnsafeSetReservedSlot", intrinsic_UnsafeSetReservedSlot, 3,
2402 0, IntrinsicUnsafeSetReservedSlot),
2403
2404 // Intrinsics and standard functions used by Intl API implementation.
2405 #ifdef JS_HAS_INTL_API
2406 JS_FN("intl_BestAvailableLocale", intl_BestAvailableLocale, 3, 0),
2407 JS_FN("intl_CallCollatorMethodIfWrapped",
2408 CallNonGenericSelfhostedMethod<Is<CollatorObject>>, 2, 0),
2409 JS_FN("intl_CallDateTimeFormatMethodIfWrapped",
2410 CallNonGenericSelfhostedMethod<Is<DateTimeFormatObject>>, 2, 0),
2411 JS_FN("intl_CallDisplayNamesMethodIfWrapped",
2412 CallNonGenericSelfhostedMethod<Is<DisplayNamesObject>>, 2, 0),
2413 JS_FN("intl_CallListFormatMethodIfWrapped",
2414 CallNonGenericSelfhostedMethod<Is<ListFormatObject>>, 2, 0),
2415 JS_FN("intl_CallNumberFormatMethodIfWrapped",
2416 CallNonGenericSelfhostedMethod<Is<NumberFormatObject>>, 2, 0),
2417 JS_FN("intl_CallPluralRulesMethodIfWrapped",
2418 CallNonGenericSelfhostedMethod<Is<PluralRulesObject>>, 2, 0),
2419 JS_FN("intl_CallRelativeTimeFormatMethodIfWrapped",
2420 CallNonGenericSelfhostedMethod<Is<RelativeTimeFormatObject>>, 2, 0),
2421 JS_FN("intl_Collator", intl_Collator, 2, 0),
2422 JS_FN("intl_CompareStrings", intl_CompareStrings, 3, 0),
2423 JS_FN("intl_ComputeDisplayName", intl_ComputeDisplayName, 6, 0),
2424 JS_FN("intl_DateTimeFormat", intl_DateTimeFormat, 2, 0),
2425 JS_FN("intl_FormatDateTime", intl_FormatDateTime, 2, 0),
2426 JS_FN("intl_FormatDateTimeRange", intl_FormatDateTimeRange, 4, 0),
2427 JS_FN("intl_FormatList", intl_FormatList, 3, 0),
2428 JS_FN("intl_FormatNumber", intl_FormatNumber, 3, 0),
2429 JS_FN("intl_FormatNumberRange", intl_FormatNumberRange, 4, 0),
2430 JS_FN("intl_FormatRelativeTime", intl_FormatRelativeTime, 4, 0),
2431 JS_FN("intl_GetCalendarInfo", intl_GetCalendarInfo, 1, 0),
2432 JS_FN("intl_GetPluralCategories", intl_GetPluralCategories, 1, 0),
2433 JS_INLINABLE_FN("intl_GuardToCollator",
2434 intrinsic_GuardToBuiltin<CollatorObject>, 1, 0,
2435 IntlGuardToCollator),
2436 JS_INLINABLE_FN("intl_GuardToDateTimeFormat",
2437 intrinsic_GuardToBuiltin<DateTimeFormatObject>, 1, 0,
2438 IntlGuardToDateTimeFormat),
2439 JS_INLINABLE_FN("intl_GuardToDisplayNames",
2440 intrinsic_GuardToBuiltin<DisplayNamesObject>, 1, 0,
2441 IntlGuardToDisplayNames),
2442 JS_INLINABLE_FN("intl_GuardToListFormat",
2443 intrinsic_GuardToBuiltin<ListFormatObject>, 1, 0,
2444 IntlGuardToListFormat),
2445 JS_INLINABLE_FN("intl_GuardToNumberFormat",
2446 intrinsic_GuardToBuiltin<NumberFormatObject>, 1, 0,
2447 IntlGuardToNumberFormat),
2448 JS_INLINABLE_FN("intl_GuardToPluralRules",
2449 intrinsic_GuardToBuiltin<PluralRulesObject>, 1, 0,
2450 IntlGuardToPluralRules),
2451 JS_INLINABLE_FN("intl_GuardToRelativeTimeFormat",
2452 intrinsic_GuardToBuiltin<RelativeTimeFormatObject>, 1, 0,
2453 IntlGuardToRelativeTimeFormat),
2454 JS_FN("intl_IsRuntimeDefaultLocale", intrinsic_IsRuntimeDefaultLocale, 1,
2455 0),
2456 JS_FN("intl_IsValidTimeZoneName", intl_IsValidTimeZoneName, 1, 0),
2457 JS_FN("intl_IsWrappedDateTimeFormat",
2458 intrinsic_IsWrappedInstanceOfBuiltin<DateTimeFormatObject>, 1, 0),
2459 JS_FN("intl_IsWrappedNumberFormat",
2460 intrinsic_IsWrappedInstanceOfBuiltin<NumberFormatObject>, 1, 0),
2461 JS_FN("intl_NumberFormat", intl_NumberFormat, 2, 0),
2462 JS_FN("intl_RuntimeDefaultLocale", intrinsic_RuntimeDefaultLocale, 0, 0),
2463 JS_FN("intl_SelectPluralRule", intl_SelectPluralRule, 2, 0),
2464 JS_FN("intl_SelectPluralRuleRange", intl_SelectPluralRuleRange, 3, 0),
2465 JS_FN("intl_SupportedValuesOf", intl_SupportedValuesOf, 1, 0),
2466 JS_FN("intl_TryValidateAndCanonicalizeLanguageTag",
2467 intl_TryValidateAndCanonicalizeLanguageTag, 1, 0),
2468 JS_FN("intl_ValidateAndCanonicalizeLanguageTag",
2469 intl_ValidateAndCanonicalizeLanguageTag, 2, 0),
2470 JS_FN("intl_ValidateAndCanonicalizeUnicodeExtensionType",
2471 intl_ValidateAndCanonicalizeUnicodeExtensionType, 3, 0),
2472 JS_FN("intl_availableCalendars", intl_availableCalendars, 1, 0),
2473 JS_FN("intl_availableCollations", intl_availableCollations, 1, 0),
2474 # if DEBUG || MOZ_SYSTEM_ICU
2475 JS_FN("intl_availableMeasurementUnits", intl_availableMeasurementUnits, 0,
2476 0),
2477 # endif
2478 JS_FN("intl_canonicalizeTimeZone", intl_canonicalizeTimeZone, 1, 0),
2479 JS_FN("intl_defaultCalendar", intl_defaultCalendar, 1, 0),
2480 JS_FN("intl_defaultTimeZone", intl_defaultTimeZone, 0, 0),
2481 JS_FN("intl_defaultTimeZoneOffset", intl_defaultTimeZoneOffset, 0, 0),
2482 JS_FN("intl_isDefaultTimeZone", intl_isDefaultTimeZone, 1, 0),
2483 JS_FN("intl_isUpperCaseFirst", intl_isUpperCaseFirst, 1, 0),
2484 JS_FN("intl_numberingSystem", intl_numberingSystem, 1, 0),
2485 JS_FN("intl_resolveDateTimeFormatComponents",
2486 intl_resolveDateTimeFormatComponents, 3, 0),
2487 JS_FN("intl_supportedLocaleOrFallback", intl_supportedLocaleOrFallback, 1,
2488 0),
2489 JS_FN("intl_toLocaleLowerCase", intl_toLocaleLowerCase, 2, 0),
2490 JS_FN("intl_toLocaleUpperCase", intl_toLocaleUpperCase, 2, 0),
2491 #endif // JS_HAS_INTL_API
2492
2493 // Standard builtins used by self-hosting.
2494 JS_INLINABLE_FN("std_Array", array_construct, 1, 0, Array),
2495 JS_FN("std_Array_includes", array_includes, 1, 0),
2496 JS_FN("std_Array_indexOf", array_indexOf, 1, 0),
2497 JS_FN("std_Array_lastIndexOf", array_lastIndexOf, 1, 0),
2498 JS_INLINABLE_FN("std_Array_pop", array_pop, 0, 0, ArrayPop),
2499 JS_INLINABLE_FN("std_Array_push", array_push, 1, 0, ArrayPush),
2500 JS_FN("std_BigInt_valueOf", BigIntObject::valueOf, 0, 0),
2501 JS_FN("std_Date_now", date_now, 0, 0),
2502 JS_FN("std_Function_apply", fun_apply, 2, 0),
2503 JS_FN("std_Map_entries", MapObject::entries, 0, 0),
2504 JS_FN("std_Map_get", MapObject::get, 1, 0),
2505 JS_FN("std_Map_set", MapObject::set, 2, 0),
2506 JS_INLINABLE_FN("std_Math_abs", math_abs, 1, 0, MathAbs),
2507 JS_INLINABLE_FN("std_Math_floor", math_floor, 1, 0, MathFloor),
2508 JS_INLINABLE_FN("std_Math_max", math_max, 2, 0, MathMax),
2509 JS_INLINABLE_FN("std_Math_min", math_min, 2, 0, MathMin),
2510 JS_INLINABLE_FN("std_Math_trunc", math_trunc, 1, 0, MathTrunc),
2511 JS_INLINABLE_FN("std_Object_create", obj_create, 2, 0, ObjectCreate),
2512 JS_INLINABLE_FN("std_Object_isPrototypeOf", obj_isPrototypeOf, 1, 0,
2513 ObjectIsPrototypeOf),
2514 JS_FN("std_Object_propertyIsEnumerable", obj_propertyIsEnumerable, 1, 0),
2515 JS_FN("std_Object_setProto", obj_setProto, 1, 0),
2516 JS_FN("std_Object_toString", obj_toString, 0, 0),
2517 JS_INLINABLE_FN("std_Reflect_getPrototypeOf", Reflect_getPrototypeOf, 1, 0,
2518 ReflectGetPrototypeOf),
2519 JS_FN("std_Reflect_isExtensible", Reflect_isExtensible, 1, 0),
2520 JS_FN("std_Reflect_ownKeys", Reflect_ownKeys, 1, 0),
2521 JS_FN("std_Set_add", SetObject::add, 1, 0),
2522 JS_FN("std_Set_has", SetObject::has, 1, 0),
2523 JS_FN("std_Set_values", SetObject::values, 0, 0),
2524 JS_INLINABLE_FN("std_String_charCodeAt", str_charCodeAt, 1, 0,
2525 StringCharCodeAt),
2526 JS_FN("std_String_endsWith", str_endsWith, 1, 0),
2527 JS_INLINABLE_FN("std_String_fromCharCode", str_fromCharCode, 1, 0,
2528 StringFromCharCode),
2529 JS_INLINABLE_FN("std_String_fromCodePoint", str_fromCodePoint, 1, 0,
2530 StringFromCodePoint),
2531 JS_FN("std_String_includes", str_includes, 1, 0),
2532 JS_FN("std_String_indexOf", str_indexOf, 1, 0),
2533 JS_FN("std_String_startsWith", str_startsWith, 1, 0),
2534 #ifdef ENABLE_RECORD_TUPLE
2535 JS_FN("std_Tuple_unchecked", tuple_construct, 1, 0),
2536 #endif
2537 JS_FN("std_TypedArray_buffer", js::TypedArray_bufferGetter, 1, 0),
2538
2539 JS_FS_END};
2540
2541 #ifdef DEBUG
CheckSelfHostedIntrinsics()2542 static void CheckSelfHostedIntrinsics() {
2543 // The `intrinsic_functions` list must be sorted so that we can use
2544 // mozilla::BinarySearch to do lookups on demand.
2545 const char* prev = "";
2546 for (JSFunctionSpec spec : intrinsic_functions) {
2547 if (spec.name.string()) {
2548 MOZ_ASSERT(strcmp(prev, spec.name.string()) < 0,
2549 "Self-hosted intrinsics must be sorted");
2550 prev = spec.name.string();
2551 }
2552 }
2553 }
2554 #endif
2555
FindIntrinsicSpec(js::PropertyName * name)2556 const JSFunctionSpec* js::FindIntrinsicSpec(js::PropertyName* name) {
2557 size_t limit = std::size(intrinsic_functions) - 1;
2558 MOZ_ASSERT(!intrinsic_functions[limit].name);
2559
2560 MOZ_ASSERT(name->hasLatin1Chars());
2561
2562 JS::AutoCheckCannotGC nogc;
2563 const char* chars = reinterpret_cast<const char*>(name->latin1Chars(nogc));
2564 size_t len = name->length();
2565
2566 // NOTE: CheckSelfHostedIntrinsics checks that the intrinsic_functions list is
2567 // sorted appropriately so that we can use binary search here.
2568
2569 size_t loc = 0;
2570 bool match = mozilla::BinarySearchIf(
2571 intrinsic_functions, 0, limit,
2572 [chars, len](const JSFunctionSpec& spec) {
2573 // The spec string is null terminated but the `name` string is not, so
2574 // compare chars up until the length of `name`. Since the `name` string
2575 // does not contain any nulls, seeing the null terminator of the spec
2576 // string will terminate the loop appropriately. A final comparison
2577 // against null is needed to determine if the spec string has an extra
2578 // suffix.
2579 const char* spec_chars = spec.name.string();
2580 for (size_t i = 0; i < len; ++i) {
2581 if (auto cmp_result = int(chars[i]) - int(spec_chars[i])) {
2582 return cmp_result;
2583 }
2584 }
2585 return int('\0') - int(spec_chars[len]);
2586 },
2587 &loc);
2588 if (match) {
2589 return &intrinsic_functions[loc];
2590 }
2591 return nullptr;
2592 }
2593
FillSelfHostingCompileOptions(CompileOptions & options)2594 void js::FillSelfHostingCompileOptions(CompileOptions& options) {
2595 /*
2596 * In self-hosting mode, scripts use JSOp::GetIntrinsic instead of
2597 * JSOp::GetName or JSOp::GetGName to access unbound variables.
2598 * JSOp::GetIntrinsic does a name lookup on a special object, whose
2599 * properties are filled in lazily upon first access for a given global.
2600 *
2601 * As that object is inaccessible to client code, the lookups are
2602 * guaranteed to return the original objects, ensuring safe implementation
2603 * of self-hosted builtins.
2604 *
2605 * Additionally, the special syntax callFunction(fun, receiver, ...args)
2606 * is supported, for which bytecode is emitted that invokes |fun| with
2607 * |receiver| as the this-object and ...args as the arguments.
2608 */
2609 options.setIntroductionType("self-hosted");
2610 options.setFileAndLine("self-hosted", 1);
2611 options.setSkipFilenameValidation(true);
2612 options.setSelfHostingMode(true);
2613 options.setForceFullParse();
2614 options.setForceStrictMode();
2615 options.setDiscardSource();
2616 options.setIsRunOnce(true);
2617 options.setNoScriptRval(true);
2618 }
2619
2620 class MOZ_STACK_CLASS AutoSelfHostingErrorReporter {
2621 JSContext* cx_;
2622 JS::WarningReporter oldReporter_;
2623
2624 public:
AutoSelfHostingErrorReporter(JSContext * cx)2625 explicit AutoSelfHostingErrorReporter(JSContext* cx) : cx_(cx) {
2626 oldReporter_ = JS::SetWarningReporter(cx_, selfHosting_WarningReporter);
2627 }
~AutoSelfHostingErrorReporter()2628 ~AutoSelfHostingErrorReporter() {
2629 JS::SetWarningReporter(cx_, oldReporter_);
2630
2631 // Exceptions in self-hosted code will usually be printed to stderr in
2632 // ErrorToException, but not all exceptions are handled there. For
2633 // instance, ReportOutOfMemory will throw the "out of memory" string
2634 // without going through ErrorToException. We handle these other
2635 // exceptions here.
2636 MaybePrintAndClearPendingException(cx_);
2637 }
2638 };
2639
InitSelfHostingFromStencil(JSContext * cx,frontend::CompilationAtomCache & atomCache,const frontend::CompilationStencil & stencil)2640 [[nodiscard]] static bool InitSelfHostingFromStencil(
2641 JSContext* cx, frontend::CompilationAtomCache& atomCache,
2642 const frontend::CompilationStencil& stencil) {
2643 // Build the JSAtom -> ScriptIndexRange mapping and save on the runtime.
2644 {
2645 auto& scriptMap = cx->runtime()->selfHostScriptMap.ref();
2646
2647 // We don't easily know the number of top-level functions, so use the total
2648 // number of stencil functions instead. There is very little nesting of
2649 // functions in self-hosted code so this is a good approximation.
2650 size_t numSelfHostedScripts = stencil.scriptData.size();
2651 if (!scriptMap.reserve(numSelfHostedScripts)) {
2652 ReportOutOfMemory(cx);
2653 return false;
2654 }
2655
2656 auto topLevelThings =
2657 stencil.scriptData[frontend::CompilationStencil::TopLevelIndex]
2658 .gcthings(stencil);
2659
2660 // Iterate over the (named) top-level functions. We record the ScriptIndex
2661 // as well as the ScriptIndex of the next top-level function. Scripts
2662 // between these two indices are the inner functions of the first one. We
2663 // only record named scripts here since they are what might be looked up.
2664 RootedAtom prevAtom(cx);
2665 frontend::ScriptIndex prevIndex;
2666 for (frontend::TaggedScriptThingIndex thing : topLevelThings) {
2667 if (!thing.isFunction()) {
2668 continue;
2669 }
2670
2671 frontend::ScriptIndex index = thing.toFunction();
2672 const auto& script = stencil.scriptData[index];
2673
2674 if (prevAtom) {
2675 frontend::ScriptIndexRange range{prevIndex, index};
2676 scriptMap.putNewInfallible(prevAtom, range);
2677 }
2678
2679 prevAtom = script.functionAtom
2680 ? atomCache.getExistingAtomAt(cx, script.functionAtom)
2681 : nullptr;
2682 prevIndex = index;
2683 }
2684 if (prevAtom) {
2685 frontend::ScriptIndexRange range{
2686 prevIndex, frontend::ScriptIndex(stencil.scriptData.size())};
2687 scriptMap.putNewInfallible(prevAtom, range);
2688 }
2689
2690 // We over-estimated the capacity of `scriptMap`, so check that the estimate
2691 // hasn't drifted too hasn't drifted too far since this was written. If this
2692 // assert fails, we may need a new way to size the `scriptMap`.
2693 MOZ_ASSERT(numSelfHostedScripts < (scriptMap.count() * 1.15));
2694 }
2695
2696 #ifdef DEBUG
2697 // Check that the list of intrinsics is well-formed.
2698 CheckSelfHostedIntrinsics();
2699 #endif
2700
2701 return true;
2702 }
2703
initSelfHostingStencil(JSContext * cx,JS::SelfHostedCache xdrCache,JS::SelfHostedWriter xdrWriter)2704 bool JSRuntime::initSelfHostingStencil(JSContext* cx,
2705 JS::SelfHostedCache xdrCache,
2706 JS::SelfHostedWriter xdrWriter) {
2707 if (parentRuntime) {
2708 MOZ_RELEASE_ASSERT(
2709 parentRuntime->hasInitializedSelfHosting(),
2710 "Parent runtime must initialize self-hosting before workers");
2711
2712 selfHostStencilInput_ = parentRuntime->selfHostStencilInput_;
2713 selfHostStencil_ = parentRuntime->selfHostStencil_;
2714 return true;
2715 }
2716
2717 /*
2718 * Set a temporary error reporter printing to stderr because it is too
2719 * early in the startup process for any other reporter to be registered
2720 * and we don't want errors in self-hosted code to be silently swallowed.
2721 *
2722 * This class also overrides the warning reporter to print warnings to
2723 * stderr. See selfHosting_WarningReporter.
2724 */
2725 AutoSelfHostingErrorReporter errorReporter(cx);
2726
2727 // Variables used to instantiate scripts.
2728 CompileOptions options(cx);
2729 FillSelfHostingCompileOptions(options);
2730
2731 // Try initializing from Stencil XDR.
2732 bool decodeOk = false;
2733 if (xdrCache.Length() > 0) {
2734 // Allow the VM to directly use bytecode from the XDR buffer without
2735 // copying it. The buffer must outlive all runtimes (including workers).
2736 options.borrowBuffer = true;
2737 options.usePinnedBytecode = true;
2738
2739 Rooted<UniquePtr<frontend::CompilationInput>> input(
2740 cx, cx->new_<frontend::CompilationInput>(options));
2741 if (!input) {
2742 return false;
2743 }
2744 if (!input->initForSelfHostingGlobal(cx)) {
2745 return false;
2746 }
2747
2748 RefPtr<frontend::CompilationStencil> stencil(
2749 cx->new_<frontend::CompilationStencil>(input->source));
2750 if (!stencil) {
2751 return false;
2752 }
2753 if (!stencil->deserializeStencils(cx, *input, xdrCache, &decodeOk)) {
2754 return false;
2755 }
2756
2757 if (decodeOk) {
2758 MOZ_ASSERT(input->atomCache.empty());
2759
2760 MOZ_ASSERT(!hasSelfHostStencil());
2761
2762 // Move it to the runtime.
2763 cx->runtime()->selfHostStencilInput_ = input.release();
2764 cx->runtime()->selfHostStencil_ = stencil.forget().take();
2765
2766 return true;
2767 }
2768 }
2769
2770 // If script wasn't generated, it means XDR was either not provided or that it
2771 // failed the decoding phase. Parse from text as before.
2772 uint32_t srcLen = GetRawScriptsSize();
2773 const unsigned char* compressed = compressedSources;
2774 uint32_t compressedLen = GetCompressedSize();
2775 auto src = cx->make_pod_array<char>(srcLen);
2776 if (!src) {
2777 return false;
2778 }
2779 if (!DecompressString(compressed, compressedLen,
2780 reinterpret_cast<unsigned char*>(src.get()), srcLen)) {
2781 return false;
2782 }
2783
2784 JS::SourceText<mozilla::Utf8Unit> srcBuf;
2785 if (!srcBuf.init(cx, std::move(src), srcLen)) {
2786 return false;
2787 }
2788
2789 Rooted<UniquePtr<frontend::CompilationInput>> input(
2790 cx, cx->new_<frontend::CompilationInput>(options));
2791 if (!input) {
2792 return false;
2793 }
2794 RefPtr<frontend::CompilationStencil> stencil =
2795 frontend::CompileGlobalScriptToStencil(cx, *input, srcBuf,
2796 ScopeKind::Global);
2797 if (!stencil) {
2798 return false;
2799 }
2800
2801 // Serialize the stencil to XDR.
2802 if (xdrWriter) {
2803 JS::TranscodeBuffer xdrBuffer;
2804 if (!stencil->serializeStencils(cx, *input, xdrBuffer)) {
2805 return false;
2806 }
2807
2808 if (!xdrWriter(cx, xdrBuffer)) {
2809 return false;
2810 }
2811 }
2812
2813 MOZ_ASSERT(input->atomCache.empty());
2814
2815 MOZ_ASSERT(!hasSelfHostStencil());
2816
2817 // Move it to the runtime.
2818 cx->runtime()->selfHostStencilInput_ = input.release();
2819 cx->runtime()->selfHostStencil_ = stencil.forget().take();
2820
2821 return true;
2822 }
2823
initSelfHostingFromStencil(JSContext * cx)2824 bool JSRuntime::initSelfHostingFromStencil(JSContext* cx) {
2825 return InitSelfHostingFromStencil(
2826 cx, cx->runtime()->selfHostStencilInput_->atomCache,
2827 *cx->runtime()->selfHostStencil_);
2828 }
2829
finishSelfHosting()2830 void JSRuntime::finishSelfHosting() {
2831 if (!parentRuntime) {
2832 js_delete(selfHostStencilInput_.ref());
2833 if (selfHostStencil_) {
2834 // delete selfHostStencil_ by decrementing the ref-count of the last
2835 // instance.
2836 RefPtr<frontend::CompilationStencil> stencil;
2837 *getter_AddRefs(stencil) = selfHostStencil_;
2838 MOZ_ASSERT(stencil->refCount == 1);
2839 }
2840 }
2841
2842 selfHostStencilInput_ = nullptr;
2843 selfHostStencil_ = nullptr;
2844
2845 selfHostScriptMap.ref().clear();
2846 }
2847
traceSelfHostingStencil(JSTracer * trc)2848 void JSRuntime::traceSelfHostingStencil(JSTracer* trc) {
2849 if (selfHostStencilInput_.ref()) {
2850 selfHostStencilInput_->trace(trc);
2851 }
2852 selfHostScriptMap.ref().trace(trc);
2853 }
2854
getSelfHostedFunctionGeneratorKind(js::PropertyName * name)2855 GeneratorKind JSRuntime::getSelfHostedFunctionGeneratorKind(
2856 js::PropertyName* name) {
2857 frontend::ScriptIndex index = getSelfHostedScriptIndexRange(name)->start;
2858 auto flags = selfHostStencil().scriptExtra[index].immutableFlags;
2859 return flags.hasFlag(js::ImmutableScriptFlagsEnum::IsGenerator)
2860 ? GeneratorKind::Generator
2861 : GeneratorKind::NotGenerator;
2862 }
2863
2864 // Returns the ScriptSourceObject to use for cloned self-hosted scripts in the
2865 // current realm.
SelfHostingScriptSourceObject(JSContext * cx)2866 ScriptSourceObject* js::SelfHostingScriptSourceObject(JSContext* cx) {
2867 return GlobalObject::getOrCreateSelfHostingScriptSourceObject(cx,
2868 cx->global());
2869 }
2870
2871 /* static */
getOrCreateSelfHostingScriptSourceObject(JSContext * cx,Handle<GlobalObject * > global)2872 ScriptSourceObject* GlobalObject::getOrCreateSelfHostingScriptSourceObject(
2873 JSContext* cx, Handle<GlobalObject*> global) {
2874 MOZ_ASSERT(cx->global() == global);
2875
2876 if (ScriptSourceObject* sso = global->data().selfHostingScriptSource) {
2877 return sso;
2878 }
2879
2880 CompileOptions options(cx);
2881 FillSelfHostingCompileOptions(options);
2882
2883 RefPtr<ScriptSource> source(cx->new_<ScriptSource>());
2884 if (!source) {
2885 return nullptr;
2886 }
2887
2888 if (!source->initFromOptions(cx, options)) {
2889 return nullptr;
2890 }
2891
2892 RootedScriptSourceObject sourceObject(
2893 cx, ScriptSourceObject::create(cx, source.get()));
2894 if (!sourceObject) {
2895 return nullptr;
2896 }
2897
2898 JS::InstantiateOptions instantiateOptions(options);
2899 if (!ScriptSourceObject::initFromOptions(cx, sourceObject,
2900 instantiateOptions)) {
2901 return nullptr;
2902 }
2903
2904 global->data().selfHostingScriptSource.init(sourceObject);
2905 return sourceObject;
2906 }
2907
delazifySelfHostedFunction(JSContext * cx,HandlePropertyName name,HandleFunction targetFun)2908 bool JSRuntime::delazifySelfHostedFunction(JSContext* cx,
2909 HandlePropertyName name,
2910 HandleFunction targetFun) {
2911 MOZ_ASSERT(targetFun->isExtended());
2912 MOZ_ASSERT(targetFun->hasSelfHostedLazyScript());
2913
2914 auto indexRange = *getSelfHostedScriptIndexRange(name);
2915 auto& stencil = cx->runtime()->selfHostStencil();
2916
2917 if (!stencil.delazifySelfHostedFunction(
2918 cx, cx->runtime()->selfHostStencilInput().atomCache, indexRange,
2919 targetFun)) {
2920 return false;
2921 }
2922
2923 // Relazifiable self-hosted functions may be relazified later into a
2924 // SelfHostedLazyScript, dropping the BaseScript entirely. This only applies
2925 // to named function being delazified. Inner functions used by self-hosting
2926 // are never relazified.
2927 BaseScript* targetScript = targetFun->baseScript();
2928 if (targetScript->isRelazifiable()) {
2929 targetScript->setAllowRelazify();
2930 }
2931
2932 return true;
2933 }
2934
2935 mozilla::Maybe<frontend::ScriptIndexRange>
getSelfHostedScriptIndexRange(js::PropertyName * name)2936 JSRuntime::getSelfHostedScriptIndexRange(js::PropertyName* name) {
2937 if (parentRuntime) {
2938 return parentRuntime->getSelfHostedScriptIndexRange(name);
2939 }
2940 MOZ_ASSERT(name->isPermanentAndMayBeShared());
2941 if (auto ptr = selfHostScriptMap.ref().readonlyThreadsafeLookup(name)) {
2942 return mozilla::Some(ptr->value());
2943 }
2944 return mozilla::Nothing();
2945 }
2946
GetComputedIntrinsic(JSContext * cx,HandlePropertyName name,MutableHandleValue vp)2947 static bool GetComputedIntrinsic(JSContext* cx, HandlePropertyName name,
2948 MutableHandleValue vp) {
2949 // If the intrinsic was not in hardcoded set, run the top-level of the
2950 // selfhosted script. This will generate values and call `SetIntrinsic` to
2951 // save them on a special "computed intrinsics holder". We then can check for
2952 // our required values and cache on the normal intrinsics holder.
2953
2954 RootedNativeObject computedIntrinsicsHolder(
2955 cx, cx->global()->getComputedIntrinsicsHolder());
2956 if (!computedIntrinsicsHolder) {
2957 auto computedIntrinsicHolderGuard = mozilla::MakeScopeExit(
2958 [cx]() { cx->global()->setComputedIntrinsicsHolder(nullptr); });
2959
2960 // Instantiate a script in current realm from the shared Stencil.
2961 JSRuntime* runtime = cx->runtime();
2962 RootedScript script(
2963 cx, runtime->selfHostStencil().instantiateSelfHostedTopLevelForRealm(
2964 cx, runtime->selfHostStencilInput()));
2965 if (!script) {
2966 return false;
2967 }
2968
2969 // Attach the computed intrinsics holder to the global now to capture
2970 // generated values.
2971 computedIntrinsicsHolder =
2972 NewPlainObjectWithProto(cx, nullptr, TenuredObject);
2973 if (!computedIntrinsicsHolder) {
2974 return false;
2975 }
2976 cx->global()->setComputedIntrinsicsHolder(computedIntrinsicsHolder);
2977
2978 // Attempt to execute the top-level script. If they fails to run to
2979 // successful completion, throw away the holder to avoid a partial
2980 // initialization state.
2981 if (!JS_ExecuteScript(cx, script)) {
2982 return false;
2983 }
2984
2985 // Successfully ran the self-host top-level in current realm, so these
2986 // computed intrinsic values are now source of truth for the realm.
2987 computedIntrinsicHolderGuard.release();
2988 }
2989
2990 // Cache the individual intrinsic on the standard holder object so that we
2991 // only have to look for it in one place when performing `GetIntrinsic`.
2992 mozilla::Maybe<PropertyInfo> prop =
2993 computedIntrinsicsHolder->lookup(cx, name);
2994 MOZ_RELEASE_ASSERT(prop, "SelfHosted intrinsic not found");
2995 RootedValue value(cx, computedIntrinsicsHolder->getSlot(prop->slot()));
2996 return GlobalObject::addIntrinsicValue(cx, cx->global(), name, value);
2997 }
2998
getSelfHostedValue(JSContext * cx,HandlePropertyName name,MutableHandleValue vp)2999 bool JSRuntime::getSelfHostedValue(JSContext* cx, HandlePropertyName name,
3000 MutableHandleValue vp) {
3001 // If the self-hosted value we want is a function in the stencil, instantiate
3002 // a lazy self-hosted function for it. This is typical when a self-hosted
3003 // function calls other self-hosted helper functions.
3004 if (auto index = getSelfHostedScriptIndexRange(name)) {
3005 JSFunction* fun =
3006 cx->runtime()->selfHostStencil().instantiateSelfHostedLazyFunction(
3007 cx, cx->runtime()->selfHostStencilInput().atomCache, index->start,
3008 name);
3009 if (!fun) {
3010 return false;
3011 }
3012 vp.setObject(*fun);
3013 return true;
3014 }
3015
3016 return GetComputedIntrinsic(cx, name, vp);
3017 }
3018
assertSelfHostedFunctionHasCanonicalName(HandlePropertyName name)3019 void JSRuntime::assertSelfHostedFunctionHasCanonicalName(
3020 HandlePropertyName name) {
3021 #ifdef DEBUG
3022 frontend::ScriptIndex index = getSelfHostedScriptIndexRange(name)->start;
3023 MOZ_ASSERT(selfHostStencil().scriptData[index].hasSelfHostedCanonicalName());
3024 #endif
3025 }
3026
IsSelfHostedFunctionWithName(JSFunction * fun,JSAtom * name)3027 bool js::IsSelfHostedFunctionWithName(JSFunction* fun, JSAtom* name) {
3028 return fun->isSelfHostedBuiltin() && fun->isExtended() &&
3029 GetClonedSelfHostedFunctionName(fun) == name;
3030 }
3031
3032 static_assert(
3033 JSString::MAX_LENGTH <= INT32_MAX,
3034 "StringIteratorNext in builtin/String.js assumes the stored index "
3035 "into the string is an Int32Value");
3036
3037 static_assert(JSString::MAX_LENGTH == MAX_STRING_LENGTH,
3038 "JSString::MAX_LENGTH matches self-hosted constant for maximum "
3039 "string length");
3040
3041 static_assert(ARGS_LENGTH_MAX == MAX_ARGS_LENGTH,
3042 "ARGS_LENGTH_MAX matches self-hosted constant for maximum "
3043 "arguments length");
3044