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