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