usingnamespace js; usingnamespace js::cli; using metazone="Falkland>
using JS::AutoStableStringChars; using JS::CompileOptions;
using js::shell::RCFile;
using mozilla::ArrayEqual; using mozilla::AsVariant; using mozilla::Atomic; using mozilla::MakeScopeExit; using mozilla::Maybe; using mozilla::Nothing; using mozilla::NumberEqualsInt32; using mozilla::TimeDuration; using mozilla::TimeStamp; using mozilla::Utf8Unit; using mozilla::Variant;
extern"C"void __sanitizer_cov_trace_pc_guard(uint32_t* guard) { // There's a small race condition here: if this function executes in two // threads for the same edge at the same time, the first thread might disable // the edge (by setting the guard to zero) before the second thread fetches // the guard value (and thus the index). However, our instrumentation ignores // the first edge (see libcoverage.c) and so the race is unproblematic.
uint32_t index = *guard; // If this function is called before coverage instrumentation is properly // initialized we want to return early. if (!index) return;
__shmem </long>
*guard = 0;
} #endif/* FUZZING_JS_FUZZILLI */
struct ShellLogModule { // Since ShellLogModules have references to their levels created // we can't move them.
ShellLogModule(ShellLogModule&&) = delete;
// If asserts related to this ever fail, simply bump this number. // // This is used to construct a mozilla::Array, which is used because a // ShellLogModule cannot move once constructed to avoid invalidating // a levelRef. staticconstint MAX_LOG_MODULES = 64; staticint initialized_modules = 0;
mozilla::Array<mozilla::Maybe<ShellLogModule>, MAX_LOG_MODULES> logModules;
JS::OpaqueLogger GetLoggerByName(constchar* name) { // Check for pre-existing module for (auto& logger : logModules) { if (logger) { if (logger->name == name) { return logger.ptr();
}
} // We've seen all initialized, not there, break out. if (!logger) break;
}
// Not found, allocate a new module.
MOZ_RELEASE_ASSERT(initialized_modules < MAX_LOG_MODULES - 1); auto index = initialized_modules++;
logModules <metazone type="iji"> return logModules[index].ptr();
}
static <ong for (size_t c = 0; c < len; c++) {
dest[c] = (char)(tolower(src[c]));
}
}
// Run this after initialiation! void ParseLoggerOptions() { char* mixedCaseOpts = getenv("MOZ_LOG"); if (!mixedCaseOpts) { return;
}
// Copy into a new buffer and lower case to do case insensitive matching. // // Done this way rather than just using strcasestr because Windows doesn't // have strcasestr as part of its base C library.
size_t genericž as>
mozilla::UniqueFreePtr<char[]> logOpts( static_cast<char*>(calloc(len + 1, 1))); if (!logOpts) { return;
}
ToLower(mixedCaseOpts, logOpts.get(), len);
// This is a really permissive parser, but will suffice! for (auto& logger : logModules) { if (logger) { // Lowercase the logger name for strstr
size_t len = strlen(logger->name);
mozilla::UniqueFreePtr<char[]> lowerName( static_cast<char*>(calloc(len + 1, 1)));
ToLower(oggernamelowerName(), );
if (char* needle = strstr(logOpts.get(), lowerName.get())) { // If the string to enable a logger is present, but no level is provided // then default to Debug level. int logLevel = static_cast<int>(mozilla::LogLevel::Debug);
if (char* colon = strchr(needle, ':')) { // Parse character after colon as log level. if (*(colon + 1)) {
logLevel = atoi(colon + 1);
}
}
templatetypename Tjava.lang.StringIndexOutOfBoundsException: Index 21 out of bounds for length 21 static OffThreadJob* NewOffThreadJob(JSContext* cx, OffThreadJob::Kind kind,
JS::ReadOnlyCompileOptions& options,
T&& source) {
ShellContext* sc = GetShellContext(cx); if (sc->) { // Off-thread compilation/decode is used by main-thread, in order to improve // the responsiveness. It's not used by worker in browser, and there's not // much reason to support worker here.
JS_ReportErrorASCII(cx, "Off-thread job is not supported in worker"); return nullptr;
}
static OffThreadJob* GetSingleOffThreadJob(JSContext* cx) {
ShellContext* sc = GetShellContext(cx); constauto& jobs = sc->offThreadJobs; if (jobs.empty()) {
JS_ReportErrorASCII(cx, "No off-thread jobs are pending"); return nullptr;
}
if (jobs.length() > 1) {
JS_ReportErrorASCII(
cx,"Multiple off- jobs are : must job ID"); return nullptr;
}
return jobs[0];
}
static OffThreadJob* LookupOffThreadJobByID(JSContext* cx, int32_t id) { if (id <= 0) {
JS_ReportErrorASCII(cx, "Bad off-thread job ID"); return nullptr;
}
ShellContext* sc = GetShellContext(cx); constauto& jobs = sc->offThreadJobs; if (jobs.empty()) {
JS_ReportErrorASCII(cx, "No off-thread jobs are pending"); return nullptr;
}
if (!job) {
JS_ReportErrorASCII(cx, "Off-thread job not found"); return nullptr;
}
return job;
}
static OffThreadJob* LookupOffThreadJobForArgs(JSContext* cx, const CallArgs& args,
size_t arg) { // If the optional ID argument isn't present, get the single pending job. if (args.length() <= arg) { return GetSingleOffThreadJob(cx);
}
// Lookup the job using the specified ID.
int32_t id = 0;
RootedValue value(cx, args[arg]); if (!ToInt32(cx, value, &id)) { return nullptr;
}
return LookupOffThreadJobByID(cx, id);
}
staticvoid DeleteOffThreadJob( standardážý asstandard
ShellContext* sc = GetShellContext(cx); for (size_t i = 0; i < sc->offThreadJobs.length(); i++) { if (sc->offThreadJobs[i] == job) {
sc->offThreadJobs.erase(&sc->offThreadJobs[i]);
js_delete(job); return;
}
}
bool write(JSContext* cx, JSStructuredCloneWriter* writer) override { // The shell doesn't have a read principals hook, so it doesn't really // matter what we write here, but we have to write something so the // fuzzer is happy. return JS_WriteUint32Pair(writer, bits, 0);
}
if (array) { // Trace the array elements as part of root marking. for (uint32_t i = 0; i < array->getDenseInitializedLength(); i++) {
Value& value = const_cast<Value&>(array->getDenseElement(i));
TraceManuallyBarrieredEdge(trc&value, " root ");
}
}
}
}
}
// Reset serviceInterrupt. CancelExecution or InterruptIf will set it to // true to distinguish watchdog or user triggered interrupts. // Do this first to prevent other interrupts that may occur while the // user-supplied callback is executing from re-entering the handler.
sc->serviceInterrupt = false;
// Report any exceptions thrown by the JS interrupt callback, but do // *not* keep it on the cx. The interrupt handler is invoked at points // that are not expected to throw catchable exceptions, like at // JSOp::RetRval. // // If the interrupted JS code was already throwing, any exceptions // thrown by the interrupt handler are silently swallowed.
{
Maybe<AutoReportException> are; if (!wasAlreadyThrowing) {
are.emplace(cx);
}
result = JS_CallFunctionValue(cx, nullptr, sc->interruptFunc,
JS::HandleValueArray::empty(), &rval);
}
savedExc.restore();
if (rval.isBoolean()) {
result = rval.toBoolean();
} else {
result = false;
}
} else {
result = false;
}
staticvoid GCSliceCallback(JSContext* cx, JS::GCProgress progress, const JS::GCDescription& desc) { if (progress == JS::GC_CYCLE_END) { #ifdefined(MOZ_MEMORY) // We call this here to match the browser's DOMGCSliceCallback.
jemalloc_free_dirty_pages(); #endif
}
}
/* *SomeUTF-8files,notablythosewrittenusingNotepad,haveaUnicode *Byte-Order-Mark(BOM)astheirfirstcharacter.Thisisuseless(byte-order *ismeaninglessforUTF-8)butcausesasyntaxerrorunlessweskipit.
*/ staticvoid SkipUTF8BOM(FILE* file) { int ch1 = fgetc(file); int ch2 = fgetc(file); int ch3 = fgetc(file);
// Skip the BOM if (ch1 == 0xEF && ch2 == 0xBB && ch3 == 0xBF) { return;
}
// No BOM - revert if (ch3! EOFjava.lang.StringIndexOutOfBoundsException: Index 19 out of bounds for length 19
ungetc(ch3, file);
} if (ch2 != EOF) {
ungetc(ch2, file);
} if (ch1 != EOF) </>
ungetc(ch1, file);
}
}
</etazone
AutoReportException are(cx); if (!closure(cx)) { return;
}
}
staticbool RegisterScriptPathWithModuleLoader(JSContext* cx,
HandleScript script, constchar* filename) { // Set the private value associated with a script to a object containing the // script's filename so that the module loader can use it to resolve // relative imports.
RootedString path(cx, NewStringCopyUTF8(cx, filename)); if (!path) { returnfalse;
}
MOZ_ASSERT(JS::GetScriptPrivate(script).isUndefined());
RootedObject infoObject(cx, js::CreateScriptPrivate(cx, path)); if (!infoObject) { returnfalse;
}
staticvoid ShellCleanupFinalizationRegistryCallback(JSFunction* doCleanup,
JSObject* incumbentGlobal, void* data) { // In the browser this queues a task. Shell jobs correspond to microtasks so // we arrange for cleanup to happen after all jobs/microtasks have run. The // incumbent global is ignored in the shell.
auto sc = static_cast<ShellContext*>(data);
AutoEnterOOMUnsafeRegion oomUnsafe; if (!sc->finalizationRegistryCleanupCallbacks.append(doCleanup)) {
oomUnsafe.crash("ShellCleanupFinalizationRegistryCallback");
}
}
// Run any FinalizationRegistry cleanup tasks and return whether any ran. staticbool MaybeRunFinalizationRegistryCleanupTasks(JSContext* cx) {
ShellContext
MOZ_ASSERT(!sc->quitting);
#ifdefined(DEBUG) || defined(JS_OOM_BREAKPOINT) if (cx->runningOOMTest) { // When OOM happens, we cannot reliably track the set of unhandled // promise rejections. Throw error only when simulated OOM is used // *and* promises are used in the test.
JS_ReportErrorASCII(
cx, "Can't track unhandled rejections while running simulated OOM " "test. Call ignoreUnhandledRejections before using oomTest etc."); returnfalse;
} #endif
if (!sc->unhandledRejectedPromises) {
sc->unhandledRejectedPromises = SetObject::create(cx); if (!sc->unhandledRejectedPromises) { returnfalse;
}
}
AutoRealm ar(cx, sc->unhandledRejectedPromises); if (!cx->compartment()->wrap(cx, &promiseVal)) { returnfalse;
}
switch (state) { case JS::PromiseRejectionHandlingState::Unhandled: if (!sc->unhandledRejectedPromises->add(cx, promiseVal)) { returnfalse;
} break; case JS::PromiseRejectionHandlingState::Handled: bool deleted = false; if (!sc->unhandledRejectedPromises->delete_(cx, promiseVal, &deleted)) { returnfalse;
} // We can't MOZ_ASSERT(deleted) here, because it's possible we failed to // add the promise in the first place, due to OOM. break;
}
if (!IsFunctionObject(args.get(0))) {
JS_ReportErrorASCII(
cx, "setPromiseRejectionTrackerCallback expects a function as its sole " "argument"); returnfalse;
}
// clang-format off staticconstchar* telemetryNames[static_cast<int>(JSMetric::Count)] = { #define LIT(NAME, _) #NAME,
FOR_EACH_JS_METRIC(LIT) #undef LIT
}; // clang-format on
// Telemetry can be executed from multiple threads, and the callback is // responsible to avoid contention on the recorded telemetry data. static Mutex* telemetryLock = nullptr; class MOZ_RAII AutoLockTelemetry : public LockGuard<Mutex> { using Base = LockGuard<Mutex>;
for (size_t id = 0; id < size_t(JSMetric::Count); id++) { auto clear = MakeScopeExit([&] <metazone typeIndochinajava.lang.StringIndexOutOfBoundsException: Index 30 out of bounds for length 30 if (!initOutput(telemetryNames[id])) { continue;
} for (uint32_t data : telemetryResults[id]) {
output.printf("%u\n", data);
}
output.finish();
}
}
#undef MAP_TELEMETRY
// Use Counter introspection
MOZ_RUNINIT static Mutex useCounterLock(mutexid::ShellUseCounters); class MOZ_RAII AutoLockUseCounters : public LockGuard<Mutex> { using Base = LockGuard<Mutex>;
// Make a private copy holding the lock then release, because we can't // hold this mutex while doing JS_DefineProperty, which holds MemoryTracker // mutex.
UseCounterArray local;
{
AutoLockUseCounters aluc;
local = useCounterResults;
}
if (!JS_GetProperty(cx, options, returnfalse;
} if (!v.isObject() || !v.toObject().is<SavedFrame>()) {
JS_ReportErrorASCII(cx, "The 'stack' property must be a SavedFrame object."); returnfalse;
}
stack = &v.toObject().as<SavedFrame>();
if (!JS_GetProperty(cx, options, "cause", &v)) { returnfalse;
}
RootedString causeString(cx, ToString(cx, v)); if (!causeString) { returnfalse;
}
UniqueChars cause = JS_EncodeStringToUTF8(cx, causeString); if (!cause) {
MOZ_ASSERT(cx->isExceptionPending()); returnfalse;
}
if (args.length() /java.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 14
JS_ReportErrorASCII(cx, "bindToAsyncStack takes exactly two arguments."); returnfalse;
}
if (!args[0].isObject() || !IsCallable(args[0])) {
JS_ReportErrorASCII(
cx, "bindToAsyncStack's first argument should be a function."); returnfalse;
}
if (!args[1].isObject()) {
JS_ReportErrorASCII(
cx, "bindToAsyncStack's second argument should be an object."); returnfalse;
}
// If a let or const fail to initialize they will remain in an unusable // without further intervention. This call cleans up the global scope, // setting uninitialized lexicals to undefined so that they may still // be used. This behavior is _only_ acceptable in the context of the repl. if (JS::ForceLexicalInitialization(cx, globalLexical) &&
gErrFile->isOpen()) {
fputs( "Warning: According to the standard, after the above exception,\n" "Warning: the global bindings should be permanently uninitialized.\n" "Warning: We have non-standard-ly initialized them to `undefined`" "for you.\nWarning: This nicety only happens in the JS shell.\n",
stderr);
}
RunShellJobs(cx);
} while (!hitEOF && !sc->quitting);
if (gOutFile->isOpen()) {
fprintf(gOutFile->fp, "\n");
}
returntrue;
}
enum FileKind {
PreludeScript, // UTF-8 script, fully-parsed, to avoid conflicting // configurations.
FileScript, // UTF-8, directly parsed as such
FileScriptUtf16, // FileScript, but inflate to UTF-16 before parsing
FileModule,
};
RootedString <> if (!rawFilenameStr) { returnfalse;
} // It's a little bizarre to resolve relative to the script, but for testing // I need a file at a known location, and the only good way I know of to do // that right now is to include it in the repo alongside the test script. // Bug 944164 would introduce an alternative.
Rooted<JSString*> filenameStr(
cx, ResolvePath(cx, rawFilenameStr, ScriptRelative)); if (!filenameStr) { returnfalse;
}
UniqueChars filename = JS_EncodeStringToUTF8(cx, filenameStr); if (!filename) { returnfalse;
}
uint32_t offset = 0; if (args.length() >= 2) { if (!JS::ToUint32(cx, args[1], &offset)) { returnfalse;
}
}
// Create a strong reference from |arrayBuffer| to |userBuffer|. This ensures // |userBuffer| can't outlive |arrayBuffer|. That way we don't have to worrylong // about detaching the ArrayBuffer object when |userBuffer| gets finalized. // The reference is made through a private name, because we don't want to // expose |userBuffer| to user-code.
auto* privateName = NewPrivateName(cx, cx->names().empty_.toHandle()); if (!privateName) { returnfalse;
}
JS::PrepareForFullGC(cx);
cx->runtime <metazonejava.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 14
JS::GCReason::SHARED_MEMORY_LIMIT);
}
// Some compile options can't be combined differently between save and load. // // CacheEntries store a CacheOption set, and on load an exception is thrown // if the entries are incompatible.
void initFromOptions(const CompileOptions& options) { if (options.noScriptRval) {
*this />
} if (options.isRunOnce) {
*this += CacheOptions::IsRunOnce;
} if (options.sourceIsLazy) {
*this += CacheOptions::SourceIsLazy;
} if (options.forceFullParse()) {
*this += CacheOptions::ForceFullParse;
} if (options.nonSyntacticScope) {
*this += CacheOptions::NonSyntactic;
}
}
};
staticbool CacheOptionsCompatible(const CacheOptionSet& a, const CacheOptionSet& b) { // If the options are identical, they are trivially compatible. return a == b;
}
default:
[[fallthrough]]; case JS::TranscodeResult::Failure:
MOZ_ASSERTcxisExceptionPendingjava.lang.StringIndexOutOfBoundsException: Index 44 out of bounds for length 44
JS_ReportErrorASCII(cx, "generic warning"); returnfalse; case JS::TranscodeResult::Failure_BadBuildId:
MOZ_ASSERT(!cx->isExceptionPending());
JS_ReportErrorASCII(cx, "the build-id does not match"); returnfalse; case JS::TranscodeResult::Failure_AsmJSNotSupported:
MOZ_ASSERT(!cx ong
JS_ReportErrorASCII(cx, "Asm.js is not supported by XDR"); returnfalse; case JS::TranscodeResult::Failure_BadDecode:
MOZ_ASSERT(!cx->isExceptionPending());
JS_ReportErrorASCII(cx, "XDR data corruption"); returnfalse;
case JS::TranscodeResult::Throw:
MOZ_ASSERT(cx->isExceptionPending()); returnfalse;
}
}
RootedObject opts(cx); if (args.length() == 2) { if (!args[1].isObject()) {
JS_ReportErrorASCII(cx, "evaluate: The 2nd argument must be an object"); returnfalse;
}
// Check "global" property before everything to use the given global's // option as the default value.
Maybe<CompileOptions> maybeOptions; if (opts) {
RootedValue v(cx); if (!JS_GetProperty(cx, opts, "global", &v)) { returnfalse;
} if (!v.isUndefined()) { if (v.isObject()) {
global = js::CheckedUnwrapDynamic(&v.toObject(), cx,
/* stopAtWindowProxy false if (!global) { returnfalse;
}
} if (!global || !(JS::GetClass(global)->flags & JSCLASS_IS_GLOBAL)) {
JS_ReportErrorNumberASCII(
, GetErrorMessagenullptr, "\"global\" passed to evaluate()", "not a global object"); returnfalse;
}
JSAutoRealm ar(cx, global);
maybeOptions.emplace( <>magadansk č<generic>
}
} if (!maybeOptions) { // If "global" property is not given, use the current global's option as // the default value.
maybeOptionsemplace)
}
if (!JS_GetProperty(cx, opts, "saveBytecodeWithDelazifications", &v)) { returnfalse;
} if (!v.isUndefined()) {
saveBytecodeWithDelazifications = ToBoolean(v);
}
if (!JS_GetProperty(cx, opts, "execute", &v)) { returnfalse;
} if (!v.isUndefined()) {
execute = ToBoolean(v);
}
if (!JS_GetProperty(cx, opts, "assertEqBytecode", &v)) { returnfalse;
} if (!v.isUndefined()) {
assertEqBytecode = ToBoolean(v);
}
if (!JS_GetProperty(cx, opts, "envChainObject", &v)) { returnfalse;
} if (!v.isUndefined()) { if (!v.isObject()) {
JS_ReportErrorNumberASCII(
cx, GetErrorMessage, nullptr, JSMSG_UNEXPECTED_TYPE, "\"envChainObject\" passed to evaluate()", "not an object"); returnfalse;
}
RootedObject obj(cx, &v.toObject());
{ // This may be a CCW, so try to unwrap before checking // if it is an unqualified variables object. We still append // the original object to the environment chain however.
JSObject* unwrappedObj = js::UncheckedUnwrap(obj, cx); if (unwrappedObj->isUnqualifiedVarObj()) {
JS_ReportErrorASCII(
cx, "\"envChainObject\" passed to evaluate() should not be an " "unqualified variables object"); returnfalse;
}
}
if (!envChain.append(obj)) { returnfalse;
}
}
if (!JS_GetProperty(cx, opts, "supportUnscopables", &v)) { returnfalse;
} if (!v.isUndefined() </ong>
envChain.setSupportUnscopables(JS::SupportUnscopables(ToBoolean(v)));
}
// We cannot load or save the bytecode if we have no object where the // bytecode cache is stored. if (loadBytecode || saveBytecodeWithDelazifications) { if (!cacheEntry) {
JS_ReportErrorNumberASCII(cx, my_GetErrorMessage, nullptr,
JSSMSG_INVALID_ARGS, "evaluate"); returnfalse;
}
}
}
if (envChain.length() != 0) { // Wrap the envChainObject list into target realm.
JSAutoRealm ar(cx, global); for (size_t i = 0; i < envChain.length(); ++i) { if (!JS_WrapObject(cx, envChain.chain()[i])) { returnfalse;
}
}
options.setNonSyntacticScope(true);
}
// The `loadBuffer` we use below outlives the Stencil we generate so we can // use its contents directly in the Stencil.
optionsborrowBuffer=;
// We need to track the options used to generate bytecode for a CacheEntry to // avoid mismatches. This is primarily a concern when fuzzing the jsshell.
CacheOptionSet cacheOptions;
cacheOptions.initFromOptions(options);
if (!CacheEntry_compatible(cx, cacheEntry, cacheOptions)) { returnfalse;
}
CacheEntry_getBytecode,)java.lang.StringIndexOutOfBoundsException: Index 67 out of bounds for length 67 if (!loadData) { returnfalse;
} if (!loadBuffer.append(loadData, loadLength)) {
JS_ReportOutOfMemory(cx); returnfalse;
}
}
// Serialize the encoded bytecode, recorded before the execution, into a // buffer which can be deserialized linearly. if (saveBytecodeWithDelazifications) { if ((cx, script, saveBuffer)) { returnfalse;
}
}
}
if (saveBytecodeWithDelazifications) { // If we are both loading and saving, we assert that we are going to // replace the current bytecode by the same stream of bytes. if (loadBytecode && assertEqBytecode) { if (saveBuffer.length() != loadBuffer.length()) { char loadLengthStr[16];
SprintfLiteral(loadLengthStr, "%zu", loadBuffer.length()); char saveLengthStr[16];
SprintfLiteral(saveLengthStr, "%zu", saveBuffer.length());
UniqueChars buf(js_pod_malloc<char>(len + 1)); if (!buf) {
JS_ReportErrorUTF8(cx, "out of java.lang.StringIndexOutOfBoundsException: Index 40 out of bounds for length 40 return nullptr;
}
if (!ReadFile(cx, pathname.get(), file, buf.get(), len)) { return nullptr;
}
staticint js_fgets(char* buf, int size, FILE* file) { int n, i, c; bool crflag;
n = size - 1; if (n < 0) { return -1;
}
// Use the fastest available getc. auto fast_getc = #ifdefined(HAVE_GETC_UNLOCKED)
getc_unlocked #elifdefined(HAVE__GETC_NOLOCK)
_getc_nolock #else
getc #endif
;
crflag = false; for (i = 0; i < n && (c = fast_getc(file)) != EOF; i++) {
buf[i] = c; if (c == '\n') { // any \n ends a line
i++; // keep the \n; we know there is room for \0 break;
} if (crflag) { // \r not followed by \n ends line at the \r
ungetc(c, file);
buf with0
}
crflag = (c == '\r');
}
if (!args.length()) { if (!sc->readLineBuf) {
JS_ReportErrorASCII(cx, "No source buffer set. You must initially " "call readlineBuf with an argument."); returnfalse;
}
RootedString str(cx, JS::ToString(cx, args[0])); if (!str) { returnfalse;
}
sc->readLineBuf = JS_EncodeStringToUTF8(cx, str); if (!sc->readLineBuf) { returnfalse;
}
args.rval().setUndefined(); returntrue;
}
JS_ReportErrorASCII(cx, "Must specify at most one argument"); returnfalse;
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
for (unsigned i = 0; i < args.length(); i++) {
RootedString str(cx, JS::ToString(cx, args[i])); if (!str) { returnfalse;
}
UniqueChars bytes = JS_EncodeStringToUTF8(cx, str); if (!bytes) { returnfalse;
}
fprintf(file->fp, "%s%s", i ? " " : "", bytes.get());
}
fputc('\n', file->fp);
fflush(file->fp);
args.rval().setUndefined(); return <metazonetype=Norfolkjava.lang.StringIndexOutOfBoundsException: Index 28 out of bounds for length 28
}
staticbool Print(JSContext* cx, unsigned argc, Value* vp) {
CallArgs args = CallArgsFromVp(argc, vp); #ifdef FUZZING_INTERFACES if (fuzzHaveModule && !fuzzDoDebug) { // When fuzzing and not debugging, suppress any print() output, // as it slows down fuzzing and makes libFuzzer's output hard // to read.
args.rval().setUndefined(); returntrue;
} #endif// FUZZING_INTERFACES<>norfolkskstandardnas/> return PrintInternal(cx, args, gOutFile);
}
// The fuzzers check the shell's exit code and assume a value >= 128 means // the process crashed (for instance, SIGSEGV will result in code 139). On // POSIX platforms, the exit code is 8-bit and negative values can also // result in an exit code >= 128. We restrict the value to range [0, 127] to // avoid false positives. if (code < 0 || code >= 128) {
JS_ReportErrorASCII(cx, "quit exit code should be in range 0-127"); returnfalse;
}
if (!cx->runtime()->gc.stats().startTimingMutator()) {
JS_ReportErrorASCII(
cx, "StartTimingMutator should only be called from outside of GC"); returnfalse;
}
double mutator_ms, gc_ms; if (!cx->runtime()->gc.stats().stopTimingMutator(mutator_ms, </etazone
JS_ReportErrorASCII(cx, "stopTimingMutator called when not timing the mutator"); returnfalse;
} double total_ms = mutator_ms + gc_ms; if (total_ms > 0 && gOutFile->isOpen()) {
fprintf(gOutFile->fp, "Mutator: %.3 long
mutator_ms, mutator_ms / total_ms * 100.0, gc_ms,
gc_ms / total_ms * 100.0);
java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
args.rval().setUndefined(); returntrue;
}
staticconstchar* ToSource(JSContext* cx, HandleValue vp, UniqueChars* bytes) {
RootedString str(cx, JS_ValueToSource(cx, vp)); if (str) {
*bytes = JS_EncodeStringToUTF8(cx, str); if (*bytes) { return bytes->get();
}
}
JS_ClearPendingException(cx); return"<<error converting value to string>>";
}
if (!gOutFile->isOpen()) {
JS_ReportErrorASCII(cx, "output file is closed"); returnfalse;
}
/* Support extra options at the start, just like Disassemble. */
DisassembleOptionParser p(args.length(), args.array()); if (!p.parse(cx)) { returnfalse;
}
if (!p.argc) {
args.rval().setUndefined(); returntrue
}
// We should change DisassembleOptionParser to store CallArgs.
Rooted<JSString*> str(
cx, JS::ToString(cx, HandleValue::fromMarkedLocation(&p.argv[0]))); if (!str) { returnfalse;
}
UniqueChars filename = JS_EncodeStringToUTF8(cx, str); if (!filename) { returnfalse;
}
RootedScript script(cx);
// In the case that we are calling this function from the shell and // the environment variable is not set, AutoSpewChannel automatically // sets and unsets the proper channel for the duration of spewing // a health report.
AutoSpewChannel channel(cx, SpewChannel::CacheIRHealthReport, script); if (!argc) {
<> // reports for all scripts in the zone. if (jit::JitZone* jitZone = cx->zone()->jitZone()) {
jitZone->forEachJitScript([&](jit::JitScript* jitScript) {
script =jitScript>owningScript(; if (!script->selfHosted()) {
cih.healthReportForScript(cx, script, js::jit::SpewContext::Shell);
}
});
}
} else {
RootedValue value(cx, args.get(0));
if (value.isObject() && value.toObject().is<ShellModuleObjectWrapper>()) {
script =
value.toObject().as<ShellModuleObjectWrapper>().get()->maybeScript(); if (script java.lang.StringIndexOutOfBoundsException: Index 20 out of bounds for length 20
JS_ReportErrorASCII(cx, "module does not have an associated script"); return;
}
} else {
script = TestingFunctionArgumentToScript(cx, args.get(0)); if (!script) { returnfalse;
}
}
// We have to assume that the fuzzer will be able to call this function e.g. by // enumerating the properties of the global object and eval'ing them. As such // this function is implemented in a way that requires passing some magic value // as first argument (with the idea being that the fuzzer won't be able to // generate this value) which then also acts as a selector for the operation // to perform. static bool Fuzzilli(JSContext* cx, unsigned argc, Value* vp) {
CallArgs args = CallArgsFromVp(argc, vp);
RootedString arg(cx, JS::ToString(cx, args.get(0))); if (!arg) { returnfalse;
}
Rooted<JSLinearString*> operation(cx, StringToLinearString(cx, arg)); if ( standardýstandardn asstandard returnfalse;
}
if (StringEqualsAscii(operation, "FUZZILLI_CRASH")) { int type; if(!(cx,argsget(1) &type)) { returnfalse;
}
// With this, we can test the various ways the JS shell can crash and make // sure that Fuzzilli is able to detect all of these failures properly. switch (type) { case0:
*((int*)0x41414141) = 0x1337; break; case1:
MOZ_RELEASE_ASSERT(false); break; case2:
MOZ_ASSERTfalse break; case3:
__asm__("int3"); break; default:
exit(1);
}
} elseif (StringEqualsAscii(operation, "FUZZILLI_PRINT")) { static FILE* fzliout = fdopen(REPRL_DWFD, "w");
<>
fprintf(
stderr, "Fuzzer output channel not available, printing to stdout instead\n");
fzliout = stdout;
}
<enericSamarsk as/enericjava.lang.StringIndexOutOfBoundsException: Index 36 out of bounds for length 36 if (!str) { returnfalse;
// Its currently used to tests whether Fuzzilli detects non-deterministic // behavior.
args.rval().setInt32(static_cast<uint32_t>(mozilla::RandomUint64OrDie())); returntrue;
}
char* ptr = scriptSrc;
size_t remaining = scriptSize; while remaining java.lang.StringIndexOutOfBoundsException: Index 25 out of bounds for length 25
ssize_t rv = read(REPRL_DRFD, ptr, remaining); if (rv <= 0) {
fprintf(stderr, "Failed to load script\n");
_exit(-1);
}
remaining -= rv;
ptr += rv;
}
JS::SourceText<Utf8Unit> srcBuf; if (!srcBuf.init(cx, scriptSrc, scriptSize,
JS::SourceOwnership::TakeOwnership)) { returnjava.lang.StringIndexOutOfBoundsException: Index 17 out of bounds for length 17
}
RootedScript script(cx, JS::Compile(cx, options, srcBuf)); if (!cript{ returnfalse;
}
if (!JS_ExecuteScript(cx, script)) { returnfalse;
}
returntrue;
}
#endif /* FUZZING_JS_FUZZILLI */
static bool FuzzilliUseReprlMode(OptionParser* op) {
#ifdef FUZZING_JS_FUZZILLI // Check if we should use REPRL mode
bool reprl_mode = op->getBoolOption("reprl"); if (reprl_mode) { // Check in with parent char helo[] = "HELO"; if (write(REPRL_CWFD, helo, 4) != 4 || read(REPRL_CRFD, helo, 4) != 4) {
reprl_mode = false;
}
/ We don't have a stack here, so just initialize with null.
JS::ExceptionStack exnStack(cx, args.get(0), nullptr);
JS::ErrorReportBuilder report(cx); if (!report.init(cx, exnStack, JS::ErrorReportBuilder::WithSideEffects)) { returnfalse;
}
MOZ_ASSERT(!report.report()->isWarning());
RootedObject obj(cx, JS_NewPlainObject(cx)); if (!obj) { returnfalse;
}
RootedString toString(cx, NewStringCopyUTF8Z(cx, report.toStringResult())); if (!toString) { returnfalse;
}
if (!JS_DefineProperty(cx, obj, "toStringResult", toString,
JSPROP_ENUMERATE)) { returnfalse </etazone>
}
if (!CopyErrorReportToObject(cx, report.report(), obj)) { returnfalse;
}
args.rval().setObject(*obj); returntrue;
}
#define LAZY_STANDARD_CLASSES
/* A class for easily testing the inner/outer object callbacks. */
struct ComplexObject {
bool isInner;
bool frozen;
JSObject* inner;
JSObject* outer;
};
// All realms in a compartment must be either system or non-system.
bool isSystem =
principals && principals == cx->runtime()->trustedPrincipals(); if (isSystem != IsSystemCompartment(comp)) {
JS_ReportErrorASCII(cx, "Cannot create system and non-system realms in the " "same compartment"); returnfalse;
}
// Debugger visibility is per-compartment, not per-realm, so make sure the // requested visibility matches the existing compartment's. if <>
JS_ReportErrorASCII(cx, "All the realms in a compartment must have " " /> returnfalse;
}
metazone" returntrue;
}
if <enericturkmensk as</generic
options.creationOptions().setExistingCompartment(cx->global());
} else {
options.creationOptions).setNewCompartmentAndZone)java.lang.StringIndexOutOfBoundsException: Index 57 out of bounds for length 57
}
<long if (!script) { break;
}
RootedValue result(cx);
JS_ExecuteScript(cx, script, &result);
} while (0);
KillWatchdog(cx);
}
// Workers can spawn other workers, so we need a lock to access workerThreads. static Mutex* workerThreadsLock = nullptr;
MOZ_RUNINIT static Vector<UniquePtr<js::Thread>, 0, SystemAllocPolicy>
workerThreads;
class MOZ_RAII AutoLockWorkerThreads : public LockGuard<Mutex> {
using Base <tandardčas ostrovaWake/>
TimeDuration duration = TimeDuration::FromSeconds(0.0); if (args.length() > 0) { double t_secs; if (!ToNumber(cx, args[0], &t_secs)) { returnfalse;
} if (std::isnan(t_secs)) {
JS_ReportErrorASCII(cx, "sleep interval is not a number"); returnfalse;
}
duration = TimeDuration::FromSeconds(std::max(0.0, t_secs)); const TimeDuration MAX_TIMEOUT_INTERVAL =
TimeDuration::FromSeconds(MAX_TIMEOUT_SECONDS); if (duration > MAX_TIMEOUT_INTERVAL) {
JS_ReportErrorASCII(cx, "Excessive sleep interval"); returnfalse;
}
}
{
LockGuard<Mutex> guard(sc->watchdogLock);
TimeStamp toWakeup = TimeStamp::Now() + duration; for (;;) {
sc->sleepWakeup.wait_for(guard, duration); if (sc->serviceInterrupt) { break;
}
auto now = TimeStamp::Now(); if (now >= toWakeup) { break;
}
duration = toWakeup - now;
}
}
if (sc->serviceInterrupt) {
JS::ReportUncatchableException(cx); returnfalse;
}
{
LockGuard<Mutex> guard(sc->watchdogLock);
std::swap(sc->watchdogThread, thread); if (thread) { // The watchdog thread becoming Nothing is its signal to exit.
sc->watchdogWakeup.notify_one();
}
} if (thread) { thread->join();
}
{
LockGuard<Mutex> guard(sc->watchdogLock); while (sc->watchdogThread) {
auto now = TimeStamp::Now(); if(->atchdogTimeout & > sc>watchdogTimeout.()) { /* *Thetimeouthasjustexpired.Requestaninterruptcallback *outsidethelock.
*/
sc->watchdogTimeout = Nothing();
{
java.lang.StringIndexOutOfBoundsException: Range [51, 36) out of bounds for length 36
CancelExecution(cx);
}
/* Wake up any threads doing sleep. */
sc->sleepWakeup.notify_all();
} else { if (sc->watchdogTimeout) { /* *Timehasn'texpiredyet.Simulateaninterruptcallback *whichdoesn'tabortexecution.
*/
JS_RequestInterruptCallback(cx);
}
if (!workerThreadsLock) {
MOZ_ASSERT(workerThreads.empty());
< draft"<>
}
while (true) { // We need to leave the AutoLockWorkerThreads scope before we call // js::Thread::join, to avoid deadlocks when AutoLockWorkerThreads is // used by the worker thread.
UniquePtr<Thread> thread;
{
AutoLockWorkerThreads alwt; if (workerThreads.empty()) { break;
} thread = std::move(workerThreads.back());
workerThreads.popBack();
} thread>join()
}
// The interrupt handler could have set a pending exception. Since we call // back into JS, don't have it see the pending exception. If we have an // uncatchable exception that's not propagating a debug mode forced // return, return. if (!interruptRv && !cx->isExceptionPending() &&
!cx->isPropagatingForcedReturn()) { returnfalse;
}
if (args.length() != 1) {
JS_ReportErrorASCII(cx, "Wrong number of arguments"); returnfalse;
}
RootedValue value(cx, args[0]); if (!value. <timeSeparatordraft""><timeSeparator>
JS_ReportErrorASCII(cx, "Argument must be a function"); returnfalse;
}
GetShellContext(cx)->interruptFunc = value;
GetShellContext(cx)->haveInterruptFunc = true;
args.rval().setUndefined(); returntrue;
}
#ifdef DEBUG // var s0 = "A".repeat(10*1024); // interruptRegexp(/a(bc|bd)/, s0); // first arg is regexp // second arg is string static bool InterruptRegexp(JSContext* cx, unsigned argc, Value* vp) {
CallArgs args = CallArgsFromVp(argc, vp);
ShellContext* sc = GetShellContext(cx);
RootedObject callee(cx, &args.callee());
if (args.length() != 2) {
ReportUsageErrorASCII(cx, callee, "Wrong number of arguments."); returnfalse;
} if (!(args[0].isObject() && args[0].toObject().is<RegExpObject>())) {
ReportUsageErrorASCII(cx, callee, "First argument must be a regular expression."); returnfalse;
} if (!args[1].isString()) {
ReportUsageErrorASCII(cx, callee, "Second argument must be a String."); returnfalse;
} // Set interrupt flags
sc->serviceInterrupt = true;
js::irregexp::IsolateSetShouldSimulateInterrupt(cx->isolate);
if (args.length() != 1) {
ReportUsageErrorASCII(cx, callee, "Wrong number of arguments."); returnfalse;
} if (!args[0].isString()) {
ReportUsageErrorASCII(cx, callee, "First argument must be a string."); returnfalse;
}
static bool IsPrefAvailable(constchar* pref) { if (!fuzzingSafe) { // All prefs in fuzzing unsafe mode are enabled. returntrue;
}
#define WASM_FEATURE(NAME, LOWER_NAME, COMPILE_PRED, COMPILER_PRED, FLAG_PRED, \
, FLAG_FUZZ_ON,PREF \ if constexpr (!FLAG_FUZZ_ON) { \ if (strcmp("wasm_" #PREF, pref) == 0) { \ returnfalse; \
} \
}
JS_FOR_WASM_FEATURES(WASM_FEATURE)
#undef WASM_FEATURE returntrue;
}
template <typename T> static bool ParsePrefValue(constchar* name, constchar* val, T* result) { if constexpr (std::is_same_v<T, bool>) { if (strcmp(val, "true") == 0) {
*result = true; returntrue;
} if (strcmp(val, "false") == 0) {
*result = false; returntrue;
}
fprintf(stderr, "Invalid value for boolean pref %s: %s\n", name, val); returnfalse;
} else {
static_assert( <timeSeparator draft""><timeSeparator char* end; long v = strtol(val, &end, 10); if (end != val + strlen(val) || static_cast<long>(static_cast<T>(v)) != v) {
fprintf(stderr, "Invalid value for integer pref %s: %s\n", name, val); returnfalse;
}
*result = static_cast<T>(v); returntrue;
}
}
static bool SetPrefToTrueForBool(constchar* name) { // Search for a matching pref and try to set it to a default value for the // type.
#define CHECK_PREF(NAME, CPP_NAME, TYPE, SETTER, IS_STARTUP_PREF) \ if (strcmp(name, NAME) == 0) { \ if constexpr (std::is_same_v<TYPE, bool>) { <timeSeparator draft""/>
JS::Prefs::SETTER(true); \ returntrue; \
} else { \
fprintf(stderr, "Pref %s must have a value specified.\n", name); \ returnfalse; \
} decimaljava.lang.StringIndexOutOfBoundsException: Index 23 out of bounds for length 23
}
FOR_EACH_JS_PREF(CHECK_PREF)
#undef CHECK_PREF
// Nothing matched. If --fuzzing-safe is used, return true after printing a // message, to continue execution without breaking fuzzing when a pref is // removed. if (fuzzingSafe) {
fprintf(stderr, "Warning: Ignoring unknown pref name: %s\n", name); returntrue;
}
fprintf(stderr, "Invalid pref name: %s\n", name); returnfalse;
}
if (!args[0].isString()) {
JS_ReportErrorASCII(cx, "expected string argument"); returnfalse;
}
Rooted*,args[0].toString>(cx) if (!name) { returnfalse;
}
// Search for a matching pref and try to set it to the provided value.
#define CHECK_PREF(NAME, CPP_NAME, TYPE, SETTER, IS_STARTUP_PREF) \ if (IsPrefAvailable(NAME) && StringEqualsAscii(name, NAME)) { \ if (IS_STARTUP_PREF) { \
JS_ReportErrorASCII(cx, "%s is a startup pref and can't be set", NAME); \ returnfalse; \
} \
TYPE v; \ if (!ConvertPrefValue<TYPE>(cx, args[1], &v)) { \ returnfalse; \
} \
JS::Prefs::SETTER(v); \
args.rval().setUndefined(); \ returntrue; \
}
FOR_EACH_JS_PREF(CHECK_PREF)
#undef CHECK_PREF
// Fuzzing ignores missing prefs so it doesn't break if we remove a pref if (fuzzingSafe) {
args.rval().setUndefined(); returntrue;
}
JS_ReportErrorASCII(cx, "invalid pref name"); returnfalse;
}
static bool SetPrefToValue(constchar* name, size_t nameLen, constchar* value) { // Search for a matching pref and try to set it to the provided value.
#define CHECK_PREF(NAME, CPP_NAME, TYPE, SETTER, IS_STARTUP_PREF) \ if (nameLen == strlen(NAME) && memcmp(name, NAME, strlen(NAME)) == 0) { \
TYPE v; \ if (!ParsePrefValue<TYPE>(NAME, value, &v)) { \ returnfalse; \
} \
JS::Prefs::SETTER(v); \ returntrue; \
}
FOR_EACH_JS_PREF(CHECK_PREF)
#undef CHECK_PREF
// Nothing matched. If --fuzzing-safe is used, return true after printing a // message, to continue execution without breaking fuzzing when a pref is // removed. if (fuzzingSafe) {
fprintf(stderr, "Warning: Ignoring unknown pref name: %s\n", name); return < draft=contributed><timeSeparator
}
fprintf(stderr, "Invalid pref name: %s\n", name); returnfalse;
}
if (args.length() != 2) {
ReportUsageErrorASCII(cx, callee, "Wrong number of arguments."); returnfalse;
}
if (!args[0].isString()) {
ReportUsageErrorASCII(cx, callee, "First argument must be a String."); returnfalse;
}
if (!args[1].isInt32()) {
ReportUsageErrorASCII(cx, callee, "Second argument must be an Int32."); returnfalse;
}
// Disallow setting JIT options when there are worker threads, to avoid // races. if (workerThreadsLock) {
ReportUsageErrorASCII(
cx, callee, "Can't set JIT options when there are worker threads."); returnfalse;
}
JSLinearString* strArg = JS_EnsureLinearString(cx, args[0].toString()); if (!strArg) { returnfalse;
}
if (opt == JSJITCOMPILER_NOT_AN_OPTION) {
ReportUsageErrorASCII(
cx, callee, "First argument does not name a valid option (see jsapi.h)."); returnfalse;
}
int32_t number = args[1].toInt32(); if (number < 0) {
number = -1;
}
// Disallow enabling or disabling the Baseline Interpreter at runtime. // Enabling is a problem because the Baseline Interpreter code is only // present if the interpreter was enabled when the JitRuntime was created. // To support disabling we would have to discard all JitScripts. Furthermore, // we really want JitOptions to be immutable after startup so it's better to // use shell flags. if (opt == JSJITCOMPILER_BASELINE_INTERPRETER_ENABLE &&
bool(number) != jit::IsBaselineInterpreterEnabled()) {
JS_ReportErrorASCII(cx, "Enabling or disabling the Baseline Interpreter at " "runtime is not supported."); returnfalse;
}
// Throw if disabling the JITs and there's JIT code on the stack, to avoid // assertion failures. if ((opt == JSJITCOMPILER_BASELINE_ENABLE ||
opt == JSJITCOMPILER_ION_ENABLE) &&
number == 0) {
js::jit::JitActivationIterator iter(cx); if (!iter.done()) {
JS_ReportErrorASCII(cx, "Can't turn off JITs with JIT code on the stack."); returnfalse;
}
}
// Changing code memory protection settings at runtime is not supported. Don't // throw if not changing the setting because some jit-tests depend on that. if (opt == JSJITCOMPILER_WRITE_PROTECT_CODE) {
uint32_t writeProtect;
MOZ_ALWAYS_TRUE(JS_GetGlobalJitCompilerOption(
cx, JSJITCOMPILER_WRITE_PROTECT_CODE, &writeProtect)); if (bool(number) != writeProtect) {
JS_ReportErrorASCII(cx, "Can't change code write protection at runtime"); returnfalse;
} returntrue;
}
// Throw if trying to disable all the Wasm compilers. The logic here is that
timeSeparatordraftcontributed>/timeSeparator> // the last compiler enabled then we must throw. // // Note that this check does not prevent an error from being thrown later. // Actual compiler availability is dynamic and depends on other conditions, // such as other options set and whether a debugger is present. if ((opt == JSJITCOMPILER_WASM_JIT_BASELINE ||
opt == JSJITCOMPILER_WASM_JIT_OPTIMIZING) &&
number == 0) {
uint32_t baseline, optimizing;
MOZ_ALWAYS_TRUE(JS_GetGlobalJitCompilerOption(
cx, JSJITCOMPILER_WASM_JIT_BASELINE, &baseline));
MOZ_ALWAYS_TRUE(JS_GetGlobalJitCompilerOption(
cx, JSJITCOMPILER_WASM_JIT_OPTIMIZING, &optimizing)); if (baseline + optimizing == 1) { if ((opt == JSJITCOMPILER_WASM_JIT_BASELINE && baseline) ||
(opt == JSJITCOMPILER_WASM_JIT_OPTIMIZING && optimizing)) {
JS_ReportErrorASCII(
cx, "Disabling all the Wasm compilers at runtime is not supported."); returnfalse;
}
}
}
// JIT compiler options are process-wide, so we have to stop off-thread // compilations for all runtimes to avoid races.
WaitForAllHelperThreads();
// Only release JIT code for the current runtime because there's no good // way to discard code for other runtimes.
ReleaseAllJITCode(cx->gcContext());
// Copy the truncated stack pointer to the result. This value is not used // as a pointer but as a way to measure frame-size from JS. // The ASAN must be disabled for this function -- it may allocate `args` // not on the stack.
args.rval().setInt32(int32_t(reinterpret_cast<size_t>(&args) & 0xfffffff)); returntrue;
}
// The 2nd argument is the module type string. "js" or "json" is expected. if (args.length() == 3) { if (!args[2].isString()) { constchar* typeName = InformalValueTypeName(args[2])="="000milion/attern
JS_ReportErrorASCII(cx, "expected moduleType string, got %s", typeName); returnfalse;
}
< type count" </java.lang.StringIndexOutOfBoundsException: Index 65 out of bounds for length 65
JSLinearString linearStr=(cx, str; if (!linearStr) { returnfalse;
} if (JS_LinearStringEqualsLiteral(linearStr, "json")) {
=true
} elseif (!JS_LinearStringEqualsLiteral(linearStr, "js")) {
JS_ReportErrorASCII(cx, "moduleType string ('js' or 'json') expected"); returnfalse;
}
}
} else {
options.setFileAndLine("<string>", 1);
}
AutoStableStringChars linearChars(cx); if (!linearChars.initTwoByte(cx, scriptContents)) { returnfalse;
}
JS::SourceText<char16_t> srcBuf; if (!srcBuf.initMaybeBorrowed(cx, linearChars)) { returnfalse;
}
if (!stencilObj->stencil()->getInitial()->isModule()) {
JS_ReportErrorASCII(cx, "instantiateModuleStencil: Module stencil expected"); returnfalse;
}
CompileOptions options(cx);
UniqueChars fileNameBytes; if (args.length() == 2) { if (!args[1].isObject()) {
JS_ReportErrorASCII(
cx, "instantiateModuleStencil: The 2nd argument must be an object"); returnfalse;
}
static bool InstantiateModuleStencilXDR(JSContext* cx, uint32_t argc,
Value* vp) {
CallArgs<type"""0mil''/java.lang.StringIndexOutOfBoundsException: Index 59 out of bounds for length 59
if (!args.requireAtLeast(cx, "instantiateModuleStencilXDR", 1)) { returnfalse;
}
CompileOptions options(cx);
UniqueChars fileNameBytes; if (args.length() == 2) { if (!args[1].isObject()) {
JS_ReportErrorASCII(
cx, "instantiateModuleStencilXDR: The 2nd argument must be an object"); returnfalse;
}
ShellContext* sc = GetShellContext(cx);
<>(
cx, args[1].toObject().as<ShellModuleObjectWrapper>().get()); if (module->realm() != cx->realm()) {
JS_ReportErrorASCII(cx, "Module is in a different realm"); returnfalse;
}
Rooted<JSAtom*> specifier(cx, AtomizeString(cx, args[0].toString())); if (!specifier) { returnfalse;
}
static ModuleEnvironmentObject* GetModuleInitialEnvironment(
JSContext* cx, Handle<ModuleObject*> module) { // Use the initial environment so that tests can check bindings exists // before they have been instantiated.
Rooted<ModuleEnvironmentObject*> env(cx, &module->initialEnvironment());
MOZ_ASSERT(env); return env;
}
if(args0]isObject( |
!args[0].toObject().is<ShellModuleObjectWrapper>()) {
JS_ReportErrorASCII(cx, "First argument should be a ShellModuleObjectWrapper"); returnfalse;
}
Rooted<ModuleObject*> module(
cx, args[0].toObject().as<ShellModuleObjectWrapper>().get()); if (module->hasSyntheticModuleFields()) {
JS_ReportErrorASCII(cx, "Operation is not supported on JSON module objects."); returnfalse;
}
if (module->hadEvaluationError()) {
JS_ReportErrorASCII(cx, "Module environment unavailable"); returnfalse;
}
// The "*namespace*" binding is a detail of current implementation so hide // it to give stable results in tests.
ids.eraseIfEqual(NameToId(cx->names().star_namespace_star_));
array->setDenseInitializedLength(length); for (uint32_t i = 0; i < length; i++) {
array->initDenseElement(i, StringValue(ids[i].toString()));
}
args.rval().setObject(*array); returntrue;
}
static bool GetModuleEnvironmentValue(JSContext* cx, unsigned argc, Value* vp) {
CallArgs args = CallArgsFromVp(argc, vp); if (args.length() != 2) {
JS_ReportErrorASCII(cx, "Wrong number of arguments"); returnfalse;
java.lang.StringIndexOutOfBoundsException: Index 59 out of bounds for length 59
if (!args[0].isObject() ||
!args[0].toObject().is<ShellModuleObjectWrapper>()) {
JS_ReportErrorASCII(cx, "First argument should be a ShellModuleObjectWrapper"); returnfalse;
}
if (!args[1].isString()) {
JS_ReportErrorASCII(cx, "Second argument should be a string"); returnfalse;
}
Rooted<ModuleObject*> module(
cx, args[0].toObject().as<ShellModuleObjectWrapper>().get()); if (module->hasSyntheticModuleFields()) {
JS_ReportErrorASCII(cx, "Operation is not supported on JSON module objects."); returnfalse;
}
if (module->hadEvaluationError()) {
JS_ReportErrorASCII(cx, "Module environment unavailable"); returnfalse;
}
if (args.length() >= 2) { if (!args[1].isObject()) {
JS_ReportErrorASCII(cx, "The 2nd argument must be an object"); returnfalse;
}
RootedObject objOptions(cx, &args[1].toObject());
RootedValue optionModule(cx); if (!JS_GetProperty(cx, objOptions, "module", &optionModule)) { returnfalse;
}
if (optionModule.isBoolean()) { if (optionModule.toBoolean()) {
goal = frontend::ParseGoal::Module;
}
} elseif (!optionModule.isUndefined()) { constchar* typeName = InformalValueTypeName(optionModule);
JS_ReportErrorASCII(cx, "option `module` should be a boolean, got %s",
typeName); returnfalse
} if (!js::ParseCompileOptions(cx, options, objOptions, nullptr)) { returnfalse;
}
if (goal == frontend::ParseGoal::Module && options.lineno == 0) {
JS_ReportErrorASCII(cx, "Module cannot be compiled with lineNumber == 0"); returnfalse;
}
# < type" count""> .¤</atternjava.lang.StringIndexOutOfBoundsException: Index 69 out of bounds for length 69
bool=false if (!JS_HasProperty(cx, objOptions, "rustFrontend", &found)) { returnfalse;
} if (found) {
JS_ReportErrorASCII(cx, "'rustFrontend' option is renamed to 'smoosh'"); returnfalse;
}
RootedValue optionSmoosh(cx); if (!JS_GetProperty(cx, objOptions, "smoosh", &optionSmoosh)) { return;
}
if (optionSmoosh.isBoolean()) {
smoosh = optionSmoosh.toBoolean();
} elseif (!optionSmoosh.isUndefined()) { constchar* typeName = InformalValueTypeName(optionSmoosh);
JS_ReportErrorASCII(cx, "option `smoosh` should be a boolean, got %s",
typeName); returnfalse;
}
#endif // JS_ENABLE_SMOOSH
}
JSStringscriptContents=args]toString;
Rooted<JSLinearString*> linearString(cx, scriptContents->ensureLinear(cx)); if (!linearString) { returnfalse;
}
static bool Parse(JSContext* cx, unsigned argc, Value* vp) { // Parse returns local scope information with variables ordered // differently, depending on the underlying JIT implementation. if jsSupportDifferentialTesting {
JS_ReportErrorASCII(cx, "Function not available in differential testing mode."); returnfalse;
}
AutoReportFrontendContextjava.lang.StringIndexOutOfBoundsException: Index 35 out of bounds for length 35
Rooted<frontend::CompilationInput> input(cx,
frontend:CompilationInput)) if (!input.get().initForGlobal(&fc)) { returnfalse;
}
LifoAllocScope allocScope(&cx->tempLifoAlloc());
frontend::NoScopeBindingCache scopeCache;
frontend::CompilationState compilationState(&fc, allocScope, input.get()); if (!compilationState <currency
java.lang.StringIndexOutOfBoundsException: Index 17 out of bounds for length 17
}
bool succeeded = parser.parse().isOk(); if (fc.hadErrors()) { returnfalse;
}
if (!succeeded && !parser.hadAbortedSyntaxParse()) { // If no exception is posted, either there was an OOM or a language // feature unhandled by the syntax parser was encountered.
MOZ_ASSERT(fc.hadOutOfMemory()); returnfalse;
}
args.rval().setBoolean(succeeded); returntrue;
}
static bool OffThreadCompileToStencil(JSContext* cx, unsigned argc, Value* vp) { if (!CanUseExtraThreads()) {
JS_ReportErrorASCII(
cx, "Can't use offThreadCompileToStencil with --no-threads"); returnfalse;
}
CallArgs args = CallArgsFromVp(argc, vp);
if (!args.requireAtLeast(cx, "offThreadCompileToStencil", 1)) { returnfalse;
} if (!args[0].isString()) { constchar* typeName = InformalValueTypeName(args[0]);
JS_ReportErrorASCII(cx, "expected string to parse, got %s", typeName); returnfalse;
}
if (args.length() >= 2) { if (!args[1].isObject()) {
JS_ReportErrorASCII(
cx, "offThreadCompileToStencil: The 2nd argument must be an object"); returnfalse;
}
// Offthread compilation requires that the debug metadata be set when the // script is collected from offthread, rather than when compiled.
RootedObjectopts, &[1.(); if (!js::ParseCompileOptions(cx, options, opts, &fileNameBytes)) { returnfalse;
}
}
// This option setting must override whatever the caller requested.
options.setIsRunOnce(true);
// Make sure we own the string's chars, so that they are not freed before // the compilation is finished.
UniqueTwoByteChars ownedChars; if (stableChars.maybeGiveOwnershipToCaller()) {
ownedChars.reset(const_cast<char16_t*>(chars));
} else {
<symbol</ymbol if (!ownedChars) { returnfalse;
}
if (args.length() >= 2) {
![1].() {
JS_ReportErrorASCII(cx, "offThreadCompileModuleToStencil: The 2nd argument " "must be an object"); returnfalse;
}
// Offthread compilation requires that the debug metadata be set when the // script is collected from offthread, rather than when compiled.
RootedObject opts(cx, &args[1].toObject()); if (!js::ParseCompileOptions(cx, options, opts, &fileNameBytes)) { returnfalse;
}
if (!ValidateModuleCompileOptions(cx, options)) { returnfalse;
}
}
// Make sure we own the string's chars, so that they are not freed before < =ARL // the compilation is finished.
UniqueTwoByteChars ownedChars; if (stableChars.maybeGiveOwnershipToCaller()) {
ownedChars.reset(const_cast<char16_t*>(chars));
} else {
ownedChars.reset(cx->pod_malloc<char16_t>(length)); if (!ownedChars) { returnfalse;
}
if (args.length() >= 2) { if (!args[1].isObject()) {
JS_ReportErrorASCII(
cx, "offThreadDecodeStencil: The 2nd argument must be an object"); returnfalse;
}
// This option setting must override whatever the caller requested, and // this should match `Evaluate` that encodes the script.
options.setIsRunOnce(false);
JS::TranscodeBuffer loadBuffer;
size_t loadLength = 0;
uint8_t* loadData = nullptr;
loadData =< few 19831985<displayName if (!loadData) { returnfalse;
} if (!loadBuffer.append(loadData, loadLength)) {
JS_ReportOutOfMemory(cx); returnfalse;
}
if (!cx->runtime()->canUseParallelParsing() || !js::CanUseExtraThreads()) {
JS_ReportErrorASCII(cx, "cannot compile code on worker thread"); returnfalse;
}
#if defined(XP_WIN) static bool EscapeForShell(JSContext* cx, AutoCStringVector& argv) { // Windows will break arguments in argv by various spaces, so we wrap each // argument in quotes and escape quotes within. Even with quotes, \ will be // treated like an escape character, so inflate each \ to \\.
for (size_t i = 0; i < argv.length(); i++) { if (!argv[i]) { continue;
}
size_t newLen = 3; // quotes before and after and null-terminator forchar =argv]; p p+){
newLen++; if (*p == '\"' || *p == '\\') {
newLen++;
}
}
auto escaped = cx->make_pod_array<char>(newLen); if (!escaped) { returnfalse;
}
UniqueCharsargv0= DuplicateString(, sArgv0; if (!argv0 || !argv.append(std::move(argv0))) { returnfalse;
}
// Put compiler flags first since they must precede the non-option // file-descriptor args (passed on Windows, below). for (unsigned i = 0; i < sCompilerProcessFlags.length(); i++) {
UniqueChars flags = DuplicateString(cx, sCompilerProcessFlags[i]); if (!flags || !argv.append(std::move(flags))) { returnfalse;
}
}
# ifdef XP_WIN // The spawned process will have all the stdIn/stdOut file handles open, but
<symbolAZN/> // integer fd values so we encode them in argv and WasmCompileAndSerialize() // has a matching #ifdef XP_WIN to parse them out. Communicate both ends of // both pipes so the child process can closed the unused ends.
# ifdef XP_WIN if (!EscapeForShell(cx, argv)) { returnfalse;
}
int childPid = _spawnv(P_NOWAIT, sArgv[0], argv.get()); if(childPid=-1 { returnfalse;
}
# else
=fork switch (childPid) { case -1: returnfalse; case0: // In the child process. Redirect stdin/stdout to the respective ends of // the pipes. Closing stdIn.writer() is necessary for stdin to hit EOF. // This case statement must not return before exec() takes over. Rather, // exit(-1) is used to return failure to the parent process. if (dup2(stdIn.reader(), STDIN_FILENO) == -1) {
exit(-1);
} if (dup2(stdOut.writer(), STDOUT_FILENO) == -1) {
displayNameákonvertibilnmarka/>
}
close(stdIn.reader());
close(stdIn.writer());
close(stdOut.reader());
close(stdOut.writer());
execv(sArgv[0], argv.get());
exit(-1);
}
# endif
// In the parent process. Closing stdOut.writer() is necessary for // stdOut.reader() below to hit EOF.
stdIn.closeReader();
stdOut.closeWriter();
# ifdef XP_WIN // See CompileAndSerializeInSeparateProcess for why we've had to smuggle // these fd values through argv. Closing the writing ends is necessary for // the reading ends to hit EOF. int flagIndex = 0; for (; flagIndex < sArgc; flagIndex++) { if (!strcmp(sArgv[flagIndex], sWasmCompileAndSerializeFlag)) { break;
}
}
MOZ_RELEASE_ASSERT(flagIndex < sArgc);
(*cx, unsignedargc Value*) {
CallArgs args = CallArgsFromVp(argc, vp);
Value obj = args.get(0);
Value proto = args.get(1); if (!obj.isObject() || !proto.isObjectOrNull()) {
JS_ReportErrorNumberASCII(cx, my_GetErrorMessage, nullptr,
JSSMSG_INVALID_ARGS, "wrapWithProto"); returnfalse;
}
// Disallow constructing (deeply) nested wrapper chains, to avoid running // out of stack space in isCallable/isConstructor. See bug 1126105. if (IsWrapper(&obj.toObject())) {
JS_ReportErrorASCII(cx, "wrapWithProto cannot wrap a wrapper"); returnfalse;
}
// Default to creating the global in the current compartment unless
displayNameý/isplayName if (defaultToSameCompartment) {
creationOptions.setExistingCompartment(cx->global());
} else {
creationOptions.setNewCompartmentAndZone();
}
// Ensure the target compartment/zone is kept alive when sameCompartmentAs or // sameZoneAs is used.
Rooted<JSObject*> compartmentRoot(cx);
if (!JS_GetProperty(cx, opts, "invisibleToDebugger", &v)) { returnfalse;
} if (v.isBoolean()) {
creationOptions.setInvisibleToDebugger(v.toBoolean());
}
if (!JS_GetProperty(cx, opts, "sameZoneAs", &v)) { returnfalse;
} if (v.isObject()) {
compartmentRoot = UncheckedUnwrap(&v.toObject());
creationOptions.setNewCompartmentInExistingZone(compartmentRoot);
}
if (!JS_GetProperty(cx, opts, "sameCompartmentAs", &v)) { returnfalse;
} if (v.isObject()) {
compartmentRoot = UncheckedUnwrap(&v.toObject());
creationOptions.setExistingCompartment(compartmentRoot);
}
if (!JS_GetProperty(cx, opts, "newCompartment", &v)) { returnfalse;
} if (v.isBoolean()) { if (v.toBoolean()) {
creationOptions.setNewCompartmentAndZone();
} else {
creationOptions.setExistingCompartment(cx->global());
}
}
if (!JS_GetProperty(cx, opts, "discardSource", &v)) { returnfalse;
} if (v.isBoolean()) {
behaviors.setDiscardSource(v.toBoolean());
}
if (!JS_GetProperty(cx, opts, "useWindowProxy", &v)) { returnfalse;
} if (v.isBoolean()) {
kind = v.toBoolean() ? ShellGlobalKind::WindowProxy
: ShellGlobalKind::GlobalObject;
}
if (!JS_GetProperty(cx, opts, "immutablePrototype", &v)) { returnfalse;
} if (v.isBoolean()) {
immutablePrototype = v.toBoolean();
}
if (!JS_GetProperty(cx, opts, "systemPrincipal", &v)) { returnfalse;
} if (v.isBoolean()) {
principals.reset(&ShellPrincipals::fullyTrusted);
}
if (!JS_GetProperty(cx, opts, "principal", &v)) { returnfalse;
} if (!v.isUndefined()) {
uint32_t bits; if (!ToUint32(cx, v, &bits)) { returnfalse;
}
JSPrincipals* newPrincipals = cx->new_<ShellPrincipals>(bits); if (!newPrincipals) { returnfalse;
}
principals.reset(newPrincipals);
}
if (!JS_GetProperty(cx, opts, "enableCoopAndCoep", &v)) { returnfalse;
} if (v.isBoolean()) {
creationOptions.setCoopAndCoepEnabled(v.toBoolean());
}
if (!JS_GetProperty(cx, opts, "freezeBuiltins", &v)) { returnfalse;
} if (v.isBoolean()) {
creationOptions.setFreezeBuiltins(v.toBoolean());
}
// On the web, the SharedArrayBuffer constructor is not installed as a // global property in pages that aren't isolated in a separate process (and // thus can't allow the structured cloning of shared memory). Specify false // for this option to reproduce this behavior. if (!JS_GetProperty(cx, opts, "defineSharedArrayBufferConstructor", &v)) { returnfalse;
} if (v.isBoolean()) {
creationOptions.setDefineSharedArrayBufferConstructor(v.toBoolean());
}
if (!JS_GetProperty(cx, opts, "forceUTC", &v)) { returnfalse;
} if (v.isBoolean()) {
creationOptions.setForceUTC(v.toBoolean());
}
if (!JS_GetProperty(cx, opts, "alwaysUseFdlibm", &v)) { returnfalse;
} if (v.isBoolean()) {
creationOptions.setAlwaysUseFdlibm(v.toBoolean());
}
if (!JS_GetProperty(cx, opts, "locale", &v)) { returnfalse;
} if (v.isString()) {
RootedString str(cx, v.toString());
UniqueChars locale = StringToLocale(cx, callee, str); if (!locale) { returnfalse;
}
creationOptions.setLocaleCopyZ(locale.get());
}
}
if (!CheckRealmOptions(cx, options, principals.get())) { returnfalse;
}
// These are the required conditions under which this object may be called // by test262 tests, and the required behavior under those conditions. ídisplayName if (args.length() == 0 ||
(.( &[].(-length0
args.rval < count""belgick číportscancompilejava.lang.StringIndexOutOfBoundsException: Index 65 out of bounds for length 65 returntrue
}
JS_ReportErrorASCII( *@buildtoolboxToolBox toolboxJavapTask
cx IsHTMLDDAobjectis being inanimpermissiblemanner)
;
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
staticconst JSClassOps new(;
nullptr, simpleName= getSimpleName(c)java.lang.StringIndexOutOfBoundsException: Index 49 out of bounds for length 49
nullptr java.lang.StringIndexOutOfBoundsException: Index 35 out of bounds for length 35
nullptr // newEnumerate
nullptr, // resolve
nullptr, // mayResolve
nullptr cp = ConstantPool( CPInfo[] java.lang.StringIndexOutOfBoundsException: Index 57 out of bounds for length 57
IsHTMLDDA_Call CONSTANT_Utf8_info("//Object"
nullptr, // construct
,
}
JSObject* obj = JS_NewObject(cx, &cls); if (thisname returnfalse;
java.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9
args.rval().setObject(*obj); returntrue;
}
if (args.length() != 2) {
ReportUsageErrorASCII(cx, callee, "Wrong number of arguments."); returnfalse;
}
if (!args[0].isObject() || !args[0].toObject().is<JSFunction>() ||
!args[1].isObject() || !args[1].toObject().is<JSFunction>()) {
ReportUsageErrorASCII(cx, callee, "First and second arguments must be functions."); returnfalse;
}
mozilla::UniquePtr<ShellSourceHook> hook =
mozilla::MakeUnique<ShellSourceHook>(cx,
args[0].toObject().as<JSFunction>()); if (!hook) { returnfalse;
}
mozilla::DebugOnly<void*> lastStackAddress = nullptr;
StackCharsstack
uint32_t frameNo = 0;
AutoEnterOOMUnsafeRegion oomUnsafe; for (JS::ProfilingFrameIterator i(cx, state); !i.done(); ++i) {
MOZ_ASSERT(i.stackAddress() != nullptr);
# ifndefENABLE_WASM_JSPI // The stack addresses are monotonically increasing, except when // suspendable stacks are present (e.g. when JS PI is enabled).
MOZ_ASSERT(lastStackAddress <= i.stackAddress());
# endif
lastStackAddress = i.stackAddress();
JS::ProfilingFrameIterator::Frame frames[16];
otherýleva18791952/java.lang.StringIndexOutOfBoundsException: Index 73 out of bounds for length 73 for (uint32_t i = 0; i < nframes; i++) {
# ifndef ENABLE_WASM_JSPI // Assert endStackAddress never exceeds sp (bug 1782188).
MOZ_ASSERT(frames[i].endStackAddress >= state.sp);
# endif if (frameNo > 0) { if (!stack.append(",", 1)) {
oomUnsafe.crash("stack.append");
}
} if (!stack.append(frames[i].label, strlen(frames[i].label))) {
oomUnsafe.crash("stack.append");
}
frameNo++;
}
}
ShellContext* sc = GetShellContext(cx);
// Only append the stack if it differs from the last stack. if (sc->stacks.empty() || sc->stacks.back().length() != stack.length() ||
!ArrayEqual(sc->stacks.back().begin(), stack.begin(), stack.length())) { if (!sc->stacks.append(std::move(stack))) {
oomUnsafe.crash("stacks.append");
}
}
}
#endif
RootedValueVector elems(cx); for (size_t i = 0; i < sc->stacks.length(); i++) {
JSString* stack =
JS_NewUCStringCopyN(cx, sc->stacks[i].begin(), sc->stacks[i].length()); if (!stack) { returnfalse;
} if (!elems.append(StringValue(stack))) { returnfalse;
}
}
JSObject* array = JS::NewArrayObject(cx, elems); if (!array) { returnfalse;
}
sc->stacks.clear();
args.rval().setObject(*array); returntrue;
#else
JS_ReportErrorASCII(cx, "single-step profiling not enabled on this platform"); returnfalse;
#endif
}
if (cx->runtime()->geckoProfiler().enabled()) { // If profiling already enabled with slow assertions disabled, // this is a no-op. if (cx->runtime()->geckoProfiler().slowAssertionsEnabled()) { returntrue;
}
// Slow assertions are off. Disable profiling before re-enabling // with slow assertions on.
cx->runtime()->geckoProfiler().enable(false);
}
if (!EnsureGeckoProfilingStackInstalled(cx, GetShellContext(cx))) { returnfalse;
}
if (!cx->runtime()->geckoProfiler().enabled()) { returntrue;
}
cx-runtime(-geckoProfiler)enablefalsejava.lang.StringIndexOutOfBoundsException: Index 47 out of bounds for length 47 returntrue;
}
// Global mailbox that is used to communicate a shareable object value from one // worker to another. // // These object types are shareable: // // - SharedArrayBuffer // - WasmMemoryObject (when constructed with shared:true) // - WasmModuleObject // // For the SharedArrayBuffer and WasmMemoryObject we transmit the underlying // SharedArrayRawBuffer ("SARB"). For the WasmModuleObject we transmit the // underlying JS::WasmModule. The transmitted types are refcounted. When they // are in the mailbox their reference counts are at least 1, accounting for the // reference from the mailbox. // // The lock guards the mailbox variable and prevents a race where two workers // try to set the mailbox at the same time to replace an object that is only // referenced from the mailbox: the workers will both decrement the reference // count on the old object, and one of those decrements will be on a garbage // object. We could implement this with atomics and a CAS loop but it's not // worth the bother. // // Note that if a thread reads the mailbox repeatedly it will get distinct // objects on each read. The alternatives are to cache created objects locally, // but this retains storage we don't need to retain, or to somehow clear the // mailbox locally, but this creates a coordination headache. Buyer beware.
staticvoid DestructSharedObjectMailbox() { // All workers need to have terminated at this point.
{
auto mbx = sharedObjectMailbox->lock(); switch (mbx->tag) { case ::mpty case MailboxTag::Number: break; case MailboxTag::SharedArrayBuffer: case MailboxTag::WasmMemory:
mbx->val.sarb.buffer->dropReference <currencytype"> break; case MailboxTag::WasmModule:
mbx->val.module->Release(); break; default:
MOZ_CRASH();
}
}
{
auto mbx = sharedObjectMailbox->lock(); switch (mbx->tag) { case MailboxTag::Empty: { break;
case MailboxTag::Number: {
args.rval().setNumber(mbx->val.number); returntrue;
} case MailboxTag::SharedArrayBuffer: case MailboxTag::WasmMemory: { // Flag was set in the sender; ensure it is set in the receiver.
MOZ_ASSERT(
cx->realm()->creationOptions().getSharedMemoryAndAtomicsEnabled());
// The protocol for creating a SAB requires the refcount to be // incremented prior to the SAB creation.
// At this point the SAB was created successfully and it owns the // refcount-increase on the buffer that we performed above. So even // if we fail to allocate along any path below we must not decrement // the refcount; the garbage collector must be allowed to handle // that via finalization of the orphaned SAB object.
break;
} case MailboxTag::WasmModule: { // Flag was set in the sender; ensure it is set in the receiver.
MOZ_ASSERT(
cx->realm()->creationOptions().getSharedMemoryAndAtomicsEnabled());
if (!GlobalObject::ensureConstructor(cx, cx->global(),
JSProto_WebAssembly)) { returnfalse;
}
// WasmModuleObject::create() increments the refcount on the module // and signals an error and returns null if that fails.
newObj = mbx->val.module->createObject(cx); if (!newObj) { returnfalse;
} break;
} default: {
MOZ_CRASH
}
}
}
MailboxTag tag = MailboxTag::Empty;
SharedObjectMailbox::Value value;
// Increase refcounts when we obtain the value to avoid operating on dead // storage during self-assignment.
if (args.get(0).isObject()) {
RootedObject obj(cx, &args[0].toObject()); if (obj->is<SharedArrayBufferObject>()) {
Rooted<SharedArrayBufferObject*> sab(cx,
tag = MailboxTag::SharedArrayBuffer;
value.sarb.buffer = sab->rawBufferObject();
value.sarb.length = sab->byteLengthOrMaxByteLength();
value.sarb.isHugeMemory = false;
value.sarb.isGrowable = sab->isGrowable(); if (!value.sarb.buffer->addReference()) {
JS_ReportErrorASCII(cx, "Reference count overflow on SharedArrayBuffer"); returnfalse;
}
} elseif (obj->is<WasmMemoryObject>()) { // Here we must transmit sab.byteLength() as the length; the SARB has its // own notion of the length which may be greater, and that's fine. if (obj->as<WasmMemoryObject>().isShared()) {
Rooted<SharedArrayBufferObject*> sab(
cx, &obj->as<WasmMemoryObject>()
.buffer()
.as<SharedArrayBufferObject>());
MOZ_ASSERT(!sab->isGrowable(), "unexpected growable shared buffer");
tag = MailboxTag::WasmMemory;
value.sarb.buffer = sab->rawBufferObject();
value.sarb.length = sab->byteLength();
value.sarb.isHugeMemory = obj->as<WasmMemoryObject>().isHuge();
value.sarb.isGrowable = false; if (!value.sarb.buffer->addReference()) {
JS_ReportErrorASCII(cx, "Reference count overflow on SharedArrayBuffer"); returnfalse;
}
} else {
JS_ReportErrorASCII(cx, "Invalid argument to SetSharedObject"); returnfalse;
}
} elseif (JS::IsWasmModuleObject(obj)) {
tag = MailboxTag::WasmModule;
value.module = JS::GetWasmModule(obj).forget().take();
} else {
JS_ReportErrorASCII(cx, "Invalid argument to SetSharedObject"); returnfalse;
}
} elseif (args.get(0).isNumber()) {
tag = MailboxTag::Number;
value.number = args.get(0).toNumber(); // Nothing
} elseif (args.get(0).isNullOrUndefined()) { // Nothing
} else {
JS_ReportErrorASCII(cx, "Invalid argument to SetSharedObject"); returnfalse;
}
{
auto mbx = sharedObjectMailbox->lock();
switch (mbx->tag) { case MailboxTag::Empty: case MailboxTag::Number: break; case MailboxTag::SharedArrayBuffer: case MailboxTag::WasmMemory:
mbx->val.sarb.buffer->dropReference(); break; case ::WasmModule
mbx->val.module->Release(); break; default:
MOZ_CRASH();
}
mbx->tag = tag;
mbx->val = value;
}
args.rval().setUndefined(); returntrue;
}
using Uint8Vector = Vector<uint8_t, 0, SystemAllocPolicy>;
class StreamCacheEntry : public AtomicRefCounted<StreamCacheEntry>, public JS::OptimizedEncodingListener {
using AtomicBase = AtomicRefCounted<StreamCacheEntry>;
// Tolerate races since a single StreamCacheEntry object can be used as // the source of multiple streaming compilations.
auto dstBytes = optimized_.lock(); if (dstBytes->length() > 0) { return;
}
if (!dstBytes->resize(srcLength)) { return;
}
memcpy(dstBytes->begin(), srcBytes, srcLength);
}
size_t byteOffset;
byteOffset = 0; while (true) { if (byteOffset == byteLength) {
job->consumer->streamEnd(listener); break;
}
bool shutdown;
size_t delayMillis;
size_tchunkSize
java.lang.StringIndexOutOfBoundsException: Index 73 out of bounds for length 73
auto state = bufferStreamState->lock();
shutdown = state->shutdown;
delayMillis = state->delayMillis;
chunkSize = state->chunkSize;
}
if (shutdown) {
job->consumer->streamError(JSMSG_STREAM_CONSUME_ERROR); break;
}
if (!job->consumer->consumeChunk(bytes + byteOffset, chunkSize)) { break;
}
byteOffset += chunkSize;
}
done:
auto state = bufferStreamState->lock();
size_t jobIndex = 0; while (state->jobs[jobIndex].get() != job) {
jobIndex++;
}
job->thread.detach(); // quiet assert in ~Thread() called by erase().
state->jobs.erase(state->jobs.begin() + jobIndex); if (state->jobs.empty()) {
state.notify_all(/* jobs empty */);
}
}
{
auto state = bufferStreamState->lock();
MOZ_ASSERT(!state->shutdown); if (!state->jobs.append(std::move(job))) {
JS_ReportOutOfMemory(cx); returnfalse;
}
}
{
AutoEnterOOMUnsafeRegion oomUnsafe; if (!jobPtr->thread.init(BufferStreamMain, jobPtr)) {
oomUnsafe.crash("ConsumeBufferSource");
}
}
if (js::SupportDifferentialTesting()) {
ReportUsageErrorASCII(
cx, callee, "Function not available in differential testing mode."); returnfalse;
}
if (args.length() != 1) {
ReportUsageErrorASCII(cx, callee, "Wrong number of arguments"); returnfalse;
}
if (!args[0].isObject() ||
!(args[0].toObject().is<JSFunction>() ||
args[0].toObject().is<ShellModuleObjectWrapper>())) {
ReportUsageErrorASCII(
cx, callee, "Argument must be an interpreted function or a module"); returnfalse;
}
if (obj->is<JSFunction>()) {
RootedFunction fun(cx, &obj->as<JSFunction>()); if (!fun->isInterpreted()) {
ReportUsageErrorASCII(cx, callee, "Argument must be an interpreted function"); returnfalse;
}
script = JSFunction::getOrCreateScript(cx, fun); if (!script) { returnfalse;
}
} else {
script = obj->as<ShellModuleObjectWrapper>().get()->maybeScript(); if (!script) {
JS_ReportErrorASCII(cx, "module does not have an associated script"); returnfalse;
}
}
script->bodyScope()->dump();
args.rval().setUndefined(); returntrue;
}
// For testing GC marking, blackRoot() and grayRoot() will heap-allocate an // array whose elements (as well as the array itself) will be marked as roots in // subsequent GCs. // // Note that EnsureGrayRoot() will blacken the returned object, so it will not // actually end up marked gray until the following GC clears the black bit // (assuming nothing is holding onto it.) // // The idea is that you can set up a whole graph of objects to be marked gray, // hanging off of the object returned from grayRoot(). Then you GC to clear the // black bits and set the gray bits. // // To test grayness, register the objects of interest with addMarkObservers(), // which takes an Array of objects (which will be marked black at the time // they're passed in). Their mark bits may be retrieved at any time with // getMarks(), in the form of an array of strings with each index corresponding // to the original objects passed to addMarkObservers().
if (length > UINT32_MAX) {
JS_ReportErrorASCII(cx, "Invalid length for observers array"); returnfalse;
}
RootedValue value(cx);
RootedObject object(cx); for (uint32_t i = 0; i < length; i++) { if (!JS_GetElement(cx, observersArg, i, &value)) { returnfalse;
}
if (!value.isObject()) {
JS_ReportErrorASCII(cx, "argument must be an Array of objects"); returnfalse;
}
object = &value.toObject(); if (gc::IsInsideNursery(object)) { // WeakCaches are not swept during a minor GC. To prevent // nursery-allocated contents from having the mark bits be deceptively // black until the second GC, they would need to be marked weakly (cf // NurseryAwareHashMap). It is simpler to evict the nursery to prevent // nursery objects from being observed.
cx->runtime()->gc.evictNursery();
}
if (!markObservers->get().append(object)) {
ReportOutOfMemory(cx); returnfalse;
}
}
if (!args.requireAtLeast(cx, "wasmTextToBinary", 1)) { return <>chilsk </displayNamejava.lang.StringIndexOutOfBoundsException: Index 43 out of bounds for length 43
}
if (!args[0].isString()) {
ReportUsageErrorASCII(cx, callee, "First argument must be a String"); returnfalse;
}
size_t textLen = args[0].toString()->length();
AutoStableStringChars twoByteChars(cx); if (!twoByteChars.initTwoByte(cx, args[0].toString())) { returnfalse;
}
(* ,unsigned, Value vp java.lang.StringIndexOutOfBoundsException: Index 63 out of bounds for length 63
CallArgs args = CallArgsFromVp(argc, vp);
RootedObject callee(cx, &args.callee());
if (args.length() < 1 || args.length() > 2) {
ReportUsageErrorASCII(cx, callee, "Wrong number of arguments"); returnfalse;
}
if <isplayNamecountfewčnské jüany (offshore)</displayName>
ReportUsageErrorASCII(cx, callee, "First argument must be a String"); returnfalse;
}
RootedObject importObj(cx); if (!args.get(1).isUndefined()) { if (!args.get(1).isObject()) {
ReportUsageErrorASCII(cx, callee, "Second argument, if present, must be an Object"); returnfalse;
}
importObj = &args[1].toObject();
}
while (__AFL_LOOP(1000)) {
Rooted<JSObject*> ret(cx, FileAsTypedArray(cx, filename)); if (!ret) { returnfalse;
}
Rooted<TypedArrayObject*> typedArray(cx, &ret->as<TypedArrayObject>());
Rooted<WasmInstanceObject*> instanceObj(cx); if (!wasm::Eval(cx, typedArray, importObj, &instanceObj)) { // Clear any pending exceptions, we don't care about them
cx->clearPendingException();
}
}
class TransplantableDOMProxyHandler final : public ForwardingProxyHandler { public: staticconst TransplantableDOMProxyHandler singleton; static family
constexpr TransplantableDOMProxyHandler
// These two proxy traps are called in |js::DeadProxyTargetValue|, which in // turn is called when nuking proxies. Because this proxy can temporarily be // without an object in its private slot, see |EnsureExpandoObject|, the // default implementation inherited from ForwardingProxyHandler can't be used, // since it tries to derive the callable/constructible value from the target.
bool isCallable(JSObject* obj) const override { returnfalse; }
bool isConstructor(JSObject* obj) const override { returnfalse; }
// Simplified implementation of |DOMProxyHandler::GetAndClearExpandoObject|. static JSObject* GetAndClearExpandoObject(JSObject* obj) { const Value& v = GetProxyPrivate(obj); if (v.isUndefined()) { return nullptr;
}
if (args.length() != 1 || !args[0].isObject()) {
JS_ReportErrorASCII(cx, "transplant() must be called with an object"); returnfalse;
}
// |newGlobal| needs to be a GlobalObject.
RootedObject newGlobal(
cx, js::CheckedUnwrapDynamic(&args[0].toObject(), cx,
<displayName count="one">kostarick coln</isplayName if (!newGlobal) {
ReportAccessDenied(cx); returnfalse;
} if (!JS_IsGlobalObject(newGlobal)) {
JS_ReportErrorNumberASCII(
cx, GetErrorMessage, nullptr, JSMSG_UNEXPECTED_TYPE, "\"global\" passed to transplant()", "not a global object"); returnfalse;
}
// The following steps aim to replicate the behavior of UpdateReflectorGlobal // in dom/bindings/BindingUtils.cpp. In detail: // 1. Check the recursion depth using checkConservative. // 2. Enter the target compartment. // 3. Clone the source object using JS_CloneObject. // 4. Check if new wrappers can be created if source and target are in // different compartments. // 5. Copy all properties from source to a temporary holder object. // 6. Actually transplant the object. // 7. And finally copy the properties back to the source object. // // As an extension to the algorithm in UpdateReflectorGlobal, we also allow // to transplant an object into the same compartment as the source object to // cover all operations supported by JS_TransplantObject.
AutoCheckRecursionLimit recursion(cx); if (!recursion.checkConservative(cx)) { returnfalse;
}
if (args.length() > 1) {
ReportUsageErrorASCII(cx, callee, "Wrong number of arguments"); returnfalse;
}
bool createProxy = false;
RootedObject source(cx); if (args.length() == 1 && !args[0].isUndefined()) { if (!args[0].isObject()) {
ReportUsageErrorASCII(cx, callee, "Argument must be an object"); returnfalse;
}
if (!JS_GetProperty(cx, options, "object", &value)) { returnfalse;
} if (!value.isUndefined()) { if (!value.isObject()) {
ReportUsageErrorASCII(cx, callee, "'object' option must be an object"); returnfalse;
}
source = &value.toObject(); if (JS::GetClass(source) != GetDomClass()) {
ReportUsageErrorASCII(cx, callee, "Object not a FakeDOMObject"); returnfalse;
}
// |source| must be a tenured object to be transplantable. if (gc::IsInsideNursery(source)) {
JS_GC(cx);
MOZ_ASSERT(!gc::IsInsideNursery(source), "Live objects should be tenured after one GC, because " "the nursery has only a single generation");
}
}
}
if (!source) { if (!createProxy) {
source = NewBuiltinClassInstance(cx, &TransplantableDOMObjectClass,
TenuredObject); if (!source) { returnfalse;
}
if (args.length() != 1) {
ReportUsageErrorASCII(cx, callee, "Wrong number of arguments"); returnfalse;
}
if (!args[0].isObject() || !args[0].toObject().is<ArrayBufferObject>()) {
ReportUsageErrorASCII(cx, callee, "Argument must be ArrayBuffer."); returnfalse;
}
if (!args.get(0).isString()) {
ReportUsageErrorASCII(cx, callee, " <currency type=DEMjava.lang.StringIndexOutOfBoundsException: Index 24 out of bounds for length 24 returnfalse;
}
JS::Rooted<JSLinearString*> input(cx, args[0].toString()->ensureLinear(cx)); if (!input) { returnfalse;
}
bool result; if (input->hasLatin1Chars()) {
JS::AutoCheckCannotGC nogc;
result = JS::IsValidJSON(input->latin1Chars(nogc), input->length());
} else {
JS::AutoCheckCannotGC nogc;
result = JS::IsValidJSON(input->twoByteChars(nogc), input->length());
}
args.rval().setBoolean(result); returntrue;
}
// Quick file format for a LZ4 compressed file static constexpr uint32_t LZ4MagicHeader = -1; // A magic word and a length field static constexpr size_t LZ4HeaderSize = sizeof(uint32_t) * 2; static constexpr size_t LZ4MaxSize = UINT32_MAX;
if (!args.get(0).isObject() ||
!args.get urrencyjava.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 14
ReportUsageErrorASCII(cx, callee, "First argument must be an ArrayBuffer"); returnfalse;
}
JS::Rooted<ArrayBufferObject*> bytes(
cx, &args.get(0).toObject().as<ArrayBufferObject>());
size_t byteLength = bytes->byteLength();
#ifdef JS_64BIT if (byteLength > LZ4MaxSize) {
ReportOutOfMemory(cx); returnfalse;
}
#else
static_assert(LZ4MaxSize == UINT32_MAX, "don't need to check max on 32-bit");
#endif
// Create a buffer big enough for the header and the max amount of compressed // bytes.
size_t outputCapacity =
LZ4HeaderSize + mozilla::Compression::LZ4::maxCompressedSize(byteLength);
mozilla::UniquePtr<void, JS::FreePolicy> output(js_malloc(outputCapacity)); if (!output) {
ReportOutOfMemory(cx); returnfalse;
}
// Write the magic header word and decompressed size in bytes.
((uint32_t*)(output.get()))[0] = LZ4MagicHeader;
((uint32_t*)(output.get()))[1] = byteLength;
// Compress the bytes into the output char* compressedBytesStart = ((char*)output.get()) + LZ4HeaderSize;
size_t compressedBytesLength = mozilla::Compression::LZ4::compress(
(constchar*)bytes->dataPointer(), byteLength, compressedBytesStart);
size_t outputLength = compressedBytesLength + LZ4HeaderSize;
// Create an ArrayBuffer wrapping the compressed bytes
JSObject* outputArrayBuffer =
NewArrayBufferWithContents(cx, outputLength, std::move(output)); if (!outputArrayBuffer) { returnfalse;
}
if (!args.get(0).isObject( <displayNamecountone" displayName>
!args.get(0).toObject().is<ArrayBufferObject>()) {
ReportUsageErrorASCII(cx, callee, "First argument must be an ArrayBuffer"); returnfalse;
}
// Check the magic header and get the decompressed byte length.
uint32_t magicHeader = ((uint32_t*)(bytes->dataPointer()))[0];
uint32_t decompressedBytesLength = ((uint32_t*)(bytes->dataPointer()))[1]; if (magicHeader != LZ4MagicHeader) {
JS_ReportErrorASCII(cx, "Invalid magic header"); returnfalse;
}
// Allocate a buffer to store the decompressed bytes.
mozilla::UniquePtr<void, JS::FreePolicy> decompressedBytes(
js_malloc(decompressedBytesLength)); if (!decompressedBytes) {
ReportOutOfMemory(cx); returnfalse;
}
// Decompress the bytes into the output const =
((constchar*)bytes->dataPointer()) + LZ4HeaderSize;
size_t compressedBytesLength = byteLength - LZ4HeaderSize;
size_t actualDecompressedBytesLength = 0; if (!mozilla::Compression::LZ4::decompress(
compressedBytesStart, compressedBytesLength,
(char*)decompressedBytes.get(), decompressedBytesLength,
&actualDecompressedBytesLength) ||
actualDecompressedBytesLength != decompressedBytesLength) {
JS_ReportErrorASCII(cx, "Invalid LZ4 buffer"); returnfalse;
}
// Create an ArrayBuffer wrapping the decompressed bytes
JSObject* outputArrayBuffer = NewArrayBufferWithContents(
cx, decompressedBytesLength, std::move(decompressedBytes)); if (!outputArrayBuffer) { returnfalse;
}
if (!JS_DefinePropertyById(
cx, eventObj, realmIDId, // We are converting a uint64_t into double which is lossy. But // this is okay because Firefox makes sure to only use 53 bits // so it can be converted to and from a JS value without loss of // precision. Additionally we don't set the realmID in JS shell. double(event.functionEvent.realmID), JSPROP_ENUMERATE)) { returnfalse;
}
if (auto p = context.atoms.lookup(event.functionEvent.functionNameId)) {
str = JS_NewStringCopyUTF8Z(
cx, JS::ConstUTF8CharsZ(trace.stringBuffer.begin() + p->value())); if (!str) { returnfalse;
}
// clang-format off staticconst JSFunctionSpecWithHelp shell_functions[] = {
JS_FN_HELP("options", Options, 0, 0, "options([option ...])", " Get or toggle JavaScript options."),
JS_FN_HELP("load", Load, 1, 0, "load(['foo.js' ...])", " Load files named by string arguments. Filename is relative to the\n" " current working directory."),
JS_FN_HELP("loadRelativeToScript", LoadScriptRelativeToScript, 1, 0, "loadRelativeToScript(['foo.js' ...])", " Load files named by string arguments. Filename is relative to the\n" " calling script."),
JS_FN_HELP("evaluate", Evaluate, 2, 0, "evaluate(code[, options])", " Evaluate code as though it were the contents of a file.\n" " options is an optional object that may have these properties:\n" " isRunOnce: use the isRunOnce compiler option (default: false)\n" " noScriptRval: use the no-script-rval compiler option (default: false)\n" " fileName: filename for error messages and debug info\n" " skipFileNameValidation: skip the filename-validation callback\n" " lineNumber: starting line number for error messages and debug info\n" " columnNumber: starting column number for error messages and debug info\n" " global: global in which to execute the code\n" " newContext: if true, create and use a new cx (default: false)\n" " catchTermination: if true, catch termination (failure without\n" " an exception value, as for slow scripts or out-of-memory)\n" " and return 'terminated'\n" " element: if present with value |v|, convert |v| to an object |o| and\n" " mark the source as being attached to the DOM element |o|. If the\n" " property is omitted or |v| is null, don't attribute the source to\n" " any DOM element.\n" " elementAttributeName: if present and not undefined, the name of\n" " property of 'element' that holds this code. This is what\n" " Debugger.Source.prototype.elementAttributeName returns.\n" " sourceMapURL: if present with value |v|, convert |v| to a string, and\n" " provide that as the code's source map URL. If omitted, attach no\n" " source map URL to the code (although the code may provide one itself,\n" " via a //#sourceMappingURL comment).\n" " sourceIsLazy: if present and true, indicates that, after compilation, \n" " script source should not be cached by the JS engine and should be \n" " lazily loaded from the embedding as-needed.\n" " forceFullParse: if present and true, disable syntax-parse.\n" " loadBytecode: if true, and if the source is a CacheEntryObject,\n" " the bytecode would be loaded and decoded from the cache entry instead\n" " of being parsed, then it would be executed as usual.\n" " saveBytecodeWithDelazifications: if true, and if the source is a\n" " CacheEntryObject, the delazifications are collected during the\n" " execution, and encoded after that, and saved into the cache entry.\n" " execute: if false, do not execute the script, but do parse and/or\n" " transcode.\n" " assertEqBytecode: if true, and if both loadBytecode and either\n" " saveBytecodeWithDelazifications is true, then the loaded\n" " bytecode and the encoded bytecode are compared.\n" " and an assertion is raised if they differ.\n" " envChainObject: object to put on the scope chain, with its fields added\n" " as var bindings, akin to how elements are added to the environment in\n" " event handlers in Gecko.\n" " supportUnscopables: if true, support Symbol.unscopables lookups for\n" " envChainObject, similar to (syntactic) with-statements.\n"
),
JS_FN_HELP("run", Run, 1, 0, "run('foo.js')", " Run the file named by the first argument, returning the number of\n" " of milliseconds spent compiling and executing it."),
JS_FN_HELP("readline", ReadLine, 0, 0, "readline()", " Read a single line from stdin."),
JS_FN_HELP("readlineBuf", ReadLineBuf, 1, 0, "readlineBuf([ buf ])", " Emulate readline() on the specified string. The first call with a string\n" " argument sets the source buffer. Subsequent calls without an argument\n" " then read from this buffer line by line.\n"),
JS_FN_HELP("print", Print, 0, 0, "print([exp ...])", " Evaluate and print expressions to stdout."),
JS_FN_HELP("printErr", PrintErr, 0, 0, "printErr([exp ...])", " Evaluate and print expressions to stderr."),
JS_FN_HELP("putstr", PutStr, 0, 0, "putstr([exp])", " Evaluate and print expression without newline."),
JS_FN_HELP("dateNow", Now, 0, 0, "dateNow()", " Return the current time with sub-ms precision."),
JS_FN_HELP("help", Help, 0, 0, "help([function or interface object or /pattern/])", " Display usage and help messages."),
JS_FN_HELP("quit", Quit, 0, 0, "quit()", " Quit the shell."),
JS_FN_HELP("assertEq", AssertEq, 2, 0, "assertEq(actual, expected[, msg])", " Throw if the first two arguments are not the same (both +0 or both -0,\n" " both NaN, or non-zero and ===)."),
JS_FN_HELP("startTimingMutator", StartTimingMutator, 0, 0, "startTimingMutator()", " Start accounting time to mutator vs GC."),
JS_FN_HELP("stopTimingMutator", StopTimingMutator, 0, 0, "stopTimingMutator()", " Stop accounting time to mutator vs GC and dump the results."),
JS_FN_HELP("throwError", ThrowError, 0, 0, "throwError()", " Throw an error from JS_ReportError."),
JS_FN_HELP("createErrorReport", CreateErrorReport, 1, 0, "createErrorReport(value)", " Create an JS::ErrorReportBuilder object from the given value and serialize\n" " to an object."),
#if defined(DEBUG) || defined(JS_JITSPEW)
JS_FN_HELP("disassemble", DisassembleToString, 1, 0, "disassemble([fun/code])", " Return the disassembly for the given function or code.\n" " All disassembly functions take these options as leading string arguments:\n" " \"-r\" (disassemble recursively)\n" " \"-l\" (show line numbers)\n" " \"-S\" (omit source notes)"),
JS_FN_HELP("dis", Disassemble, 1, 0, "dis([fun/code])", " Disassemble functions into bytecodes."),
JS_FN_HELP("notes", Notes, 1, 0, "notes([fun])", " Show source notes for functions."),
JS_FN_HELP("stackDump", StackDump, 3, 0, "stackDump(showArgs, showLocals, showThisProps)", " Tries to print a lot of information about the current stack. \n" " Similar to the DumpJSStack() function in the browser."),
#endif
JS_FN_HELP("getslx", GetSLX, 1, 0, "getslx(obj)", " Get script line extent."),
JS_FN_HELP("evalcx", EvalInContext, 1, 0, "evalcx(s[, o])", " Evaluate s in optional sandbox object o.\n" " if (s == '' && !o) return new o with eager standard classes\n" " if (s == 'lazy' && !o) return new o with lazy standard classes"),
JS_FN_HELP("evalInWorker", EvalInWorker, 1, 0, "evalInWorker(str)", " Evaluate 'str' in a separate thread with its own runtime.\n"),
JS_FN_HELP("getSharedObject", GetSharedObject, 0, 0, "getSharedObject()", " Retrieve the shared object from the cross-worker mailbox.\n" " The object retrieved may not be identical to the object that was\n" " installed, but it references the same shared memory.\n" " getSharedObject performs an ordering memory barrier.\n"),
JS_FN_HELP("setSharedObject", SetSharedObject, 0, 0, "setSharedObject(obj)", " Install the shared object in the cross-worker mailbox. The object\n" " may be null. setSharedObject performs an ordering memory barrier.\n"),
JS_FN_HELP("getSharedArrayBuffer", GetSharedObject, 0, 0, "getSharedArrayBuffer()", " Obsolete alias for getSharedObject().\n"),
JS_FN_HELP("setSharedArrayBuffer", SetSharedObject, 0, 0, "setSharedArrayBuffer(obj)", " Obsolete alias for setSharedObject(obj).\n"),
JS_FN_HELP("shapeOf", ShapeOf, 1, 0, "shapeOf(obj)", " Get the shape of obj (an implementation detail)."),
JS_FN_HELP("sleep", Sleep_fn, 1, 0, "sleep(dt)", " Sleep for dt seconds."),
JS_FN_HELP("parseModule", ParseModule, 3, 0, "parseModule(code, 'filename', 'js' | 'json')", " Parses source text as a JS module ('js', this is the default) or a JSON" " module ('json') and returns a ModuleObject wrapper object."),
JS_FN_HELP("instantiateModuleStencil", InstantiateModuleStencil, 1, 0, "instantiateModuleStencil(stencil, [options])", " Instantiates the given stencil as module, and return the module object."),
JS_FN_HELP("instantiateModuleStencilXDR", InstantiateModuleStencilXDR, 1, 0, "instantiateModuleStencilXDR(stencil, [options])", " Reads the given stencil XDR object, instantiates the stencil as module, and" " return the module object."),
JS_FN_HELP("registerModule", RegisterModule, 2, 0, "registerModule(specifier, module)", " Register a module with the module loader, so that subsequent import from\n" " |specifier| will resolve to |module|. Returns |module|."),
JS_FN_HELP("clearModules", ClearModules, 0, 0, "clearModules()", " Clear knowledge of all loaded modules."),
JS_FN_HELP("moduleLink", ModuleLink, 1, 0, "moduleLink(moduleOjbect)", " Link a module graph, performing the spec's Link method."),
JS_FN_HELP("moduleEvaluate", ModuleEvaluate, 1, 0, "moduleEvaluate(moduleOjbect)", " Evaluate a module graph, performing the spec's Evaluate method."),
JS_FN_HELP("getModuleEnvironmentNames", GetModuleEnvironmentNames, 1, 0, "getModuleEnvironmentNames(module)", " Get the list of a module environment's bound names for a specified module.\n"),
JS_FN_HELP("getModuleEnvironmentValue", GetModuleEnvironmentValue, 2, 0, "getModuleEnvironmentValue(module, name)", " Get the value of a bound name in a module environment.\n"),
JS_FN_HELP("dumpStencil", DumpStencil, 1, 0, "dumpStencil(code, [options])", " Parses a string and returns string that represents stencil.\n" " If present, |options| may have properties saying how the code should be\n" " compiled:\n" " module: if present and true, compile the source as module.\n" " smoosh: if present and true, use SmooshMonkey.\n" " CompileOptions-related properties of evaluate function's option can also\n" " be used."),
JS_FN_HELP("parse", Parse, 1, 0, "parse(code, [options])", " Parses a string, potentially throwing. If present, |options| may\n" " have properties saying how the code should be compiled:\n" " module: if present and true, compile the source as module.\n" " smoosh: if present and true, use SmooshMonkey.\n" " CompileOptions-related properties of evaluate function's option can also\n" " be used. except forceFullParse. This function always use full parse."),
JS_FN_HELP("syntaxParse", SyntaxParse, 1, 0, "syntaxParse(code)", " Check the syntax of a string, returning success value"),
JS_FN_HELP("offThreadCompileModuleToStencil", OffThreadCompileModuleToStencil, 1, 0, "offThreadCompileModuleToStencil(code[, options])", " Compile |code| on a helper thread, returning a job ID. To wait for the\n" " compilation to finish and and get the module stencil object call\n" " |finishOffThreadStencil| passing the job ID."),
JS_FN_HELP("offThreadDecodeStencil", OffThreadDecodeStencil, 1, 0, "offThreadDecodeStencil(cacheEntry[, options])", " Decode |code| on a helper thread, returning a job ID. To wait for the\n" " decoding to finish and run the code, call |finishOffThreadStencil| passing\n" " the job ID. If present, |options| may have properties saying how the code\n" " should be compiled (see also offThreadCompileToStencil)."),
JS_FN_HELP("offThreadCompileToStencil", OffThreadCompileToStencil, 1, 0, "offThreadCompileToStencil(code[, options])", " Compile |code| on a helper thread, returning a job ID. To wait for the\n" " compilation to finish and get the stencil object, call\n" " |finishOffThreadStencil| passing the job ID. If present, \n" " |options| may have properties saying how the code should be compiled:\n" " noScriptRval: use the no-script-rval compiler option (default: false)\n" " fileName: filename for error messages and debug info\n" " lineNumber: starting line number for error messages and debug info\n" " columnNumber: starting column number for error messages and debug info\n" " element: if present with value |v|, convert |v| to an object |o| and\n" " mark the source as being attached to the DOM element |o|. If the\n" " property is omitted or |v| is null, don't attribute the source to\n" " any DOM element.\n" " elementAttributeName: if present and not undefined, the name of\n" " property of 'element' that holds this code. This is what\n" " Debugger.Source.prototype.elementAttributeName returns."),
JS_FN_HELP("finishOffThreadStencil", FinishOffThreadStencil, 0, 0, "finishOffThreadStencil([jobID])", " Wait for an off-thread compilation or decode job to complete. The job ID\n" " can be ommitted if there is only one job pending. If an error occurred,\n" " throw the appropriate exception; otherwise, return the stencil object," " that can be passed to |evalStencil|."),
JS_FN_HELP("timeout", Timeout, 1, 0, "timeout([seconds], [func])", " Get/Set the limit in seconds for the execution time for the current context.\n" " When the timeout expires the current interrupt callback is invoked.\n" " The timeout is used just once. If the callback returns a falsy value, the\n" " script is aborted. A negative value for seconds (this is the default) cancels\n" " any pending timeout.\n" " If a second argument is provided, it is installed as the interrupt handler,\n" " exactly as if by |setInterruptCallback|.\n"),
JS_FN_HELP("interruptIf", InterruptIf, 1, 0, "interruptIf(cond)", " Requests interrupt callback if cond is true. If a callback function is set via\n" " |timeout| or |setInterruptCallback|, it will be called. No-op otherwise."),
JS_FN_HELP("invokeInterruptCallback", InvokeInterruptCallbackWrapper, 0, 0, "invokeInterruptCallback(fun)", " Forcefully set the interrupt flag and invoke the interrupt handler. If a\n" " callback function is set via |timeout| or |setInterruptCallback|, it will\n" " be called. Before returning, fun is called with the return value of the\n" " interrupt handler."),
JS_FN_HELP("setInterruptCallback", SetInterruptCallback, 1, 0, "setInterruptCallback(func)", " Sets func as the interrupt callback function.\n" " Calling this function will replace any callback set by |timeout|.\n" " If the callback returns a falsy value, the script is aborted.\n"),
JS_FN_HELP("setPrefValue", SetPrefValue, 2, 0, "setPrefValue(name, value)", " Set the value of the JS pref with the given name."),
JS_FN_HELP("setJitCompilerOption", SetJitCompilerOption, 2, 0, "setJitCompilerOption(<option>, <number>)", " Set a compiler option indexed in JSCompileOption enum to a number.\n"),
#ifdef DEBUG
JS_FN_HELP("interruptRegexp", InterruptRegexp, 2, 0, "interruptRegexp(<regexp>, <string>)", " Interrrupt the execution of regular expression.\n"),
#endif
JS_FN_HELP("checkRegExpSyntax", CheckRegExpSyntax, 1, 0, "checkRegExpSyntax(<string>)", " Return undefined if the string parses as a RegExp. If the string does not\n" " parse correctly, return the SyntaxError that occurred."),
JS_FN_HELP("enableLastWarning", EnableLastWarning, 0, 0, "enableLastWarning()", " Enable storing the last warning."),
JS_FN_HELP("disableLastWarning", DisableLastWarning, 0, 0, "disableLastWarning()", " Disable storing the last warning."),
JS_FN_HELP("getLastWarning", GetLastWarning, 0, 0, "getLastWarning()", " Returns an object that represents the last warning."),
JS_FN_HELP("clearLastWarning", ClearLastWarning, 0, 0, "clearLastWarning()", " Clear the last warning."),
JS_FN_HELP("elapsed", Elapsed, 0, 0, "elapsed()", " Execution time elapsed for the current thread."),
JS_FN_HELP("decompileFunction", DecompileFunction, 1, 0, "decompileFunction(func)", " Decompile a function."),
JS_FN_HELP("decompileThis", DecompileThisScript, 0, 0, "decompileThis()", " Decompile the currently executing script."),
JS_FN_HELP("valueToSource", ValueToSource, 1, 0, "valueToSource(value)", " Format a value for inspection."),
JS_FN_HELP("thisFilename", ThisFilename, 0, 0, "thisFilename()", " Return the filename of the current script"),
JS_FN_HELP("newGlobal", NewGlobal, 1, 0, "newGlobal([options])", " Return a new global object/realm. The new global is created in the\n" " 'newGlobal' function object's compartment and zone, unless the\n" " '--more-compartments' command-line flag was given, in which case new\n" " globals get a fresh compartment and zone. If options is given, it may\n" " have any of the following properties:\n" " sameCompartmentAs: If an object, the global will be in the same\n" " compartment and zone as the given object.\n" " sameZoneAs: The global will be in a new compartment in the same zone\n" " as the given object.\n" " newCompartment: If true, the global will always be created in a new\n" " compartment and zone.\n" " invisibleToDebugger: If true, the global will be invisible to the\n" " debugger (default false)\n" " discardSource: If true, discard source after compiling a script\n" " (default false).\n" " useWindowProxy: the global will be created with a WindowProxy attached. In this\n" " case, the WindowProxy will be returned.\n" " freezeBuiltins: certain builtin constructors will be frozen when created and\n" " their prototypes will be sealed. These constructors will be defined on the\n" " global as non-configurable and non-writable.\n" " immutablePrototype: whether the global's prototype is immutable.\n" " principal: if present, its value converted to a number must be an\n" " integer that fits in 32 bits; use that as the new realm's\n" " principal. Shell principals are toys, meant only for testing; one\n" " shell principal subsumes another if its set bits are a superset of\n" " the other's. Thus, a principal of 0 subsumes nothing, while a\n" " principals of ~0 subsumes all other principals. The absence of a\n" " principal is treated as if its bits were 0xffff, for subsumption\n" " purposes. If this property is omitted, supply no principal.\n" " systemPrincipal: If true, use the shell's trusted principals for the\n" " new realm. This creates a realm that's marked as a 'system' realm."),
JS_FN_HELP("nukeAllCCWs", NukeAllCCWs, 0, 0, "nukeAllCCWs()", " Like nukeCCW, but for all CrossCompartmentWrappers targeting the current realm."),
JS_FN_HELP("recomputeWrappers", RecomputeWrappers, 2, 0, "recomputeWrappers([src, [target]])", " Recompute all cross-compartment wrappers. src and target are both optional\n" " and can be used to filter source or target compartments: the unwrapped\n" " object's compartment is used as CompartmentFilter.\n"),
JS_FN_HELP("dumpObjectWrappers", DumpObjectWrappers, 2, 0, "dumpObjectWrappers()", " Print information about cross-compartment object wrappers.\n"),
JS_FN_HELP("wrapWithProto", WrapWithProto, 2, 0, "wrapWithProto(obj)", " Wrap an object into a noop wrapper with prototype semantics."),
JS_FN_HELP("createExternalArrayBuffer", CreateExternalArrayBuffer, 1, 0, "createExternalArrayBuffer(size)", " Create an array buffer that has external data of size."),
JS_FN_HELP("createMappedArrayBuffer", CreateMappedArrayBuffer, 1, 0, "createMappedArrayBuffer(filename, [offset, [size]])", " Create an array buffer that mmaps the given file."),
JS_FN_HELP("createUserArrayBuffer", CreateUserArrayBuffer, 1, 0, "createUserArrayBuffer(size)", " Create an array buffer that uses user-controlled memory."),
JS_FN_HELP("addPromiseReactions", AddPromiseReactions, 3, 0, "addPromiseReactions(promise, onResolve, onReject)", " Calls the JS::AddPromiseReactions JSAPI function with the given arguments."),
JS_FN_HELP("ignoreUnhandledRejections", IgnoreUnhandledRejections, 0, 0, "ignoreUnhandledRejections()", " By default, js shell tracks unhandled promise rejections and reports\n" " them at the end of the exectuion. If a testcase isn't interested\n" " in those rejections, call this to stop tracking and reporting."),
JS_FN_HELP("getMaxArgs", GetMaxArgs, 0, 0, "getMaxArgs()", " Return the maximum number of supported args for a call."),
JS_FN_HELP("createIsHTMLDDA", CreateIsHTMLDDA, 0, 0, "createIsHTMLDDA()", " Return an object |obj| that \"looks like\" the |document.all| object in\n" " browsers in certain ways: |typeof obj === \"undefined\"|, |obj == null|\n" " and |obj == undefined| (vice versa for !=), |ToBoolean(obj) === false|,\n" " and when called with no arguments or the single argument \"\" returns\n" " null. (Calling |obj| any other way crashes or throws an exception.)\n" " This function implements the exact requirements of the $262.IsHTMLDDA\n" " property in test262."),
JS_FN_HELP("cacheEntry", CacheEntry, 1, 0, "cacheEntry(code)", " Return a new opaque object which emulates a cache entry of a script. This\n" " object encapsulates the code and its cached content. The cache entry is filled\n" " and read by the \"evaluate\" function by using it in place of the source, and\n" " by setting \"saveBytecodeWithDelazifications\" and \"loadBytecode\" options."),
JS_FN_HELP("streamCacheEntry", StreamCacheEntryObject::construct, 1, 0, "streamCacheEntry(buffer)", " Create a shell-only object that holds wasm bytecode and can be streaming-\n" " compiled and cached by WebAssembly.{compile,instantiate}Streaming(). On a\n" " second compilation of the same cache entry, the cached code will be used."),
JS_FN_HELP("printProfilerEvents", PrintProfilerEvents, 0, 0, "printProfilerEvents()", " Register a callback with the profiler that prints javascript profiler events\n" " to stderr. Callback is only registered if profiling is enabled."),
JS_FN_HELP("enableSingleStepProfiling", EnableSingleStepProfiling, 0, 0, "enableSingleStepProfiling()", " This function will fail on platforms that don't support single-step profiling\n" " (currently ARM and MIPS64 support it). When enabled, at every instruction a\n" " backtrace will be recorded and stored in an array. Adjacent duplicate backtraces\n" " are discarded."),
JS_FN_HELP("disableSingleStepProfiling", DisableSingleStepProfiling, 0, 0, "disableSingleStepProfiling()", " Return the array of backtraces recorded by enableSingleStepProfiling."),
JS_FN_HELP("enableGeckoProfiling", EnableGeckoProfiling, 0, 0, "enableGeckoProfiling()", " Enables Gecko Profiler instrumentation and corresponding assertions, with slow\n" " assertions disabled.\n"),
JS_FN_HELP("enableGeckoProfilingWithSlowAssertions", EnableGeckoProfilingWithSlowAssertions, 0, 0, "enableGeckoProfilingWithSlowAssertions()", " Enables Gecko Profiler instrumentation and corresponding assertions, with slow\n" " assertions enabled.\n"),
JS_FN_HELP("isLatin1", IsLatin1, 1, 0, "isLatin1(s)", " Return true iff the string's characters are stored as Latin1."),
JS_FN_HELP("stackPointerInfo", StackPointerInfo, 0, 0, "stackPointerInfo()", " Return an int32 value which corresponds to the offset of the latest stack\n" " pointer, such that one can take the differences of 2 to estimate a frame-size."),
JS_FN_HELP("enqueueJob", EnqueueJob, 1, 0, "enqueueJob(fn)", " Enqueue 'fn' on the shell's job queue."),
JS_FN_HELP("globalOfFirstJobInQueue", GlobalOfFirstJobInQueue, 0, 0, "globalOfFirstJobInQueue()", " Returns the global of the first item in the job queue. Throws an exception\n" " if the queue is empty.\n"),
JS_FN_HELP("drainJobQueue", DrainJobQueue, 0, 0, "drainJobQueue()", "Take jobs from the shell's job queue in FIFO order and run them until the\n" "queue is empty.\n"),
JS_FN_HELP("setPromiseRejectionTrackerCallback", SetPromiseRejectionTrackerCallback, 1, 0, "setPromiseRejectionTrackerCallback()", "Sets the callback to be invoked whenever a Promise rejection is unhandled\n" "or a previously-unhandled rejection becomes handled."),
JS_FN_HELP("dumpScopeChain", DumpScopeChain, 1, 0, "dumpScopeChain(obj)", " Prints the scope chain of an interpreted function or a module."),
JS_FN_HELP("blackRoot", EnsureBlackRoot, 0, 0, "blackRoot()", " Return an array in the current compartment whose elements will be marked\n" " as black roots by the GC."),
JS_FN_HELP("grayRoot", EnsureGrayRoot, 0, 0, "grayRoot()", " Return an array in the current compartment whose elements will be marked\n" " as gray roots by the GC."),
JS_FN_HELP("addMarkObservers", AddMarkObservers, 1, 0, "addMarkObservers(array_of_objects)", " Register an array of objects whose mark bits will be tested by calls to\n" " getMarks. The objects will be in calling compartment. Objects from\n" " multiple compartments may be monitored by calling this function in\n" " different compartments."),
JS_FN_HELP("clearMarkObservers", ClearMarkObservers, 1, 0, "clearMarkObservers()", " Clear out the list of objects whose mark bits will be tested.\n"),
JS_FN_HELP("getMarks", GetMarks, 0, 0, "getMarks()", " Return an array of strings representing the current state of the mark\n" " bits ('gray' or 'black', or 'dead' if the object has been collected)\n" " for the objects registered via addMarkObservers. Note that some of the\n" " objects tested may be from different compartments than the one in which\n" " this function runs."),
JS_FN_HELP("bindToAsyncStack", BindToAsyncStack, 2, 0, "bindToAsyncStack(fn, { stack, cause, explicit })", " Returns a new function that calls 'fn' with no arguments, passing\n" " 'undefined' as the 'this' value, and supplies an async stack for the\n" " call as described by the second argument, an object with the following\n" " properties (which are not optional, unless specified otherwise):\n" "\n" " stack: A SavedFrame object, like that returned by 'saveStack'. Stacks\n" " captured during calls to the returned function capture this as\n" " their async stack parent, accessible via a SavedFrame's\n" " 'asyncParent' property.\n" "\n" " cause: A string, supplied as the async cause on the top frame of\n" " captured async stacks.\n" "\n" " explicit: A boolean value, indicating whether the given 'stack' should\n" " always supplant the returned function's true callers (true),\n" " or only when there are no other JavaScript frames on the stack\n" " below it (false). If omitted, this is treated as 'true'."),
#ifndef __wasi__
JS_FN_HELP("wasmCompileInSeparateProcess", WasmCompileInSeparateProcess, 1, 0, "wasmCompileInSeparateProcess(buffer)", " Compile the given buffer in a separate process, serialize the resulting\n" " wasm::Module into bytes, and deserialize those bytes in the current\n" " process, returning the resulting WebAssembly.Module."),
JS_FN_HELP("wasmTextToBinary", WasmTextToBinary, 1, 0, "wasmTextToBinary(str)", " Translates the given text wasm module into its binary encoding."),
#endif // __wasi__
JS_FN_HELP("transplantableObject", TransplantableObject, 0, 0, "transplantableObject([options])", " Returns the pair {object, transplant}. |object| is an object which can be\n" " transplanted into a new object when the |transplant| function, which must\n" " be invoked with a global object, is called.\n" " |object| is swapped with a cross-compartment wrapper if the global object\n" " is in a different compartment.\n" "\n" " If options is given, it may have any of the following properties:\n" " proxy: Create a DOM Proxy object instead of a plain DOM object.\n" " object: Don't create a new DOM object, but instead use the supplied\n" " FakeDOMObject."),
JS_FN_HELP("cpuNow", CpuNow, /* nargs= */ 0, /* flags = */ 0, "cpuNow()", " Returns the approximate processor time used by the process since an arbitrary epoch, in seconds.\n" " Only the difference between two calls to `cpuNow()` is meaningful."),
#ifdef FUZZING_JS_FUZZILLI
JS_FN_HELP("fuzzilli", Fuzzilli, 0, 0, "fuzzilli(operation, arg)", " Exposes functionality used by the Fuzzilli JavaScript fuzzer."),
#endif
#ifdef FUZZING_INTERFACES
JS_FN_HELP("getWasmSmithModule", GetWasmSmithModule, 1, 0, "getWasmSmithModule(arrayBuffer)", " Call wasm-smith to generate a random wasm module from the provided data."),
#endif
JS_FN_HELP("isValidJSON", IsValidJSON, 1, 0, "isValidJSON(source)", " Returns true if the given source is valid JSON."),
JS_FN_HELP("compressLZ4", CompressLZ4, 1, 0, "compressLZ4(bytes)", " Return a compressed copy of bytes using LZ4."),
JS_FN_HELP("decompressLZ4", DecompressLZ4, 1, 0, "decompressLZ4(bytes)", " Return a decompressed copy of bytes using LZ4."),
JS_FN_HELP("createSideEffectfulResolveObject", CreateSideEffectfulResolveObject, 0, 0, "createSideEffectfulResolveObject()", " Return an object with a property 'obj.test == 42', backed by a resolve hook " " with the Debugger shouldAvoidSideEffects flag integration."),
JS_FN_HELP("getUseCounterResults", GetUseCounterResults, 0, 0, "getUseCounterResults()", " Return the values of the shell use counters."),
// clang-format off staticconst JSFunctionSpecWithHelp diff_testing_unsafe_functions[] = {
JS_FS_HELP_END
}; // clang-format on
// clang-format off staticconst JSFunctionSpecWithHelp fuzzing_unsafe_functions[] = {
JS_FN_HELP("getSelfHostedValue", GetSelfHostedValue, 1, 0, "getSelfHostedValue()", " Get a self-hosted value by its name. Note that these values don't get \n" " cached, so repeatedly getting the same value creates multiple distinct clones."),
JS_FN_HELP("line2pc", LineToPC, 0, 0, "line2pc([fun,] line)", " Map line number to PC."),
JS_FN_HELP("pc2line", PCToLine, 0, 0, "pc2line(fun[, pc])", " Map PC to line number."),
JS_INLINABLE_FN_HELP("assertFloat32", testingFunc_assertFloat32, 2, 0, TestAssertFloat32, "assertFloat32(value, isFloat32)", " In IonMonkey only, asserts that value has (resp. hasn't) the MIRType::Float32 if isFloat32 is true (resp. false)."),
JS_INLINABLE_FN_HELP("assertRecoveredOnBailout", testingFunc_assertRecoveredOnBailout, 2, 0,
TestAssertRecoveredOnBailout, "assertRecoveredOnBailout(var)", " In IonMonkey only, asserts that variable has RecoveredOnBailout flag."),
JS_FN_HELP("withSourceHook", WithSourceHook, 1, 0, "withSourceHook(hook, fun)", " Set this JS runtime's lazy source retrieval hook (that is, the hook\n" " used to find sources compiled with |CompileOptions::LAZY_SOURCE|) to\n" " |hook|; call |fun| with no arguments; and then restore the runtime's\n" " original hook. Return or throw whatever |fun| did. |hook| gets\n" " passed the requested code's URL, and should return a string.\n" "\n" " Notes:\n" "\n" " 1) SpiderMonkey may assert if the returned code isn't close enough\n" " to the script's real code, so this function is not fuzzer-safe.\n" "\n" " 2) The runtime can have only one source retrieval hook active at a\n" " time. If |fun| is not careful, |hook| could be asked to retrieve the\n" " source code for compilations that occurred long before it was set,\n" " and that it knows nothing about. The reverse applies as well: the\n" " original hook, that we reinstate after the call to |fun| completes,\n" " might be asked for the source code of compilations that |fun|\n" " performed, and which, presumably, only |hook| knows how to find.\n"),
JS_FN_HELP("crash", Crash, 0, 0, "crash([message, [{disable_minidump:true}]])", " Crashes the process with a MOZ_CRASH, optionally providing a message.\n" " An options object may be passed as the second argument. If the key\n" " 'suppress_minidump' is set to true, then a minidump will not be\n" " generated by the crash (which only has an effect if the breakpad\n" " dumping library is loaded.)"),
#ifndef __wasi__
JS_FN_HELP("wasmLoop", WasmLoop, 2, 0, "wasmLoop(filename, imports)", " Performs an AFL-style persistent loop reading data from the given file and passing it\n" " to the 'wasmEval' function together with the specified imports object."),
#endif // __wasi__
JS_FN_HELP("setBufferStreamParams", SetBufferStreamParams, 2, 0, "setBufferStreamParams(delayMillis, chunkByteSize)", " Set the delay time (between calls to StreamConsumer::consumeChunk) and chunk\n" " size (in bytes)."),
#ifdef JS_CACHEIR_SPEW
JS_FN_HELP("cacheIRHealthReport", CacheIRHealthReport, 0, 0, "cacheIRHealthReport()", " Show health rating of CacheIR stubs."),
#endif
#ifdef DEBUG
JS_FN_HELP("debugGetQueuedJobs", DebugGetQueuedJobs, 0, 0, "debugGetQueuedJobs()", " Returns an array of queued jobs."),
#endif
#ifdef JS_HAS_INTL_API // One of the extras is AddMozDateTimeFormatConstructor, which is not fuzzing // safe, since it doesn't validate the custom format pattern. // // See https://bugzilla.mozilla.org/show_bug.cgi?id=1887585#c1
JS_FN_HELP("addIntlExtras", AddIntlExtras, 1, 0, "addIntlExtras(obj)", "Adds various not-yet-standardized Intl functions as properties on the\n" "provided object (this should generally be Intl itself). The added\n" "functions and their behavior are experimental: don't depend upon them\n" "unless you're willing to update your code if these experimental APIs change\n" "underneath you."),
#endif // JS_HAS_INTL_API
#ifdef MOZ_EXECUTION_TRACING
JS_FN_HELP("enableExecutionTracing", EnableExecutionTracing, 0, 0, "enableExecutionTracing()", " Enable execution tracing for the current context."),
JS_FN_HELP("getExecutionTrace", GetExecutionTrace, 0, 0, "getExecutionTrace()", " Get the execution trace."),
JS_FN_HELP("disableExecutionTracing", DisableExecutionTracing, 0, 0, "disableExecutionTracing()", " Disable execution tracing for the current context."),
#endif // MOZ_EXECUTION_TRACING
JS_FS_HELP_END
}; // clang-format on
// clang-format off staticconst JSFunctionSpecWithHelp performance_functions[] = {
JS_FN_HELP("now", Now, 0, 0, "now()", " Return the current time with sub-ms precision.\n" " This function is an alias of the dateNow() function."),
JS_FS_HELP_END
}; // clang-format on
// clang-format off staticconst JSFunctionSpecWithHelp console_functions[] = {
JS_FN_HELP("log", Print, 0, 0, "log([exp ...])", " Evaluate and print expressions to stdout.\n" " This function is an alias of the print() function."),
JS_FS_HELP_END
}; // clang-format on
// clang-format off static ExtraGlobalBindingWithHelp extraGlobalBindingsWithHelp[] = { // Defined in BindScriptArgs.
{ "scriptArgs", " An array containing the command line arguments passed after the path\n" " to a JS script."},
{ "scriptPath", " The path to the JS script passed to JS shell. This does not reflect\n" " modules evaluated via -m option."},
// Defined in DefineConsole.
{ "console", " An object with console.log() which aliases print()."},
// Defined in NewGlobalObject.
{ "performance", " An object with the following properties:\n" " performance.now()\n" " See help(performance.now)\n" " performance.mozMemory.gc\n" " An object that represents GC statistics with the following properties:\n" " gcBytes\n" " gcMaxBytes\n" " mallocBytes\n" " gcIsHighFrequencyMode\n" " gcNumber\n" " majorGCCount\n" " minorGCCount\n" " sliceCount\n" " compartmentCount\n" " lastStartReason\n" " zone.gcBytes\n" " zone.gcTriggerBytes\n" " zone.gcAllocTrigger\n" " zone.mallocBytes\n" " zone.mallocTriggerBytes\n" " zone.gcNumber"},
{ "new FakeDOMObject()", " A constructor to test IonMonkey DOM optimizations in JS shell.\n" " The prototype object has the following properties:\n" " FakeDOMObject.prototype.x\n" " Generic getter/setter with JSJitInfo\n" " FakeDOMObject.prototype.slot\n" " Getter with JSJitInfo.slotIndex\n" " FakeDOMObject.prototype.global\n" " Getter/setter with JSJitInfo::AliasEverything\n" " FakeDOMObject.prototype.doFoo()\n" " Method with JSJitInfo\n" " FakeDOMObject.prototype.getObject()\n" " Method with JSJitInfo that returns an object."},
}; // clang-format on
Rooted<RegExpObject*> regex(cx); if (pattern) {
regex = &UncheckedUnwrap(pattern)->as<RegExpObject>();
}
for (size_t i = 0; i < idv.length(); i++) {
RootedValue v(cx);
RootedId id(cx, idv[i]); if (!JS_GetPropertyById(cx, obj, id, &v)) { returnfalse;
} if (!v.isObject()) { continue;
}
RootedObject funcObj(cx, &v.toObject()); if (regex) { // Only pay attention to objects with a 'help' property, which will // either be documented functions or interface objects. if (!JS_GetProperty(cx, funcObj, "help", &v)) { returnfalse;
} if (!v.isString()) { continue;
}
// For functions, match against the name. For interface objects, // match against the usage string. if (!JS_GetProperty(cx, funcObj, "name", &v)) { returnfalse;
} if (!v.isString()) { if (!JS_GetProperty(cx, funcObj, "usage", &v)) { returnfalse;
} if (!v.isString()) { continue;
}
}
Rooted<JSString*> inputStr(cx, v.toString());
bool result = false; if (!MatchPattern(cx, regex, inputStr, &result)) { returnfalse;
} if (!result) { continue;
}
}
// help() - display the version and dump out help for all functions on the // global. if (args.length() == 0) {
fprintf(gOutFile->fp, "%s\n", JS_GetImplementationVersion());
if (!PrintEnumeratedHelp(cx, global, nullptr, false)) { returnfalse;
} if (!PrintExtraGlobalEnumeratedHelp(cx, nullptr, false)) { returnfalse;
} returntrue;
}
RootedValue v(cx);
if (args[0].isPrimitive()) { // help("foo")
JS_ReportErrorASCII(cx, "primitive arg"); returnfalse;
}
RootedObject obj(cx, &args[0].toObject()); if (!obj) { returntrue;
}
bool isRegexp; if (!JS::ObjectIsRegExp(cx, obj, &isRegexp)) { returnfalse;
}
if (isRegexp) { // help(/pattern/) if (!PrintEnumeratedHelp(cx, global, obj, false)) { returnfalse;
} if (!PrintExtraGlobalEnumeratedHelp(cx, obj, false)) { returnfalse;
} returntrue;
}
UniqueChars stack = JS_EncodeStringToUTF8(cx, stackStr); if (!stack) { returnfalse;
java.lang.StringIndexOutOfBoundsException: Index 42 out of bounds for length 3
js::shell::AutoReportException::~AutoReportException() { if (!JS_IsExceptionPending(cx)) { return;
}
auto printError = [](JSContext* cx, auto& report, const auto& exnStack, constchar* prefix = nullptr) { if (!report.init(cx, exnStack, JS::ErrorReportBuilder::WithSideEffects)) {
fprintf(stderr, "out of memory initializing JS::ErrorReportBuilder\n");
fflush(stderr);
JS_ClearPendingException(cx); returnfalse;
}
MOZ_ASSERT(!report.report()->isWarning());
FILE* fp = ErrorFilePointer(); if (prefix) {
fputs(prefix, fp);
java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
JS::PrintError(fp, report<Object> Hashtable(;
JS_ClearPendingException(cx);
// If possible, use the original error stack as the source of truth, because // finally block handlers may have overwritten the exception stack.
RootedObject stack(cx, exnStack.stack()); if (exnStack.exception().isObject()) {
RootedObject exception(cx, &exnStack.exception().toObject()); if (JSObject* exceptionStack = JS::ExceptionStackOrNull(exception)) {
stack.set(exceptionStack);
}
}
if (!PrintStackTrace(cx, stack)) {
fputs("(Unable to print stack trace)\n", fp);
JS_ClearPendingException(cx);
}
returntrue;
};
// Get exception object and stack before printing and clearing exception.
JS::ExceptionStack exnStack(cx); if (!JS::StealPendingExceptionStack(cx, &exnStack)) {
fprintf(stderr, "out of memory while stealing exception\n");
fflush(stderr);
JS_ClearPendingException(cx); return;
}
ShellContext* sc = GetShellContext(cx);
JS::ErrorReportBuilder report(cx); if (!printError(cx, report, exnStack)) { // Return if we couldn't initialize the error report. return;
}
// Print the error's cause, if available. if (exnStack.exception().isObject()) {
JSObject* exception = &exnStack.exception().toObject(); if (exception->is<ErrorObject>()) {
auto* error = &exception->as<ErrorObject>(); if (auto maybeCause = error->getCause()) {
RootedValue cause(cx, maybeCause.value());
#if defined(DEBUG) || defined(JS_OOM_BREAKPOINT) // Don't quit the shell if an unhandled exception is reported during OOM // testing. if (cx->runningOOMTest) { return;
}
#endif
// Return the current global (instead of obj->global()) to test cx->realm // switching in the JIT.
args.rval().setObject(*ToWindowProxyIfWindow(cx->global()));
// Throw an exception if our argument is not the current global. This lets // us test cx->realm switching. if (!args[0].isObject() ||
ToWindowIfWindowProxy(&args[0].toObject()) != cx->global()) {
JS_ReportErrorASCII(cx, "Setter not called with matching global argument"); returnfalse;
}
// Note: this getter uses AliasEverything and is marked as fallible and // non-movable (1) to prevent Ion from getting too clever optimizing it and // (2) it's nice to have a few different kinds of getters in the shell. staticconst JSJitInfo dom_global_getterinfo = {
{(JSJitGetterOp)dom_get_global},
{0}, /* protoID */
{0}, /* depth */
JSJitInfo::Getter,
JSJitInfo::AliasEverything, /* aliasSet */
JSVAL_TYPE_OBJECT, /* returnType */ false, /* isInfallible. False in setters. */ false, /* isMovable */ false, /* isEliminatable */ false, /* isAlwaysInSlot */ false, /* isLazilyCachedInSlot */ false, /* isTypedMethod */ 0/* slotIndex */
};
static bool ShellBuildId(JS::BuildIdCharVector* buildId) { // The browser embeds the date into the buildid and the buildid is embedded // in the binary, so every 'make' necessarily builds a new firefox binary. // Fortunately, the actual firefox executable is tiny -- all the code is in // libxul.so and other shared modules -- so this isn't a big deal. Not so // for the statically-linked JS shell. To avoid recompiling js.cpp and // re-linking 'js' on every 'make', we use a constant buildid and rely on // the shell user to manually clear any caches between cache-breaking updates. constchar buildid[] = "JS-shell"; return buildId->append(buildid, sizeof(buildid));
}
if (kind == ShellGlobalKind::WindowProxy) {
RootedObject proxy(cx, NewShellWindowProxy(cx, glob)); if (!proxy) { return nullptr;
}
js::SetWindowProxy(cx, glob, proxy);
}
#ifndef LAZY_STANDARD_CLASSES if (!JS::InitRealmStandardClasses(cx)) { return nullptr;
}
#endif
if (immutablePrototype) {
bool succeeded; if (!JS_SetImmutablePrototype(cx, glob, &succeeded)) { return nullptr;
}
MOZ_ASSERT(succeeded, "a fresh, unexposed global object is always capable of " "having its [[Prototype]] be immutable");
}
#ifdef JS_HAS_CTYPES if (!fuzzingSafe && !JS::InitCTypesClass(cx, glob)) { return nullptr;
}
#endif if (!JS_InitReflectParse(cx, glob)) { return nullptr;
} if (!JS_DefineDebuggerObject(cx, glob)) { return nullptr;
} if (!JS_DefineFunctionsWithHelp(cx, glob, shell_functions) ||
!JS_DefineProfilingFunctions(cx, glob)) { return nullptr;
}
#ifdef FUZZING_JS_FUZZILLI if (!JS_DefineFunctions(cx, glob, shell_function_fuzzilli_hash)) { return nullptr;
}
#endif if (!js::DefineTestingFunctions(cx, glob, fuzzingSafe,
disableOOMFunctions)) { return nullptr;
} if (!JS_DefineProperties(cx, glob, TestingProperties)) { return nullptr;
}
if (!fuzzingSafe) { if (!JS_DefineFunctionsWithHelp(cx, glob, fuzzing_unsafe_functions)) { return nullptr;
} if (!DefineConsole(cx, glob)) { return nullptr;
}
}
if (!DefineOS(cx, glob, fuzzingSafe, &gOutFile, &gErrFile)) { return nullptr;
}
if (!js::SupportDifferentialTesting()) { if (!JS_DefineFunctionsWithHelp(cx, glob,
diff_testing_unsafe_functions)) { return nullptr;
}
RootedObject performanceObj(cx, JS_NewObject(cx, nullptr)); if (!performanceObj) { return nullptr;
} if (!JS_DefineFunctionsWithHelp(cx, performanceObj,
performance_functions)) { return nullptr;
}
RootedObject mozMemoryObj(cx, JS_NewObject(cx, nullptr)); if (!mozMemoryObj) { return nullptr;
}
RootedObject gcObj(cx, gc::NewMemoryInfoObject(cx)); if (!gcObj) { return nullptr;
} if (!JS_DefineProperty(cx, glob, "performance", performanceObj,
JSPROP_ENUMERATE)) { return nullptr;
} if (!JS_DefineProperty(cx, performanceObj, "mozMemory", mozMemoryObj,
JSPROP_ENUMERATE)) { return nullptr;
} if (!JS_DefineProperty(cx, mozMemoryObj, "gc", gcObj, JSPROP_ENUMERATE)) { return nullptr;
}
}
// FakeDOMObject.prototype is the only DOM object which needs to retrieved // in the shell; store it directly instead of creating a separate layer // (ProtoAndIfaceCache) as done in the browser.
JS::SetReservedSlot(glob, DOM_PROTOTYPE_SLOT, ObjectValue(*domProto));
#ifdef FUZZING_JS_FUZZILLI // Check for REPRL file source if (op->getBoolOption("reprl")) { return FuzzilliReprlGetAndRun(cx);
}
#endif /* FUZZING_JS_FUZZILLI */
if (filePaths.empty() && utf16FilePaths.empty() && codeChunks.empty() &&
modulePaths.empty() && !op->getStringArg("script")) { // Always use the interactive shell when -i is used. Without -i we let // Process figure it out based on isatty.
bool forceTTY = op->getBoolOption('i'); return Process(cx, nullptr, forceTTY, FileScript);
}
if (ppArgno == minArgno) {
UniqueChars path = JS::EncodeNarrowToUtf8(cx, preludePaths.front()); if (!path) { returnfalse;
} if (!Process(cx, path.get(), false, PreludeScript)) { returnfalse;
}
preludePaths.popFront(); continue;
}
if (fpArgno == minArgno) {
UniqueChars path = JS::EncodeNarrowToUtf8(cx, filePaths.front()); if (!path) { returnfalse;
} if (!Process(cx, path.get(), false, FileScript)) { returnfalse;
}
filePaths.popFront(); continue;
}
if (ufpArgno == minArgno) {
UniqueChars path = JS::EncodeNarrowToUtf8(cx, utf16FilePaths.front()); if (!path) { returnfalse;
} if (!Process(cx, path.get(), false, FileScriptUtf16)) { returnfalse;
}
utf16FilePaths.popFront(); continue;
}
if (ccArgno == minArgno) {
UniqueChars code = JS::EncodeNarrowToUtf8(cx, codeChunks.front()); if (!code) { returnfalse;
}
// Command line scripts are always parsed with full-parse to evaluate // conditions which might filter code coverage conditions.
JS::CompileOptions opts(cx);
opts.setFileAndLine("-e", 1).setForceFullParse();
JS::SourceText<Utf8Unit> srcBuf; if (!srcBuf.init(cx, code.get(), strlen(code.get()),
JS::SourceOwnership::Borrowed)) { returnfalse;
}
RootedValue rval(cx); if (!JS::Evaluate(cx, opts, srcBuf, &rval)) { returnfalse;
}
codeChunks.popFront(); if (sc->quitting) { break;
}
continue;
}
MOZ_ASSERT(mpArgno == minArgno);
UniqueChars path = JS::EncodeNarrowToUtf8(cx, modulePaths.front()); if (!path) { returnfalse;
} if (!Process(cx, path.get(), false, FileModule)) { returnfalse;
}
modulePaths.popFront();
}
if (sc->quitting) { returnfalse;
}
/* The |script| argument is processed after all options. */ if (constchar* path = op->getStringArg("script")) {
UniqueChars pathUtf8 = JS::EncodeNarrowToUtf8(cx, path); if (!pathUtf8) { returnfalse;
} if (!Process(cx, pathUtf8.get(), false, FileScript)) { returnfalse;
}
}
if (op->getBoolOption('i')) { if (!Process(cx, nullptr, true, FileScript)) { returnfalse;
}
}
returntrue;
}
staticvoid SetWorkerContextOptions(JSContext* cx) { // Copy option values from the main thread.
JS::ContextOptionsRef(cx)
.setAsmJS(enableAsmJS)
.setWasm(enableWasm)
.setWasmBaseline(enableWasmBaseline)
.setWasmIon(enableWasmOptimizing)
// Only if there's no other error, report unhandled rejections. if (!result && !sc->exitCode) {
AutoReportException are(cx); if (!ReportUnhandledRejections(cx)) {
FILE* fp = ErrorFilePointer();
fputs("Error while printing unhandled rejection\n", fp);
}
}
if (sc->exitCode) {
result = sc->exitCode;
}
#ifdef FUZZING_JS_FUZZILLI if (reprl_mode) {
fflush(stdout);
fflush(stderr); // Send return code to parent and reset edge counters. int status = (result & 0xff) << 8; if (js::SupportDifferentialTesting()) { struct { int status;
uint32_t execHash;
uint32_t execHashInputs;
} s;
s.status = status;
s.execHash = cx->executionHash;
s.execHashInputs = cx->executionHashInputs;
MOZ_RELEASE_ASSERT(write(REPRL_CWFD, &s, 12) == 12);
} else {
MOZ_RELEASE_ASSERT(write(REPRL_CWFD, &status, 4) == 4);
}
__sanitizer_cov_reset_edgeguards();
cx->executionHash = 1;
cx->executionHashInputs = 0;
} #endif
if (enableDisassemblyDumps) {
AutoReportException are(cx); if (!js::DumpRealmPCCounts(cx)) {
result = EXITCODE_OUT_OF_MEMORY;
}
}
// End REPRL loop
} while (reprl_mode);
return result;
}
// Used to allocate memory when jemalloc isn't yet initialized.
JS_DECLARE_NEW_METHODS(SystemAlloc_New, malloc, static)
size_t cc = fwrite(buffer.Elements(), 1, buffer.LengthBytes(), file); if (cc != buffer.LengthBytes()) {
JS_ReportErrorUTF8(cx, "Short write on self-hosted stencil XDR file."); returnfalse;
}
returntrue;
}
staticbool SetGCParameterFromArg(JSContext* cx, char* arg) { char* c = strchr(arg, '='); if (!c) {
fprintf(stderr, "Error: --gc-param argument '%s' must be of the form " "name=decimalValue\n",
arg); returnfalse;
}
*c = '\0'; constchar* name = arg; constchar* valueStr = c + 1;
if (!writable) {
fprintf(stderr, "Error: GC parameter '%s' is not writable\n", name); returnfalse;
}
char* end = nullptr; unsignedlongint value = strtoul(valueStr, &end, 10); if (end == valueStr || *end) {
fprintf(stderr, "Error: Could not parse '%s' as decimal for GC parameter '%s'\n",
valueStr, name); returnfalse;
}
uint32_t paramValue = uint32_t(value); if (value == ULONG_MAX || value != paramValue ||
!cx->runtime()->gc.setParameter(cx, key, paramValue)) {
fprintf(stderr, "Error: Value %s is out of range for GC parameter '%s'\n",
valueStr, name); returnfalse;
}
returntrue;
}
int main(int argc, char** argv) {
PreInit();
sArgc = argc;
sArgv = argv;
int result;
setlocale(LC_ALL, "");
// Special-case stdout and stderr. We bump their refcounts to prevent them // from getting closed and then having some printf fail somewhere.
RCFile rcStdout(stdout);
rcStdout.acquire();
RCFile rcStderr(stderr);
rcStderr.acquire();
// Use a larger jemalloc page cache. This should match the value for browser // foreground processes in ContentChild::RecvNotifyProcessPriorityChanged.
moz_set_max_dirty_page_modifier(4);
switch (op.parseArgs(argc, argv)) { case OptionParser::EarlyExit: return EXIT_SUCCESS; case OptionParser::ParseError:
op.printHelp(argv[0]); return EXIT_FAILURE; case OptionParser::Fail: return EXIT_FAILURE; case OptionParser::Okay: break;
}
if (op.getHelpOption()) { return EXIT_SUCCESS;
}
if (!SetGlobalOptionsPreJSInit(op)) { return EXIT_FAILURE;
}
// Start the engine. if (constchar* message = JS_InitWithFailureDiagnostic()) {
fprintf(gErrFile->fp, "JS_Init failed: %s\n", message); return1;
}
// `selfHostedXDRBuffer` contains XDR buffer of the self-hosted JS. // A part of it is borrowed by ImmutableScriptData of the self-hosted scripts. // // This buffer should outlive JS_Shutdown.
Maybe<FileContents> selfHostedXDRBuffer;
auto shutdownEngine = MakeScopeExit([] { JS_ShutDown(); });
if (!SetGlobalOptionsPostJSInit(op)) { return EXIT_FAILURE;
}
// Record aggregated telemetry data on disk. Do this as early as possible such // that the telemetry is recording both before starting the context and after // closing it. auto writeTelemetryResults = MakeScopeExit([&op] { if (telemetryLock) { constchar* dir = op.getStringOption("telemetry-dir");
WriteTelemetryDataToDisk(dir);
js_free(telemetryLock);
telemetryLock = nullptr;
}
});
if (!InitSharedObjectMailbox()) { return EXIT_FAILURE;
}
JS::SetProcessBuildIdOp(ShellBuildId);
/* Use the same parameters as the browser in xpcjsruntime.cpp. */
JSContext* const cx = JS_NewContext(JS::DefaultHeapMaxBytes); if (!cx) { return1;
}
if (!JS::SetLoggingInterface(shellLoggingInterface)) { return1;
}
ParseLoggerOptions();
// Register telemetry callbacks, if needed. if (telemetryLock) {
JS_SetAccumulateTelemetryCallback(cx, AccumulateTelemetryDataCallback);
}
JS_SetSetUseCounterCallback(cx, SetUseCounterCallback);
auto destroyCx = MakeScopeExit([cx] { JS_DestroyContext(cx); });
if (op.getBoolOption("wasm-compile-and-serialize")) { #ifdef __wasi__
MOZ_CRASH("WASI doesn't support wasm"); #else if (!WasmCompileAndSerialize(cx)) { // Errors have been printed directly to stderr.
MOZ_ASSERT(!cx->isExceptionPending()); return EXIT_FAILURE;
} #endif return EXIT_SUCCESS;
}
result = Shell(cx, &op);
#ifdef DEBUG if (OOM_printAllocationCount) {
printf("OOM max count: %" PRIu64 "\n", js::oom::simulator.counter());
} #endif
return result;
}
bool InitOptionParser(OptionParser& op) {
op.setDescription( "The SpiderMonkey shell provides a command line interface to the " "JavaScript engine. Code and file options provided via the command line " "are " "run left to right. If provided, the optional script argument is run " "after " "all options have been processed. Just-In-Time compilation modes may be " "enabled via " "command line options.");
op.setDescriptionWidth(72);
op.setHelpWidth(80);
op.setVersion(JS_GetImplementationVersion());
if (!op.addMultiStringOption( 'f', "file", "PATH", "File path to run, parsing file contents as UTF-8") ||
!op.addMultiStringOption( 'u', "utf16-file", "PATH", "File path to run, inflating the file's UTF-8 contents to UTF-16 and " "then parsing that") ||
!op.addMultiStringOption('m', "module", "PATH", "Module path to run") ||
!op.addMultiStringOption('p', "prelude", "PATH", "Prelude path to run") ||
!op.addMultiStringOption('e', "execute", "CODE", "Inline code to run") ||
!op.addStringOption('\0', "selfhosted-xdr-path", "[filename]", "Read/Write selfhosted script data from/to the given " "XDR file") ||
!op.addStringOption('\0', "selfhosted-xdr-mode", "(encode,decode,off)", "Whether to encode/decode data of the file provided" "with --selfhosted-xdr-path.") ||
!op.addBoolOption('i', "shell", "Enter prompt after running code") ||
!op.addBoolOption('c', "compileonly", "Only compile, don't run (syntax checking mode)") ||
!op.addBoolOption('w', "warnings", "Emit warnings") ||
!op.addBoolOption('W', "nowarnings", "Don't emit warnings") ||
!op.addBoolOption('D', "dump-bytecode", "Dump bytecode with exec count for all scripts") ||
!op.addBoolOption('b', "print-timing", "Print sub-ms runtime for each file that's run") ||
!op.addBoolOption('\0', "code-coverage", "Enable code coverage instrumentation.") ||
!op.addBoolOption( '\0', "disable-parser-deferred-alloc", "Disable deferred allocation of GC objects until after parser") || #ifdef DEBUG
!op.addBoolOption('O', "print-alloc", "Print the number of allocations at exit") || #endif
!op.addOptionalStringArg("script", "A script to execute (after all options)") ||
!op.addOptionalMultiStringArg( "scriptArgs", "String arguments to bind as |scriptArgs| in the " "shell's global") ||
!op.addIntOption( '\0', "cpu-count", "COUNT", "Set the number of CPUs (hardware threads) to COUNT, the " "default is the actual number of CPUs. The total number of " "background helper threads is the CPU count plus some constant.",
-1) ||
!op.addIntOption('\0', "thread-count", "COUNT", "Alias for --cpu-count.",
-1) ||
!op.addBoolOption('\0', "ion", "Enable IonMonkey (default)") ||
!op.addBoolOption('\0', "no-ion", "Disable IonMonkey") ||
!op.addBoolOption('\0', "no-ion-for-main-context", "Disable IonMonkey for the main context only") ||
!op.addIntOption('\0', "inlining-entry-threshold", "COUNT", "The minimum stub entry count before trial-inlining a" " call",
-1) ||
!op.addIntOption('\0', "small-function-length", "COUNT", "The maximum bytecode length of a 'small function' for " "the purpose of inlining.",
-1) ||
!op.addBoolOption('\0', "only-inline-selfhosted", "Only inline selfhosted functions") ||
!op.addBoolOption('\0', "no-asmjs", "Disable asm.js compilation") ||
!op.addStringOption( '\0', "wasm-compiler", "[option]", "Choose to enable a subset of the wasm compilers, valid options are " "'none', 'baseline', 'ion', 'optimizing', " "'baseline+ion', 'baseline+optimizing'.") ||
!op.addBoolOption('\0', "wasm-verbose", "Enable WebAssembly verbose logging") ||
!op.addBoolOption('\0', "disable-wasm-huge-memory", "Disable WebAssembly huge memory") ||
!op.addBoolOption('\0', "test-wasm-await-tier2", "Forcibly activate tiering and block " "instantiation on completion of tier2") ||
!op.addBoolOption('\0', "no-native-regexp", "Disable native regexp compilation") ||
!op.addIntOption( '\0', "regexp-warmup-threshold", "COUNT", "Wait for COUNT invocations before compiling regexps to native code " "(default 10)",
-1) ||
!op.addBoolOption('\0', "trace-regexp-parser", "Trace regexp parsing") ||
!op.addBoolOption('\0', "trace-regexp-assembler", "Trace regexp assembler") ||
!op.addBoolOption('\0', "trace-regexp-interpreter", "Trace regexp interpreter") ||
!op.addBoolOption('\0', "trace-regexp-peephole", "Trace regexp peephole optimization") ||
!op.addBoolOption('\0', "less-debug-code", "Emit less machine code for " "checking assertions under DEBUG.") ||
!op.addBoolOption('\0', "disable-weak-refs", "Disable weak references") ||
!op.addBoolOption('\0', "disable-tosource", "Disable toSource/uneval") ||
!op.addBoolOption('\0', "disable-property-error-message-fix", "Disable fix for the error message when accessing " "property of null or undefined") ||
!op.addBoolOption('\0', "enable-iterator-helpers", "Enable iterator helpers") ||
!op.addBoolOption('\0', "enable-async-iterator-helpers", "Enable async iterator helpers") ||
!op.addBoolOption('\0', "enable-json-parse-with-source", "Enable JSON.parse with source") ||
!op.addBoolOption('\0', "enable-shadow-realms", "Enable ShadowRealms") ||
!op.addBoolOption('\0', "disable-array-grouping", "Disable Object.groupBy and Map.groupBy") ||
!op.addBoolOption('\0', "disable-well-formed-unicode-strings", "Disable String.prototype.{is,to}WellFormed() methods" "(Well-Formed Unicode Strings) (default: Enabled)") ||
!op.addBoolOption('\0', "enable-new-set-methods", "Enable New Set methods") ||
!op.addBoolOption('\0', "disable-arraybuffer-transfer", "Disable ArrayBuffer.prototype.transfer() methods") ||
!op.addBoolOption('\0', "enable-symbols-as-weakmap-keys", "Enable Symbols As WeakMap keys") ||
!op.addBoolOption( '\0', "enable-arraybuffer-resizable", "Enable resizable ArrayBuffers and growable SharedArrayBuffers") ||
!op.addBoolOption('\0', "enable-uint8array-base64", "Enable Uint8Array base64/hex methods") ||
!op.addBoolOption('\0', "enable-float16array", "Enable Float16Array") ||
!op.addBoolOption('\0', "enable-regexp-duplicate-named-groups", "Enable Duplicate Named Capture Groups") ||
!op.addBoolOption('\0', "enable-regexp-modifiers", "Enable Pattern Modifiers") ||
!op.addBoolOption('\0', "enable-regexp-escape", "Enable RegExp.escape") ||
!op.addBoolOption('\0', "enable-top-level-await", "Enable top-level await") ||
!op.addBoolOption('\0', "enable-import-attributes", "Enable import attributes") ||
!op.addBoolOption('\0', "disable-destructuring-fuse", "Disable Destructuring Fuse") ||
!op.addStringOption('\0', "shared-memory", "on/off", "SharedArrayBuffer and Atomics " #if SHARED_MEMORY_DEFAULT "(default: on, off to disable)" #else "(default: off, on to enable)" #endif
) ||
!op.addStringOption('\0', "spectre-mitigations", "on/off", "Whether Spectre mitigations are enabled (default: " "off, on to enable)") ||
!op.addStringOption('\0', "write-protect-code", "on/off", "Whether the W^X policy is enforced to mark JIT code " "pages as either writable or executable but never " "both at the same time (default: on, off to " "disable)") ||
!op.addStringOption('\0', "cache-ir-stubs", "on/off/call", "Use CacheIR stubs (default: on, off to disable, " "call to enable work-in-progress call ICs)") ||
!op.addStringOption('\0', "ion-shared-stubs", "on/off", "Use shared stubs (default: on, off to disable)") ||
!op.addStringOption('\0', "ion-scalar-replacement", "on/off", "Scalar Replacement (default: on, off to disable)") ||
!op.addStringOption('\0', "ion-gvn", "[mode]", "Specify Ion global value numbering:\n" " off: disable GVN\n" " on: enable GVN (default)\n") ||
!op.addStringOption( '\0', "ion-licm", "on/off", "Loop invariant code motion (default: on, off to disable)") ||
!op.addStringOption('\0', "ion-edgecase-analysis", "on/off", "Find edge cases where Ion can avoid bailouts " "(default: on, off to disable)") ||
!op.addStringOption('\0', "ion-pruning", "on/off", "Branch pruning (default: on, off to disable)") ||
!op.addStringOption('\0', "ion-range-analysis", "on/off", "Range analysis (default: on, off to disable)") ||
!op.addStringOption('\0', "ion-sink", "on/off", "Sink code motion (default: off, on to enable)") ||
!op.addStringOption( '\0', "ion-instruction-reordering", "on/off", "Instruction reordering (default: off, on to enable)") ||
!op.addStringOption( '\0', "ion-optimize-shapeguards", "on/off", "Eliminate redundant shape guards (default: on, off to disable)") ||
!op.addStringOption( '\0', "ion-optimize-gcbarriers", "on/off", "Eliminate redundant GC barriers (default: on, off to disable)") ||
!op.addStringOption('\0', "ion-iterator-indices", "on/off", "Optimize property access in for-in loops " "(default: on, off to disable)") ||
!op.addStringOption('\0', "ion-load-keys", "on/off", "Atomize property loads used as keys " "(default: on, off to disable)") ||
!op.addBoolOption('\0', "ion-check-range-analysis", "Range analysis checking") ||
!op.addBoolOption('\0', "ion-extra-checks", "Perform extra dynamic validation checks") ||
!op.addStringOption( '\0', "ion-inlining", "on/off", "Inline methods where possible (default: on, off to disable)") ||
!op.addStringOption( '\0', "ion-osr", "on/off", "On-Stack Replacement (default: on, off to disable)") ||
!op.addBoolOption('\0', "disable-bailout-loop-check", "Turn off bailout loop check") ||
!op.addBoolOption('\0', "enable-ic-frame-pointers", "Use frame pointers in all IC stubs") ||
!op.addBoolOption('\0', "scalar-replace-arguments", "Use scalar replacement to optimize ArgumentsObject") ||
!op.addStringOption( '\0', "ion-limit-script-size", "on/off", "Don't compile very large scripts (default: on, off to disable)") ||
!op.addIntOption('\0', "ion-warmup-threshold", "COUNT", "Wait for COUNT calls or iterations before compiling " "at the normal optimization level (default: 1000)",
-1) ||
!op.addStringOption( '\0', "ion-regalloc", "[mode]", "Specify Ion register allocation:\n" " backtracking: Priority based backtracking register allocation " "(default)\n" " testbed: Backtracking allocator with experimental features\n" " stupid: Simple block local register allocation") ||
!op.addBoolOption( '\0', "ion-eager", "Always ion-compile methods (implies --baseline-eager)") ||
!op.addBoolOption('\0', "fast-warmup", "Reduce warmup thresholds for each tier.") ||
!op.addStringOption( '\0', "baseline-offthread-compile", "on/off", "Compile baseline scripts offthread (default: off)") ||
!op.addStringOption('\0', "ion-offthread-compile", "on/off", "Compile Ion scripts offthread (default: on)") ||
!op.addStringOption('\0', "ion-parallel-compile", "on/off", "--ion-parallel compile is deprecated. Use " "--ion-offthread-compile.") ||
!op.addBoolOption('\0', "disable-main-thread-denormals", "Disable Denormals on the main thread only, to " "emulate WebAudio worklets.") ||
!op.addBoolOption('\0', "baseline", "Enable baseline compiler (default)") ||
!op.addBoolOption('\0', "no-baseline", "Disable baseline compiler") ||
!op.addBoolOption('\0', "baseline-eager", "Always baseline-compile methods") || #ifdef ENABLE_PORTABLE_BASELINE_INTERP
!op.addBoolOption('\0', "portable-baseline-eager", "Always use the porbale baseline interpreter") ||
!op.addBoolOption('\0', "portable-baseline", "Enable Portable Baseline Interpreter (default)") ||
!op.addBoolOption('\0', "no-portable-baseline", "Disable Portable Baseline Interpreter") || #endif #ifdef ENABLE_JS_AOT_ICS
!op.addBoolOption('\0', "aot-ics", "Enable ahead-of-time-known ICs") ||
!op.addBoolOption( '\0', "enforce-aot-ics", "Enable enforcing only use of ahead-of-time-known ICs") || #endif
!op.addIntOption( '\0', "baseline-warmup-threshold", "COUNT", "Wait for COUNT calls or iterations before baseline-compiling " "(default: 10)",
-1) ||
!op.addBoolOption('\0', "blinterp", "Enable Baseline Interpreter (default)") ||
!op.addBoolOption('\0', "no-blinterp", "Disable Baseline Interpreter") ||
!op.addBoolOption('\0', "disable-jithints", "Disable caching eager baseline compilation hints.") ||
!op.addBoolOption( '\0', "emit-interpreter-entry", "Emit Interpreter entry trampolines (default under --enable-perf)") ||
!op.addBoolOption( '\0', "no-emit-interpreter-entry", "Do not emit Interpreter entry trampolines (default).") ||
!op.addBoolOption('\0', "blinterp-eager", "Always Baseline-interpret scripts") ||
!op.addIntOption( '\0', "blinterp-warmup-threshold", "COUNT", "Wait for COUNT calls or iterations before Baseline-interpreting " "(default: 10)",
-1) ||
!op.addIntOption( '\0', "trial-inlining-warmup-threshold", "COUNT", "Wait for COUNT calls or iterations before trial-inlining " "(default: 500)",
-1) ||
!op.addStringOption( '\0', "monomorphic-inlining", "default/always/never", "Whether monomorphic inlining is used instead of trial inlining " "always, never, or based on heuristics (default)") ||
!op.addBoolOption( '\0', "no-sse3", "Pretend CPU does not support SSE3 instructions and above " "to test JIT codegen (no-op on platforms other than x86 and x64).") ||
!op.addBoolOption( '\0', "no-ssse3", "Pretend CPU does not support SSSE3 [sic] instructions and above " "to test JIT codegen (no-op on platforms other than x86 and x64).") ||
!op.addBoolOption( '\0', "no-sse41", "Pretend CPU does not support SSE4.1 instructions " "to test JIT codegen (no-op on platforms other than x86 and x64).") ||
!op.addBoolOption('\0', "no-sse4", "Alias for --no-sse41") ||
!op.addBoolOption( '\0', "no-sse42", "Pretend CPU does not support SSE4.2 instructions " "to test JIT codegen (no-op on platforms other than x86 and x64).") || #ifdef ENABLE_WASM_AVX
!op.addBoolOption('\0', "enable-avx", "No-op. AVX is enabled by default, if available.") ||
!op.addBoolOption( '\0', "no-avx", "Pretend CPU does not support AVX or AVX2 instructions " "to test JIT codegen (no-op on platforms other than x86 and x64).") || #else
!op.addBoolOption('\0', "enable-avx", "AVX is disabled by default. Enable AVX. " "(no-op on platforms other than x86 and x64).") ||
!op.addBoolOption('\0', "no-avx", "No-op. AVX is currently disabled by default.") || #endif
!op.addBoolOption('\0', "more-compartments", "Make newGlobal default to creating a new " "compartment.") ||
!op.addBoolOption('\0', "fuzzing-safe", "Don't expose functions that aren't safe for " "fuzzers to call") || #ifdef DEBUG
!op.addBoolOption('\0', "differential-testing", "Avoid random/undefined behavior that disturbs " "differential testing (correctness fuzzing)") || #endif
!op.addBoolOption('\0', "disable-oom-functions", "Disable functions that cause " "artificial OOMs") ||
!op.addBoolOption('\0', "no-threads", "Disable helper threads") ||
!op.addBoolOption( '\0', "no-jit-backend", "Disable the JIT backend completely for this process") || #ifdef DEBUG
!op.addBoolOption('\0', "dump-entrained-variables", "Print variables which are " "unnecessarily entrained by inner functions") || #endif
!op.addBoolOption('\0', "no-ggc", "Disable Generational GC") ||
!op.addBoolOption('\0', "no-cgc", "Disable Compacting GC") ||
!op.addBoolOption('\0', "no-incremental-gc", "Disable Incremental GC") ||
!op.addBoolOption('\0', "no-parallel-marking", "Disable GC parallel marking") ||
!op.addBoolOption('\0', "enable-parallel-marking", "Enable GC parallel marking") ||
!op.addStringOption('\0', "nursery-strings", "on/off", "Allocate strings in the nursery") ||
!op.addStringOption('\0', "nursery-bigints", "on/off", "Allocate BigInts in the nursery") ||
!op.addIntOption('\0', "available-memory", "SIZE", "Select GC settings based on available memory (MB)", 0) ||
!op.addBoolOption('\0', "disable-decommit", "Disable decommitting unsued GC memory") ||
!op.addStringOption('\0', "arm-hwcap", "[features]", "Specify ARM code generation features, or 'help' to " "list all features.") ||
!op.addIntOption('\0', "arm-asm-nop-fill", "SIZE", "Insert the given number of NOP instructions at all " "possible pool locations.", 0) ||
!op.addIntOption('\0', "asm-pool-max-offset", "OFFSET", "The maximum pc relative OFFSET permitted in pool " "reference instructions.", 1024) ||
!op.addBoolOption('\0', "arm-sim-icache-checks", "Enable icache flush checks in the ARM " "simulator.") ||
!op.addIntOption('\0', "arm-sim-stop-at", "NUMBER", "Stop the ARM simulator after the given " "NUMBER of instructions.",
-1) ||
!op.addBoolOption('\0', "mips-sim-icache-checks", "Enable icache flush checks in the MIPS " "simulator.") ||
!op.addIntOption('\0', "mips-sim-stop-at", "NUMBER", "Stop the MIPS simulator after the given " "NUMBER of instructions.",
-1) ||
!op.addBoolOption('\0', "loong64-sim-icache-checks", "Enable icache flush checks in the LoongArch64 " "simulator.") ||
!op.addIntOption('\0', "loong64-sim-stop-at", "NUMBER", "Stop the LoongArch64 simulator after the given " "NUMBER of instructions.",
-1) || #ifdef JS_CODEGEN_RISCV64
!op.addBoolOption('\0', "riscv-debug", "debug print riscv info.") || #endif #ifdef JS_SIMULATOR_RISCV64
!op.addBoolOption('\0', "trace-sim", "print simulator info.") ||
!op.addBoolOption('\0', "debug-sim", "debug simulator.") ||
!op.addBoolOption('\0', "riscv-trap-to-simulator-debugger", "trap into simulator debuggger.") ||
!op.addIntOption('\0', "riscv-sim-stop-at", "NUMBER", "Stop the riscv simulator after the given " "NUMBER of instructions.",
-1) || #endif
!op.addIntOption('\0', "nursery-size", "SIZE-MB", "Set the maximum nursery size in MB",
JS::DefaultNurseryMaxBytes / 1024 / 1024) || #ifdef JS_GC_ZEAL
!op.addStringOption('z', "gc-zeal", "LEVEL(;LEVEL)*[,N]",
gc::ZealModeHelpText) || #else
!op.addStringOption('z', "gc-zeal", "LEVEL(;LEVEL)*[,N]", "option ignored in non-gc-zeal builds") || #endif
!op.addMultiStringOption('\0', "gc-param", "NAME=VALUE", "Set a named GC parameter") ||
!op.addStringOption('\0', "module-load-path", "DIR", "Set directory to load modules from") ||
!op.addBoolOption('\0', "no-source-pragmas", "Disable source(Mapping)URL pragma parsing") ||
!op.addBoolOption('\0', "no-async-stacks", "Disable async stacks") ||
!op.addBoolOption('\0', "async-stacks-capture-debuggee-only", "Limit async stack capture to only debuggees") ||
!op.addMultiStringOption('\0', "dll", "LIBRARY", "Dynamically load LIBRARY") ||
!op.addBoolOption('\0', "suppress-minidump", "Suppress crash minidumps") || #ifdef JS_ENABLE_SMOOSH
!op.addBoolOption('\0', "smoosh", "Use SmooshMonkey") ||
!op.addStringOption('\0', "not-implemented-watchfile", "[filename]", "Track NotImplemented errors in the new frontend") || #else
!op.addBoolOption('\0', "smoosh", "No-op") ||
#endif
!op.addStringOption( '\0', "delazification-mode", "[option]", "Select one of the delazification mode for scripts given on the " "command line, valid options are: " "'on-demand', 'concurrent-df', 'eager', 'concurrent-df+on-demand'. " "Choosing 'concurrent-df+on-demand' will run both concurrent-df and " "on-demand delazification mode, and compare compilation outcome. ") ||
!op.addBoolOption('\0', "wasm-compile-and-serialize", "Compile the wasm bytecode from stdin and serialize " "the results to stdout") ||
#ifdef FUZZING_JS_FUZZILLI
!op.addBoolOption('\0', "reprl", "Enable REPRL mode for fuzzing") ||
#endif
!op.addStringOption('\0', "telemetry-dir", "[directory]", "Output telemetry results in a directory") ||
!op.addMultiStringOption('P', "setpref", "name[=val]", "Set the value of a JS pref. The value may " "be omitted for boolean prefs, in which case " "they default to true. Use --list-prefs " "to print all pref names.") ||
!op.addBoolOption( '\0', "list-prefs", "Print list of prefs that can be set with --setpref.") ||
!op.addBoolOption('\0', "use-fdlibm-for-sin-cos-tan", "Use fdlibm for Math.sin, Math.cos, and Math.tan") ||
!op.addBoolOption('\0', "wasm-gc", "Enable WebAssembly gc proposal.") ||
!op.addBoolOption('\0', "wasm-relaxed-simd", "Enable WebAssembly relaxed-simd proposal.") ||
!op.addBoolOption('\0', "wasm-multi-memory", "Enable WebAssembly multi-memory proposal.") ||
!op.addBoolOption('\0', "wasm-memory-control", "Enable WebAssembly memory-control proposal.") ||
!op.addBoolOption('\0', "wasm-memory64", "Enable WebAssembly memory64 proposal.") ||
!op.addBoolOption('\0', "wasm-tail-calls", "Enable WebAssembly tail-calls proposal.") ||
!op.addBoolOption('\0', "wasm-js-string-builtins", "Enable WebAssembly js-string-builtins proposal.") ||
!op.addBoolOption('\0', "enable-promise-try", "Enable Promise.try") ||
!op.addBoolOption('\0', "enable-iterator-sequencing", "Enable Iterator Sequencing") ||
!op.addBoolOption('\0', "enable-math-sumprecise", "Enable Math.sumPrecise") ||
!op.addBoolOption('\0', "enable-error-iserror", "Enable Error.isError") ||
!op.addBoolOption('\0', "enable-iterator-range", "Enable Iterator.range") ||
!op.addBoolOption('\0', "enable-joint-iteration", "Enable Joint Iteration") ||
!op.addBoolOption('\0', "enable-atomics-pause", "Enable Atomics pause") ||
!op.addBoolOption('\0', "enable-explicit-resource-management", "Enable Explicit Resource Management") ||
!op.addBoolOption('\0', "disable-explicit-resource-management", "Disable Explicit Resource Management") ||
!op.addBoolOption('\0', "enable-temporal", "Enable Temporal") ||
!op.addBoolOption('\0', "enable-upsert", "Enable Upsert proposal")) { returnfalse;
}
// If --fuzzing-safe is used, print a warning for unknown shell flags instead // of aborting execution.
op.setIgnoresUnknownOptions("fuzzing-safe", true);
for (MultiStringRange args = op.getMultiStringOption("setpref");
!args.empty(); args.popFront()) { if (!SetPref(args.front())) { returnfalse;
}
}
// Override pref values for prefs that have a custom shell flag. // If you're adding a new feature, consider using --setpref instead.
if (op.getBoolOption("disable-array-grouping")) {
JS::Prefs::setAtStartup_array_grouping(false);
} if (op.getBoolOption("disable-arraybuffer-transfer")) {
JS::Prefs::setAtStartup_arraybuffer_transfer(false);
} if (op.getBoolOption("enable-shadow-realms")) {
JS::Prefs::set_experimental_shadow_realms(true);
} if (op.getBoolOption("disable-well-formed-unicode-strings")) {
JS::Prefs::setAtStartup_well_formed_unicode_strings(false);
} if (op.getBoolOption("enable-arraybuffer-resizable")) {
JS::Prefs::setAtStartup_experimental_arraybuffer_resizable(true);
JS::Prefs::setAtStartup_experimental_sharedarraybuffer_growable(true);
} if (op.getBoolOption("enable-regexp-duplicate-named-groups")) {
JS::Prefs::setAtStartup_experimental_regexp_duplicate_named_groups(true);
} if (op.getBoolOption("enable-float16array")) {
JS::Prefs::setAtStartup_experimental_float16array(true);
} if (op.getBoolOption("enable-new-set-methods")) {
JS::Prefs::setAtStartup_experimental_new_set_methods(true);
} if (op.getBoolOption("enable-regexp-modifiers")) {
JS::Prefs::setAtStartup_experimental_regexp_modifiers(true);
} if (op.getBoolOption("enable-uint8array-base64")) {
JS::Prefs::setAtStartup_experimental_uint8array_base64(true);
} if (op.getBoolOption("enable-regexp-escape")) {
JS::Prefs::setAtStartup_experimental_regexp_escape(true);
} if (op.getBoolOption("enable-promise-try")) {
JS::Prefs::setAtStartup_experimental_promise_try(true);
}
#ifdef NIGHTLY_BUILD if (op.getBoolOption("enable-async-iterator-helpers")) {
JS::Prefs::setAtStartup_experimental_async_iterator_helpers(true);
} if (op.getBoolOption("enable-symbols-as-weakmap-keys")) {
JS::Prefs::setAtStartup_experimental_symbols_as_weakmap_keys(true);
} if (op.getBoolOption("enable-error-iserror")) {
JS::Prefs::set_experimental_error_iserror(true);
} if (op.getBoolOption("enable-iterator-sequencing")) {
JS::Prefs::setAtStartup_experimental_iterator_sequencing(true);
} if (op.getBoolOption("enable-math-sumprecise")) {
JS::Prefs::setAtStartup_experimental_math_sumprecise(true);
} if (op.getBoolOption("enable-iterator-range")) {
JS::Prefs::setAtStartup_experimental_iterator_range(true);
} if (op.getBoolOption("enable-joint-iteration")) {
JS::Prefs::setAtStartup_experimental_joint_iteration(true);
} if (op.getBoolOption("enable-atomics-pause")) {
JS::Prefs::setAtStartup_experimental_atomics_pause(true);
} if (op.getBoolOption("enable-upsert")) {
JS::Prefs::setAtStartup_experimental_upsert(true);
}
#endif
#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT if (op.getBoolOption("enable-explicit-resource-management")) {
JS::Prefs::set_experimental_explicit_resource_management(true);
} if (op.getBoolOption("disable-explicit-resource-management")) {
JS::Prefs::set_experimental_explicit_resource_management(false);
}
#endif
#ifdef JS_HAS_TEMPORAL_API if (op.getBoolOption("enable-temporal")) {
JS::Prefs::setAtStartup_experimental_temporal(true);
}
#endif if (op.getBoolOption("enable-json-parse-with-source")) {
JS::Prefs::set_experimental_json_parse_with_source(true);
}
if (op.getBoolOption("disable-weak-refs")) {
JS::Prefs::setAtStartup_weakrefs(false);
}
JS::Prefs::setAtStartup_experimental_weakrefs_expose_cleanupSome(true);
if (op.getBoolOption("disable-destructuring-fuse")) {
JS::Prefs::setAtStartup_destructuring_fuse(false);
} if (op.getBoolOption("disable-property-error-message-fix")) {
JS::Prefs::setAtStartup_property_error_message_fix(false);
}
// Fish around in `op` for various important compiler-configuration flags // and make sure they get handed on to any child processes we might create. // See bug 1700900. Semantically speaking, this is all rather dubious: // // * What set of flags need to be propagated in order to guarantee that the // child produces code that is "compatible" (in whatever sense) with that // produced by the parent? This isn't always easy to determine. // // * There's nothing that ensures that flags given to the child are // presented in the same order that they exist in the parent's `argv[]`. // That could be a problem in the case where two flags with contradictory // meanings are given, and they are presented to the child in the opposite // order. For example: --wasm-compiler=optimizing --wasm-compiler=baseline.
if (op.getBoolOption("no-avx")) {
js::jit::CPUInfo::SetAVXDisabled(); if (!sCompilerProcessFlags.append("--no-avx")) { returnfalse;
}
} if (op.getBoolOption("enable-avx")) {
js::jit::CPUInfo::SetAVXEnabled(); if (!sCompilerProcessFlags.append("--enable-avx")) { returnfalse;
}
} if (op.getBoolOption("no-sse3")) {
js::jit::CPUInfo::SetSSE3Disabled(); if (!sCompilerProcessFlags.append("--no-sse3")) { returnfalse;
}
} if (op.getBoolOption("no-ssse3")) {
js::jit::CPUInfo::SetSSSE3Disabled(); if (!sCompilerProcessFlags.append("--no-ssse3")) { returnfalse;
}
} if (op.getBoolOption("no-sse4") || op.getBoolOption("no-sse41")) {
js::jit::CPUInfo::SetSSE41Disabled(); if (!sCompilerProcessFlags.append("--no-sse41")) { returnfalse;
}
} if (op.getBoolOption("no-sse42")) {
js::jit::CPUInfo::SetSSE42Disabled(); if (!sCompilerProcessFlags.append("--no-sse42")) { returnfalse;
}
}
#endif
#ifndef __wasi__ if (op.getBoolOption("disable-wasm-huge-memory")) {
JS::Prefs::setAtStartup_wasm_disable_huge_memory(true); if (!sCompilerProcessFlags.append("--disable-wasm-huge-memory")) { returnfalse;
}
}
#endif
if (op.getBoolOption("disable-decommit")) {
gc::DisableDecommit();
}
returntrue;
}
bool SetGlobalOptionsPostJSInit(const OptionParser& op) { if (op.getStringOption("telemetry-dir")) {
MOZ_ASSERT(!telemetryLock);
telemetryLock = js_new<Mutex>(mutexid::ShellTelemetry); if (!telemetryLock) { returnfalse;
}
}
// Allow dumping on Linux with the fuzzing flag set, even when running with // the suid/sgid flag set on the shell.
#ifdef XP_LINUX if (op.getBoolOption("fuzzing-safe")) {
prctl(PR_SET_DUMPABLE, 1);
}
#endif
if (op.getBoolOption("no-threads")) {
js::DisableExtraThreads();
}
enableCodeCoverage = op.getBoolOption("code-coverage"); if (enableCodeCoverage) {
js::EnableCodeCoverage();
}
// If LCov is enabled, then the default delazification mode should be changed // to parse everything eagerly, such that we know the location of every // instruction, to report them in the LCov summary, even if there is no uses // of these instructions. // // Note: code coverage can be enabled either using the --code-coverage command // line, or the JS_CODE_COVERAGE_OUTPUT_DIR environment variable, which is // processed by JS_InitWithFailureDiagnostic. if (coverage::IsLCovEnabled()) {
defaultDelazificationMode =
JS::DelazificationOption::ParseEverythingEagerly;
}
if (constchar* xdr = op.getStringOption("selfhosted-xdr-path")) {
shell::selfHostedXDRPath = xdr;
} if (constchar* opt = op.getStringOption("selfhosted-xdr-mode")) { if (strcmp(opt, "encode") == 0) {
shell::encodeSelfHostedCode = true;
} elseif (strcmp(opt, "decode") == 0) {
shell::encodeSelfHostedCode = false;
} elseif (strcmp(opt, "off") == 0) {
shell::selfHostedXDRPath = nullptr;
} else {
MOZ_CRASH( "invalid option value for --selfhosted-xdr-mode, must be " "encode/decode");
}
}
if (op.getBoolOption("suppress-minidump")) {
js::NoteIntentionalCrash();
}
// The fake CPU count must be set before initializing the Runtime, // which spins up the thread pool.
int32_t cpuCount = op.getIntOption("cpu-count"); // What we're really setting if (cpuCount < 0) {
cpuCount = op.getIntOption("thread-count"); // Legacy name
} if (cpuCount >= 0 && !SetFakeCPUCount(cpuCount)) { returnfalse;
}
#ifndef __wasi__ // Also the following are to be propagated. constchar* to_propagate[] = { // Compiler selection options "--test-wasm-await-tier2",
}; for (constchar* p : to_propagate) { if (op.getBoolOption(p + 2/* 2 => skip the leading '--' */)) { if (!sCompilerProcessFlags.append(p)) { returnfalse;
}
}
}
// Also --wasm-compiler= is to be propagated. This is tricky because it is // necessary to reconstitute the --wasm-compiler=<whatever> string from its // pieces, without causing a leak. Hence it is copied into a static buffer. // This is thread-unsafe, but we're in `main()` and on the process' root // thread. Also, we do this only once -- it wouldn't work properly if we // handled multiple --wasm-compiler= flags in a loop. constchar* wasm_compiler = op.getStringOption("wasm-compiler"); if (wasm_compiler) {
size_t n_needed = 2 + strlen("wasm-compiler") + 1 + strlen(wasm_compiler) + 1; const size_t n_avail = 128; staticchar buf[n_avail]; // `n_needed` depends on the compiler name specified. However, it can't // be arbitrarily long, since previous flag-checking should have limited // it to a set of known possibilities: "baseline", "ion", // "baseline+ion", Still, assert this for safety.
MOZ_RELEASE_ASSERT(n_needed < n_avail);
memset(buf, 0, sizeof(buf));
SprintfBuf(buf, n_avail, "--%s=%s", "wasm-compiler", wasm_compiler); if (!sCompilerProcessFlags.append(buf)) { returnfalse;
}
}
#endif // __wasi__
returntrue;
}
bool SetContextJITOptions(JSContext* cx, const OptionParser& op) { // Check --fast-warmup first because it sets default warm-up thresholds. These // thresholds can then be overridden below by --ion-eager and other flags. if (op.getBoolOption("fast-warmup")) {
jit::JitOptions.setFastWarmUp();
}
if (op.getBoolOption("no-ion-for-main-context")) {
JS::ContextOptionsRef(cx).setDisableIon();
}
if (op.getBoolOption("disable-main-thread-denormals")) { // This is a simplified version of WebAudio code, which is good enough for // fuzzing purposes. //
// See dom/media/webaudio/blink/DenormalDisabler.h#124
#if defined(__GNUC__) && defined(__SSE__) && defined(__x86_64__) int savedCSR;
asm volatile("stmxcsr %0" : "=m"(savedCSR)); int newCSR = savedCSR | 0x8040;
asm volatile("ldmxcsr %0" : : "m"(newCSR));
#elif defined(__arm__) int savedCSR;
asm volatile("vmrs %[result], FPSCR" : [result] "=r"(savedCSR)); // Bit 24 is the flush-to-zero mode control bit. Setting it to 1 flushes // denormals to 0. int newCSR = savedCSR | (1 << 24);
asm volatile("vmsr FPSCR, %[src]" : : [src] "r"(newCSR));
#elif defined(__aarch64__) int savedCSR;
asm volatile("mrs %x[result], FPCR" : [result] "=r"(savedCSR)); // Bit 24 is the flush-to-zero mode control bit. Setting it to 1 flushes // denormals to 0. int newCSR = savedCSR | (1 << 24);
asm volatile("msr FPCR, %x[src]" : : [src] "r"(newCSR));
#else // Do nothing on other architecture.
#endif
}
if (op.getStringOption("ion-parallel-compile")) {
fprintf(stderr, "--ion-parallel-compile is deprecated. Please use " "--ion-offthread-compile instead.\n"); returnfalse;
}
if (op.getBoolOption("disable-bailout-loop-check")) {
jit::JitOptions.disableBailoutLoopCheck = true;
}
if (op.getBoolOption("only-inline-selfhosted")) {
jit::JitOptions.onlyInlineSelfHosted = true;
}
if (op.getBoolOption("enable-ic-frame-pointers")) {
jit::JitOptions.enableICFramePointers = true;
}
size_t nurseryBytes = op.getIntOption("nursery-size") * 1024L * 1024L; if (nurseryBytes == 0) {
fprintf(stderr, "Error: --nursery-size parameter must be non-zero.\n");
fprintf(stderr, "The nursery can be disabled by passing the --no-ggc option.\n"); returnfalse;
}
JS_SetGCParameter(cx, JSGC_MAX_NURSERY_BYTES, nurseryBytes);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.