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