/ jsc.cpp
jsc.cpp
   1  /*
   2   *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
   3   *  Copyright (C) 2004-2021 Apple Inc. All rights reserved.
   4   *  Copyright (C) 2006 Bjoern Graf (bjoern.graf@gmail.com)
   5   *
   6   *  This library is free software; you can redistribute it and/or
   7   *  modify it under the terms of the GNU Library General Public
   8   *  License as published by the Free Software Foundation; either
   9   *  version 2 of the License, or (at your option) any later version.
  10   *
  11   *  This library is distributed in the hope that it will be useful,
  12   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14   *  Library General Public License for more details.
  15   *
  16   *  You should have received a copy of the GNU Library General Public License
  17   *  along with this library; see the file COPYING.LIB.  If not, write to
  18   *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  19   *  Boston, MA 02110-1301, USA.
  20   *
  21   */
  22  
  23  #include "config.h"
  24  
  25  #include "ArrayBuffer.h"
  26  #include "BigIntConstructor.h"
  27  #include "BytecodeCacheError.h"
  28  #include "CatchScope.h"
  29  #include "CodeBlock.h"
  30  #include "CodeCache.h"
  31  #include "CompilerTimingScope.h"
  32  #include "Completion.h"
  33  #include "ConfigFile.h"
  34  #include "DeferredWorkTimer.h"
  35  #include "Disassembler.h"
  36  #include "Exception.h"
  37  #include "ExceptionHelpers.h"
  38  #include "HeapSnapshotBuilder.h"
  39  #include "InitializeThreading.h"
  40  #include "Interpreter.h"
  41  #include "JIT.h"
  42  #include "JITOperationList.h"
  43  #include "JSArray.h"
  44  #include "JSArrayBuffer.h"
  45  #include "JSBigInt.h"
  46  #include "JSFinalizationRegistry.h"
  47  #include "JSFunction.h"
  48  #include "JSInternalPromise.h"
  49  #include "JSLock.h"
  50  #include "JSNativeStdFunction.h"
  51  #include "JSONObject.h"
  52  #include "JSObjectInlines.h"
  53  #include "JSSourceCode.h"
  54  #include "JSString.h"
  55  #include "JSTypedArrays.h"
  56  #include "JSWebAssemblyInstance.h"
  57  #include "JSWebAssemblyMemory.h"
  58  #include "LLIntThunks.h"
  59  #include "ObjectConstructor.h"
  60  #include "ParserError.h"
  61  #include "ProfilerDatabase.h"
  62  #include "ReleaseHeapAccessScope.h"
  63  #include "SamplingProfiler.h"
  64  #include "SimpleTypedArrayController.h"
  65  #include "StackVisitor.h"
  66  #include "StructureInlines.h"
  67  #include "SuperSampler.h"
  68  #include "TestRunnerUtils.h"
  69  #include "TypedArrayInlines.h"
  70  #include "VMInspector.h"
  71  #include "WasmCapabilities.h"
  72  #include "WasmFaultSignalHandler.h"
  73  #include "WasmMemory.h"
  74  #include <stdio.h>
  75  #include <stdlib.h>
  76  #include <string.h>
  77  #include <sys/stat.h>
  78  #include <sys/types.h>
  79  #include <type_traits>
  80  #include <wtf/CPUTime.h>
  81  #include <wtf/FileSystem.h>
  82  #include <wtf/MainThread.h>
  83  #include <wtf/MemoryPressureHandler.h>
  84  #include <wtf/MonotonicTime.h>
  85  #include <wtf/Scope.h>
  86  #include <wtf/StringPrintStream.h>
  87  #include <wtf/URL.h>
  88  #include <wtf/WallTime.h>
  89  #include <wtf/text/StringBuilder.h>
  90  #include <wtf/threads/Signals.h>
  91  
  92  #if OS(WINDOWS)
  93  #include <direct.h>
  94  #include <fcntl.h>
  95  #include <io.h>
  96  #else
  97  #include <unistd.h>
  98  #endif
  99  
 100  #if PLATFORM(COCOA)
 101  #include <crt_externs.h>
 102  #endif
 103  
 104  #if PLATFORM(GTK)
 105  #include <locale.h>
 106  #endif
 107  
 108  #if HAVE(READLINE)
 109  // readline/history.h has a Function typedef which conflicts with the WTF::Function template from WTF/Forward.h
 110  // We #define it to something else to avoid this conflict.
 111  #define Function ReadlineFunction
 112  #include <readline/history.h>
 113  #include <readline/readline.h>
 114  #undef Function
 115  #endif
 116  
 117  #if COMPILER(MSVC)
 118  #include <crtdbg.h>
 119  #include <mmsystem.h>
 120  #include <windows.h>
 121  #endif
 122  
 123  #if OS(DARWIN) && CPU(ARM_THUMB2)
 124  #include <fenv.h>
 125  #include <arm/arch.h>
 126  #endif
 127  
 128  #if OS(DARWIN)
 129  #include <wtf/spi/darwin/ProcessMemoryFootprint.h>
 130  #elif OS(LINUX)
 131  #include <wtf/linux/ProcessMemoryFootprint.h>
 132  #endif
 133  
 134  #if OS(DARWIN) || OS(LINUX)
 135  struct MemoryFootprint : ProcessMemoryFootprint {
 136      MemoryFootprint(const ProcessMemoryFootprint& src)
 137          : ProcessMemoryFootprint(src)
 138      {
 139      }
 140  };
 141  #else
 142  struct MemoryFootprint {
 143      uint64_t current;
 144      uint64_t peak;
 145  
 146      static MemoryFootprint now()
 147      {
 148          return { 0L, 0L };
 149      }
 150      
 151      static void resetPeak()
 152      {
 153      }
 154  };
 155  #endif
 156  
 157  #if !defined(PATH_MAX)
 158  #define PATH_MAX 4096
 159  #endif
 160  
 161  using namespace JSC;
 162  
 163  namespace {
 164  
 165  #define EXIT_EXCEPTION 3
 166  
 167  NO_RETURN_WITH_VALUE static void jscExit(int status)
 168  {
 169      waitForAsynchronousDisassembly();
 170      
 171  #if ENABLE(DFG_JIT)
 172      if (DFG::isCrashing()) {
 173          for (;;) {
 174  #if OS(WINDOWS)
 175              Sleep(1000);
 176  #else
 177              pause();
 178  #endif
 179          }
 180      }
 181  #endif // ENABLE(DFG_JIT)
 182      exit(status);
 183  }
 184  
 185  static unsigned asyncTestPasses { 0 };
 186  static unsigned asyncTestExpectedPasses { 0 };
 187  
 188  }
 189  
 190  template<typename Vector>
 191  static bool fillBufferWithContentsOfFile(const String& fileName, Vector& buffer);
 192  static RefPtr<Uint8Array> fillBufferWithContentsOfFile(const String& fileName);
 193  
 194  class CommandLine;
 195  class GlobalObject;
 196  class Workers;
 197  
 198  template<typename Func>
 199  int runJSC(const CommandLine&, bool isWorker, const Func&);
 200  static void checkException(GlobalObject*, bool isLastFile, bool hasException, JSValue, const CommandLine&, bool& success);
 201  
 202  class Message : public ThreadSafeRefCounted<Message> {
 203  public:
 204  #if ENABLE(WEBASSEMBLY)
 205      using Content = Variant<ArrayBufferContents, Ref<Wasm::MemoryHandle>>;
 206  #else
 207      using Content = Variant<ArrayBufferContents>;
 208  #endif
 209      Message(Content&&, int32_t);
 210      ~Message();
 211      
 212      Content&& releaseContents() { return WTFMove(m_contents); }
 213      int32_t index() const { return m_index; }
 214  
 215  private:
 216      Content m_contents;
 217      int32_t m_index { 0 };
 218  };
 219  
 220  class Worker : public BasicRawSentinelNode<Worker> {
 221  public:
 222      Worker(Workers&);
 223      ~Worker();
 224      
 225      void enqueue(const AbstractLocker&, RefPtr<Message>);
 226      RefPtr<Message> dequeue();
 227      
 228      static Worker& current();
 229  
 230  private:
 231      static ThreadSpecific<Worker*>& currentWorker();
 232  
 233      Workers& m_workers;
 234      Deque<RefPtr<Message>> m_messages;
 235  };
 236  
 237  class Workers {
 238      WTF_MAKE_FAST_ALLOCATED;
 239      WTF_MAKE_NONCOPYABLE(Workers);
 240  public:
 241      Workers();
 242      ~Workers();
 243      
 244      template<typename Func>
 245      void broadcast(const Func&);
 246      
 247      void report(const String&);
 248      String tryGetReport();
 249      String getReport();
 250      
 251      static Workers& singleton();
 252      
 253  private:
 254      friend class Worker;
 255      
 256      Lock m_lock;
 257      Condition m_condition;
 258      SentinelLinkedList<Worker, BasicRawSentinelNode<Worker>> m_workers;
 259      Deque<String> m_reports;
 260  };
 261  
 262  
 263  static JSC_DECLARE_HOST_FUNCTION(functionCreateGlobalObject);
 264  static JSC_DECLARE_HOST_FUNCTION(functionCreateHeapBigInt);
 265  #if USE(BIGINT32)
 266  static JSC_DECLARE_HOST_FUNCTION(functionCreateBigInt32);
 267  #endif
 268  static JSC_DECLARE_HOST_FUNCTION(functionUseBigInt32);
 269  static JSC_DECLARE_HOST_FUNCTION(functionIsBigInt32);
 270  static JSC_DECLARE_HOST_FUNCTION(functionIsHeapBigInt);
 271  
 272  static JSC_DECLARE_HOST_FUNCTION(functionPrintStdOut);
 273  static JSC_DECLARE_HOST_FUNCTION(functionPrintStdErr);
 274  static JSC_DECLARE_HOST_FUNCTION(functionDebug);
 275  static JSC_DECLARE_HOST_FUNCTION(functionDescribe);
 276  static JSC_DECLARE_HOST_FUNCTION(functionDescribeArray);
 277  static JSC_DECLARE_HOST_FUNCTION(functionSleepSeconds);
 278  static JSC_DECLARE_HOST_FUNCTION(functionJSCStack);
 279  static JSC_DECLARE_HOST_FUNCTION(functionGCAndSweep);
 280  static JSC_DECLARE_HOST_FUNCTION(functionFullGC);
 281  static JSC_DECLARE_HOST_FUNCTION(functionEdenGC);
 282  static JSC_DECLARE_HOST_FUNCTION(functionHeapSize);
 283  static JSC_DECLARE_HOST_FUNCTION(functionCreateMemoryFootprint);
 284  static JSC_DECLARE_HOST_FUNCTION(functionResetMemoryPeak);
 285  static JSC_DECLARE_HOST_FUNCTION(functionAddressOf);
 286  static JSC_DECLARE_HOST_FUNCTION(functionVersion);
 287  static JSC_DECLARE_HOST_FUNCTION(functionRun);
 288  static JSC_DECLARE_HOST_FUNCTION(functionRunString);
 289  static JSC_DECLARE_HOST_FUNCTION(functionLoad);
 290  static JSC_DECLARE_HOST_FUNCTION(functionLoadString);
 291  static JSC_DECLARE_HOST_FUNCTION(functionReadFile);
 292  static JSC_DECLARE_HOST_FUNCTION(functionCheckSyntax);
 293  static JSC_DECLARE_HOST_FUNCTION(functionReadline);
 294  static JSC_DECLARE_HOST_FUNCTION(functionPreciseTime);
 295  static JSC_DECLARE_HOST_FUNCTION(functionNeverInlineFunction);
 296  static JSC_DECLARE_HOST_FUNCTION(functionNoDFG);
 297  static JSC_DECLARE_HOST_FUNCTION(functionNoFTL);
 298  static JSC_DECLARE_HOST_FUNCTION(functionNoOSRExitFuzzing);
 299  static JSC_DECLARE_HOST_FUNCTION(functionOptimizeNextInvocation);
 300  static JSC_DECLARE_HOST_FUNCTION(functionNumberOfDFGCompiles);
 301  static JSC_DECLARE_HOST_FUNCTION(functionCallerIsOMGCompiled);
 302  static JSC_DECLARE_HOST_FUNCTION(functionJSCOptions);
 303  static JSC_DECLARE_HOST_FUNCTION(functionReoptimizationRetryCount);
 304  static JSC_DECLARE_HOST_FUNCTION(functionTransferArrayBuffer);
 305  static JSC_DECLARE_HOST_FUNCTION(functionFailNextNewCodeBlock);
 306  static NO_RETURN_WITH_VALUE JSC_DECLARE_HOST_FUNCTION(functionQuit);
 307  static JSC_DECLARE_HOST_FUNCTION(functionFalse);
 308  static JSC_DECLARE_HOST_FUNCTION(functionUndefined1);
 309  static JSC_DECLARE_HOST_FUNCTION(functionUndefined2);
 310  static JSC_DECLARE_HOST_FUNCTION(functionIsInt32);
 311  static JSC_DECLARE_HOST_FUNCTION(functionIsPureNaN);
 312  static JSC_DECLARE_HOST_FUNCTION(functionEffectful42);
 313  static JSC_DECLARE_HOST_FUNCTION(functionIdentity);
 314  static JSC_DECLARE_HOST_FUNCTION(functionMakeMasquerader);
 315  static JSC_DECLARE_HOST_FUNCTION(functionCallMasquerader);
 316  static JSC_DECLARE_HOST_FUNCTION(functionHasCustomProperties);
 317  static JSC_DECLARE_HOST_FUNCTION(functionDumpTypesForAllVariables);
 318  static JSC_DECLARE_HOST_FUNCTION(functionDrainMicrotasks);
 319  static JSC_DECLARE_HOST_FUNCTION(functionSetTimeout);
 320  static JSC_DECLARE_HOST_FUNCTION(functionReleaseWeakRefs);
 321  static JSC_DECLARE_HOST_FUNCTION(functionFinalizationRegistryLiveCount);
 322  static JSC_DECLARE_HOST_FUNCTION(functionFinalizationRegistryDeadCount);
 323  static JSC_DECLARE_HOST_FUNCTION(functionIs32BitPlatform);
 324  static JSC_DECLARE_HOST_FUNCTION(functionCheckModuleSyntax);
 325  static JSC_DECLARE_HOST_FUNCTION(functionPlatformSupportsSamplingProfiler);
 326  static JSC_DECLARE_HOST_FUNCTION(functionGenerateHeapSnapshot);
 327  static JSC_DECLARE_HOST_FUNCTION(functionGenerateHeapSnapshotForGCDebugging);
 328  static JSC_DECLARE_HOST_FUNCTION(functionResetSuperSamplerState);
 329  static JSC_DECLARE_HOST_FUNCTION(functionEnsureArrayStorage);
 330  #if ENABLE(SAMPLING_PROFILER)
 331  static JSC_DECLARE_HOST_FUNCTION(functionStartSamplingProfiler);
 332  static JSC_DECLARE_HOST_FUNCTION(functionSamplingProfilerStackTraces);
 333  #endif
 334  
 335  static JSC_DECLARE_HOST_FUNCTION(functionMaxArguments);
 336  static JSC_DECLARE_HOST_FUNCTION(functionAsyncTestStart);
 337  static JSC_DECLARE_HOST_FUNCTION(functionAsyncTestPassed);
 338  
 339  #if ENABLE(WEBASSEMBLY)
 340  static JSC_DECLARE_HOST_FUNCTION(functionWebAssemblyMemoryMode);
 341  #endif
 342  
 343  #if ENABLE(SAMPLING_FLAGS)
 344  static JSC_DECLARE_HOST_FUNCTION(functionSetSamplingFlags);
 345  static JSC_DECLARE_HOST_FUNCTION(functionClearSamplingFlags);
 346  #endif
 347  
 348  static JSC_DECLARE_HOST_FUNCTION(functionGetRandomSeed);
 349  static JSC_DECLARE_HOST_FUNCTION(functionSetRandomSeed);
 350  static JSC_DECLARE_HOST_FUNCTION(functionIsRope);
 351  static JSC_DECLARE_HOST_FUNCTION(functionCallerSourceOrigin);
 352  static JSC_DECLARE_HOST_FUNCTION(functionDollarCreateRealm);
 353  static JSC_DECLARE_HOST_FUNCTION(functionDollarEvalScript);
 354  static JSC_DECLARE_HOST_FUNCTION(functionDollarAgentStart);
 355  static JSC_DECLARE_HOST_FUNCTION(functionDollarAgentReceiveBroadcast);
 356  static JSC_DECLARE_HOST_FUNCTION(functionDollarAgentReport);
 357  static JSC_DECLARE_HOST_FUNCTION(functionDollarAgentSleep);
 358  static JSC_DECLARE_HOST_FUNCTION(functionDollarAgentBroadcast);
 359  static JSC_DECLARE_HOST_FUNCTION(functionDollarAgentGetReport);
 360  static JSC_DECLARE_HOST_FUNCTION(functionDollarAgentLeaving);
 361  static JSC_DECLARE_HOST_FUNCTION(functionDollarAgentMonotonicNow);
 362  static JSC_DECLARE_HOST_FUNCTION(functionWaitForReport);
 363  static JSC_DECLARE_HOST_FUNCTION(functionHeapCapacity);
 364  static JSC_DECLARE_HOST_FUNCTION(functionFlashHeapAccess);
 365  static JSC_DECLARE_HOST_FUNCTION(functionDisableRichSourceInfo);
 366  static JSC_DECLARE_HOST_FUNCTION(functionMallocInALoop);
 367  static JSC_DECLARE_HOST_FUNCTION(functionTotalCompileTime);
 368  
 369  static JSC_DECLARE_HOST_FUNCTION(functionSetUnhandledRejectionCallback);
 370  static JSC_DECLARE_HOST_FUNCTION(functionAsDoubleNumber);
 371  
 372  static JSC_DECLARE_HOST_FUNCTION(functionDropAllLocks);
 373  
 374  struct Script {
 375      enum class StrictMode {
 376          Strict,
 377          Sloppy
 378      };
 379  
 380      enum class ScriptType {
 381          Script,
 382          Module
 383      };
 384  
 385      enum class CodeSource {
 386          File,
 387          CommandLine
 388      };
 389  
 390      StrictMode strictMode;
 391      CodeSource codeSource;
 392      ScriptType scriptType;
 393      char* argument;
 394  
 395      Script(StrictMode strictMode, CodeSource codeSource, ScriptType scriptType, char *argument)
 396          : strictMode(strictMode)
 397          , codeSource(codeSource)
 398          , scriptType(scriptType)
 399          , argument(argument)
 400      {
 401          if (strictMode == StrictMode::Strict)
 402              ASSERT(codeSource == CodeSource::File);
 403      }
 404  };
 405  
 406  class CommandLine {
 407  public:
 408      CommandLine(int argc, char** argv)
 409      {
 410          parseArguments(argc, argv);
 411      }
 412  
 413      enum CommandLineForWorkersTag { CommandLineForWorkers };
 414      CommandLine(CommandLineForWorkersTag)
 415      {
 416      }
 417  
 418      Vector<Script> m_scripts;
 419      Vector<String> m_arguments;
 420      String m_profilerOutput;
 421      String m_uncaughtExceptionName;
 422      bool m_interactive { false };
 423      bool m_dump { false };
 424      bool m_module { false };
 425      bool m_exitCode { false };
 426      bool m_destroyVM { false };
 427      bool m_profile { false };
 428      bool m_treatWatchdogExceptionAsSuccess { false };
 429      bool m_alwaysDumpUncaughtException { false };
 430      bool m_dumpMemoryFootprint { false };
 431      bool m_dumpSamplingProfilerData { false };
 432      bool m_enableRemoteDebugging { false };
 433      bool m_canBlockIsFalse { false };
 434  
 435      void parseArguments(int, char**);
 436  };
 437  
 438  static const char interactivePrompt[] = ">>> ";
 439  
 440  class StopWatch {
 441  public:
 442      void start();
 443      void stop();
 444      long getElapsedMS(); // call stop() first
 445  
 446  private:
 447      MonotonicTime m_startTime;
 448      MonotonicTime m_stopTime;
 449  };
 450  
 451  void StopWatch::start()
 452  {
 453      m_startTime = MonotonicTime::now();
 454  }
 455  
 456  void StopWatch::stop()
 457  {
 458      m_stopTime = MonotonicTime::now();
 459  }
 460  
 461  long StopWatch::getElapsedMS()
 462  {
 463      return (m_stopTime - m_startTime).millisecondsAs<long>();
 464  }
 465  
 466  template<typename Vector>
 467  static inline String stringFromUTF(const Vector& utf8)
 468  {
 469      return String::fromUTF8WithLatin1Fallback(utf8.data(), utf8.size());
 470  }
 471  
 472  static JSC_DECLARE_CUSTOM_GETTER(accessorMakeMasquerader);
 473  static JSC_DECLARE_CUSTOM_SETTER(testCustomAccessorSetter);
 474  static JSC_DECLARE_CUSTOM_SETTER(testCustomValueSetter);
 475  
 476  JSC_DEFINE_CUSTOM_GETTER(accessorMakeMasquerader, (JSGlobalObject* globalObject, EncodedJSValue, PropertyName))
 477  {
 478      VM& vm = globalObject->vm();
 479      return JSValue::encode(InternalFunction::createFunctionThatMasqueradesAsUndefined(vm, globalObject, 0, "IsHTMLDDA"_s, functionCallMasquerader));
 480  }
 481  
 482  
 483  class GlobalObject final : public JSGlobalObject {
 484  public:
 485      using Base = JSGlobalObject;
 486  
 487      static GlobalObject* create(VM& vm, Structure* structure, const Vector<String>& arguments)
 488      {
 489          GlobalObject* object = new (NotNull, allocateCell<GlobalObject>(vm.heap)) GlobalObject(vm, structure);
 490          object->finishCreation(vm, arguments);
 491          return object;
 492      }
 493  
 494      DECLARE_INFO;
 495      static const GlobalObjectMethodTable s_globalObjectMethodTable;
 496  
 497      static Structure* createStructure(VM& vm, JSValue prototype)
 498      {
 499          return Structure::create(vm, nullptr, prototype, TypeInfo(GlobalObjectType, StructureFlags), info());
 500      }
 501  
 502      static RuntimeFlags javaScriptRuntimeFlags(const JSGlobalObject*) { return RuntimeFlags::createAllEnabled(); }
 503  
 504  private:
 505      GlobalObject(VM&, Structure*);
 506  
 507      static constexpr unsigned DontEnum = 0 | PropertyAttribute::DontEnum;
 508  
 509      void finishCreation(VM& vm, const Vector<String>& arguments)
 510      {
 511          Base::finishCreation(vm);
 512          JSC_TO_STRING_TAG_WITHOUT_TRANSITION();
 513  
 514          addFunction(vm, "debug", functionDebug, 1);
 515          addFunction(vm, "describe", functionDescribe, 1);
 516          addFunction(vm, "describeArray", functionDescribeArray, 1);
 517          addFunction(vm, "print", functionPrintStdOut, 1);
 518          addFunction(vm, "printErr", functionPrintStdErr, 1);
 519          addFunction(vm, "quit", functionQuit, 0);
 520          addFunction(vm, "gc", functionGCAndSweep, 0);
 521          addFunction(vm, "fullGC", functionFullGC, 0);
 522          addFunction(vm, "edenGC", functionEdenGC, 0);
 523          addFunction(vm, "gcHeapSize", functionHeapSize, 0);
 524          addFunction(vm, "MemoryFootprint", functionCreateMemoryFootprint, 0);
 525          addFunction(vm, "resetMemoryPeak", functionResetMemoryPeak, 0);
 526          addFunction(vm, "addressOf", functionAddressOf, 1);
 527          addFunction(vm, "version", functionVersion, 1);
 528          addFunction(vm, "run", functionRun, 1);
 529          addFunction(vm, "runString", functionRunString, 1);
 530          addFunction(vm, "load", functionLoad, 1);
 531          addFunction(vm, "loadString", functionLoadString, 1);
 532          addFunction(vm, "readFile", functionReadFile, 2);
 533          addFunction(vm, "read", functionReadFile, 2);
 534          addFunction(vm, "checkSyntax", functionCheckSyntax, 1);
 535          addFunction(vm, "sleepSeconds", functionSleepSeconds, 1);
 536          addFunction(vm, "jscStack", functionJSCStack, 1);
 537          addFunction(vm, "readline", functionReadline, 0);
 538          addFunction(vm, "preciseTime", functionPreciseTime, 0);
 539          addFunction(vm, "neverInlineFunction", functionNeverInlineFunction, 1);
 540          addFunction(vm, "noInline", functionNeverInlineFunction, 1);
 541          addFunction(vm, "noDFG", functionNoDFG, 1);
 542          addFunction(vm, "noFTL", functionNoFTL, 1);
 543          addFunction(vm, "noOSRExitFuzzing", functionNoOSRExitFuzzing, 1);
 544          addFunction(vm, "numberOfDFGCompiles", functionNumberOfDFGCompiles, 1);
 545          addFunction(vm, "callerIsOMGCompiled", functionCallerIsOMGCompiled, 0);
 546          addFunction(vm, "jscOptions", functionJSCOptions, 0);
 547          addFunction(vm, "optimizeNextInvocation", functionOptimizeNextInvocation, 1);
 548          addFunction(vm, "reoptimizationRetryCount", functionReoptimizationRetryCount, 1);
 549          addFunction(vm, "transferArrayBuffer", functionTransferArrayBuffer, 1);
 550          addFunction(vm, "failNextNewCodeBlock", functionFailNextNewCodeBlock, 1);
 551  #if ENABLE(SAMPLING_FLAGS)
 552          addFunction(vm, "setSamplingFlags", functionSetSamplingFlags, 1);
 553          addFunction(vm, "clearSamplingFlags", functionClearSamplingFlags, 1);
 554  #endif
 555  
 556          putDirectNativeFunction(vm, this, Identifier::fromString(vm, "OSRExit"), 0, functionUndefined1, OSRExitIntrinsic, DontEnum);
 557          putDirectNativeFunction(vm, this, Identifier::fromString(vm, "isFinalTier"), 0, functionFalse, IsFinalTierIntrinsic, DontEnum);
 558          putDirectNativeFunction(vm, this, Identifier::fromString(vm, "predictInt32"), 0, functionUndefined2, SetInt32HeapPredictionIntrinsic, DontEnum);
 559          putDirectNativeFunction(vm, this, Identifier::fromString(vm, "isInt32"), 0, functionIsInt32, CheckInt32Intrinsic, DontEnum);
 560          putDirectNativeFunction(vm, this, Identifier::fromString(vm, "isPureNaN"), 0, functionIsPureNaN, CheckInt32Intrinsic, DontEnum);
 561          putDirectNativeFunction(vm, this, Identifier::fromString(vm, "fiatInt52"), 0, functionIdentity, FiatInt52Intrinsic, DontEnum);
 562          
 563          addFunction(vm, "effectful42", functionEffectful42, 0);
 564          addFunction(vm, "makeMasquerader", functionMakeMasquerader, 0);
 565          addFunction(vm, "hasCustomProperties", functionHasCustomProperties, 0);
 566  
 567          addFunction(vm, "createGlobalObject", functionCreateGlobalObject, 0);
 568          addFunction(vm, "createHeapBigInt", functionCreateHeapBigInt, 1);
 569  #if USE(BIGINT32)
 570          addFunction(vm, "createBigInt32", functionCreateBigInt32, 1);
 571  #endif
 572          addFunction(vm, "useBigInt32", functionUseBigInt32, 0);
 573          addFunction(vm, "isBigInt32", functionIsBigInt32, 1);
 574          addFunction(vm, "isHeapBigInt", functionIsHeapBigInt, 1);
 575  
 576          addFunction(vm, "dumpTypesForAllVariables", functionDumpTypesForAllVariables , 0);
 577  
 578          addFunction(vm, "drainMicrotasks", functionDrainMicrotasks, 0);
 579          addFunction(vm, "setTimeout", functionSetTimeout, 2);
 580  
 581          addFunction(vm, "releaseWeakRefs", functionReleaseWeakRefs, 0);
 582          addFunction(vm, "finalizationRegistryLiveCount", functionFinalizationRegistryLiveCount, 0);
 583          addFunction(vm, "finalizationRegistryDeadCount", functionFinalizationRegistryDeadCount, 0);
 584          
 585          addFunction(vm, "getRandomSeed", functionGetRandomSeed, 0);
 586          addFunction(vm, "setRandomSeed", functionSetRandomSeed, 1);
 587          addFunction(vm, "isRope", functionIsRope, 1);
 588          addFunction(vm, "callerSourceOrigin", functionCallerSourceOrigin, 0);
 589  
 590          addFunction(vm, "is32BitPlatform", functionIs32BitPlatform, 0);
 591  
 592          addFunction(vm, "checkModuleSyntax", functionCheckModuleSyntax, 1);
 593  
 594          addFunction(vm, "platformSupportsSamplingProfiler", functionPlatformSupportsSamplingProfiler, 0);
 595          addFunction(vm, "generateHeapSnapshot", functionGenerateHeapSnapshot, 0);
 596          addFunction(vm, "generateHeapSnapshotForGCDebugging", functionGenerateHeapSnapshotForGCDebugging, 0);
 597          addFunction(vm, "resetSuperSamplerState", functionResetSuperSamplerState, 0);
 598          addFunction(vm, "ensureArrayStorage", functionEnsureArrayStorage, 0);
 599  #if ENABLE(SAMPLING_PROFILER)
 600          addFunction(vm, "startSamplingProfiler", functionStartSamplingProfiler, 0);
 601          addFunction(vm, "samplingProfilerStackTraces", functionSamplingProfilerStackTraces, 0);
 602  #endif
 603  
 604          addFunction(vm, "maxArguments", functionMaxArguments, 0);
 605  
 606          addFunction(vm, "asyncTestStart", functionAsyncTestStart, 1);
 607          addFunction(vm, "asyncTestPassed", functionAsyncTestPassed, 1);
 608  
 609  #if ENABLE(WEBASSEMBLY)
 610          addFunction(vm, "WebAssemblyMemoryMode", functionWebAssemblyMemoryMode, 1);
 611  #endif
 612  
 613          if (!arguments.isEmpty()) {
 614              JSArray* array = constructEmptyArray(this, nullptr);
 615              for (size_t i = 0; i < arguments.size(); ++i)
 616                  array->putDirectIndex(this, i, jsString(vm, arguments[i]));
 617              putDirect(vm, Identifier::fromString(vm, "arguments"), array, DontEnum);
 618          }
 619  
 620          putDirect(vm, Identifier::fromString(vm, "console"), jsUndefined(), DontEnum);
 621          
 622          Structure* plainObjectStructure = JSFinalObject::createStructure(vm, this, objectPrototype(), 0);
 623          
 624          JSObject* dollar = JSFinalObject::create(vm, plainObjectStructure);
 625          putDirect(vm, Identifier::fromString(vm, "$"), dollar, DontEnum);
 626          putDirect(vm, Identifier::fromString(vm, "$262"), dollar, DontEnum);
 627          
 628          addFunction(vm, dollar, "createRealm", functionDollarCreateRealm, 0);
 629          addFunction(vm, dollar, "detachArrayBuffer", functionTransferArrayBuffer, 1);
 630          addFunction(vm, dollar, "evalScript", functionDollarEvalScript, 1);
 631          
 632          dollar->putDirect(vm, Identifier::fromString(vm, "global"), this, DontEnum);
 633          dollar->putDirectCustomAccessor(vm, Identifier::fromString(vm, "IsHTMLDDA"),
 634              CustomGetterSetter::create(vm, accessorMakeMasquerader, nullptr),
 635              static_cast<unsigned>(PropertyAttribute::CustomValue)
 636          );
 637  
 638          JSObject* agent = JSFinalObject::create(vm, plainObjectStructure);
 639          dollar->putDirect(vm, Identifier::fromString(vm, "agent"), agent, DontEnum);
 640          
 641          // The test262 INTERPRETING.md document says that some of these functions are just in the main
 642          // thread and some are in the other threads. We just put them in all threads.
 643          addFunction(vm, agent, "start", functionDollarAgentStart, 1);
 644          addFunction(vm, agent, "receiveBroadcast", functionDollarAgentReceiveBroadcast, 1);
 645          addFunction(vm, agent, "report", functionDollarAgentReport, 1);
 646          addFunction(vm, agent, "sleep", functionDollarAgentSleep, 1);
 647          addFunction(vm, agent, "broadcast", functionDollarAgentBroadcast, 1);
 648          addFunction(vm, agent, "getReport", functionDollarAgentGetReport, 0);
 649          addFunction(vm, agent, "leaving", functionDollarAgentLeaving, 0);
 650          addFunction(vm, agent, "monotonicNow", functionDollarAgentMonotonicNow, 0);
 651  
 652          addFunction(vm, "waitForReport", functionWaitForReport, 0);
 653  
 654          addFunction(vm, "heapCapacity", functionHeapCapacity, 0);
 655          addFunction(vm, "flashHeapAccess", functionFlashHeapAccess, 0);
 656  
 657          addFunction(vm, "disableRichSourceInfo", functionDisableRichSourceInfo, 0);
 658          addFunction(vm, "mallocInALoop", functionMallocInALoop, 0);
 659          addFunction(vm, "totalCompileTime", functionTotalCompileTime, 0);
 660  
 661          addFunction(vm, "setUnhandledRejectionCallback", functionSetUnhandledRejectionCallback, 1);
 662  
 663          addFunction(vm, "asDoubleNumber", functionAsDoubleNumber, 1);
 664  
 665          addFunction(vm, "dropAllLocks", functionDropAllLocks, 1);
 666  
 667          if (Options::exposeCustomSettersOnGlobalObjectForTesting()) {
 668              {
 669                  CustomGetterSetter* custom = CustomGetterSetter::create(vm, nullptr, testCustomAccessorSetter);
 670                  Identifier identifier = Identifier::fromString(vm, "testCustomAccessorSetter");
 671                  this->putDirectCustomAccessor(vm, identifier, custom, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::CustomAccessor);
 672              }
 673  
 674              {
 675                  CustomGetterSetter* custom = CustomGetterSetter::create(vm, nullptr, testCustomValueSetter);
 676                  Identifier identifier = Identifier::fromString(vm, "testCustomValueSetter");
 677                  this->putDirectCustomAccessor(vm, identifier, custom, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::CustomValue);
 678              }
 679          }
 680      }
 681  
 682  public:
 683      static bool testCustomSetterImpl(JSGlobalObject* lexicalGlobalObject, GlobalObject* thisObject, EncodedJSValue encodedValue, const char* propertyName)
 684      {
 685          VM& vm = lexicalGlobalObject->vm();
 686  
 687          Identifier identifier = Identifier::fromString(vm, propertyName);
 688          thisObject->putDirect(vm, identifier, JSValue::decode(encodedValue), DontEnum);
 689  
 690          return true;
 691      }
 692  
 693  private:
 694      void addFunction(VM& vm, JSObject* object, const char* name, NativeFunction function, unsigned arguments)
 695      {
 696          Identifier identifier = Identifier::fromString(vm, name);
 697          object->putDirect(vm, identifier, JSFunction::create(vm, this, arguments, identifier.string(), function), DontEnum);
 698      }
 699  
 700      void addFunction(VM& vm, const char* name, NativeFunction function, unsigned arguments)
 701      {
 702          addFunction(vm, this, name, function, arguments);
 703      }
 704      
 705      static JSInternalPromise* moduleLoaderImportModule(JSGlobalObject*, JSModuleLoader*, JSString*, JSValue, const SourceOrigin&);
 706      static Identifier moduleLoaderResolve(JSGlobalObject*, JSModuleLoader*, JSValue, JSValue, JSValue);
 707      static JSInternalPromise* moduleLoaderFetch(JSGlobalObject*, JSModuleLoader*, JSValue, JSValue, JSValue);
 708      static JSObject* moduleLoaderCreateImportMetaProperties(JSGlobalObject*, JSModuleLoader*, JSValue, JSModuleRecord*, JSValue);
 709  
 710      static void reportUncaughtExceptionAtEventLoop(JSGlobalObject*, Exception*);
 711  };
 712  STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(GlobalObject, JSGlobalObject);
 713  
 714  static bool supportsRichSourceInfo = true;
 715  static bool shellSupportsRichSourceInfo(const JSGlobalObject*)
 716  {
 717      return supportsRichSourceInfo;
 718  }
 719  
 720  const ClassInfo GlobalObject::s_info = { "global", &JSGlobalObject::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(GlobalObject) };
 721  const GlobalObjectMethodTable GlobalObject::s_globalObjectMethodTable = {
 722      &shellSupportsRichSourceInfo,
 723      &shouldInterruptScript,
 724      &javaScriptRuntimeFlags,
 725      nullptr, // queueTaskToEventLoop
 726      &shouldInterruptScriptBeforeTimeout,
 727      &moduleLoaderImportModule,
 728      &moduleLoaderResolve,
 729      &moduleLoaderFetch,
 730      &moduleLoaderCreateImportMetaProperties,
 731      nullptr, // moduleLoaderEvaluate
 732      nullptr, // promiseRejectionTracker
 733      &reportUncaughtExceptionAtEventLoop,
 734      &currentScriptExecutionOwner,
 735      &scriptExecutionStatus,
 736      nullptr, // defaultLanguage
 737      nullptr, // compileStreaming
 738      nullptr, // instantinateStreaming
 739  };
 740  
 741  GlobalObject::GlobalObject(VM& vm, Structure* structure)
 742      : JSGlobalObject(vm, structure, &s_globalObjectMethodTable)
 743  {
 744  }
 745  
 746  JSC_DEFINE_CUSTOM_SETTER(testCustomAccessorSetter, (JSGlobalObject* lexicalGlobalObject, EncodedJSValue thisValue, EncodedJSValue encodedValue))
 747  {
 748      VM& vm = lexicalGlobalObject->vm();
 749      RELEASE_ASSERT(JSValue::decode(thisValue).isCell());
 750      JSCell* thisCell = JSValue::decode(thisValue).asCell();
 751      RELEASE_ASSERT(thisCell->type() == PureForwardingProxyType);
 752      GlobalObject* thisObject = jsDynamicCast<GlobalObject*>(vm, jsCast<JSProxy*>(thisCell)->target());
 753      RELEASE_ASSERT(thisObject);
 754      return GlobalObject::testCustomSetterImpl(lexicalGlobalObject, thisObject, encodedValue, "_testCustomAccessorSetter");
 755  }
 756  
 757  JSC_DEFINE_CUSTOM_SETTER(testCustomValueSetter, (JSGlobalObject* lexicalGlobalObject, EncodedJSValue thisValue, EncodedJSValue encodedValue))
 758  {
 759      VM& vm = lexicalGlobalObject->vm();
 760      RELEASE_ASSERT(JSValue::decode(thisValue).isCell());
 761      JSCell* thisCell = JSValue::decode(thisValue).asCell();
 762      GlobalObject* thisObject = jsDynamicCast<GlobalObject*>(vm, thisCell);
 763      RELEASE_ASSERT(thisObject);
 764      return GlobalObject::testCustomSetterImpl(lexicalGlobalObject, thisObject, encodedValue, "_testCustomValueSetter");
 765  }
 766  
 767  static UChar pathSeparator()
 768  {
 769  #if OS(WINDOWS)
 770      return '\\';
 771  #else
 772      return '/';
 773  #endif
 774  }
 775  
 776  static URL currentWorkingDirectory()
 777  {
 778  #if OS(WINDOWS)
 779      // https://msdn.microsoft.com/en-us/library/windows/desktop/aa364934.aspx
 780      // https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247.aspx#maxpath
 781      // The _MAX_PATH in Windows is 260. If the path of the current working directory is longer than that, _getcwd truncates the result.
 782      // And other I/O functions taking a path name also truncate it. To avoid this situation,
 783      //
 784      // (1). When opening the file in Windows for modules, we always use the abosolute path and add "\\?\" prefix to the path name.
 785      // (2). When retrieving the current working directory, use GetCurrentDirectory instead of _getcwd.
 786      //
 787      // In the path utility functions inside the JSC shell, we does not handle the UNC and UNCW including the network host name.
 788      DWORD bufferLength = ::GetCurrentDirectoryW(0, nullptr);
 789      if (!bufferLength)
 790          return { };
 791      // In Windows, wchar_t is the UTF-16LE.
 792      // https://msdn.microsoft.com/en-us/library/dd374081.aspx
 793      // https://msdn.microsoft.com/en-us/library/windows/desktop/ff381407.aspx
 794      Vector<wchar_t> buffer(bufferLength);
 795      DWORD lengthNotIncludingNull = ::GetCurrentDirectoryW(bufferLength, buffer.data());
 796      String directoryString(buffer.data(), lengthNotIncludingNull);
 797      // We don't support network path like \\host\share\<path name>.
 798      if (directoryString.startsWith("\\\\"))
 799          return { };
 800  
 801  #else
 802      Vector<char> buffer(PATH_MAX);
 803      if (!getcwd(buffer.data(), PATH_MAX))
 804          return { };
 805      String directoryString = String::fromUTF8(buffer.data());
 806  #endif
 807      if (directoryString.isEmpty())
 808          return { };
 809  
 810      // Add a trailing slash if needed so the URL resolves to a directory and not a file.
 811      if (directoryString[directoryString.length() - 1] != pathSeparator())
 812          directoryString = makeString(directoryString, pathSeparator());
 813  
 814      return URL::fileURLWithFileSystemPath(directoryString);
 815  }
 816  
 817  static URL absolutePath(const String& fileName)
 818  {
 819      auto directoryName = currentWorkingDirectory();
 820      if (!directoryName.isValid())
 821          return URL::fileURLWithFileSystemPath(fileName);
 822  
 823      return URL(directoryName, fileName);
 824  }
 825  
 826  JSInternalPromise* GlobalObject::moduleLoaderImportModule(JSGlobalObject* globalObject, JSModuleLoader*, JSString* moduleNameValue, JSValue parameters, const SourceOrigin& sourceOrigin)
 827  {
 828      VM& vm = globalObject->vm();
 829      auto throwScope = DECLARE_THROW_SCOPE(vm);
 830  
 831      auto* promise = JSInternalPromise::create(vm, globalObject->internalPromiseStructure());
 832  
 833      auto catchScope = DECLARE_CATCH_SCOPE(vm);
 834  
 835      auto rejectWithError = [&](JSValue error) {
 836          promise->reject(globalObject, error);
 837          return promise;
 838      };
 839  
 840      auto reject = [&](Exception* exception) {
 841          if (UNLIKELY(isTerminatedExecutionException(vm, exception)))
 842              return promise;
 843          JSValue error = exception->value();
 844          catchScope.clearException();
 845          return rejectWithError(error);
 846      };
 847  
 848      auto referrer = sourceOrigin.url();
 849      auto specifier = moduleNameValue->value(globalObject);
 850      RETURN_IF_EXCEPTION(throwScope, nullptr);
 851      if (UNLIKELY(catchScope.exception()))
 852          return reject(catchScope.exception());
 853  
 854      if (!referrer.isLocalFile())
 855          return rejectWithError(createError(globalObject, makeString("Could not resolve the referrer's path '", referrer.string(), "', while trying to resolve module '", specifier, "'.")));
 856  
 857      if (!specifier.startsWith('/') && !specifier.startsWith("./") && !specifier.startsWith("../"))
 858          return rejectWithError(createTypeError(globalObject, makeString("Module specifier, '"_s, specifier, "' does not start with \"/\", \"./\", or \"../\". Referenced from: "_s, referrer.fileSystemPath())));
 859  
 860      URL moduleURL(referrer, specifier);
 861      if (!moduleURL.isLocalFile())
 862          return rejectWithError(createError(globalObject, makeString("Module url, '", moduleURL.string(), "' does not map to a local file.")));
 863  
 864      auto result = JSC::importModule(globalObject, Identifier::fromString(vm, moduleURL.string()), parameters, jsUndefined());
 865      if (UNLIKELY(catchScope.exception()))
 866          return reject(catchScope.exception());
 867      return result;
 868  }
 869  
 870  Identifier GlobalObject::moduleLoaderResolve(JSGlobalObject* globalObject, JSModuleLoader*, JSValue keyValue, JSValue referrerValue, JSValue)
 871  {
 872      VM& vm = globalObject->vm();
 873      auto scope = DECLARE_THROW_SCOPE(vm);
 874  
 875      scope.releaseAssertNoException();
 876      const Identifier key = keyValue.toPropertyKey(globalObject);
 877      RETURN_IF_EXCEPTION(scope, { });
 878  
 879      if (key.isSymbol())
 880          return key;
 881  
 882      auto resolvePath = [&] (const URL& directoryURL) -> Identifier {
 883          String specifier = key.impl();
 884          if (!specifier.startsWith('/') && !specifier.startsWith("./") && !specifier.startsWith("../")) {
 885              throwTypeError(globalObject, scope, makeString("Module specifier, '"_s, specifier, "' does not start with \"/\", \"./\", or \"../\". Referenced from: "_s, directoryURL.fileSystemPath()));
 886              return { };
 887          }
 888  
 889          if (!directoryURL.isLocalFile()) {
 890              throwException(globalObject, scope, createError(globalObject, makeString("Could not resolve the referrer's path: ", directoryURL.string())));
 891              return { };
 892          }
 893  
 894          URL resolvedURL(directoryURL, specifier);
 895          if (!resolvedURL.isValid()) {
 896              throwException(globalObject, scope, createError(globalObject, makeString("Resolved module url is not valid: ", resolvedURL.string())));
 897              return { };
 898          }
 899          ASSERT(resolvedURL.isLocalFile());
 900  
 901          return Identifier::fromString(vm, resolvedURL.string());
 902      };
 903  
 904      if (referrerValue.isUndefined())
 905          return resolvePath(currentWorkingDirectory());
 906  
 907      const Identifier referrer = referrerValue.toPropertyKey(globalObject);
 908      RETURN_IF_EXCEPTION(scope, { });
 909  
 910      if (referrer.isSymbol())
 911          return resolvePath(currentWorkingDirectory());
 912  
 913      // If the referrer exists, we assume that the referrer is the correct file url.
 914      URL url = URL({ }, referrer.impl());
 915      ASSERT(url.isLocalFile());
 916      return resolvePath(url);
 917  }
 918  
 919  template<typename Vector>
 920  static void convertShebangToJSComment(Vector& buffer)
 921  {
 922      if (buffer.size() >= 2) {
 923          if (buffer[0] == '#' && buffer[1] == '!')
 924              buffer[0] = buffer[1] = '/';
 925      }
 926  }
 927  
 928  static RefPtr<Uint8Array> fillBufferWithContentsOfFile(FILE* file)
 929  {
 930      if (fseek(file, 0, SEEK_END) == -1)
 931          return nullptr;
 932      long bufferCapacity = ftell(file);
 933      if (bufferCapacity == -1)
 934          return nullptr;
 935      if (fseek(file, 0, SEEK_SET) == -1)
 936          return nullptr;
 937      auto result = Uint8Array::tryCreate(bufferCapacity);
 938      if (!result)
 939          return nullptr;
 940      size_t readSize = fread(result->data(), 1, bufferCapacity, file);
 941      if (readSize != static_cast<size_t>(bufferCapacity))
 942          return nullptr;
 943      return result;
 944  }
 945  
 946  static RefPtr<Uint8Array> fillBufferWithContentsOfFile(const String& fileName)
 947  {
 948      FILE* f = fopen(fileName.utf8().data(), "rb");
 949      if (!f) {
 950          fprintf(stderr, "Could not open file: %s\n", fileName.utf8().data());
 951          return nullptr;
 952      }
 953  
 954      RefPtr<Uint8Array> result = fillBufferWithContentsOfFile(f);
 955      fclose(f);
 956  
 957      return result;
 958  }
 959  
 960  template<typename Vector>
 961  static bool fillBufferWithContentsOfFile(FILE* file, Vector& buffer)
 962  {
 963      // We might have injected "use strict"; at the top.
 964      size_t initialSize = buffer.size();
 965      if (fseek(file, 0, SEEK_END) == -1)
 966          return false;
 967      long bufferCapacity = ftell(file);
 968      if (bufferCapacity == -1)
 969          return false;
 970      if (fseek(file, 0, SEEK_SET) == -1)
 971          return false;
 972      buffer.resize(bufferCapacity + initialSize);
 973      size_t readSize = fread(buffer.data() + initialSize, 1, buffer.size(), file);
 974      return readSize == buffer.size() - initialSize;
 975  }
 976  
 977  static bool fillBufferWithContentsOfFile(const String& fileName, Vector<char>& buffer)
 978  {
 979      FILE* f = fopen(fileName.utf8().data(), "rb");
 980      if (!f) {
 981          fprintf(stderr, "Could not open file: %s\n", fileName.utf8().data());
 982          return false;
 983      }
 984  
 985      bool result = fillBufferWithContentsOfFile(f, buffer);
 986      fclose(f);
 987  
 988      return result;
 989  }
 990  
 991  static bool fetchScriptFromLocalFileSystem(const String& fileName, Vector<char>& buffer)
 992  {
 993      if (!fillBufferWithContentsOfFile(fileName, buffer))
 994          return false;
 995      convertShebangToJSComment(buffer);
 996      return true;
 997  }
 998  
 999  class ShellSourceProvider final : public StringSourceProvider {
1000  public:
1001      static Ref<ShellSourceProvider> create(const String& source, const SourceOrigin& sourceOrigin, String&& sourceURL, const TextPosition& startPosition, SourceProviderSourceType sourceType)
1002      {
1003          return adoptRef(*new ShellSourceProvider(source, sourceOrigin, WTFMove(sourceURL), startPosition, sourceType));
1004      }
1005  
1006      ~ShellSourceProvider() final
1007      {
1008          commitCachedBytecode();
1009      }
1010  
1011      RefPtr<CachedBytecode> cachedBytecode() const final
1012      {
1013          if (!m_cachedBytecode)
1014              loadBytecode();
1015          return m_cachedBytecode.copyRef();
1016      }
1017  
1018      void updateCache(const UnlinkedFunctionExecutable* executable, const SourceCode&, CodeSpecializationKind kind, const UnlinkedFunctionCodeBlock* codeBlock) const final
1019      {
1020          if (!cacheEnabled() || !m_cachedBytecode)
1021              return;
1022          BytecodeCacheError error;
1023          RefPtr<CachedBytecode> cachedBytecode = encodeFunctionCodeBlock(executable->vm(), codeBlock, error);
1024          if (cachedBytecode && !error.isValid())
1025              m_cachedBytecode->addFunctionUpdate(executable, kind, *cachedBytecode);
1026      }
1027  
1028      void cacheBytecode(const BytecodeCacheGenerator& generator) const final
1029      {
1030          if (!cacheEnabled())
1031              return;
1032          if (!m_cachedBytecode)
1033              m_cachedBytecode = CachedBytecode::create();
1034          auto update = generator();
1035          if (update)
1036              m_cachedBytecode->addGlobalUpdate(*update);
1037      }
1038  
1039      void commitCachedBytecode() const final
1040      {
1041          if (!cacheEnabled() || !m_cachedBytecode || !m_cachedBytecode->hasUpdates())
1042              return;
1043  
1044          auto clearBytecode = makeScopeExit([&] {
1045              m_cachedBytecode = nullptr;
1046          });
1047  
1048          String filename = cachePath();
1049          auto fd = FileSystem::openAndLockFile(filename, FileSystem::FileOpenMode::Write, {FileSystem::FileLockMode::Exclusive, FileSystem::FileLockMode::Nonblocking});
1050          if (!FileSystem::isHandleValid(fd))
1051              return;
1052  
1053          auto closeFD = makeScopeExit([&] {
1054              FileSystem::unlockAndCloseFile(fd);
1055          });
1056  
1057          long long fileSize;
1058          if (!FileSystem::getFileSize(fd, fileSize))
1059              return;
1060  
1061          size_t cacheFileSize;
1062          if (!WTF::convertSafely(fileSize, cacheFileSize) || cacheFileSize != m_cachedBytecode->size()) {
1063              // The bytecode cache has already been updated
1064              return;
1065          }
1066  
1067          if (!FileSystem::truncateFile(fd, m_cachedBytecode->sizeForUpdate()))
1068              return;
1069  
1070          m_cachedBytecode->commitUpdates([&] (off_t offset, const void* data, size_t size) {
1071              long long result = FileSystem::seekFile(fd, offset, FileSystem::FileSeekOrigin::Beginning);
1072              ASSERT_UNUSED(result, result != -1);
1073              size_t bytesWritten = static_cast<size_t>(FileSystem::writeToFile(fd, static_cast<const char*>(data), size));
1074              ASSERT_UNUSED(bytesWritten, bytesWritten == size);
1075          });
1076      }
1077  
1078  private:
1079      String cachePath() const
1080      {
1081          if (!cacheEnabled())
1082              return static_cast<const char*>(nullptr);
1083          const char* cachePath = Options::diskCachePath();
1084          String filename = FileSystem::encodeForFileName(FileSystem::lastComponentOfPathIgnoringTrailingSlash(sourceOrigin().url().fileSystemPath()));
1085          return FileSystem::pathByAppendingComponent(cachePath, makeString(source().toString().hash(), '-', filename, ".bytecode-cache"));
1086      }
1087  
1088      void loadBytecode() const
1089      {
1090          if (!cacheEnabled())
1091              return;
1092  
1093          String filename = cachePath();
1094          if (filename.isNull())
1095              return;
1096  
1097          auto fd = FileSystem::openAndLockFile(filename, FileSystem::FileOpenMode::Read, {FileSystem::FileLockMode::Shared, FileSystem::FileLockMode::Nonblocking});
1098          if (!FileSystem::isHandleValid(fd))
1099              return;
1100  
1101          auto closeFD = makeScopeExit([&] {
1102              FileSystem::unlockAndCloseFile(fd);
1103          });
1104  
1105          bool success;
1106          FileSystem::MappedFileData mappedFileData(fd, FileSystem::MappedFileMode::Private, success);
1107  
1108          if (!success)
1109              return;
1110  
1111          m_cachedBytecode = CachedBytecode::create(WTFMove(mappedFileData));
1112      }
1113  
1114      ShellSourceProvider(const String& source, const SourceOrigin& sourceOrigin, String&& sourceURL, const TextPosition& startPosition, SourceProviderSourceType sourceType)
1115          : StringSourceProvider(source, sourceOrigin, WTFMove(sourceURL), startPosition, sourceType)
1116      {
1117      }
1118  
1119      static bool cacheEnabled()
1120      {
1121          static bool enabled = !!Options::diskCachePath();
1122          return enabled;
1123      }
1124  
1125      mutable RefPtr<CachedBytecode> m_cachedBytecode;
1126  };
1127  
1128  static inline SourceCode jscSource(const String& source, const SourceOrigin& sourceOrigin, String sourceURL = String(), const TextPosition& startPosition = TextPosition(), SourceProviderSourceType sourceType = SourceProviderSourceType::Program)
1129  {
1130      return SourceCode(ShellSourceProvider::create(source, sourceOrigin, WTFMove(sourceURL), startPosition, sourceType), startPosition.m_line.oneBasedInt(), startPosition.m_column.oneBasedInt());
1131  }
1132  
1133  template<typename Vector>
1134  static inline SourceCode jscSource(const Vector& utf8, const SourceOrigin& sourceOrigin, const String& filename)
1135  {
1136      // FIXME: This should use an absolute file URL https://bugs.webkit.org/show_bug.cgi?id=193077
1137      String str = stringFromUTF(utf8);
1138      return jscSource(str, sourceOrigin, filename);
1139  }
1140  
1141  template<typename Vector>
1142  static bool fetchModuleFromLocalFileSystem(const URL& fileURL, Vector& buffer)
1143  {
1144      String fileName = fileURL.fileSystemPath();
1145  #if OS(WINDOWS)
1146      // https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247.aspx#maxpath
1147      // Use long UNC to pass the long path name to the Windows APIs.
1148      auto pathName = makeString("\\\\?\\", fileName).wideCharacters();
1149      struct _stat status { };
1150      if (_wstat(pathName.data(), &status))
1151          return false;
1152      if ((status.st_mode & S_IFMT) != S_IFREG)
1153          return false;
1154  
1155      FILE* f = _wfopen(pathName.data(), L"rb");
1156  #else
1157      auto pathName = fileName.utf8();
1158      struct stat status { };
1159      if (stat(pathName.data(), &status))
1160          return false;
1161      if ((status.st_mode & S_IFMT) != S_IFREG)
1162          return false;
1163  
1164      FILE* f = fopen(pathName.data(), "r");
1165  #endif
1166      if (!f) {
1167          fprintf(stderr, "Could not open file: %s\n", fileName.utf8().data());
1168          return false;
1169      }
1170  
1171      bool result = fillBufferWithContentsOfFile(f, buffer);
1172      if (result)
1173          convertShebangToJSComment(buffer);
1174      fclose(f);
1175  
1176      return result;
1177  }
1178  
1179  JSInternalPromise* GlobalObject::moduleLoaderFetch(JSGlobalObject* globalObject, JSModuleLoader*, JSValue key, JSValue, JSValue)
1180  {
1181      VM& vm = globalObject->vm();
1182      JSInternalPromise* promise = JSInternalPromise::create(vm, globalObject->internalPromiseStructure());
1183  
1184      auto catchScope = DECLARE_CATCH_SCOPE(vm);
1185  
1186      auto rejectWithError = [&](JSValue error) {
1187          promise->reject(globalObject, error);
1188          return promise;
1189      };
1190  
1191      auto reject = [&](Exception* exception) {
1192          if (UNLIKELY(isTerminatedExecutionException(vm, exception)))
1193              return promise;
1194          JSValue error = exception->value();
1195          catchScope.clearException();
1196          return rejectWithError(error);
1197      };
1198  
1199      String moduleKey = key.toWTFString(globalObject);
1200      if (UNLIKELY(catchScope.exception()))
1201          return reject(catchScope.exception());
1202  
1203      URL moduleURL({ }, moduleKey);
1204      ASSERT(moduleURL.isLocalFile());
1205      // Strip the URI from our key so Errors print canonical system paths.
1206      moduleKey = moduleURL.fileSystemPath();
1207  
1208      Vector<uint8_t> buffer;
1209      if (!fetchModuleFromLocalFileSystem(moduleURL, buffer))
1210          return rejectWithError(createError(globalObject, makeString("Could not open file '", moduleKey, "'.")));
1211  
1212  #if ENABLE(WEBASSEMBLY)
1213      // FileSystem does not have mime-type header. The JSC shell recognizes WebAssembly's magic header.
1214      if (buffer.size() >= 4) {
1215          if (buffer[0] == '\0' && buffer[1] == 'a' && buffer[2] == 's' && buffer[3] == 'm') {
1216              auto source = SourceCode(WebAssemblySourceProvider::create(WTFMove(buffer), SourceOrigin { moduleURL }, WTFMove(moduleKey)));
1217              catchScope.releaseAssertNoException();
1218              auto sourceCode = JSSourceCode::create(vm, WTFMove(source));
1219              catchScope.releaseAssertNoException();
1220              promise->resolve(globalObject, sourceCode);
1221              return promise;
1222          }
1223      }
1224  #endif
1225  
1226      auto sourceCode = JSSourceCode::create(vm, jscSource(stringFromUTF(buffer), SourceOrigin { moduleURL }, WTFMove(moduleKey), TextPosition(), SourceProviderSourceType::Module));
1227      catchScope.releaseAssertNoException();
1228      promise->resolve(globalObject, sourceCode);
1229      return promise;
1230  }
1231  
1232  JSObject* GlobalObject::moduleLoaderCreateImportMetaProperties(JSGlobalObject* globalObject, JSModuleLoader*, JSValue key, JSModuleRecord*, JSValue)
1233  {
1234      VM& vm = globalObject->vm();
1235      auto scope = DECLARE_THROW_SCOPE(vm);
1236  
1237      JSObject* metaProperties = constructEmptyObject(vm, globalObject->nullPrototypeObjectStructure());
1238      RETURN_IF_EXCEPTION(scope, nullptr);
1239  
1240      metaProperties->putDirect(vm, Identifier::fromString(vm, "filename"), key);
1241      RETURN_IF_EXCEPTION(scope, nullptr);
1242  
1243      return metaProperties;
1244  }
1245  
1246  static CString cStringFromViewWithString(JSGlobalObject* globalObject, ThrowScope& scope, StringViewWithUnderlyingString& viewWithString)
1247  {
1248      Expected<CString, UTF8ConversionError> expectedString = viewWithString.view.tryGetUtf8();
1249      if (expectedString)
1250          return expectedString.value();
1251      switch (expectedString.error()) {
1252      case UTF8ConversionError::OutOfMemory:
1253          throwOutOfMemoryError(globalObject, scope);
1254          break;
1255      case UTF8ConversionError::IllegalSource:
1256          scope.throwException(globalObject, createError(globalObject, "Illegal source encountered during UTF8 conversion"));
1257          break;
1258      case UTF8ConversionError::SourceExhausted:
1259          scope.throwException(globalObject, createError(globalObject, "Source exhausted during UTF8 conversion"));
1260          break;
1261      default:
1262          RELEASE_ASSERT_NOT_REACHED();
1263      }
1264      return { };
1265  }
1266  
1267  static EncodedJSValue printInternal(JSGlobalObject* globalObject, CallFrame* callFrame, FILE* out)
1268  {
1269      VM& vm = globalObject->vm();
1270      auto scope = DECLARE_THROW_SCOPE(vm);
1271  
1272      if (asyncTestExpectedPasses) {
1273          JSValue value = callFrame->argument(0);
1274          if (value.isString() && WTF::equal(asString(value)->value(globalObject).impl(), "Test262:AsyncTestComplete")) {
1275              asyncTestPasses++;
1276              return JSValue::encode(jsUndefined());
1277          }
1278      }
1279  
1280      for (unsigned i = 0; i < callFrame->argumentCount(); ++i) {
1281          if (i)
1282              if (EOF == fputc(' ', out))
1283                  goto fail;
1284  
1285          auto* jsString = callFrame->uncheckedArgument(i).toString(globalObject);
1286          RETURN_IF_EXCEPTION(scope, { });
1287          auto viewWithString = jsString->viewWithUnderlyingString(globalObject);
1288          RETURN_IF_EXCEPTION(scope, { });
1289          auto string = cStringFromViewWithString(globalObject, scope, viewWithString);
1290          RETURN_IF_EXCEPTION(scope, { });
1291          fwrite(string.data(), sizeof(char), string.length(), out);
1292          if (ferror(out))
1293              goto fail;
1294      }
1295  
1296      fputc('\n', out);
1297  fail:
1298      fflush(out);
1299      return JSValue::encode(jsUndefined());
1300  }
1301  
1302  JSC_DEFINE_HOST_FUNCTION(functionPrintStdOut, (JSGlobalObject* globalObject, CallFrame* callFrame))
1303  {
1304      return printInternal(globalObject, callFrame, stdout);
1305  }
1306  
1307  JSC_DEFINE_HOST_FUNCTION(functionPrintStdErr, (JSGlobalObject* globalObject, CallFrame* callFrame))
1308  {
1309      return printInternal(globalObject, callFrame, stderr);
1310  }
1311  
1312  JSC_DEFINE_HOST_FUNCTION(functionDebug, (JSGlobalObject* globalObject, CallFrame* callFrame))
1313  {
1314      VM& vm = globalObject->vm();
1315      auto scope = DECLARE_THROW_SCOPE(vm);
1316      auto* jsString = callFrame->argument(0).toString(globalObject);
1317      RETURN_IF_EXCEPTION(scope, { });
1318      auto viewWithString = jsString->viewWithUnderlyingString(globalObject);
1319      RETURN_IF_EXCEPTION(scope, { });
1320      auto string = cStringFromViewWithString(globalObject, scope, viewWithString);
1321      RETURN_IF_EXCEPTION(scope, { });
1322      fputs("--> ", stderr);
1323      fwrite(string.data(), sizeof(char), string.length(), stderr);
1324      fputc('\n', stderr);
1325      return JSValue::encode(jsUndefined());
1326  }
1327  
1328  JSC_DEFINE_HOST_FUNCTION(functionDescribe, (JSGlobalObject* globalObject, CallFrame* callFrame))
1329  {
1330      VM& vm = globalObject->vm();
1331      if (callFrame->argumentCount() < 1)
1332          return JSValue::encode(jsUndefined());
1333      return JSValue::encode(jsString(vm, toString(callFrame->argument(0))));
1334  }
1335  
1336  JSC_DEFINE_HOST_FUNCTION(functionDescribeArray, (JSGlobalObject* globalObject, CallFrame* callFrame))
1337  {
1338      if (callFrame->argumentCount() < 1)
1339          return JSValue::encode(jsUndefined());
1340      VM& vm = globalObject->vm();
1341      JSObject* object = jsDynamicCast<JSObject*>(vm, callFrame->argument(0));
1342      if (!object)
1343          return JSValue::encode(jsNontrivialString(vm, "<not object>"_s));
1344      return JSValue::encode(jsNontrivialString(vm, toString("<Butterfly: ", RawPointer(object->butterfly()), "; public length: ", object->getArrayLength(), "; vector length: ", object->getVectorLength(), ">")));
1345  }
1346  
1347  JSC_DEFINE_HOST_FUNCTION(functionSleepSeconds, (JSGlobalObject* globalObject, CallFrame* callFrame))
1348  {
1349      VM& vm = globalObject->vm();
1350      auto scope = DECLARE_THROW_SCOPE(vm);
1351  
1352      if (callFrame->argumentCount() >= 1) {
1353          Seconds seconds = Seconds(callFrame->argument(0).toNumber(globalObject));
1354          RETURN_IF_EXCEPTION(scope, encodedJSValue());
1355          sleep(seconds);
1356      }
1357      
1358      return JSValue::encode(jsUndefined());
1359  }
1360  
1361  class FunctionJSCStackFunctor {
1362  public:
1363      FunctionJSCStackFunctor(StringBuilder& trace)
1364          : m_trace(trace)
1365      {
1366      }
1367  
1368      StackVisitor::Status operator()(StackVisitor& visitor) const
1369      {
1370          m_trace.append(makeString("    ", visitor->index(), "   ", visitor->toString(), '\n'));
1371          return StackVisitor::Continue;
1372      }
1373  
1374  private:
1375      StringBuilder& m_trace;
1376  };
1377  
1378  JSC_DEFINE_HOST_FUNCTION(functionJSCStack, (JSGlobalObject* globalObject, CallFrame* callFrame))
1379  {
1380      VM& vm = globalObject->vm();
1381      StringBuilder trace;
1382      trace.appendLiteral("--> Stack trace:\n");
1383  
1384      FunctionJSCStackFunctor functor(trace);
1385      callFrame->iterate(vm, functor);
1386      fprintf(stderr, "%s", trace.toString().utf8().data());
1387      return JSValue::encode(jsUndefined());
1388  }
1389  
1390  JSC_DEFINE_HOST_FUNCTION(functionGCAndSweep, (JSGlobalObject* globalObject, CallFrame*))
1391  {
1392      VM& vm = globalObject->vm();
1393      JSLockHolder lock(vm);
1394      vm.heap.collectNow(Sync, CollectionScope::Full);
1395      return JSValue::encode(jsNumber(vm.heap.sizeAfterLastFullCollection()));
1396  }
1397  
1398  JSC_DEFINE_HOST_FUNCTION(functionFullGC, (JSGlobalObject* globalObject, CallFrame*))
1399  {
1400      VM& vm = globalObject->vm();
1401      JSLockHolder lock(vm);
1402      vm.heap.collectSync(CollectionScope::Full);
1403      return JSValue::encode(jsNumber(vm.heap.sizeAfterLastFullCollection()));
1404  }
1405  
1406  JSC_DEFINE_HOST_FUNCTION(functionEdenGC, (JSGlobalObject* globalObject, CallFrame*))
1407  {
1408      VM& vm = globalObject->vm();
1409      JSLockHolder lock(vm);
1410      vm.heap.collectSync(CollectionScope::Eden);
1411      return JSValue::encode(jsNumber(vm.heap.sizeAfterLastEdenCollection()));
1412  }
1413  
1414  JSC_DEFINE_HOST_FUNCTION(functionHeapSize, (JSGlobalObject* globalObject, CallFrame*))
1415  {
1416      VM& vm = globalObject->vm();
1417      JSLockHolder lock(vm);
1418      return JSValue::encode(jsNumber(vm.heap.size()));
1419  }
1420  
1421  class JSCMemoryFootprint : public JSDestructibleObject {
1422      using Base = JSDestructibleObject;
1423  public:
1424      template<typename CellType, SubspaceAccess>
1425      static CompleteSubspace* subspaceFor(VM& vm)
1426      {
1427          return &vm.destructibleObjectSpace;
1428      }
1429  
1430      JSCMemoryFootprint(VM& vm, Structure* structure)
1431          : Base(vm, structure)
1432      { }
1433  
1434      static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
1435      {
1436          return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
1437      }
1438  
1439      static JSCMemoryFootprint* create(VM& vm, JSGlobalObject* globalObject)
1440      {
1441          Structure* structure = createStructure(vm, globalObject, jsNull());
1442          JSCMemoryFootprint* footprint = new (NotNull, allocateCell<JSCMemoryFootprint>(vm.heap)) JSCMemoryFootprint(vm, structure);
1443          footprint->finishCreation(vm);
1444          return footprint;
1445      }
1446  
1447      void finishCreation(VM& vm)
1448      {
1449          Base::finishCreation(vm);
1450  
1451          auto addProperty = [&] (VM& vm, const char* name, JSValue value) {
1452              JSCMemoryFootprint::addProperty(vm, name, value);
1453          };
1454  
1455          MemoryFootprint footprint = MemoryFootprint::now();
1456  
1457          addProperty(vm, "current", jsNumber(footprint.current));
1458          addProperty(vm, "peak", jsNumber(footprint.peak));
1459      }
1460  
1461      DECLARE_INFO;
1462  
1463  private:
1464      void addProperty(VM& vm, const char* name, JSValue value)
1465      {
1466          Identifier identifier = Identifier::fromString(vm, name);
1467          putDirect(vm, identifier, value);
1468      }
1469  };
1470  
1471  const ClassInfo JSCMemoryFootprint::s_info = { "MemoryFootprint", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSCMemoryFootprint) };
1472  
1473  JSC_DEFINE_HOST_FUNCTION(functionCreateMemoryFootprint, (JSGlobalObject* globalObject, CallFrame*))
1474  {
1475      VM& vm = globalObject->vm();
1476      JSLockHolder lock(vm);
1477      return JSValue::encode(JSCMemoryFootprint::create(vm, globalObject));
1478  }
1479  
1480  JSC_DEFINE_HOST_FUNCTION(functionResetMemoryPeak, (JSGlobalObject*, CallFrame*))
1481  {
1482      MemoryFootprint::resetPeak();
1483      return JSValue::encode(jsUndefined());
1484  }
1485  
1486  // This function is not generally very helpful in 64-bit code as the tag and payload
1487  // share a register. But in 32-bit JITed code the tag may not be checked if an
1488  // optimization removes type checking requirements, such as in ===.
1489  JSC_DEFINE_HOST_FUNCTION(functionAddressOf, (JSGlobalObject*, CallFrame* callFrame))
1490  {
1491      JSValue value = callFrame->argument(0);
1492      if (!value.isCell())
1493          return JSValue::encode(jsUndefined());
1494      // Need to cast to uint64_t so bitwise_cast will play along.
1495      uint64_t asNumber = reinterpret_cast<uint64_t>(value.asCell());
1496      EncodedJSValue returnValue = JSValue::encode(jsNumber(bitwise_cast<double>(asNumber)));
1497      return returnValue;
1498  }
1499  
1500  JSC_DEFINE_HOST_FUNCTION(functionVersion, (JSGlobalObject*, CallFrame*))
1501  {
1502      // We need this function for compatibility with the Mozilla JS tests but for now
1503      // we don't actually do any version-specific handling
1504      return JSValue::encode(jsUndefined());
1505  }
1506  
1507  JSC_DEFINE_HOST_FUNCTION(functionRun, (JSGlobalObject* globalObject, CallFrame* callFrame))
1508  {
1509      VM& vm = globalObject->vm();
1510      auto scope = DECLARE_THROW_SCOPE(vm);
1511  
1512      String fileName = callFrame->argument(0).toWTFString(globalObject);
1513      RETURN_IF_EXCEPTION(scope, encodedJSValue());
1514      Vector<char> script;
1515      if (!fetchScriptFromLocalFileSystem(fileName, script))
1516          return JSValue::encode(throwException(globalObject, scope, createError(globalObject, "Could not open file."_s)));
1517  
1518      GlobalObject* realm = GlobalObject::create(vm, GlobalObject::createStructure(vm, jsNull()), Vector<String>());
1519  
1520      JSArray* array = constructEmptyArray(realm, nullptr);
1521      RETURN_IF_EXCEPTION(scope, encodedJSValue());
1522      for (unsigned i = 1; i < callFrame->argumentCount(); ++i) {
1523          array->putDirectIndex(realm, i - 1, callFrame->uncheckedArgument(i));
1524          RETURN_IF_EXCEPTION(scope, encodedJSValue());
1525      }
1526      realm->putDirect(vm, Identifier::fromString(vm, "arguments"), array);
1527  
1528      NakedPtr<Exception> exception;
1529      StopWatch stopWatch;
1530      stopWatch.start();
1531      evaluate(realm, jscSource(script, SourceOrigin { absolutePath(fileName) }, fileName), JSValue(), exception);
1532      stopWatch.stop();
1533  
1534      if (exception) {
1535          throwException(realm, scope, exception);
1536          return JSValue::encode(jsUndefined());
1537      }
1538      
1539      return JSValue::encode(jsNumber(stopWatch.getElapsedMS()));
1540  }
1541  
1542  JSC_DEFINE_HOST_FUNCTION(functionRunString, (JSGlobalObject* globalObject, CallFrame* callFrame))
1543  {
1544      VM& vm = globalObject->vm();
1545      auto scope = DECLARE_THROW_SCOPE(vm);
1546  
1547      String source = callFrame->argument(0).toWTFString(globalObject);
1548      RETURN_IF_EXCEPTION(scope, encodedJSValue());
1549  
1550      GlobalObject* realm = GlobalObject::create(vm, GlobalObject::createStructure(vm, jsNull()), Vector<String>());
1551  
1552      JSArray* array = constructEmptyArray(realm, nullptr);
1553      RETURN_IF_EXCEPTION(scope, encodedJSValue());
1554      for (unsigned i = 1; i < callFrame->argumentCount(); ++i) {
1555          array->putDirectIndex(realm, i - 1, callFrame->uncheckedArgument(i));
1556          RETURN_IF_EXCEPTION(scope, encodedJSValue());
1557      }
1558      realm->putDirect(vm, Identifier::fromString(vm, "arguments"), array);
1559  
1560      NakedPtr<Exception> exception;
1561      evaluate(realm, jscSource(source, callFrame->callerSourceOrigin(vm)), JSValue(), exception);
1562  
1563      if (exception) {
1564          scope.throwException(realm, exception);
1565          return JSValue::encode(jsUndefined());
1566      }
1567      
1568      return JSValue::encode(realm);
1569  }
1570  
1571  JSC_DEFINE_HOST_FUNCTION(functionLoad, (JSGlobalObject* globalObject, CallFrame* callFrame))
1572  {
1573      VM& vm = globalObject->vm();
1574      auto scope = DECLARE_THROW_SCOPE(vm);
1575  
1576      bool callerRelative = callFrame->argument(1).getString(globalObject) == "caller relative"_s;
1577      RETURN_IF_EXCEPTION(scope, encodedJSValue());
1578  
1579      String fileName = callFrame->argument(0).toWTFString(globalObject);
1580      RETURN_IF_EXCEPTION(scope, encodedJSValue());
1581  
1582      URL path;
1583      if (callerRelative) {
1584          path = URL(callFrame->callerSourceOrigin(vm).url(), fileName);
1585          if (!path.isLocalFile())
1586              return throwVMException(globalObject, scope, createURIError(globalObject, makeString("caller relative URL path is not a local file: ", path.string())));
1587      } else
1588          path = absolutePath(fileName);
1589      Vector<char> script;
1590      if (!fetchScriptFromLocalFileSystem(path.fileSystemPath(), script))
1591          return JSValue::encode(throwException(globalObject, scope, createError(globalObject, "Could not open file."_s)));
1592  
1593      NakedPtr<Exception> evaluationException;
1594      JSValue result = evaluate(globalObject, jscSource(script, SourceOrigin { path }, fileName), JSValue(), evaluationException);
1595      if (evaluationException)
1596          throwException(globalObject, scope, evaluationException);
1597      return JSValue::encode(result);
1598  }
1599  
1600  JSC_DEFINE_HOST_FUNCTION(functionLoadString, (JSGlobalObject* globalObject, CallFrame* callFrame))
1601  {
1602      VM& vm = globalObject->vm();
1603      auto scope = DECLARE_THROW_SCOPE(vm);
1604  
1605      String sourceCode = callFrame->argument(0).toWTFString(globalObject);
1606      RETURN_IF_EXCEPTION(scope, encodedJSValue());
1607  
1608      NakedPtr<Exception> evaluationException;
1609      JSValue result = evaluate(globalObject, jscSource(sourceCode, callFrame->callerSourceOrigin(vm)), JSValue(), evaluationException);
1610      if (evaluationException)
1611          throwException(globalObject, scope, evaluationException);
1612      return JSValue::encode(result);
1613  }
1614  
1615  JSC_DEFINE_HOST_FUNCTION(functionReadFile, (JSGlobalObject* globalObject, CallFrame* callFrame))
1616  {
1617      VM& vm = globalObject->vm();
1618      auto scope = DECLARE_THROW_SCOPE(vm);
1619  
1620      String fileName = callFrame->argument(0).toWTFString(globalObject);
1621      RETURN_IF_EXCEPTION(scope, encodedJSValue());
1622  
1623      bool isBinary = false;
1624      if (callFrame->argumentCount() > 1) {
1625          String type = callFrame->argument(1).toWTFString(globalObject);
1626          RETURN_IF_EXCEPTION(scope, encodedJSValue());
1627          if (type != "binary")
1628              return throwVMError(globalObject, scope, "Expected 'binary' as second argument.");
1629          isBinary = true;
1630      }
1631  
1632      RefPtr<Uint8Array> content = fillBufferWithContentsOfFile(fileName);
1633      if (!content)
1634          return throwVMError(globalObject, scope, "Could not open file.");
1635  
1636      if (!isBinary)
1637          return JSValue::encode(jsString(vm, String::fromUTF8WithLatin1Fallback(content->data(), content->length())));
1638  
1639      Structure* structure = globalObject->typedArrayStructure(TypeUint8);
1640      JSObject* result = JSUint8Array::create(vm, structure, WTFMove(content));
1641      RETURN_IF_EXCEPTION(scope, encodedJSValue());
1642  
1643      return JSValue::encode(result);
1644  }
1645  
1646  JSC_DEFINE_HOST_FUNCTION(functionCheckSyntax, (JSGlobalObject* globalObject, CallFrame* callFrame))
1647  {
1648      VM& vm = globalObject->vm();
1649      auto scope = DECLARE_THROW_SCOPE(vm);
1650  
1651      String fileName = callFrame->argument(0).toWTFString(globalObject);
1652      RETURN_IF_EXCEPTION(scope, encodedJSValue());
1653      Vector<char> script;
1654      if (!fetchScriptFromLocalFileSystem(fileName, script))
1655          return JSValue::encode(throwException(globalObject, scope, createError(globalObject, "Could not open file."_s)));
1656  
1657      StopWatch stopWatch;
1658      stopWatch.start();
1659  
1660      JSValue syntaxException;
1661      bool validSyntax = checkSyntax(globalObject, jscSource(script, SourceOrigin { absolutePath(fileName) }, fileName), &syntaxException);
1662      stopWatch.stop();
1663  
1664      if (!validSyntax)
1665          throwException(globalObject, scope, syntaxException);
1666      return JSValue::encode(jsNumber(stopWatch.getElapsedMS()));
1667  }
1668  
1669  #if ENABLE(SAMPLING_FLAGS)
1670  JSC_DEFINE_HOST_FUNCTION(functionSetSamplingFlags, (JSGlobalObject*, CallFrame* callFrame))
1671  {
1672      for (unsigned i = 0; i < callFrame->argumentCount(); ++i) {
1673          unsigned flag = static_cast<unsigned>(callFrame->uncheckedArgument(i).toNumber(globalObject));
1674          if ((flag >= 1) && (flag <= 32))
1675              SamplingFlags::setFlag(flag);
1676      }
1677      return JSValue::encode(jsNull());
1678  }
1679  
1680  JSC_DEFINE_HOST_FUNCTION(functionClearSamplingFlags, (JSGlobalObject*, CallFrame* callFrame))
1681  {
1682      for (unsigned i = 0; i < callFrame->argumentCount(); ++i) {
1683          unsigned flag = static_cast<unsigned>(callFrame->uncheckedArgument(i).toNumber(globalObject));
1684          if ((flag >= 1) && (flag <= 32))
1685              SamplingFlags::clearFlag(flag);
1686      }
1687      return JSValue::encode(jsNull());
1688  }
1689  #endif
1690  
1691  JSC_DEFINE_HOST_FUNCTION(functionGetRandomSeed, (JSGlobalObject* globalObject, CallFrame*))
1692  {
1693      return JSValue::encode(jsNumber(globalObject->weakRandom().seed()));
1694  }
1695  
1696  JSC_DEFINE_HOST_FUNCTION(functionSetRandomSeed, (JSGlobalObject* globalObject, CallFrame* callFrame))
1697  {
1698      VM& vm = globalObject->vm();
1699      auto scope = DECLARE_THROW_SCOPE(vm);
1700  
1701      unsigned seed = callFrame->argument(0).toUInt32(globalObject);
1702      RETURN_IF_EXCEPTION(scope, encodedJSValue());
1703      globalObject->weakRandom().setSeed(seed);
1704      return JSValue::encode(jsUndefined());
1705  }
1706  
1707  JSC_DEFINE_HOST_FUNCTION(functionIsRope, (JSGlobalObject*, CallFrame* callFrame))
1708  {
1709      JSValue argument = callFrame->argument(0);
1710      if (!argument.isString())
1711          return JSValue::encode(jsBoolean(false));
1712      const StringImpl* impl = asString(argument)->tryGetValueImpl();
1713      return JSValue::encode(jsBoolean(!impl));
1714  }
1715  
1716  JSC_DEFINE_HOST_FUNCTION(functionCallerSourceOrigin, (JSGlobalObject* globalObject, CallFrame* callFrame))
1717  {
1718      VM& vm = globalObject->vm();
1719      SourceOrigin sourceOrigin = callFrame->callerSourceOrigin(vm);
1720      if (sourceOrigin.url().isNull())
1721          return JSValue::encode(jsNull());
1722      return JSValue::encode(jsString(vm, sourceOrigin.string()));
1723  }
1724  
1725  JSC_DEFINE_HOST_FUNCTION(functionReadline, (JSGlobalObject* globalObject, CallFrame*))
1726  {
1727      Vector<char, 256> line;
1728      int c;
1729      while ((c = getchar()) != EOF) {
1730          // FIXME: Should we also break on \r? 
1731          if (c == '\n')
1732              break;
1733          line.append(c);
1734      }
1735      line.append('\0');
1736      return JSValue::encode(jsString(globalObject->vm(), line.data()));
1737  }
1738  
1739  JSC_DEFINE_HOST_FUNCTION(functionPreciseTime, (JSGlobalObject*, CallFrame*))
1740  {
1741      return JSValue::encode(jsNumber(WallTime::now().secondsSinceEpoch().value()));
1742  }
1743  
1744  JSC_DEFINE_HOST_FUNCTION(functionNeverInlineFunction, (JSGlobalObject* globalObject, CallFrame* callFrame))
1745  {
1746      return JSValue::encode(setNeverInline(globalObject, callFrame));
1747  }
1748  
1749  JSC_DEFINE_HOST_FUNCTION(functionNoDFG, (JSGlobalObject* globalObject, CallFrame* callFrame))
1750  {
1751      return JSValue::encode(setNeverOptimize(globalObject, callFrame));
1752  }
1753  
1754  JSC_DEFINE_HOST_FUNCTION(functionNoFTL, (JSGlobalObject*, CallFrame* callFrame))
1755  {
1756      if (callFrame->argumentCount()) {
1757          FunctionExecutable* executable = getExecutableForFunction(callFrame->argument(0));
1758          if (executable)
1759              executable->setNeverFTLOptimize(true);
1760      }
1761      return JSValue::encode(jsUndefined());
1762  }
1763  
1764  JSC_DEFINE_HOST_FUNCTION(functionNoOSRExitFuzzing, (JSGlobalObject* globalObject, CallFrame* callFrame))
1765  {
1766      return JSValue::encode(setCannotUseOSRExitFuzzing(globalObject, callFrame));
1767  }
1768  
1769  JSC_DEFINE_HOST_FUNCTION(functionOptimizeNextInvocation, (JSGlobalObject* globalObject, CallFrame* callFrame))
1770  {
1771      return JSValue::encode(optimizeNextInvocation(globalObject, callFrame));
1772  }
1773  
1774  JSC_DEFINE_HOST_FUNCTION(functionNumberOfDFGCompiles, (JSGlobalObject* globalObject, CallFrame* callFrame))
1775  {
1776      return JSValue::encode(numberOfDFGCompiles(globalObject, callFrame));
1777  }
1778  
1779  JSC_DEFINE_HOST_FUNCTION(functionCallerIsOMGCompiled, (JSGlobalObject* globalObject, CallFrame* callFrame))
1780  {
1781      VM& vm = globalObject->vm();
1782      auto scope = DECLARE_THROW_SCOPE(vm);
1783  
1784      if (!Options::useBBQTierUpChecks())
1785          return JSValue::encode(jsBoolean(true));
1786  
1787      CallerFunctor wasmToJSFrame;
1788      StackVisitor::visit(callFrame, vm, wasmToJSFrame);
1789      if (!wasmToJSFrame.callerFrame()->isAnyWasmCallee())
1790          return throwVMError(globalObject, scope, "caller is not a wasm->js import function");
1791  
1792      // We have a wrapper frame that we generate for imports. If we ever can direct call from wasm we would need to change this.
1793      ASSERT(!wasmToJSFrame.callerFrame()->callee().isWasm());
1794      CallerFunctor wasmFrame;
1795      StackVisitor::visit(wasmToJSFrame.callerFrame(), vm, wasmFrame);
1796      ASSERT(wasmFrame.callerFrame()->callee().isWasm());
1797  #if ENABLE(WEBASSEMBLY)
1798      auto mode = wasmFrame.callerFrame()->callee().asWasmCallee()->compilationMode();
1799      return JSValue::encode(jsBoolean(mode == Wasm::CompilationMode::OMGMode || mode == Wasm::CompilationMode::OMGForOSREntryMode));
1800  #endif
1801      RELEASE_ASSERT_NOT_REACHED();
1802  }
1803  
1804  Message::Message(Content&& contents, int32_t index)
1805      : m_contents(WTFMove(contents))
1806      , m_index(index)
1807  {
1808  }
1809  
1810  Message::~Message()
1811  {
1812  }
1813  
1814  Worker::Worker(Workers& workers)
1815      : m_workers(workers)
1816  {
1817      auto locker = holdLock(m_workers.m_lock);
1818      m_workers.m_workers.append(this);
1819      
1820      *currentWorker() = this;
1821  }
1822  
1823  Worker::~Worker()
1824  {
1825      auto locker = holdLock(m_workers.m_lock);
1826      RELEASE_ASSERT(isOnList());
1827      remove();
1828  }
1829  
1830  void Worker::enqueue(const AbstractLocker&, RefPtr<Message> message)
1831  {
1832      m_messages.append(message);
1833  }
1834  
1835  RefPtr<Message> Worker::dequeue()
1836  {
1837      auto locker = holdLock(m_workers.m_lock);
1838      while (m_messages.isEmpty())
1839          m_workers.m_condition.wait(m_workers.m_lock);
1840      return m_messages.takeFirst();
1841  }
1842  
1843  Worker& Worker::current()
1844  {
1845      return **currentWorker();
1846  }
1847  
1848  ThreadSpecific<Worker*>& Worker::currentWorker()
1849  {
1850      static ThreadSpecific<Worker*>* result;
1851      static std::once_flag flag;
1852      std::call_once(
1853          flag,
1854          [] () {
1855              result = new ThreadSpecific<Worker*>();
1856          });
1857      return *result;
1858  }
1859  
1860  Workers::Workers()
1861  {
1862  }
1863  
1864  Workers::~Workers()
1865  {
1866      UNREACHABLE_FOR_PLATFORM();
1867  }
1868  
1869  template<typename Func>
1870  void Workers::broadcast(const Func& func)
1871  {
1872      auto locker = holdLock(m_lock);
1873      for (Worker* worker = m_workers.begin(); worker != m_workers.end(); worker = worker->next()) {
1874          if (worker != &Worker::current())
1875              func(locker, *worker);
1876      }
1877      m_condition.notifyAll();
1878  }
1879  
1880  void Workers::report(const String& string)
1881  {
1882      auto locker = holdLock(m_lock);
1883      m_reports.append(string.isolatedCopy());
1884      m_condition.notifyAll();
1885  }
1886  
1887  String Workers::tryGetReport()
1888  {
1889      auto locker = holdLock(m_lock);
1890      if (m_reports.isEmpty())
1891          return String();
1892      return m_reports.takeFirst();
1893  }
1894  
1895  String Workers::getReport()
1896  {
1897      auto locker = holdLock(m_lock);
1898      while (m_reports.isEmpty())
1899          m_condition.wait(m_lock);
1900      return m_reports.takeFirst();
1901  }
1902  
1903  Workers& Workers::singleton()
1904  {
1905      static Workers* result;
1906      static std::once_flag flag;
1907      std::call_once(
1908          flag,
1909          [] {
1910              result = new Workers();
1911          });
1912      return *result;
1913  }
1914  
1915  JSC_DEFINE_HOST_FUNCTION(functionDollarCreateRealm, (JSGlobalObject* globalObject, CallFrame*))
1916  {
1917      VM& vm = globalObject->vm();
1918      GlobalObject* result = GlobalObject::create(vm, GlobalObject::createStructure(vm, jsNull()), Vector<String>());
1919      return JSValue::encode(result->getDirect(vm, Identifier::fromString(vm, "$")));
1920  }
1921  
1922  JSC_DEFINE_HOST_FUNCTION(functionDollarEvalScript, (JSGlobalObject* globalObject, CallFrame* callFrame))
1923  {
1924      VM& vm = globalObject->vm();
1925      auto scope = DECLARE_THROW_SCOPE(vm);
1926  
1927      String sourceCode = callFrame->argument(0).toWTFString(globalObject);
1928      RETURN_IF_EXCEPTION(scope, encodedJSValue());
1929      
1930      JSValue global = callFrame->thisValue().get(globalObject, Identifier::fromString(vm, "global"));
1931      RETURN_IF_EXCEPTION(scope, encodedJSValue());
1932      GlobalObject* realm = jsDynamicCast<GlobalObject*>(vm, global);
1933      RETURN_IF_EXCEPTION(scope, encodedJSValue());
1934      if (!realm)
1935          return JSValue::encode(throwException(globalObject, scope, createError(globalObject, "Expected global to point to a global object"_s)));
1936      
1937      NakedPtr<Exception> evaluationException;
1938      JSValue result = evaluate(realm, jscSource(sourceCode, callFrame->callerSourceOrigin(vm)), JSValue(), evaluationException);
1939      if (evaluationException)
1940          throwException(globalObject, scope, evaluationException);
1941      return JSValue::encode(result);
1942  }
1943  
1944  JSC_DEFINE_HOST_FUNCTION(functionDollarAgentStart, (JSGlobalObject* globalObject, CallFrame* callFrame))
1945  {
1946      VM& vm = globalObject->vm();
1947      auto scope = DECLARE_THROW_SCOPE(vm);
1948  
1949      String sourceCode = callFrame->argument(0).toWTFString(globalObject);
1950      RETURN_IF_EXCEPTION(scope, encodedJSValue());
1951      
1952      Lock didStartLock;
1953      Condition didStartCondition;
1954      bool didStart = false;
1955  
1956      auto isGigacageMemoryExhausted = [&](Gigacage::Kind kind) {
1957          if (!Gigacage::isEnabled(kind))
1958              return false;
1959          if (Gigacage::footprint(kind) < Gigacage::size(kind) * 0.8)
1960              return false;
1961          return true;
1962      };
1963  
1964      if (isGigacageMemoryExhausted(Gigacage::JSValue) || isGigacageMemoryExhausted(Gigacage::Primitive))
1965          return JSValue::encode(throwOutOfMemoryError(globalObject, scope, "Gigacage is exhausted"_s));
1966  
1967      String workerPath = "worker"_s;
1968      if (!callFrame->argument(1).isUndefined()) {
1969          workerPath = callFrame->argument(1).toWTFString(globalObject);
1970          RETURN_IF_EXCEPTION(scope, encodedJSValue());
1971      }
1972      
1973      Thread::create(
1974          "JSC Agent",
1975          [sourceCode = sourceCode.isolatedCopy(), workerPath = workerPath.isolatedCopy(), &didStartLock, &didStartCondition, &didStart] () {
1976              CommandLine commandLine(CommandLine::CommandLineForWorkers);
1977              commandLine.m_interactive = false;
1978              runJSC(
1979                  commandLine, true,
1980                  [&] (VM&, GlobalObject* globalObject, bool& success) {
1981                      // Notify the thread that started us that we have registered a worker.
1982                      {
1983                          auto locker = holdLock(didStartLock);
1984                          didStart = true;
1985                          didStartCondition.notifyOne();
1986                      }
1987                      
1988                      NakedPtr<Exception> evaluationException;
1989                      JSValue result;
1990                      result = evaluate(globalObject, jscSource(sourceCode, SourceOrigin(URL({ }, workerPath))), JSValue(), evaluationException);
1991                      if (evaluationException)
1992                          result = evaluationException->value();
1993                      checkException(globalObject, true, evaluationException, result, commandLine, success);
1994                      if (!success)
1995                          exit(1);
1996                  });
1997          })->detach();
1998      
1999      {
2000          auto locker = holdLock(didStartLock);
2001          while (!didStart)
2002              didStartCondition.wait(didStartLock);
2003      }
2004      
2005      return JSValue::encode(jsUndefined());
2006  }
2007  
2008  JSC_DEFINE_HOST_FUNCTION(functionDollarAgentReceiveBroadcast, (JSGlobalObject* globalObject, CallFrame* callFrame))
2009  {
2010      VM& vm = globalObject->vm();
2011      auto scope = DECLARE_THROW_SCOPE(vm);
2012  
2013      JSValue callback = callFrame->argument(0);
2014      auto callData = getCallData(vm, callback);
2015      if (callData.type == CallData::Type::None)
2016          return JSValue::encode(throwException(globalObject, scope, createError(globalObject, "Expected callback"_s)));
2017      
2018      RefPtr<Message> message;
2019      {
2020          ReleaseHeapAccessScope releaseAccess(vm.heap);
2021          message = Worker::current().dequeue();
2022      }
2023  
2024      auto content = message->releaseContents();
2025      JSValue result = ([&]() -> JSValue {
2026          if (WTF::holds_alternative<ArrayBufferContents>(content)) {
2027              auto nativeBuffer = ArrayBuffer::create(WTF::get<ArrayBufferContents>(WTFMove(content)));
2028              ArrayBufferSharingMode sharingMode = nativeBuffer->sharingMode();
2029              return JSArrayBuffer::create(vm, globalObject->arrayBufferStructure(sharingMode), WTFMove(nativeBuffer));
2030          }
2031  #if ENABLE(WEBASSEMBLY)
2032          if (WTF::holds_alternative<Ref<Wasm::MemoryHandle>>(content)) {
2033              JSWebAssemblyMemory* jsMemory = JSC::JSWebAssemblyMemory::tryCreate(globalObject, vm, globalObject->webAssemblyMemoryStructure());
2034              scope.releaseAssertNoException();
2035              Ref<Wasm::Memory> memory = Wasm::Memory::create(WTF::get<Ref<Wasm::MemoryHandle>>(WTFMove(content)),
2036                  [&vm] (Wasm::Memory::NotifyPressure) { vm.heap.collectAsync(CollectionScope::Full); },
2037                  [&vm] (Wasm::Memory::SyncTryToReclaim) { vm.heap.collectSync(CollectionScope::Full); },
2038                  [&vm, jsMemory] (Wasm::Memory::GrowSuccess, Wasm::PageCount oldPageCount, Wasm::PageCount newPageCount) { jsMemory->growSuccessCallback(vm, oldPageCount, newPageCount); });
2039              jsMemory->adopt(WTFMove(memory));
2040              return jsMemory;
2041          }
2042  #endif
2043          return jsUndefined();
2044      })();
2045  
2046      MarkedArgumentBuffer args;
2047      args.append(result);
2048      args.append(jsNumber(message->index()));
2049      if (UNLIKELY(args.hasOverflowed()))
2050          return JSValue::encode(throwOutOfMemoryError(globalObject, scope));
2051      RELEASE_AND_RETURN(scope, JSValue::encode(call(globalObject, callback, callData, jsNull(), args)));
2052  }
2053  
2054  JSC_DEFINE_HOST_FUNCTION(functionDollarAgentReport, (JSGlobalObject* globalObject, CallFrame* callFrame))
2055  {
2056      VM& vm = globalObject->vm();
2057      auto scope = DECLARE_THROW_SCOPE(vm);
2058  
2059      String report = callFrame->argument(0).toWTFString(globalObject);
2060      RETURN_IF_EXCEPTION(scope, encodedJSValue());
2061      
2062      Workers::singleton().report(report);
2063      
2064      return JSValue::encode(jsUndefined());
2065  }
2066  
2067  JSC_DEFINE_HOST_FUNCTION(functionDollarAgentSleep, (JSGlobalObject* globalObject, CallFrame* callFrame))
2068  {
2069      VM& vm = globalObject->vm();
2070      auto scope = DECLARE_THROW_SCOPE(vm);
2071  
2072      if (callFrame->argumentCount() >= 1) {
2073          Seconds seconds = Seconds::fromMilliseconds(callFrame->argument(0).toNumber(globalObject));
2074          RETURN_IF_EXCEPTION(scope, encodedJSValue());
2075          sleep(seconds);
2076      }
2077      return JSValue::encode(jsUndefined());
2078  }
2079  
2080  JSC_DEFINE_HOST_FUNCTION(functionDollarAgentBroadcast, (JSGlobalObject* globalObject, CallFrame* callFrame))
2081  {
2082      VM& vm = globalObject->vm();
2083      auto scope = DECLARE_THROW_SCOPE(vm);
2084  
2085      int32_t index = callFrame->argument(1).toInt32(globalObject);
2086      RETURN_IF_EXCEPTION(scope, encodedJSValue());
2087  
2088      JSArrayBuffer* jsBuffer = jsDynamicCast<JSArrayBuffer*>(vm, callFrame->argument(0));
2089      if (jsBuffer && jsBuffer->isShared()) {
2090          Workers::singleton().broadcast(
2091              [&] (const AbstractLocker& locker, Worker& worker) {
2092                  ArrayBuffer* nativeBuffer = jsBuffer->impl();
2093                  ArrayBufferContents contents;
2094                  nativeBuffer->transferTo(vm, contents); // "transferTo" means "share" if the buffer is shared.
2095                  RefPtr<Message> message = adoptRef(new Message(WTFMove(contents), index));
2096                  worker.enqueue(locker, message);
2097              });
2098          return JSValue::encode(jsUndefined());
2099      }
2100  
2101  #if ENABLE(WEBASSEMBLY)
2102      JSWebAssemblyMemory* memory = jsDynamicCast<JSWebAssemblyMemory*>(vm, callFrame->argument(0));
2103      if (memory && memory->memory().sharingMode() == Wasm::MemorySharingMode::Shared) {
2104          Workers::singleton().broadcast(
2105              [&] (const AbstractLocker& locker, Worker& worker) {
2106                  Ref<Wasm::MemoryHandle> handle { memory->memory().handle() };
2107                  RefPtr<Message> message = adoptRef(new Message(WTFMove(handle), index));
2108                  worker.enqueue(locker, message);
2109              });
2110          return JSValue::encode(jsUndefined());
2111      }
2112  #endif
2113  
2114      return JSValue::encode(throwException(globalObject, scope, createError(globalObject, "Not supported object"_s)));
2115  }
2116  
2117  JSC_DEFINE_HOST_FUNCTION(functionDollarAgentGetReport, (JSGlobalObject* globalObject, CallFrame*))
2118  {
2119      VM& vm = globalObject->vm();
2120  
2121      String string = Workers::singleton().tryGetReport();
2122      if (!string)
2123          return JSValue::encode(jsNull());
2124      
2125      return JSValue::encode(jsString(vm, string));
2126  }
2127  
2128  JSC_DEFINE_HOST_FUNCTION(functionDollarAgentLeaving, (JSGlobalObject*, CallFrame*))
2129  {
2130      return JSValue::encode(jsUndefined());
2131  }
2132  
2133  JSC_DEFINE_HOST_FUNCTION(functionDollarAgentMonotonicNow, (JSGlobalObject*, CallFrame*))
2134  {
2135      return JSValue::encode(jsNumber(MonotonicTime::now().secondsSinceEpoch().milliseconds()));
2136  }
2137  
2138  JSC_DEFINE_HOST_FUNCTION(functionWaitForReport, (JSGlobalObject* globalObject, CallFrame*))
2139  {
2140      VM& vm = globalObject->vm();
2141  
2142      String string;
2143      {
2144          ReleaseHeapAccessScope releaseAccess(vm.heap);
2145          string = Workers::singleton().getReport();
2146      }
2147      if (!string)
2148          return JSValue::encode(jsNull());
2149      
2150      return JSValue::encode(jsString(vm, string));
2151  }
2152  
2153  JSC_DEFINE_HOST_FUNCTION(functionHeapCapacity, (JSGlobalObject* globalObject, CallFrame*))
2154  {
2155      VM& vm = globalObject->vm();
2156      return JSValue::encode(jsNumber(vm.heap.capacity()));
2157  }
2158  
2159  JSC_DEFINE_HOST_FUNCTION(functionFlashHeapAccess, (JSGlobalObject* globalObject, CallFrame* callFrame))
2160  {
2161      VM& vm = globalObject->vm();
2162      auto scope = DECLARE_THROW_SCOPE(vm);
2163      
2164      double sleepTimeMs = 0;
2165      if (callFrame->argumentCount() >= 1) {
2166          sleepTimeMs = callFrame->argument(0).toNumber(globalObject);
2167          RETURN_IF_EXCEPTION(scope, encodedJSValue());
2168      }
2169  
2170      vm.heap.releaseAccess();
2171      if (sleepTimeMs)
2172          sleep(Seconds::fromMilliseconds(sleepTimeMs));
2173      vm.heap.acquireAccess();
2174      return JSValue::encode(jsUndefined());
2175  }
2176  
2177  JSC_DEFINE_HOST_FUNCTION(functionDisableRichSourceInfo, (JSGlobalObject*, CallFrame*))
2178  {
2179      supportsRichSourceInfo = false;
2180      return JSValue::encode(jsUndefined());
2181  }
2182  
2183  JSC_DEFINE_HOST_FUNCTION(functionMallocInALoop, (JSGlobalObject*, CallFrame*))
2184  {
2185      Vector<void*> ptrs;
2186      for (unsigned i = 0; i < 5000; ++i)
2187          ptrs.append(fastMalloc(1024 * 2));
2188      for (void* ptr : ptrs)
2189          fastFree(ptr);
2190      return JSValue::encode(jsUndefined());
2191  }
2192  
2193  JSC_DEFINE_HOST_FUNCTION(functionTotalCompileTime, (JSGlobalObject*, CallFrame*))
2194  {
2195  #if ENABLE(JIT)
2196      return JSValue::encode(jsNumber(JIT::totalCompileTime().milliseconds()));
2197  #else
2198      return JSValue::encode(jsNumber(0));
2199  #endif
2200  }
2201  
2202  template<typename ValueType>
2203  typename std::enable_if<!std::is_fundamental<ValueType>::value>::type addOption(VM&, JSObject*, const Identifier&, ValueType) { }
2204  
2205  template<typename ValueType>
2206  typename std::enable_if<std::is_fundamental<ValueType>::value>::type addOption(VM& vm, JSObject* optionsObject, const Identifier& identifier, ValueType value)
2207  {
2208      optionsObject->putDirect(vm, identifier, JSValue(value));
2209  }
2210  
2211  JSC_DEFINE_HOST_FUNCTION(functionJSCOptions, (JSGlobalObject* globalObject, CallFrame*))
2212  {
2213      VM& vm = globalObject->vm();
2214      JSObject* optionsObject = constructEmptyObject(globalObject);
2215  #define READ_OPTION(type_, name_, defaultValue_, availability_, description_) \
2216      addOption(vm, optionsObject, Identifier::fromString(vm, #name_), Options::name_());
2217      FOR_EACH_JSC_OPTION(READ_OPTION)
2218  #undef READ_OPTION
2219      return JSValue::encode(optionsObject);
2220  }
2221  
2222  JSC_DEFINE_HOST_FUNCTION(functionReoptimizationRetryCount, (JSGlobalObject*, CallFrame* callFrame))
2223  {
2224      if (callFrame->argumentCount() < 1)
2225          return JSValue::encode(jsUndefined());
2226      
2227      CodeBlock* block = getSomeBaselineCodeBlockForFunction(callFrame->argument(0));
2228      if (!block)
2229          return JSValue::encode(jsNumber(0));
2230      
2231      return JSValue::encode(jsNumber(block->reoptimizationRetryCounter()));
2232  }
2233  
2234  JSC_DEFINE_HOST_FUNCTION(functionTransferArrayBuffer, (JSGlobalObject* globalObject, CallFrame* callFrame))
2235  {
2236      VM& vm = globalObject->vm();
2237      auto scope = DECLARE_THROW_SCOPE(vm);
2238  
2239      if (callFrame->argumentCount() < 1)
2240          return JSValue::encode(throwException(globalObject, scope, createError(globalObject, "Not enough arguments"_s)));
2241      
2242      JSArrayBuffer* buffer = jsDynamicCast<JSArrayBuffer*>(vm, callFrame->argument(0));
2243      if (!buffer)
2244          return JSValue::encode(throwException(globalObject, scope, createError(globalObject, "Expected an array buffer"_s)));
2245      
2246      ArrayBufferContents dummyContents;
2247      buffer->impl()->transferTo(vm, dummyContents);
2248      
2249      return JSValue::encode(jsUndefined());
2250  }
2251  
2252  JSC_DEFINE_HOST_FUNCTION(functionFailNextNewCodeBlock, (JSGlobalObject* globalObject, CallFrame*))
2253  {
2254      VM& vm = globalObject->vm();
2255      vm.setFailNextNewCodeBlock();
2256      return JSValue::encode(jsUndefined());
2257  }
2258  
2259  JSC_DEFINE_HOST_FUNCTION(functionQuit, (JSGlobalObject* globalObject, CallFrame*))
2260  {
2261      VM& vm = globalObject->vm();
2262      vm.codeCache()->write(vm);
2263  
2264      jscExit(EXIT_SUCCESS);
2265  
2266  #if COMPILER(MSVC)
2267      // Without this, Visual Studio will complain that this method does not return a value.
2268      return JSValue::encode(jsUndefined());
2269  #endif
2270  }
2271  
2272  JSC_DEFINE_HOST_FUNCTION(functionFalse, (JSGlobalObject*, CallFrame*))
2273  {
2274      return JSValue::encode(jsBoolean(false));
2275  }
2276  
2277  JSC_DEFINE_HOST_FUNCTION(functionUndefined1, (JSGlobalObject*, CallFrame*))
2278  {
2279      return JSValue::encode(jsUndefined());
2280  }
2281  
2282  JSC_DEFINE_HOST_FUNCTION(functionUndefined2, (JSGlobalObject*, CallFrame*))
2283  {
2284      return JSValue::encode(jsUndefined());
2285  }
2286  
2287  JSC_DEFINE_HOST_FUNCTION(functionIsInt32, (JSGlobalObject*, CallFrame* callFrame))
2288  {
2289      for (size_t i = 0; i < callFrame->argumentCount(); ++i) {
2290          if (!callFrame->argument(i).isInt32())
2291              return JSValue::encode(jsBoolean(false));
2292      }
2293      return JSValue::encode(jsBoolean(true));
2294  }
2295  
2296  JSC_DEFINE_HOST_FUNCTION(functionIsPureNaN, (JSGlobalObject*, CallFrame* callFrame))
2297  {
2298      for (size_t i = 0; i < callFrame->argumentCount(); ++i) {
2299          JSValue value = callFrame->argument(i);
2300          if (!value.isNumber())
2301              return JSValue::encode(jsBoolean(false));
2302          double number = value.asNumber();
2303          if (!std::isnan(number))
2304              return JSValue::encode(jsBoolean(false));
2305          if (isImpureNaN(number))
2306              return JSValue::encode(jsBoolean(false));
2307      }
2308      return JSValue::encode(jsBoolean(true));
2309  }
2310  
2311  JSC_DEFINE_HOST_FUNCTION(functionIdentity, (JSGlobalObject*, CallFrame* callFrame))
2312  {
2313      return JSValue::encode(callFrame->argument(0));
2314  }
2315  
2316  JSC_DEFINE_HOST_FUNCTION(functionEffectful42, (JSGlobalObject*, CallFrame*))
2317  {
2318      return JSValue::encode(jsNumber(42));
2319  }
2320  
2321  JSC_DEFINE_HOST_FUNCTION(functionMakeMasquerader, (JSGlobalObject* globalObject, CallFrame*))
2322  {
2323      VM& vm = globalObject->vm();
2324      return JSValue::encode(InternalFunction::createFunctionThatMasqueradesAsUndefined(vm, globalObject, 0, "IsHTMLDDA"_s, functionCallMasquerader));
2325  }
2326  
2327  JSC_DEFINE_HOST_FUNCTION(functionCallMasquerader, (JSGlobalObject*, CallFrame*))
2328  {
2329      return JSValue::encode(jsNull());
2330  }
2331  
2332  JSC_DEFINE_HOST_FUNCTION(functionHasCustomProperties, (JSGlobalObject* globalObject, CallFrame* callFrame))
2333  {
2334      JSValue value = callFrame->argument(0);
2335      if (value.isObject())
2336          return JSValue::encode(jsBoolean(asObject(value)->hasCustomProperties(globalObject->vm())));
2337      return JSValue::encode(jsBoolean(false));
2338  }
2339  
2340  JSC_DEFINE_HOST_FUNCTION(functionDumpTypesForAllVariables, (JSGlobalObject* globalObject, CallFrame*))
2341  {
2342      VM& vm = globalObject->vm();
2343      vm.dumpTypeProfilerData();
2344      return JSValue::encode(jsUndefined());
2345  }
2346  
2347  JSC_DEFINE_HOST_FUNCTION(functionDrainMicrotasks, (JSGlobalObject* globalObject, CallFrame*))
2348  {
2349      VM& vm = globalObject->vm();
2350      vm.drainMicrotasks();
2351      return JSValue::encode(jsUndefined());
2352  }
2353  
2354  JSC_DEFINE_HOST_FUNCTION(functionSetTimeout, (JSGlobalObject* globalObject, CallFrame* callFrame))
2355  {
2356      VM& vm = globalObject->vm();
2357      auto scope = DECLARE_THROW_SCOPE(vm);
2358  
2359      // FIXME: This means we can't pass any internal function but I don't think that's common for testing.
2360      auto callback = jsDynamicCast<JSFunction*>(vm, callFrame->argument(0));
2361      if (!callback)
2362          return throwVMTypeError(globalObject, scope, "First argument is not a JS function"_s);
2363  
2364      // FIXME: We don't look at the timeout parameter because we don't have a schedule work later API.
2365      vm.deferredWorkTimer->addPendingWork(vm, callback, { });
2366      vm.deferredWorkTimer->scheduleWorkSoon(callback, [callback] {
2367          JSGlobalObject* globalObject = callback->globalObject();
2368          VM& vm = globalObject->vm();
2369  
2370          MarkedArgumentBuffer args;
2371          call(globalObject, callback, jsUndefined(), args, "You shouldn't see this...");
2372          vm.deferredWorkTimer->cancelPendingWork(callback);
2373      });
2374      return JSValue::encode(jsUndefined());
2375  }
2376  
2377  JSC_DEFINE_HOST_FUNCTION(functionReleaseWeakRefs, (JSGlobalObject* globalObject, CallFrame*))
2378  {
2379      VM& vm = globalObject->vm();
2380      vm.finalizeSynchronousJSExecution();
2381      return JSValue::encode(jsUndefined());
2382  }
2383  
2384  JSC_DEFINE_HOST_FUNCTION(functionFinalizationRegistryLiveCount, (JSGlobalObject* globalObject, CallFrame* callFrame))
2385  {
2386      VM& vm = globalObject->vm();
2387      auto scope = DECLARE_THROW_SCOPE(vm);
2388  
2389      auto* finalizationRegistry = jsDynamicCast<JSFinalizationRegistry*>(vm, callFrame->argument(0));
2390      if (!finalizationRegistry)
2391          return throwVMTypeError(globalObject, scope, "first argument is not a finalizationRegistry"_s);
2392  
2393      auto locker = holdLock(finalizationRegistry->cellLock());
2394      return JSValue::encode(jsNumber(finalizationRegistry->liveCount(locker)));
2395  }
2396  
2397  JSC_DEFINE_HOST_FUNCTION(functionFinalizationRegistryDeadCount, (JSGlobalObject* globalObject, CallFrame* callFrame))
2398  {
2399      VM& vm = globalObject->vm();
2400      auto scope = DECLARE_THROW_SCOPE(vm);
2401  
2402      auto* finalizationRegistry = jsDynamicCast<JSFinalizationRegistry*>(vm, callFrame->argument(0));
2403      if (!finalizationRegistry)
2404          return throwVMTypeError(globalObject, scope, "first argument is not a finalizationRegistry"_s);
2405  
2406      auto locker = holdLock(finalizationRegistry->cellLock());
2407      return JSValue::encode(jsNumber(finalizationRegistry->deadCount(locker)));
2408  }
2409  
2410  JSC_DEFINE_HOST_FUNCTION(functionIs32BitPlatform, (JSGlobalObject*, CallFrame*))
2411  {
2412  #if USE(JSVALUE64)
2413      return JSValue::encode(JSValue(JSC::JSValue::JSFalse));
2414  #else
2415      return JSValue::encode(JSValue(JSC::JSValue::JSTrue));
2416  #endif
2417  }
2418  
2419  JSC_DEFINE_HOST_FUNCTION(functionCreateGlobalObject, (JSGlobalObject* globalObject, CallFrame*))
2420  {
2421      VM& vm = globalObject->vm();
2422      return JSValue::encode(GlobalObject::create(vm, GlobalObject::createStructure(vm, jsNull()), Vector<String>()));
2423  }
2424  
2425  JSC_DEFINE_HOST_FUNCTION(functionCreateHeapBigInt, (JSGlobalObject* globalObject, CallFrame* callFrame))
2426  {
2427      VM& vm = globalObject->vm();
2428      auto scope = DECLARE_THROW_SCOPE(vm);
2429      JSValue argument = callFrame->argument(0);
2430      JSValue bigInt = argument.toBigInt(globalObject);
2431      RETURN_IF_EXCEPTION(scope, encodedJSValue());
2432  #if USE(BIGINT32)
2433      if (bigInt.isHeapBigInt())
2434          return JSValue::encode(bigInt);
2435      ASSERT(bigInt.isBigInt32());
2436      int32_t value = bigInt.bigInt32AsInt32();
2437      RELEASE_AND_RETURN(scope, JSValue::encode(JSBigInt::createFrom(globalObject, value)));
2438  #else
2439      return JSValue::encode(bigInt);
2440  #endif
2441  }
2442  
2443  #if USE(BIGINT32)
2444  JSC_DEFINE_HOST_FUNCTION(functionCreateBigInt32, (JSGlobalObject* globalObject, CallFrame* callFrame))
2445  {
2446      VM& vm = globalObject->vm();
2447      auto scope = DECLARE_THROW_SCOPE(vm);
2448      JSValue argument = callFrame->argument(0);
2449      JSValue bigIntValue = argument.toBigInt(globalObject);
2450      RETURN_IF_EXCEPTION(scope, encodedJSValue());
2451      if (bigIntValue.isBigInt32())
2452          return JSValue::encode(bigIntValue);
2453      ASSERT(bigIntValue.isHeapBigInt());
2454      JSBigInt* bigInt = jsCast<JSBigInt*>(bigIntValue);
2455      if (!bigInt->length())
2456          return JSValue::encode(jsBigInt32(0));
2457      if (bigInt->length() == 1) {
2458          JSBigInt::Digit digit = bigInt->digit(0);
2459          if (bigInt->sign()) {
2460              if (digit <= static_cast<uint64_t>(-static_cast<int64_t>(INT32_MIN)))
2461                  return JSValue::encode(jsBigInt32(static_cast<int32_t>(-static_cast<int64_t>(digit))));
2462          } else {
2463              if (digit <= INT32_MAX)
2464                  return JSValue::encode(jsBigInt32(static_cast<int32_t>(digit)));
2465          }
2466      }
2467      throwTypeError(globalObject, scope, "Out of range of BigInt32"_s);
2468      return { };
2469  }
2470  #endif
2471  
2472  JSC_DEFINE_HOST_FUNCTION(functionUseBigInt32, (JSGlobalObject*, CallFrame*))
2473  {
2474  #if USE(BIGINT32)
2475      return JSValue::encode(jsBoolean(true));
2476  #else
2477      return JSValue::encode(jsBoolean(false));
2478  #endif
2479  }
2480  
2481  JSC_DEFINE_HOST_FUNCTION(functionIsBigInt32, (JSGlobalObject*, CallFrame* callFrame))
2482  {
2483  #if USE(BIGINT32)
2484      return JSValue::encode(jsBoolean(callFrame->argument(0).isBigInt32()));
2485  #else
2486      UNUSED_PARAM(callFrame);
2487      return JSValue::encode(jsBoolean(false));
2488  #endif
2489  }
2490  
2491  JSC_DEFINE_HOST_FUNCTION(functionIsHeapBigInt, (JSGlobalObject*, CallFrame* callFrame))
2492  {
2493      return JSValue::encode(jsBoolean(callFrame->argument(0).isHeapBigInt()));
2494  }
2495  
2496  JSC_DEFINE_HOST_FUNCTION(functionCheckModuleSyntax, (JSGlobalObject* globalObject, CallFrame* callFrame))
2497  {
2498      VM& vm = globalObject->vm();
2499      auto scope = DECLARE_THROW_SCOPE(vm);
2500  
2501      String source = callFrame->argument(0).toWTFString(globalObject);
2502      RETURN_IF_EXCEPTION(scope, encodedJSValue());
2503  
2504      StopWatch stopWatch;
2505      stopWatch.start();
2506  
2507      ParserError error;
2508      bool validSyntax = checkModuleSyntax(globalObject, jscSource(source, { }, String(), TextPosition(), SourceProviderSourceType::Module), error);
2509      RETURN_IF_EXCEPTION(scope, encodedJSValue());
2510      stopWatch.stop();
2511  
2512      if (!validSyntax)
2513          throwException(globalObject, scope, jsNontrivialString(vm, toString("SyntaxError: ", error.message(), ":", error.line())));
2514      return JSValue::encode(jsNumber(stopWatch.getElapsedMS()));
2515  }
2516  
2517  JSC_DEFINE_HOST_FUNCTION(functionPlatformSupportsSamplingProfiler, (JSGlobalObject*, CallFrame*))
2518  {
2519  #if ENABLE(SAMPLING_PROFILER)
2520      return JSValue::encode(JSValue(JSC::JSValue::JSTrue));
2521  #else
2522      return JSValue::encode(JSValue(JSC::JSValue::JSFalse));
2523  #endif
2524  }
2525  
2526  JSC_DEFINE_HOST_FUNCTION(functionGenerateHeapSnapshot, (JSGlobalObject* globalObject, CallFrame*))
2527  {
2528      VM& vm = globalObject->vm();
2529      JSLockHolder lock(vm);
2530      auto scope = DECLARE_THROW_SCOPE(vm);
2531  
2532      HeapSnapshotBuilder snapshotBuilder(vm.ensureHeapProfiler());
2533      snapshotBuilder.buildSnapshot();
2534  
2535      String jsonString = snapshotBuilder.json();
2536      EncodedJSValue result = JSValue::encode(JSONParse(globalObject, jsonString));
2537      scope.releaseAssertNoException();
2538      return result;
2539  }
2540  
2541  JSC_DEFINE_HOST_FUNCTION(functionGenerateHeapSnapshotForGCDebugging, (JSGlobalObject* globalObject, CallFrame*))
2542  {
2543      VM& vm = globalObject->vm();
2544      JSLockHolder lock(vm);
2545      auto scope = DECLARE_THROW_SCOPE(vm);
2546      String jsonString;
2547      {
2548          DeferGCForAWhile deferGC(vm.heap); // Prevent concurrent GC from interfering with the full GC that the snapshot does.
2549  
2550          HeapSnapshotBuilder snapshotBuilder(vm.ensureHeapProfiler(), HeapSnapshotBuilder::SnapshotType::GCDebuggingSnapshot);
2551          snapshotBuilder.buildSnapshot();
2552  
2553          jsonString = snapshotBuilder.json();
2554      }
2555      scope.releaseAssertNoException();
2556      return JSValue::encode(jsString(vm, jsonString));
2557  }
2558  
2559  JSC_DEFINE_HOST_FUNCTION(functionResetSuperSamplerState, (JSGlobalObject*, CallFrame*))
2560  {
2561      resetSuperSamplerState();
2562      return JSValue::encode(jsUndefined());
2563  }
2564  
2565  JSC_DEFINE_HOST_FUNCTION(functionEnsureArrayStorage, (JSGlobalObject* globalObject, CallFrame* callFrame))
2566  {
2567      VM& vm = globalObject->vm();
2568      for (unsigned i = 0; i < callFrame->argumentCount(); ++i) {
2569          if (JSObject* object = jsDynamicCast<JSObject*>(vm, callFrame->argument(i)))
2570              object->ensureArrayStorage(vm);
2571      }
2572      return JSValue::encode(jsUndefined());
2573  }
2574  
2575  #if ENABLE(SAMPLING_PROFILER)
2576  JSC_DEFINE_HOST_FUNCTION(functionStartSamplingProfiler, (JSGlobalObject* globalObject, CallFrame*))
2577  {
2578      VM& vm = globalObject->vm();
2579      SamplingProfiler& samplingProfiler = vm.ensureSamplingProfiler(WTF::Stopwatch::create());
2580      samplingProfiler.noticeCurrentThreadAsJSCExecutionThread();
2581      samplingProfiler.start();
2582      return JSValue::encode(jsUndefined());
2583  }
2584  
2585  JSC_DEFINE_HOST_FUNCTION(functionSamplingProfilerStackTraces, (JSGlobalObject* globalObject, CallFrame*))
2586  {
2587      VM& vm = globalObject->vm();
2588      auto scope = DECLARE_THROW_SCOPE(vm);
2589  
2590      if (!vm.samplingProfiler())
2591          return JSValue::encode(throwException(globalObject, scope, createError(globalObject, "Sampling profiler was never started"_s)));
2592  
2593      String jsonString = vm.samplingProfiler()->stackTracesAsJSON();
2594      EncodedJSValue result = JSValue::encode(JSONParse(globalObject, jsonString));
2595      scope.releaseAssertNoException();
2596      return result;
2597  }
2598  #endif // ENABLE(SAMPLING_PROFILER)
2599  
2600  JSC_DEFINE_HOST_FUNCTION(functionMaxArguments, (JSGlobalObject*, CallFrame*))
2601  {
2602      return JSValue::encode(jsNumber(JSC::maxArguments));
2603  }
2604  
2605  JSC_DEFINE_HOST_FUNCTION(functionAsyncTestStart, (JSGlobalObject* globalObject, CallFrame* callFrame))
2606  {
2607      VM& vm = globalObject->vm();
2608      auto scope = DECLARE_THROW_SCOPE(vm);
2609  
2610      JSValue numberOfAsyncPasses = callFrame->argument(0);
2611      if (!numberOfAsyncPasses.isUInt32())
2612          return throwVMError(globalObject, scope, "Expected first argument to be a uint32"_s);
2613  
2614      asyncTestExpectedPasses += numberOfAsyncPasses.asUInt32();
2615      return encodedJSUndefined();
2616  }
2617  
2618  JSC_DEFINE_HOST_FUNCTION(functionAsyncTestPassed, (JSGlobalObject*, CallFrame*))
2619  {
2620      asyncTestPasses++;
2621      return encodedJSUndefined();
2622  }
2623  
2624  #if ENABLE(WEBASSEMBLY)
2625  
2626  JSC_DEFINE_HOST_FUNCTION(functionWebAssemblyMemoryMode, (JSGlobalObject* globalObject, CallFrame* callFrame))
2627  {
2628      VM& vm = globalObject->vm();
2629      auto scope = DECLARE_THROW_SCOPE(vm);
2630      
2631      if (!Wasm::isSupported())
2632          return throwVMTypeError(globalObject, scope, "WebAssemblyMemoryMode should only be called if the useWebAssembly option is set"_s);
2633  
2634      if (JSObject* object = callFrame->argument(0).getObject()) {
2635          if (auto* memory = jsDynamicCast<JSWebAssemblyMemory*>(vm, object))
2636              return JSValue::encode(jsString(vm, makeString(memory->memory().mode())));
2637          if (auto* instance = jsDynamicCast<JSWebAssemblyInstance*>(vm, object))
2638              return JSValue::encode(jsString(vm, makeString(instance->memoryMode())));
2639      }
2640  
2641      return throwVMTypeError(globalObject, scope, "WebAssemblyMemoryMode expects either a WebAssembly.Memory or WebAssembly.Instance"_s);
2642  }
2643  
2644  #endif // ENABLE(WEBASSEMBLY)
2645  
2646  JSC_DEFINE_HOST_FUNCTION(functionSetUnhandledRejectionCallback, (JSGlobalObject* globalObject, CallFrame* callFrame))
2647  {
2648      VM& vm = globalObject->vm();
2649      JSObject* object = callFrame->argument(0).getObject();
2650      auto scope = DECLARE_THROW_SCOPE(vm);
2651  
2652      if (!object || !object->isCallable(vm))
2653          return throwVMTypeError(globalObject, scope);
2654  
2655      globalObject->setUnhandledRejectionCallback(vm, object);
2656      return JSValue::encode(jsUndefined());
2657  }
2658  
2659  JSC_DEFINE_HOST_FUNCTION(functionAsDoubleNumber, (JSGlobalObject* globalObject, CallFrame* callFrame))
2660  {
2661      VM& vm = globalObject->vm();
2662      auto scope = DECLARE_THROW_SCOPE(vm);
2663      double num = callFrame->argument(0).toNumber(globalObject);
2664      RETURN_IF_EXCEPTION(scope, encodedJSValue());
2665      return JSValue::encode(jsDoubleNumber(num));
2666  }
2667  
2668  JSC_DEFINE_HOST_FUNCTION(functionDropAllLocks, (JSGlobalObject* globalObject, CallFrame*))
2669  {
2670      JSLock::DropAllLocks dropAllLocks(globalObject);
2671      return JSValue::encode(jsUndefined());
2672  }
2673  
2674  // Use SEH for Release builds only to get rid of the crash report dialog
2675  // (luckily the same tests fail in Release and Debug builds so far). Need to
2676  // be in a separate main function because the jscmain function requires object
2677  // unwinding.
2678  
2679  #if COMPILER(MSVC) && !defined(_DEBUG)
2680  #define TRY       __try {
2681  #define EXCEPT(x) } __except (EXCEPTION_EXECUTE_HANDLER) { x; }
2682  #else
2683  #define TRY
2684  #define EXCEPT(x)
2685  #endif
2686  
2687  int jscmain(int argc, char** argv);
2688  
2689  #if OS(DARWIN) || OS(LINUX)
2690  static size_t memoryLimit;
2691  
2692  static void crashIfExceedingMemoryLimit()
2693  {
2694      if (!memoryLimit)
2695          return;
2696      MemoryFootprint footprint = MemoryFootprint::now();
2697      if (footprint.current > memoryLimit) {
2698          dataLogLn("Crashing because current footprint: ", footprint.current, " exceeds limit: ", memoryLimit);
2699          CRASH();
2700      }
2701  }
2702  
2703  static void startMemoryMonitoringThreadIfNeeded()
2704  {
2705      char* memoryLimitString = getenv("JSCTEST_memoryLimit");
2706      if (!memoryLimitString)
2707          return;
2708  
2709      if (sscanf(memoryLimitString, "%zu", &memoryLimit) != 1) {
2710          dataLogLn("WARNING: malformed JSCTEST_memoryLimit environment variable");
2711          return;
2712      }
2713  
2714      if (!memoryLimit)
2715          return;
2716  
2717      Thread::create("jsc Memory Monitor", [=] {
2718          while (true) {
2719              sleep(Seconds::fromMilliseconds(5));
2720              crashIfExceedingMemoryLimit();
2721          }
2722      });
2723  }
2724  #endif // OS(DARWIN) || OS(LINUX)
2725  
2726  static double s_desiredTimeout;
2727  static double s_timeoutMultiplier = 1.0;
2728  static Seconds s_timeoutDuration;
2729  static Seconds s_maxAllowedCPUTime;
2730  static VM* s_vm;
2731  
2732  static void startTimeoutTimer(Seconds duration)
2733  {
2734      Thread::create("jsc Timeout Thread", [=] () {
2735          sleep(duration);
2736          VMInspector::forEachVM([&] (VM& vm) -> VMInspector::FunctorStatus {
2737              if (&vm != s_vm)
2738                  return VMInspector::FunctorStatus::Continue;
2739              vm.notifyNeedShellTimeoutCheck();
2740              return VMInspector::FunctorStatus::Done;
2741          });
2742  
2743          if (const char* timeoutString = getenv("JSCTEST_hardTimeout")) {
2744              double hardTimeoutInDouble = 0;
2745              if (sscanf(timeoutString, "%lf", &hardTimeoutInDouble) != 1)
2746                  dataLog("WARNING: hardTimeout string is malformed, got ", timeoutString, " but expected a number. Not using a timeout.\n");
2747              else {
2748                  Seconds hardTimeout { hardTimeoutInDouble };
2749                  sleep(hardTimeout);
2750                  dataLogLn("HARD TIMEOUT after ", hardTimeout);
2751                  exit(EXIT_FAILURE);
2752              }
2753          }
2754      });
2755  }
2756  
2757  static void timeoutCheckCallback(VM& vm)
2758  {
2759      RELEASE_ASSERT(&vm == s_vm);
2760      auto cpuTime = CPUTime::forCurrentThread();
2761      if (cpuTime >= s_maxAllowedCPUTime) {
2762          dataLog("Timed out after ", s_timeoutDuration, " seconds!\n");
2763          CRASH();
2764      }
2765      auto remainingTime = s_maxAllowedCPUTime - cpuTime;
2766      startTimeoutTimer(remainingTime);
2767  }
2768  
2769  static void initializeTimeoutIfNeeded()
2770  {
2771      if (char* timeoutString = getenv("JSCTEST_timeout")) {
2772          if (sscanf(timeoutString, "%lf", &s_desiredTimeout) != 1) {
2773              dataLog("WARNING: timeout string is malformed, got ", timeoutString,
2774                  " but expected a number. Not using a timeout.\n");
2775          } else
2776              g_jscConfig.shellTimeoutCheckCallback = timeoutCheckCallback;
2777      }
2778  }
2779  
2780  static void startTimeoutThreadIfNeeded(VM& vm)
2781  {
2782      if (!g_jscConfig.shellTimeoutCheckCallback)
2783          return;
2784  
2785      s_vm = &vm;
2786      s_timeoutDuration = Seconds(s_desiredTimeout * s_timeoutMultiplier);
2787      s_maxAllowedCPUTime = CPUTime::forCurrentThread() + s_timeoutDuration;
2788      Seconds timeoutDuration(s_desiredTimeout * s_timeoutMultiplier);
2789      startTimeoutTimer(timeoutDuration);
2790  }
2791  
2792  int main(int argc, char** argv)
2793  {
2794  #if OS(DARWIN) && CPU(ARM_THUMB2)
2795      // Enabled IEEE754 denormal support.
2796      fenv_t env;
2797      fegetenv( &env );
2798      env.__fpscr &= ~0x01000000u;
2799      fesetenv( &env );
2800  #endif
2801  
2802  #if OS(WINDOWS)
2803      // Cygwin calls ::SetErrorMode(SEM_FAILCRITICALERRORS), which we will inherit. This is bad for
2804      // testing/debugging, as it causes the post-mortem debugger not to be invoked. We reset the
2805      // error mode here to work around Cygwin's behavior. See <http://webkit.org/b/55222>.
2806      ::SetErrorMode(0);
2807  
2808      _setmode(_fileno(stdout), _O_BINARY);
2809      _setmode(_fileno(stderr), _O_BINARY);
2810  
2811  #if defined(_DEBUG)
2812      _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
2813      _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2814      _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
2815      _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
2816      _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
2817      _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
2818  #endif
2819  
2820      timeBeginPeriod(1);
2821  #endif
2822  
2823  #if PLATFORM(GTK)
2824      if (!setlocale(LC_ALL, ""))
2825          WTFLogAlways("Locale not supported by C library.\n\tUsing the fallback 'C' locale.");
2826  #endif
2827  
2828      // Need to initialize WTF before we start any threads. Cannot initialize JSC
2829      // yet, since that would do somethings that we'd like to defer until after we
2830      // have a chance to parse options.
2831      WTF::initialize();
2832  
2833      // We can't use destructors in the following code because it uses Windows
2834      // Structured Exception Handling
2835      int res = EXIT_SUCCESS;
2836      TRY
2837          res = jscmain(argc, argv);
2838      EXCEPT(res = EXIT_EXCEPTION)
2839      finalizeStatsAtEndOfTesting();
2840      if (getenv("JS_SHELL_WAIT_FOR_INPUT_TO_EXIT")) {
2841          WTF::fastDisableScavenger();
2842          fprintf(stdout, "\njs shell waiting for input to exit\n");
2843          fflush(stdout);
2844          getc(stdin);
2845      }
2846  
2847      jscExit(res);
2848  }
2849  
2850  static void dumpException(GlobalObject* globalObject, JSValue exception)
2851  {
2852      VM& vm = globalObject->vm();
2853      auto scope = DECLARE_CATCH_SCOPE(vm);
2854  
2855  #define CHECK_EXCEPTION() do { \
2856          if (scope.exception()) { \
2857              scope.clearException(); \
2858              return; \
2859          } \
2860      } while (false)
2861  
2862      auto exceptionString = exception.toWTFString(globalObject);
2863      CHECK_EXCEPTION();
2864      Expected<CString, UTF8ConversionError> expectedCString = exceptionString.tryGetUtf8();
2865      if (expectedCString)
2866          printf("Exception: %s\n", expectedCString.value().data());
2867      else
2868          printf("Exception: <out of memory while extracting exception string>\n");
2869  
2870      Identifier nameID = Identifier::fromString(vm, "name");
2871      CHECK_EXCEPTION();
2872      Identifier fileNameID = Identifier::fromString(vm, "sourceURL");
2873      CHECK_EXCEPTION();
2874      Identifier lineNumberID = Identifier::fromString(vm, "line");
2875      CHECK_EXCEPTION();
2876      Identifier stackID = Identifier::fromString(vm, "stack");
2877      CHECK_EXCEPTION();
2878  
2879      JSValue nameValue = exception.get(globalObject, nameID);
2880      CHECK_EXCEPTION();
2881      JSValue fileNameValue = exception.get(globalObject, fileNameID);
2882      CHECK_EXCEPTION();
2883      JSValue lineNumberValue = exception.get(globalObject, lineNumberID);
2884      CHECK_EXCEPTION();
2885      JSValue stackValue = exception.get(globalObject, stackID);
2886      CHECK_EXCEPTION();
2887      
2888      auto nameString = nameValue.toWTFString(globalObject);
2889      CHECK_EXCEPTION();
2890  
2891      if (nameString == "SyntaxError" && (!fileNameValue.isUndefinedOrNull() || !lineNumberValue.isUndefinedOrNull())) {
2892          auto fileNameString = fileNameValue.toWTFString(globalObject);
2893          CHECK_EXCEPTION();
2894          auto lineNumberString = lineNumberValue.toWTFString(globalObject);
2895          CHECK_EXCEPTION();
2896          printf("at %s:%s\n", fileNameString.utf8().data(), lineNumberString.utf8().data());
2897      }
2898      
2899      if (!stackValue.isUndefinedOrNull()) {
2900          auto stackString = stackValue.toWTFString(globalObject);
2901          CHECK_EXCEPTION();
2902          if (stackString.length())
2903              printf("%s\n", stackString.utf8().data());
2904      }
2905  
2906  #undef CHECK_EXCEPTION
2907  }
2908  
2909  static bool checkUncaughtException(VM& vm, GlobalObject* globalObject, JSValue exception, const CommandLine& options)
2910  {
2911      const String& expectedExceptionName = options.m_uncaughtExceptionName;
2912      auto scope = DECLARE_CATCH_SCOPE(vm);
2913      scope.clearException();
2914      if (!exception) {
2915          printf("Expected uncaught exception with name '%s' but none was thrown\n", expectedExceptionName.utf8().data());
2916          return false;
2917      }
2918  
2919      JSValue exceptionClass = globalObject->get(globalObject, Identifier::fromString(vm, expectedExceptionName));
2920      if (!exceptionClass.isObject() || scope.exception()) {
2921          printf("Expected uncaught exception with name '%s' but given exception class is not defined\n", expectedExceptionName.utf8().data());
2922          return false;
2923      }
2924  
2925      bool isInstanceOfExpectedException = jsCast<JSObject*>(exceptionClass)->hasInstance(globalObject, exception);
2926      if (scope.exception()) {
2927          printf("Expected uncaught exception with name '%s' but given exception class fails performing hasInstance\n", expectedExceptionName.utf8().data());
2928          return false;
2929      }
2930      if (isInstanceOfExpectedException) {
2931          if (options.m_alwaysDumpUncaughtException)
2932              dumpException(globalObject, exception);
2933          return true;
2934      }
2935  
2936      printf("Expected uncaught exception with name '%s' but exception value is not instance of this exception class\n", expectedExceptionName.utf8().data());
2937      dumpException(globalObject, exception);
2938      return false;
2939  }
2940  
2941  static void checkException(GlobalObject* globalObject, bool isLastFile, bool hasException, JSValue value, const CommandLine& options, bool& success)
2942  {
2943      VM& vm = globalObject->vm();
2944  
2945      if (options.m_treatWatchdogExceptionAsSuccess && value.inherits<TerminatedExecutionError>(vm)) {
2946          ASSERT(hasException);
2947          return;
2948      }
2949  
2950      if (!options.m_uncaughtExceptionName || !isLastFile) {
2951          success = success && !hasException;
2952          if (options.m_dump && !hasException)
2953              printf("End: %s\n", value.toWTFString(globalObject).utf8().data());
2954          if (hasException)
2955              dumpException(globalObject, value);
2956      } else
2957          success = success && checkUncaughtException(vm, globalObject, (hasException) ? value : JSValue(), options);
2958  }
2959  
2960  void GlobalObject::reportUncaughtExceptionAtEventLoop(JSGlobalObject* globalObject, Exception* exception)
2961  {
2962      auto* global = jsCast<GlobalObject*>(globalObject);
2963      dumpException(global, exception->value());
2964      bool hideNoReturn = true;
2965      if (hideNoReturn)
2966          jscExit(EXIT_EXCEPTION);
2967  }
2968  
2969  static void runWithOptions(GlobalObject* globalObject, CommandLine& options, bool& success)
2970  {
2971      Vector<Script>& scripts = options.m_scripts;
2972      String fileName;
2973      Vector<char> scriptBuffer;
2974  
2975      VM& vm = globalObject->vm();
2976      auto scope = DECLARE_CATCH_SCOPE(vm);
2977  
2978  #if ENABLE(SAMPLING_FLAGS)
2979      SamplingFlags::start();
2980  #endif
2981  
2982      for (size_t i = 0; i < scripts.size(); i++) {
2983          JSInternalPromise* promise = nullptr;
2984          bool isModule = options.m_module || scripts[i].scriptType == Script::ScriptType::Module;
2985          if (scripts[i].codeSource == Script::CodeSource::File) {
2986              fileName = scripts[i].argument;
2987              if (scripts[i].strictMode == Script::StrictMode::Strict)
2988                  scriptBuffer.append("\"use strict\";\n", strlen("\"use strict\";\n"));
2989  
2990              if (isModule) {
2991                  // If the passed file isn't an absolute path append "./" so the module loader doesn't think this is a bare-name specifier.
2992                  fileName = fileName.startsWith('/') ? fileName : makeString("./", fileName);
2993                  promise = loadAndEvaluateModule(globalObject, fileName, jsUndefined(), jsUndefined());
2994                  scope.releaseAssertNoException();
2995              } else {
2996                  if (!fetchScriptFromLocalFileSystem(fileName, scriptBuffer)) {
2997                      success = false; // fail early so we can catch missing files
2998                      return;
2999                  }
3000              }
3001          } else {
3002              size_t commandLineLength = strlen(scripts[i].argument);
3003              scriptBuffer.resize(commandLineLength);
3004              std::copy(scripts[i].argument, scripts[i].argument + commandLineLength, scriptBuffer.begin());
3005              fileName = "[Command Line]"_s;
3006          }
3007  
3008          bool isLastFile = i == scripts.size() - 1;
3009          SourceOrigin sourceOrigin { absolutePath(fileName) };
3010          if (isModule) {
3011              if (!promise) {
3012                  // FIXME: This should use an absolute file URL https://bugs.webkit.org/show_bug.cgi?id=193077
3013                  promise = loadAndEvaluateModule(globalObject, jscSource(stringFromUTF(scriptBuffer), sourceOrigin, fileName, TextPosition(), SourceProviderSourceType::Module), jsUndefined());
3014                  RETURN_IF_EXCEPTION(scope, void());
3015              }
3016  
3017              JSFunction* fulfillHandler = JSNativeStdFunction::create(vm, globalObject, 1, String(), [&success, &options, isLastFile](JSGlobalObject* globalObject, CallFrame* callFrame) {
3018                  checkException(jsCast<GlobalObject*>(globalObject), isLastFile, false, callFrame->argument(0), options, success);
3019                  return JSValue::encode(jsUndefined());
3020              });
3021  
3022              JSFunction* rejectHandler = JSNativeStdFunction::create(vm, globalObject, 1, String(), [&success, &options, isLastFile](JSGlobalObject* globalObject, CallFrame* callFrame) {
3023                  checkException(jsCast<GlobalObject*>(globalObject), isLastFile, true, callFrame->argument(0), options, success);
3024                  return JSValue::encode(jsUndefined());
3025              });
3026  
3027              promise->then(globalObject, fulfillHandler, rejectHandler);
3028              scope.releaseAssertNoException();
3029              vm.drainMicrotasks();
3030          } else {
3031              NakedPtr<Exception> evaluationException;
3032              JSValue returnValue = evaluate(globalObject, jscSource(scriptBuffer, sourceOrigin , fileName), JSValue(), evaluationException);
3033              scope.assertNoException();
3034              if (evaluationException)
3035                  returnValue = evaluationException->value();
3036              checkException(globalObject, isLastFile, evaluationException, returnValue, options, success);
3037          }
3038  
3039          scriptBuffer.clear();
3040          scope.clearException();
3041      }
3042  
3043  #if ENABLE(REGEXP_TRACING)
3044      vm.dumpRegExpTrace();
3045  #endif
3046  }
3047  
3048  #define RUNNING_FROM_XCODE 0
3049  
3050  static void runInteractive(GlobalObject* globalObject)
3051  {
3052      VM& vm = globalObject->vm();
3053      auto scope = DECLARE_CATCH_SCOPE(vm);
3054  
3055      URL directoryName = currentWorkingDirectory();
3056      if (!directoryName.isValid())
3057          return;
3058      SourceOrigin sourceOrigin(URL(directoryName, "./interpreter"_s));
3059      
3060      bool shouldQuit = false;
3061      while (!shouldQuit) {
3062  #if HAVE(READLINE) && !RUNNING_FROM_XCODE
3063          ParserError error;
3064          String source;
3065          do {
3066              error = ParserError();
3067              char* line = readline(source.isEmpty() ? interactivePrompt : "... ");
3068              shouldQuit = !line;
3069              if (!line)
3070                  break;
3071              source = source + String::fromUTF8(line);
3072              source = source + '\n';
3073              checkSyntax(vm, jscSource(source, sourceOrigin), error);
3074              if (!line[0]) {
3075                  free(line);
3076                  break;
3077              }
3078              add_history(line);
3079              free(line);
3080          } while (error.syntaxErrorType() == ParserError::SyntaxErrorRecoverable);
3081          
3082          if (error.isValid()) {
3083              printf("%s:%d\n", error.message().utf8().data(), error.line());
3084              continue;
3085          }
3086          
3087          
3088          NakedPtr<Exception> evaluationException;
3089          JSValue returnValue = evaluate(globalObject, jscSource(source, sourceOrigin), JSValue(), evaluationException);
3090  #else
3091          printf("%s", interactivePrompt);
3092          Vector<char, 256> line;
3093          int c;
3094          while ((c = getchar()) != EOF) {
3095              // FIXME: Should we also break on \r? 
3096              if (c == '\n')
3097                  break;
3098              line.append(c);
3099          }
3100          if (line.isEmpty())
3101              break;
3102  
3103          NakedPtr<Exception> evaluationException;
3104          JSValue returnValue = evaluate(globalObject, jscSource(line, sourceOrigin, sourceOrigin.string()), JSValue(), evaluationException);
3105  #endif
3106          Expected<CString, UTF8ConversionError> utf8;
3107          if (evaluationException) {
3108              fputs("Exception: ", stdout);
3109              utf8 = evaluationException->value().toWTFString(globalObject).tryGetUtf8();
3110          } else
3111              utf8 = returnValue.toWTFString(globalObject).tryGetUtf8();
3112  
3113          CString result;
3114          if (utf8)
3115              result = utf8.value();
3116          else if (utf8.error() == UTF8ConversionError::OutOfMemory)
3117              result = "OutOfMemory while processing string";
3118          else
3119              result = "Error while processing string";
3120          fwrite(result.data(), sizeof(char), result.length(), stdout);
3121          putchar('\n');
3122  
3123          scope.clearException();
3124          vm.drainMicrotasks();
3125      }
3126      printf("\n");
3127  }
3128  
3129  static NO_RETURN void printUsageStatement(bool help = false)
3130  {
3131      fprintf(stderr, "Usage: jsc [options] [files] [-- arguments]\n");
3132      fprintf(stderr, "  -d         Dumps bytecode (debug builds only)\n");
3133      fprintf(stderr, "  -e         Evaluate argument as script code\n");
3134      fprintf(stderr, "  -f         Specifies a source file (deprecated)\n");
3135      fprintf(stderr, "  -h|--help  Prints this help message\n");
3136      fprintf(stderr, "  -i         Enables interactive mode (default if no files are specified)\n");
3137      fprintf(stderr, "  -m         Execute as a module\n");
3138  #if OS(UNIX)
3139      fprintf(stderr, "  -s         Installs signal handlers that exit on a crash (Unix platforms only, lldb will not work with this option) \n");
3140  #endif
3141      fprintf(stderr, "  -p <file>  Outputs profiling data to a file\n");
3142      fprintf(stderr, "  -x         Output exit code before terminating\n");
3143      fprintf(stderr, "\n");
3144      fprintf(stderr, "  --sample                   Collects and outputs sampling profiler data\n");
3145      fprintf(stderr, "  --test262-async            Check that some script calls the print function with the string 'Test262:AsyncTestComplete'\n");
3146      fprintf(stderr, "  --strict-file=<file>       Parse the given file as if it were in strict mode (this option may be passed more than once)\n");
3147      fprintf(stderr, "  --module-file=<file>       Parse and evaluate the given file as module (this option may be passed more than once)\n");
3148      fprintf(stderr, "  --exception=<name>         Check the last script exits with an uncaught exception with the specified name\n");
3149      fprintf(stderr, "  --watchdog-exception-ok    Uncaught watchdog exceptions exit with success\n");
3150      fprintf(stderr, "  --dumpException            Dump uncaught exception text\n");
3151      fprintf(stderr, "  --footprint                Dump memory footprint after done executing\n");
3152      fprintf(stderr, "  --options                  Dumps all JSC VM options and exits\n");
3153      fprintf(stderr, "  --dumpOptions              Dumps all non-default JSC VM options before continuing\n");
3154      fprintf(stderr, "  --<jsc VM option>=<value>  Sets the specified JSC VM option\n");
3155      fprintf(stderr, "  --destroy-vm               Destroy VM before exiting\n");
3156      fprintf(stderr, "  --can-block-is-false       Make main thread's Atomics.wait throw\n");
3157      fprintf(stderr, "\n");
3158      fprintf(stderr, "Files with a .mjs extension will always be evaluated as modules.\n");
3159      fprintf(stderr, "\n");
3160  
3161      jscExit(help ? EXIT_SUCCESS : EXIT_FAILURE);
3162  }
3163  
3164  static bool isMJSFile(char *filename)
3165  {
3166      filename = strrchr(filename, '.');
3167  
3168      if (filename)
3169          return !strcmp(filename, ".mjs");
3170  
3171      return false;
3172  }
3173  
3174  void CommandLine::parseArguments(int argc, char** argv)
3175  {
3176      Options::AllowUnfinalizedAccessScope scope;
3177      Options::initialize();
3178      Options::useSharedArrayBuffer() = true;
3179      Options::useAtMethod() = true;
3180      
3181  #if PLATFORM(IOS_FAMILY)
3182      Options::crashIfCantAllocateJITMemory() = true;
3183  #endif
3184  
3185      if (Options::dumpOptions()) {
3186          printf("Command line:");
3187  #if PLATFORM(COCOA)
3188          for (char** envp = *_NSGetEnviron(); *envp; envp++) {
3189              const char* env = *envp;
3190              if (!strncmp("JSC_", env, 4))
3191                  printf(" %s", env);
3192          }
3193  #endif // PLATFORM(COCOA)
3194          for (int i = 0; i < argc; ++i)
3195              printf(" %s", argv[i]);
3196          printf("\n");
3197      }
3198  
3199      int i = 1;
3200      JSC::Options::DumpLevel dumpOptionsLevel = JSC::Options::DumpLevel::None;
3201      bool needToExit = false;
3202  
3203      bool hasBadJSCOptions = false;
3204      for (; i < argc; ++i) {
3205          const char* arg = argv[i];
3206          if (!strcmp(arg, "-f")) {
3207              if (++i == argc)
3208                  printUsageStatement();
3209              m_scripts.append(Script(Script::StrictMode::Sloppy, Script::CodeSource::File, Script::ScriptType::Script, argv[i]));
3210              continue;
3211          }
3212          if (!strcmp(arg, "-e")) {
3213              if (++i == argc)
3214                  printUsageStatement();
3215              m_scripts.append(Script(Script::StrictMode::Sloppy, Script::CodeSource::CommandLine, Script::ScriptType::Script, argv[i]));
3216              continue;
3217          }
3218          if (!strcmp(arg, "-i")) {
3219              m_interactive = true;
3220              continue;
3221          }
3222          if (!strcmp(arg, "-d")) {
3223              m_dump = true;
3224              continue;
3225          }
3226          if (!strcmp(arg, "-p")) {
3227              if (++i == argc)
3228                  printUsageStatement();
3229              m_profile = true;
3230              m_profilerOutput = argv[i];
3231              continue;
3232          }
3233          if (!strcmp(arg, "-m")) {
3234              m_module = true;
3235              continue;
3236          }
3237          if (!strcmp(arg, "-s")) {
3238  #if OS(UNIX)
3239              SignalAction (*exit)(Signal, SigInfo&, PlatformRegisters&) = [] (Signal, SigInfo&, PlatformRegisters&) {
3240                  dataLogLn("Signal handler hit. Exiting with status 0");
3241                  _exit(0);
3242                  return SignalAction::ForceDefault;
3243              };
3244  
3245              addSignalHandler(Signal::IllegalInstruction, SignalHandler(exit));
3246              addSignalHandler(Signal::AccessFault, SignalHandler(exit));
3247              addSignalHandler(Signal::FloatingPoint, SignalHandler(exit));
3248              // once we do this lldb won't work anymore because we will exit on any breakpoints it sets.
3249              addSignalHandler(Signal::Breakpoint, SignalHandler(exit));
3250  
3251              activateSignalHandlersFor(Signal::IllegalInstruction);
3252              activateSignalHandlersFor(Signal::AccessFault);
3253              activateSignalHandlersFor(Signal::FloatingPoint);
3254              activateSignalHandlersFor(Signal::Breakpoint);
3255  
3256  #if !OS(DARWIN)
3257              addSignalHandler(Signal::Abort, SignalHandler(exit));
3258              activateSignalHandlersFor(Signal::Abort);
3259  #endif
3260  #endif
3261              continue;
3262          }
3263          if (!strcmp(arg, "-x")) {
3264              m_exitCode = true;
3265              continue;
3266          }
3267          if (!strcmp(arg, "--")) {
3268              ++i;
3269              break;
3270          }
3271          if (!strcmp(arg, "-h") || !strcmp(arg, "--help"))
3272              printUsageStatement(true);
3273  
3274          if (!strcmp(arg, "--options")) {
3275              dumpOptionsLevel = JSC::Options::DumpLevel::Verbose;
3276              needToExit = true;
3277              continue;
3278          }
3279          if (!strcmp(arg, "--dumpOptions")) {
3280              dumpOptionsLevel = JSC::Options::DumpLevel::Overridden;
3281              continue;
3282          }
3283          if (!strcmp(arg, "--sample")) {
3284              JSC::Options::useSamplingProfiler() = true;
3285              JSC::Options::collectSamplingProfilerDataForJSCShell() = true;
3286              m_dumpSamplingProfilerData = true;
3287              continue;
3288          }
3289          if (!strcmp(arg, "--destroy-vm")) {
3290              m_destroyVM = true;
3291              continue;
3292          }
3293          if (!strcmp(arg, "--can-block-is-false")) {
3294              m_canBlockIsFalse = true;
3295              continue;
3296          }
3297          if (!strcmp(arg, "--disableOptionsFreezingForTesting")) {
3298              Config::disableFreezingForTesting();
3299              continue;
3300          }
3301  
3302          static const char* timeoutMultiplierOptStr = "--timeoutMultiplier=";
3303          static const unsigned timeoutMultiplierOptStrLength = strlen(timeoutMultiplierOptStr);
3304          if (!strncmp(arg, timeoutMultiplierOptStr, timeoutMultiplierOptStrLength)) {
3305              const char* valueStr = &arg[timeoutMultiplierOptStrLength];
3306              if (sscanf(valueStr, "%lf", &s_timeoutMultiplier) != 1)
3307                  dataLog("WARNING: --timeoutMultiplier=", valueStr, " is invalid. Expects a numeric ratio.\n");
3308              continue;
3309          }
3310  
3311          if (!strcmp(arg, "--test262-async")) {
3312              asyncTestExpectedPasses++;
3313              continue;
3314          }
3315  
3316          if (!strcmp(arg, "--remote-debug")) {
3317              m_enableRemoteDebugging = true;
3318              continue;
3319          }
3320  
3321          static const unsigned strictFileStrLength = strlen("--strict-file=");
3322          if (!strncmp(arg, "--strict-file=", strictFileStrLength)) {
3323              m_scripts.append(Script(Script::StrictMode::Strict, Script::CodeSource::File, Script::ScriptType::Script, argv[i] + strictFileStrLength));
3324              continue;
3325          }
3326  
3327          static const unsigned moduleFileStrLength = strlen("--module-file=");
3328          if (!strncmp(arg, "--module-file=", moduleFileStrLength)) {
3329              m_scripts.append(Script(Script::StrictMode::Sloppy, Script::CodeSource::File, Script::ScriptType::Module, argv[i] + moduleFileStrLength));
3330              continue;
3331          }
3332  
3333          if (!strcmp(arg, "--dumpException")) {
3334              m_alwaysDumpUncaughtException = true;
3335              continue;
3336          }
3337  
3338          if (!strcmp(arg, "--footprint")) {
3339              m_dumpMemoryFootprint = true;
3340              continue;
3341          }
3342  
3343          static const unsigned exceptionStrLength = strlen("--exception=");
3344          if (!strncmp(arg, "--exception=", exceptionStrLength)) {
3345              m_uncaughtExceptionName = String(arg + exceptionStrLength);
3346              continue;
3347          }
3348  
3349          if (!strcmp(arg, "--watchdog-exception-ok")) {
3350              m_treatWatchdogExceptionAsSuccess = true;
3351              continue;
3352          }
3353  
3354          // See if the -- option is a JSC VM option.
3355          if (strstr(arg, "--") == arg) {
3356              if (!JSC::Options::setOption(&arg[2])) {
3357                  hasBadJSCOptions = true;
3358                  dataLog("ERROR: invalid option: ", arg, "\n");
3359              }
3360              continue;
3361          }
3362  
3363          // This arg is not recognized by the VM nor by jsc. Pass it on to the
3364          // script.
3365          Script::ScriptType scriptType = isMJSFile(argv[i]) ? Script::ScriptType::Module : Script::ScriptType::Script;
3366          m_scripts.append(Script(Script::StrictMode::Sloppy, Script::CodeSource::File, scriptType, argv[i]));
3367      }
3368  
3369      if (hasBadJSCOptions && JSC::Options::validateOptions())
3370          CRASH();
3371  
3372      if (m_scripts.isEmpty())
3373          m_interactive = true;
3374  
3375      for (; i < argc; ++i)
3376          m_arguments.append(argv[i]);
3377  
3378      if (dumpOptionsLevel != JSC::Options::DumpLevel::None) {
3379          const char* optionsTitle = (dumpOptionsLevel == JSC::Options::DumpLevel::Overridden)
3380              ? "Modified JSC runtime options:"
3381              : "All JSC runtime options:";
3382          JSC::Options::dumpAllOptions(stderr, dumpOptionsLevel, optionsTitle);
3383      }
3384      JSC::Options::ensureOptionsAreCoherent();
3385      if (needToExit)
3386          jscExit(EXIT_SUCCESS);
3387  }
3388  
3389  template<typename Func>
3390  int runJSC(const CommandLine& options, bool isWorker, const Func& func)
3391  {
3392      Worker worker(Workers::singleton());
3393      
3394      VM& vm = VM::create(LargeHeap).leakRef();
3395      if (!isWorker && options.m_canBlockIsFalse)
3396          vm.m_typedArrayController = adoptRef(new JSC::SimpleTypedArrayController(false));
3397  #if ENABLE(WEBASSEMBLY)
3398      Wasm::enableFastMemory();
3399  #endif
3400  
3401      int result;
3402      bool success = true;
3403      GlobalObject* globalObject = nullptr;
3404      {
3405          JSLockHolder locker(vm);
3406  
3407          startTimeoutThreadIfNeeded(vm);
3408          if (options.m_profile && !vm.m_perBytecodeProfiler)
3409              vm.m_perBytecodeProfiler = makeUnique<Profiler::Database>(vm);
3410  
3411          globalObject = GlobalObject::create(vm, GlobalObject::createStructure(vm, jsNull()), options.m_arguments);
3412          globalObject->setRemoteDebuggingEnabled(options.m_enableRemoteDebugging);
3413          func(vm, globalObject, success);
3414          vm.drainMicrotasks();
3415      }
3416      vm.deferredWorkTimer->runRunLoop();
3417      {
3418          JSLockHolder locker(vm);
3419          if (options.m_interactive && success)
3420              runInteractive(globalObject);
3421      }
3422  
3423      result = success && (asyncTestExpectedPasses == asyncTestPasses) ? 0 : 3;
3424  
3425      if (options.m_exitCode) {
3426          printf("jsc exiting %d", result);
3427          if (asyncTestExpectedPasses != asyncTestPasses)
3428              printf(" because expected: %d async test passes but got: %d async test passes", asyncTestExpectedPasses, asyncTestPasses);
3429          printf("\n");
3430      }
3431  
3432      if (options.m_profile) {
3433          JSLockHolder locker(vm);
3434          if (!vm.m_perBytecodeProfiler->save(options.m_profilerOutput.utf8().data()))
3435              fprintf(stderr, "could not save profiler output.\n");
3436      }
3437  
3438  #if ENABLE(JIT)
3439      {
3440          JSLockHolder locker(vm);
3441          if (Options::useExceptionFuzz())
3442              printf("JSC EXCEPTION FUZZ: encountered %u checks.\n", numberOfExceptionFuzzChecks());
3443          bool fireAtEnabled =
3444          Options::fireExecutableAllocationFuzzAt() || Options::fireExecutableAllocationFuzzAtOrAfter();
3445          if (Options::useExecutableAllocationFuzz() && (!fireAtEnabled || Options::verboseExecutableAllocationFuzz()))
3446              printf("JSC EXECUTABLE ALLOCATION FUZZ: encountered %u checks.\n", numberOfExecutableAllocationFuzzChecks());
3447          if (Options::useOSRExitFuzz() && Options::verboseOSRExitFuzz()) {
3448              printf("JSC OSR EXIT FUZZ: encountered %u static checks.\n", numberOfStaticOSRExitFuzzChecks());
3449              printf("JSC OSR EXIT FUZZ: encountered %u dynamic checks.\n", numberOfOSRExitFuzzChecks());
3450          }
3451  
3452          
3453          auto compileTimeStats = JIT::compileTimeStats();
3454          Vector<CString> compileTimeKeys;
3455          for (auto& entry : compileTimeStats)
3456              compileTimeKeys.append(entry.key);
3457          std::sort(compileTimeKeys.begin(), compileTimeKeys.end());
3458          for (const CString& key : compileTimeKeys) {
3459              if (key.data())
3460                  printf("%40s: %.3lf ms\n", key.data(), compileTimeStats.get(key).milliseconds());
3461          }
3462  
3463          if (Options::reportTotalPhaseTimes())
3464              logTotalPhaseTimes();
3465      }
3466  #endif
3467  
3468      if (Options::gcAtEnd()) {
3469          // We need to hold the API lock to do a GC.
3470          JSLockHolder locker(&vm);
3471          vm.heap.collectNow(Sync, CollectionScope::Full);
3472      }
3473  
3474      if (options.m_dumpSamplingProfilerData) {
3475  #if ENABLE(SAMPLING_PROFILER)
3476          JSLockHolder locker(&vm);
3477          vm.samplingProfiler()->reportTopFunctions();
3478          vm.samplingProfiler()->reportTopBytecodes();
3479  #else
3480          dataLog("Sampling profiler is not enabled on this platform\n");
3481  #endif
3482      }
3483  
3484      vm.codeCache()->write(vm);
3485  
3486      if (options.m_destroyVM || isWorker) {
3487          JSLockHolder locker(vm);
3488          // This is needed because we don't want the worker's main
3489          // thread to die before its compilation threads finish.
3490          vm.deref();
3491      }
3492  
3493      return result;
3494  }
3495  
3496  #if ENABLE(JIT_OPERATION_VALIDATION)
3497  extern const uintptr_t startOfJITOperationsInShell __asm("section$start$__DATA_CONST$__jsc_ops");
3498  extern const uintptr_t endOfJITOperationsInShell __asm("section$end$__DATA_CONST$__jsc_ops");
3499  #endif
3500  
3501  int jscmain(int argc, char** argv)
3502  {
3503      // Need to override and enable restricted options before we start parsing options below.
3504      Config::enableRestrictedOptions();
3505  
3506      WTF::initializeMainThread();
3507  
3508      // Note that the options parsing can affect VM creation, and thus
3509      // comes first.
3510      CommandLine options(argc, argv);
3511  
3512      {
3513          Options::AllowUnfinalizedAccessScope scope;
3514          processConfigFile(Options::configFile(), "jsc");
3515          if (options.m_dump)
3516              Options::dumpGeneratedBytecodes() = true;
3517      }
3518  
3519      JSC::initialize();
3520  #if ENABLE(JIT_OPERATION_VALIDATION)
3521      JSC::JITOperationList::populatePointersInEmbedder(&startOfJITOperationsInShell, &endOfJITOperationsInShell);
3522  #endif
3523      initializeTimeoutIfNeeded();
3524  
3525  #if OS(DARWIN) || OS(LINUX)
3526      startMemoryMonitoringThreadIfNeeded();
3527  #endif
3528  
3529      if (Options::useSuperSampler())
3530          enableSuperSampler();
3531  
3532      bool gigacageDisableRequested = false;
3533  #if GIGACAGE_ENABLED && !COMPILER(MSVC)
3534      if (char* gigacageEnabled = getenv("GIGACAGE_ENABLED")) {
3535          if (!strcasecmp(gigacageEnabled, "no") || !strcasecmp(gigacageEnabled, "false") || !strcasecmp(gigacageEnabled, "0"))
3536              gigacageDisableRequested = true;
3537      }
3538  #endif
3539      if (!gigacageDisableRequested)
3540          Gigacage::forbidDisablingPrimitiveGigacage();
3541  
3542  #if PLATFORM(COCOA)
3543      auto& memoryPressureHandler = MemoryPressureHandler::singleton();
3544      {
3545          dispatch_queue_t queue = dispatch_queue_create("jsc shell memory pressure handler", DISPATCH_QUEUE_SERIAL);
3546          memoryPressureHandler.setDispatchQueue(queue);
3547          dispatch_release(queue);
3548      }
3549      Box<Critical> memoryPressureCriticalState = Box<Critical>::create(Critical::No);
3550      Box<Synchronous> memoryPressureSynchronousState = Box<Synchronous>::create(Synchronous::No);
3551      memoryPressureHandler.setLowMemoryHandler([=] (Critical critical, Synchronous synchronous) {
3552          crashIfExceedingMemoryLimit();
3553  
3554          // We set these racily with respect to reading them from the JS execution thread.
3555          *memoryPressureCriticalState = critical;
3556          *memoryPressureSynchronousState = synchronous;
3557      });
3558      memoryPressureHandler.setShouldLogMemoryMemoryPressureEvents(false);
3559      memoryPressureHandler.install();
3560  
3561      auto onEachMicrotaskTick = [&] (VM& vm) {
3562          if (*memoryPressureCriticalState == Critical::No)
3563              return;
3564  
3565          *memoryPressureCriticalState = Critical::No;
3566          bool isSynchronous = *memoryPressureSynchronousState == Synchronous::Yes;
3567  
3568          WTF::releaseFastMallocFreeMemory();
3569          vm.deleteAllCode(DeleteAllCodeIfNotCollecting);
3570  
3571          if (!vm.heap.isCurrentThreadBusy()) {
3572              if (isSynchronous) {
3573                  vm.heap.collectNow(Sync, CollectionScope::Full);
3574                  WTF::releaseFastMallocFreeMemory();
3575              } else
3576                  vm.heap.collectNowFullIfNotDoneRecently(Async);
3577          }
3578      };
3579  #endif
3580  
3581      int result = runJSC(
3582          options, false,
3583          [&] (VM& vm, GlobalObject* globalObject, bool& success) {
3584              UNUSED_PARAM(vm);
3585  #if PLATFORM(COCOA)
3586              vm.setOnEachMicrotaskTick(WTFMove(onEachMicrotaskTick));
3587  #endif
3588              runWithOptions(globalObject, options, success);
3589          });
3590  
3591      printSuperSamplerState();
3592  
3593      if (options.m_dumpMemoryFootprint) {
3594          MemoryFootprint footprint = MemoryFootprint::now();
3595  
3596          printf("Memory Footprint:\n    Current Footprint: %" PRIu64 "\n    Peak Footprint: %" PRIu64 "\n", footprint.current, footprint.peak);
3597      }
3598  
3599      return result;
3600  }
3601  
3602  #if OS(WINDOWS)
3603  extern "C" __declspec(dllexport) int WINAPI dllLauncherEntryPoint(int argc, const char* argv[])
3604  {
3605      return main(argc, const_cast<char**>(argv));
3606  }
3607  #endif