source: webkit/trunk/Source/JavaScriptCore/jsc.cpp@ 204330

Last change on this file since 204330 was 204330, checked in by Yusuke Suzuki, 9 years ago

[ES6] Add ModuleLoaderPrototype and move methods to it
https://bugs.webkit.org/show_bug.cgi?id=160633

Reviewed by Saam Barati.

Source/JavaScriptCore:

In the future, we need to add the ability to create the new Loader object (by users).
So rather than holding all the methods in the ModuleLoaderObject instance, moving them
to ModuleLoaderPrototype and create the default JSModuleLoader instance is better.

No behavior change.

  • CMakeLists.txt:
  • DerivedSources.make:
  • JavaScriptCore.xcodeproj/project.pbxproj:
  • builtins/ModuleLoaderObject.js:

(setStateToMax): Deleted.
(newRegistryEntry): Deleted.
(ensureRegistered): Deleted.
(forceFulfillPromise): Deleted.
(fulfillFetch): Deleted.
(fulfillTranslate): Deleted.
(fulfillInstantiate): Deleted.
(commitInstantiated): Deleted.
(instantiation): Deleted.
(requestFetch): Deleted.
(requestTranslate): Deleted.
(requestInstantiate): Deleted.
(requestResolveDependencies.): Deleted.
(requestResolveDependencies): Deleted.
(requestInstantiateAll): Deleted.
(requestLink): Deleted.
(requestReady): Deleted.
(link): Deleted.
(moduleEvaluation): Deleted.
(provide): Deleted.
(loadAndEvaluateModule): Deleted.
(loadModule): Deleted.
(linkAndEvaluateModule): Deleted.

  • builtins/ModuleLoaderPrototype.js: Renamed from Source/JavaScriptCore/builtins/ModuleLoaderObject.js.

(setStateToMax):
(newRegistryEntry):
(ensureRegistered):
(forceFulfillPromise):
(fulfillFetch):
(fulfillTranslate):
(fulfillInstantiate):
(commitInstantiated):
(instantiation):
(requestFetch):
(requestTranslate):
(requestInstantiate):
(requestResolveDependencies.):
(requestResolveDependencies):
(requestInstantiateAll):
(requestLink):
(requestReady):
(link):
(moduleEvaluation):
(provide):
(loadAndEvaluateModule):
(loadModule):
(linkAndEvaluateModule):

  • bytecode/BytecodeIntrinsicRegistry.cpp:

(JSC::BytecodeIntrinsicRegistry::BytecodeIntrinsicRegistry):

  • jsc.cpp:

(GlobalObject::moduleLoaderResolve):
(GlobalObject::moduleLoaderFetch):

  • runtime/Completion.cpp:

(JSC::loadAndEvaluateModule):
(JSC::loadModule):

  • runtime/JSGlobalObject.cpp:

(JSC::JSGlobalObject::init):
(JSC::JSGlobalObject::visitChildren):

  • runtime/JSGlobalObject.h:

(JSC::JSGlobalObject::moduleLoader):
(JSC::JSGlobalObject::moduleLoaderStructure):

  • runtime/JSModuleLoader.cpp: Added.

(JSC::JSModuleLoader::JSModuleLoader):
(JSC::JSModuleLoader::finishCreation):
(JSC::printableModuleKey):
(JSC::JSModuleLoader::provide):
(JSC::JSModuleLoader::loadAndEvaluateModule):
(JSC::JSModuleLoader::loadModule):
(JSC::JSModuleLoader::linkAndEvaluateModule):
(JSC::JSModuleLoader::resolve):
(JSC::JSModuleLoader::fetch):
(JSC::JSModuleLoader::translate):
(JSC::JSModuleLoader::instantiate):
(JSC::JSModuleLoader::evaluate):

  • runtime/JSModuleLoader.h: Copied from Source/JavaScriptCore/runtime/ModuleLoaderObject.h.

(JSC::JSModuleLoader::create):
(JSC::JSModuleLoader::createStructure):

  • runtime/JSModuleRecord.h:
  • runtime/ModuleLoaderObject.cpp: Removed.

(JSC::ModuleLoaderObject::ModuleLoaderObject): Deleted.
(JSC::ModuleLoaderObject::finishCreation): Deleted.
(JSC::printableModuleKey): Deleted.
(JSC::ModuleLoaderObject::provide): Deleted.
(JSC::ModuleLoaderObject::loadAndEvaluateModule): Deleted.
(JSC::ModuleLoaderObject::loadModule): Deleted.
(JSC::ModuleLoaderObject::linkAndEvaluateModule): Deleted.
(JSC::ModuleLoaderObject::resolve): Deleted.
(JSC::ModuleLoaderObject::fetch): Deleted.
(JSC::ModuleLoaderObject::translate): Deleted.
(JSC::ModuleLoaderObject::instantiate): Deleted.
(JSC::ModuleLoaderObject::evaluate): Deleted.
(JSC::moduleLoaderObjectParseModule): Deleted.
(JSC::moduleLoaderObjectRequestedModules): Deleted.
(JSC::moduleLoaderObjectModuleDeclarationInstantiation): Deleted.
(JSC::moduleLoaderObjectResolve): Deleted.
(JSC::moduleLoaderObjectFetch): Deleted.
(JSC::moduleLoaderObjectTranslate): Deleted.
(JSC::moduleLoaderObjectInstantiate): Deleted.
(JSC::moduleLoaderObjectEvaluate): Deleted.

  • runtime/ModuleLoaderObject.h:

(JSC::ModuleLoaderObject::create): Deleted.
(JSC::ModuleLoaderObject::createStructure): Deleted.

  • runtime/ModuleLoaderPrototype.cpp: Added.

(JSC::ModuleLoaderPrototype::ModuleLoaderPrototype):
(JSC::moduleLoaderPrototypeParseModule):
(JSC::moduleLoaderPrototypeRequestedModules):
(JSC::moduleLoaderPrototypeModuleDeclarationInstantiation):
(JSC::moduleLoaderPrototypeResolve):
(JSC::moduleLoaderPrototypeFetch):
(JSC::moduleLoaderPrototypeTranslate):
(JSC::moduleLoaderPrototypeInstantiate):
(JSC::moduleLoaderPrototypeEvaluate):

  • runtime/ModuleLoaderPrototype.h: Renamed from Source/JavaScriptCore/runtime/ModuleLoaderObject.h.

(JSC::ModuleLoaderPrototype::create):
(JSC::ModuleLoaderPrototype::createStructure):

Source/WebCore:

No behavior change.

  • ForwardingHeaders/runtime/JSModuleLoader.h: Added.
  • bindings/js/JSDOMWindowBase.cpp:

(WebCore::JSDOMWindowBase::moduleLoaderResolve):
(WebCore::JSDOMWindowBase::moduleLoaderFetch):
(WebCore::JSDOMWindowBase::moduleLoaderEvaluate):

  • bindings/js/JSDOMWindowBase.h:
  • bindings/js/JSModuleLoader.cpp:

(WebCore::JSModuleLoader::resolve):
(WebCore::JSModuleLoader::fetch):
(WebCore::JSModuleLoader::evaluate):

  • bindings/js/JSModuleLoader.h:
  • Property svn:eol-style set to native
File size: 88.9 KB
Line 
1/*
2 * Copyright (C) 1999-2000 Harri Porten ([email protected])
3 * Copyright (C) 2004-2008, 2012-2013, 2015-2016 Apple Inc. All rights reserved.
4 * Copyright (C) 2006 Bjoern Graf ([email protected])
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 "ArrayPrototype.h"
26#include "BuiltinExecutableCreator.h"
27#include "ButterflyInlines.h"
28#include "CodeBlock.h"
29#include "Completion.h"
30#include "CopiedSpaceInlines.h"
31#include "Disassembler.h"
32#include "Exception.h"
33#include "ExceptionHelpers.h"
34#include "GetterSetter.h"
35#include "HeapProfiler.h"
36#include "HeapSnapshotBuilder.h"
37#include "HeapStatistics.h"
38#include "InitializeThreading.h"
39#include "Interpreter.h"
40#include "JIT.h"
41#include "JSArray.h"
42#include "JSArrayBuffer.h"
43#include "JSCInlines.h"
44#include "JSFunction.h"
45#include "JSInternalPromise.h"
46#include "JSInternalPromiseDeferred.h"
47#include "JSLock.h"
48#include "JSNativeStdFunction.h"
49#include "JSONObject.h"
50#include "JSProxy.h"
51#include "JSString.h"
52#include "JSWASMModule.h"
53#include "LLIntData.h"
54#include "ParserError.h"
55#include "ProfilerDatabase.h"
56#include "SamplingProfiler.h"
57#include "ShadowChicken.h"
58#include "StackVisitor.h"
59#include "StructureInlines.h"
60#include "StructureRareDataInlines.h"
61#include "SuperSampler.h"
62#include "TestRunnerUtils.h"
63#include "TypeProfilerLog.h"
64#include <locale.h>
65#include <math.h>
66#include <stdio.h>
67#include <stdlib.h>
68#include <string.h>
69#include <thread>
70#include <wtf/CurrentTime.h>
71#include <wtf/MainThread.h>
72#include <wtf/StringPrintStream.h>
73#include <wtf/text/StringBuilder.h>
74
75#if OS(WINDOWS)
76#include <direct.h>
77#else
78#include <unistd.h>
79#endif
80
81#if HAVE(READLINE)
82// readline/history.h has a Function typedef which conflicts with the WTF::Function template from WTF/Forward.h
83// We #define it to something else to avoid this conflict.
84#define Function ReadlineFunction
85#include <readline/history.h>
86#include <readline/readline.h>
87#undef Function
88#endif
89
90#if HAVE(SYS_TIME_H)
91#include <sys/time.h>
92#endif
93
94#if HAVE(SIGNAL_H)
95#include <signal.h>
96#endif
97
98#if COMPILER(MSVC)
99#include <crtdbg.h>
100#include <mmsystem.h>
101#include <windows.h>
102#endif
103
104#if PLATFORM(IOS) && CPU(ARM_THUMB2)
105#include <fenv.h>
106#include <arm/arch.h>
107#endif
108
109#if PLATFORM(EFL)
110#include <Ecore.h>
111#endif
112
113#if !defined(PATH_MAX)
114#define PATH_MAX 4096
115#endif
116
117using namespace JSC;
118using namespace WTF;
119
120namespace {
121
122NO_RETURN_WITH_VALUE static void jscExit(int status)
123{
124 waitForAsynchronousDisassembly();
125
126#if ENABLE(DFG_JIT)
127 if (DFG::isCrashing()) {
128 for (;;) {
129#if OS(WINDOWS)
130 Sleep(1000);
131#else
132 pause();
133#endif
134 }
135 }
136#endif // ENABLE(DFG_JIT)
137 exit(status);
138}
139
140class Element;
141class ElementHandleOwner;
142class Masuqerader;
143class Root;
144class RuntimeArray;
145
146class Element : public JSNonFinalObject {
147public:
148 Element(VM& vm, Structure* structure)
149 : Base(vm, structure)
150 {
151 }
152
153 typedef JSNonFinalObject Base;
154 static const bool needsDestruction = false;
155
156 Root* root() const { return m_root.get(); }
157 void setRoot(VM& vm, Root* root) { m_root.set(vm, this, root); }
158
159 static Element* create(VM& vm, JSGlobalObject* globalObject, Root* root)
160 {
161 Structure* structure = createStructure(vm, globalObject, jsNull());
162 Element* element = new (NotNull, allocateCell<Element>(vm.heap, sizeof(Element))) Element(vm, structure);
163 element->finishCreation(vm, root);
164 return element;
165 }
166
167 void finishCreation(VM&, Root*);
168
169 static void visitChildren(JSCell* cell, SlotVisitor& visitor)
170 {
171 Element* thisObject = jsCast<Element*>(cell);
172 ASSERT_GC_OBJECT_INHERITS(thisObject, info());
173 Base::visitChildren(thisObject, visitor);
174 visitor.append(&thisObject->m_root);
175 }
176
177 static ElementHandleOwner* handleOwner();
178
179 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
180 {
181 return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
182 }
183
184 DECLARE_INFO;
185
186private:
187 WriteBarrier<Root> m_root;
188};
189
190class ElementHandleOwner : public WeakHandleOwner {
191public:
192 virtual bool isReachableFromOpaqueRoots(Handle<JSC::Unknown> handle, void*, SlotVisitor& visitor)
193 {
194 Element* element = jsCast<Element*>(handle.slot()->asCell());
195 return visitor.containsOpaqueRoot(element->root());
196 }
197};
198
199class Masquerader : public JSNonFinalObject {
200public:
201 Masquerader(VM& vm, Structure* structure)
202 : Base(vm, structure)
203 {
204 }
205
206 typedef JSNonFinalObject Base;
207 static const unsigned StructureFlags = Base::StructureFlags | JSC::MasqueradesAsUndefined;
208
209 static Masquerader* create(VM& vm, JSGlobalObject* globalObject)
210 {
211 globalObject->masqueradesAsUndefinedWatchpoint()->fireAll(vm, "Masquerading object allocated");
212 Structure* structure = createStructure(vm, globalObject, jsNull());
213 Masquerader* result = new (NotNull, allocateCell<Masquerader>(vm.heap, sizeof(Masquerader))) Masquerader(vm, structure);
214 result->finishCreation(vm);
215 return result;
216 }
217
218 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
219 {
220 return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
221 }
222
223 DECLARE_INFO;
224};
225
226class Root : public JSDestructibleObject {
227public:
228 Root(VM& vm, Structure* structure)
229 : Base(vm, structure)
230 {
231 }
232
233 Element* element()
234 {
235 return m_element.get();
236 }
237
238 void setElement(Element* element)
239 {
240 Weak<Element> newElement(element, Element::handleOwner());
241 m_element.swap(newElement);
242 }
243
244 static Root* create(VM& vm, JSGlobalObject* globalObject)
245 {
246 Structure* structure = createStructure(vm, globalObject, jsNull());
247 Root* root = new (NotNull, allocateCell<Root>(vm.heap, sizeof(Root))) Root(vm, structure);
248 root->finishCreation(vm);
249 return root;
250 }
251
252 typedef JSDestructibleObject Base;
253
254 DECLARE_INFO;
255 static const bool needsDestruction = true;
256
257 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
258 {
259 return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
260 }
261
262 static void visitChildren(JSCell* thisObject, SlotVisitor& visitor)
263 {
264 Base::visitChildren(thisObject, visitor);
265 visitor.addOpaqueRoot(thisObject);
266 }
267
268private:
269 Weak<Element> m_element;
270};
271
272class ImpureGetter : public JSNonFinalObject {
273public:
274 ImpureGetter(VM& vm, Structure* structure)
275 : Base(vm, structure)
276 {
277 }
278
279 DECLARE_INFO;
280 typedef JSNonFinalObject Base;
281 static const unsigned StructureFlags = Base::StructureFlags | JSC::GetOwnPropertySlotIsImpure | JSC::OverridesGetOwnPropertySlot;
282
283 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
284 {
285 return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
286 }
287
288 static ImpureGetter* create(VM& vm, Structure* structure, JSObject* delegate)
289 {
290 ImpureGetter* getter = new (NotNull, allocateCell<ImpureGetter>(vm.heap, sizeof(ImpureGetter))) ImpureGetter(vm, structure);
291 getter->finishCreation(vm, delegate);
292 return getter;
293 }
294
295 void finishCreation(VM& vm, JSObject* delegate)
296 {
297 Base::finishCreation(vm);
298 if (delegate)
299 m_delegate.set(vm, this, delegate);
300 }
301
302 static bool getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName name, PropertySlot& slot)
303 {
304 ImpureGetter* thisObject = jsCast<ImpureGetter*>(object);
305
306 if (thisObject->m_delegate) {
307 if (thisObject->m_delegate->getPropertySlot(exec, name, slot))
308 return true;
309 if (exec->hadException())
310 return false;
311 }
312
313 return Base::getOwnPropertySlot(object, exec, name, slot);
314 }
315
316 static void visitChildren(JSCell* cell, SlotVisitor& visitor)
317 {
318 Base::visitChildren(cell, visitor);
319 ImpureGetter* thisObject = jsCast<ImpureGetter*>(cell);
320 visitor.append(&thisObject->m_delegate);
321 }
322
323 void setDelegate(VM& vm, JSObject* delegate)
324 {
325 m_delegate.set(vm, this, delegate);
326 }
327
328private:
329 WriteBarrier<JSObject> m_delegate;
330};
331
332class CustomGetter : public JSNonFinalObject {
333public:
334 CustomGetter(VM& vm, Structure* structure)
335 : Base(vm, structure)
336 {
337 }
338
339 DECLARE_INFO;
340 typedef JSNonFinalObject Base;
341 static const unsigned StructureFlags = Base::StructureFlags | JSC::OverridesGetOwnPropertySlot;
342
343 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
344 {
345 return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
346 }
347
348 static CustomGetter* create(VM& vm, Structure* structure)
349 {
350 CustomGetter* getter = new (NotNull, allocateCell<CustomGetter>(vm.heap, sizeof(CustomGetter))) CustomGetter(vm, structure);
351 getter->finishCreation(vm);
352 return getter;
353 }
354
355 static bool getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot)
356 {
357 CustomGetter* thisObject = jsCast<CustomGetter*>(object);
358 if (propertyName == PropertyName(Identifier::fromString(exec, "customGetter"))) {
359 slot.setCacheableCustom(thisObject, DontDelete | ReadOnly | DontEnum, thisObject->customGetter);
360 return true;
361 }
362 return JSObject::getOwnPropertySlot(thisObject, exec, propertyName, slot);
363 }
364
365private:
366 static EncodedJSValue customGetter(ExecState* exec, EncodedJSValue thisValue, PropertyName)
367 {
368 CustomGetter* thisObject = jsDynamicCast<CustomGetter*>(JSValue::decode(thisValue));
369 if (!thisObject)
370 return throwVMTypeError(exec);
371 bool shouldThrow = thisObject->get(exec, PropertyName(Identifier::fromString(exec, "shouldThrow"))).toBoolean(exec);
372 if (shouldThrow)
373 return throwVMTypeError(exec);
374 return JSValue::encode(jsNumber(100));
375 }
376};
377
378class RuntimeArray : public JSArray {
379public:
380 typedef JSArray Base;
381 static const unsigned StructureFlags = Base::StructureFlags | OverridesGetOwnPropertySlot | InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero | OverridesGetPropertyNames;
382
383 static RuntimeArray* create(ExecState* exec)
384 {
385 VM& vm = exec->vm();
386 JSGlobalObject* globalObject = exec->lexicalGlobalObject();
387 Structure* structure = createStructure(vm, globalObject, createPrototype(vm, globalObject));
388 RuntimeArray* runtimeArray = new (NotNull, allocateCell<RuntimeArray>(*exec->heap())) RuntimeArray(exec, structure);
389 runtimeArray->finishCreation(exec);
390 vm.heap.addFinalizer(runtimeArray, destroy);
391 return runtimeArray;
392 }
393
394 ~RuntimeArray() { }
395
396 static void destroy(JSCell* cell)
397 {
398 static_cast<RuntimeArray*>(cell)->RuntimeArray::~RuntimeArray();
399 }
400
401 static const bool needsDestruction = false;
402
403 static bool getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot)
404 {
405 RuntimeArray* thisObject = jsCast<RuntimeArray*>(object);
406 if (propertyName == exec->propertyNames().length) {
407 slot.setCacheableCustom(thisObject, DontDelete | ReadOnly | DontEnum, thisObject->lengthGetter);
408 return true;
409 }
410
411 Optional<uint32_t> index = parseIndex(propertyName);
412 if (index && index.value() < thisObject->getLength()) {
413 slot.setValue(thisObject, DontDelete | DontEnum, jsNumber(thisObject->m_vector[index.value()]));
414 return true;
415 }
416
417 return JSObject::getOwnPropertySlot(thisObject, exec, propertyName, slot);
418 }
419
420 static bool getOwnPropertySlotByIndex(JSObject* object, ExecState* exec, unsigned index, PropertySlot& slot)
421 {
422 RuntimeArray* thisObject = jsCast<RuntimeArray*>(object);
423 if (index < thisObject->getLength()) {
424 slot.setValue(thisObject, DontDelete | DontEnum, jsNumber(thisObject->m_vector[index]));
425 return true;
426 }
427
428 return JSObject::getOwnPropertySlotByIndex(thisObject, exec, index, slot);
429 }
430
431 static NO_RETURN_DUE_TO_CRASH bool put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&)
432 {
433 RELEASE_ASSERT_NOT_REACHED();
434 }
435
436 static NO_RETURN_DUE_TO_CRASH bool deleteProperty(JSCell*, ExecState*, PropertyName)
437 {
438 RELEASE_ASSERT_NOT_REACHED();
439 }
440
441 unsigned getLength() const { return m_vector.size(); }
442
443 DECLARE_INFO;
444
445 static ArrayPrototype* createPrototype(VM&, JSGlobalObject* globalObject)
446 {
447 return globalObject->arrayPrototype();
448 }
449
450 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
451 {
452 return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info(), ArrayClass);
453 }
454
455protected:
456 void finishCreation(ExecState* exec)
457 {
458 Base::finishCreation(exec->vm());
459 ASSERT(inherits(info()));
460
461 for (size_t i = 0; i < exec->argumentCount(); i++)
462 m_vector.append(exec->argument(i).toInt32(exec));
463 }
464
465private:
466 RuntimeArray(ExecState* exec, Structure* structure)
467 : JSArray(exec->vm(), structure, 0)
468 {
469 }
470
471 static EncodedJSValue lengthGetter(ExecState* exec, EncodedJSValue thisValue, PropertyName)
472 {
473 RuntimeArray* thisObject = jsDynamicCast<RuntimeArray*>(JSValue::decode(thisValue));
474 if (!thisObject)
475 return throwVMTypeError(exec);
476 return JSValue::encode(jsNumber(thisObject->getLength()));
477 }
478
479 Vector<int> m_vector;
480};
481
482class SimpleObject : public JSNonFinalObject {
483public:
484 SimpleObject(VM& vm, Structure* structure)
485 : Base(vm, structure)
486 {
487 }
488
489 typedef JSNonFinalObject Base;
490 static const bool needsDestruction = false;
491
492 static SimpleObject* create(VM& vm, JSGlobalObject* globalObject)
493 {
494 Structure* structure = createStructure(vm, globalObject, jsNull());
495 SimpleObject* simpleObject = new (NotNull, allocateCell<SimpleObject>(vm.heap, sizeof(SimpleObject))) SimpleObject(vm, structure);
496 simpleObject->finishCreation(vm);
497 return simpleObject;
498 }
499
500 static void visitChildren(JSCell* cell, SlotVisitor& visitor)
501 {
502 SimpleObject* thisObject = jsCast<SimpleObject*>(cell);
503 ASSERT_GC_OBJECT_INHERITS(thisObject, info());
504 Base::visitChildren(thisObject, visitor);
505 visitor.append(&thisObject->m_hiddenValue);
506 }
507
508 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
509 {
510 return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
511 }
512
513 JSValue hiddenValue()
514 {
515 return m_hiddenValue.get();
516 }
517
518 void setHiddenValue(VM& vm, JSValue value)
519 {
520 ASSERT(value.isCell());
521 m_hiddenValue.set(vm, this, value);
522 }
523
524 DECLARE_INFO;
525
526private:
527 WriteBarrier<JSC::Unknown> m_hiddenValue;
528};
529
530
531const ClassInfo Element::s_info = { "Element", &Base::s_info, 0, CREATE_METHOD_TABLE(Element) };
532const ClassInfo Masquerader::s_info = { "Masquerader", &Base::s_info, 0, CREATE_METHOD_TABLE(Masquerader) };
533const ClassInfo Root::s_info = { "Root", &Base::s_info, 0, CREATE_METHOD_TABLE(Root) };
534const ClassInfo ImpureGetter::s_info = { "ImpureGetter", &Base::s_info, 0, CREATE_METHOD_TABLE(ImpureGetter) };
535const ClassInfo CustomGetter::s_info = { "CustomGetter", &Base::s_info, 0, CREATE_METHOD_TABLE(CustomGetter) };
536const ClassInfo RuntimeArray::s_info = { "RuntimeArray", &Base::s_info, 0, CREATE_METHOD_TABLE(RuntimeArray) };
537const ClassInfo SimpleObject::s_info = { "SimpleObject", &Base::s_info, 0, CREATE_METHOD_TABLE(SimpleObject) };
538static bool test262AsyncPassed { false };
539static bool test262AsyncTest { false };
540
541ElementHandleOwner* Element::handleOwner()
542{
543 static ElementHandleOwner* owner = 0;
544 if (!owner)
545 owner = new ElementHandleOwner();
546 return owner;
547}
548
549void Element::finishCreation(VM& vm, Root* root)
550{
551 Base::finishCreation(vm);
552 setRoot(vm, root);
553 m_root->setElement(this);
554}
555
556}
557
558static bool fillBufferWithContentsOfFile(const String& fileName, Vector<char>& buffer);
559
560static EncodedJSValue JSC_HOST_CALL functionCreateProxy(ExecState*);
561static EncodedJSValue JSC_HOST_CALL functionCreateRuntimeArray(ExecState*);
562static EncodedJSValue JSC_HOST_CALL functionCreateImpureGetter(ExecState*);
563static EncodedJSValue JSC_HOST_CALL functionCreateCustomGetterObject(ExecState*);
564static EncodedJSValue JSC_HOST_CALL functionCreateBuiltin(ExecState*);
565static EncodedJSValue JSC_HOST_CALL functionCreateGlobalObject(ExecState*);
566static EncodedJSValue JSC_HOST_CALL functionSetImpureGetterDelegate(ExecState*);
567
568static EncodedJSValue JSC_HOST_CALL functionSetElementRoot(ExecState*);
569static EncodedJSValue JSC_HOST_CALL functionCreateRoot(ExecState*);
570static EncodedJSValue JSC_HOST_CALL functionCreateElement(ExecState*);
571static EncodedJSValue JSC_HOST_CALL functionGetElement(ExecState*);
572static EncodedJSValue JSC_HOST_CALL functionCreateSimpleObject(ExecState*);
573static EncodedJSValue JSC_HOST_CALL functionGetHiddenValue(ExecState*);
574static EncodedJSValue JSC_HOST_CALL functionSetHiddenValue(ExecState*);
575static EncodedJSValue JSC_HOST_CALL functionPrint(ExecState*);
576static EncodedJSValue JSC_HOST_CALL functionDebug(ExecState*);
577static EncodedJSValue JSC_HOST_CALL functionDescribe(ExecState*);
578static EncodedJSValue JSC_HOST_CALL functionDescribeArray(ExecState*);
579static EncodedJSValue JSC_HOST_CALL functionJSCStack(ExecState*);
580static EncodedJSValue JSC_HOST_CALL functionGCAndSweep(ExecState*);
581static EncodedJSValue JSC_HOST_CALL functionFullGC(ExecState*);
582static EncodedJSValue JSC_HOST_CALL functionEdenGC(ExecState*);
583static EncodedJSValue JSC_HOST_CALL functionForceGCSlowPaths(ExecState*);
584static EncodedJSValue JSC_HOST_CALL functionHeapSize(ExecState*);
585static EncodedJSValue JSC_HOST_CALL functionAddressOf(ExecState*);
586static EncodedJSValue JSC_HOST_CALL functionGetGetterSetter(ExecState*);
587#ifndef NDEBUG
588static EncodedJSValue JSC_HOST_CALL functionDumpCallFrame(ExecState*);
589#endif
590static EncodedJSValue JSC_HOST_CALL functionVersion(ExecState*);
591static EncodedJSValue JSC_HOST_CALL functionRun(ExecState*);
592static EncodedJSValue JSC_HOST_CALL functionLoad(ExecState*);
593static EncodedJSValue JSC_HOST_CALL functionLoadString(ExecState*);
594static EncodedJSValue JSC_HOST_CALL functionReadFile(ExecState*);
595static EncodedJSValue JSC_HOST_CALL functionCheckSyntax(ExecState*);
596static EncodedJSValue JSC_HOST_CALL functionReadline(ExecState*);
597static EncodedJSValue JSC_HOST_CALL functionPreciseTime(ExecState*);
598static EncodedJSValue JSC_HOST_CALL functionNeverInlineFunction(ExecState*);
599static EncodedJSValue JSC_HOST_CALL functionNoDFG(ExecState*);
600static EncodedJSValue JSC_HOST_CALL functionNoFTL(ExecState*);
601static EncodedJSValue JSC_HOST_CALL functionOptimizeNextInvocation(ExecState*);
602static EncodedJSValue JSC_HOST_CALL functionNumberOfDFGCompiles(ExecState*);
603static EncodedJSValue JSC_HOST_CALL functionReoptimizationRetryCount(ExecState*);
604static EncodedJSValue JSC_HOST_CALL functionTransferArrayBuffer(ExecState*);
605static EncodedJSValue JSC_HOST_CALL functionFailNextNewCodeBlock(ExecState*);
606static NO_RETURN_WITH_VALUE EncodedJSValue JSC_HOST_CALL functionQuit(ExecState*);
607static NO_RETURN_DUE_TO_CRASH EncodedJSValue JSC_HOST_CALL functionAbort(ExecState*);
608static EncodedJSValue JSC_HOST_CALL functionFalse1(ExecState*);
609static EncodedJSValue JSC_HOST_CALL functionFalse2(ExecState*);
610static EncodedJSValue JSC_HOST_CALL functionUndefined1(ExecState*);
611static EncodedJSValue JSC_HOST_CALL functionUndefined2(ExecState*);
612static EncodedJSValue JSC_HOST_CALL functionIsInt32(ExecState*);
613static EncodedJSValue JSC_HOST_CALL functionEffectful42(ExecState*);
614static EncodedJSValue JSC_HOST_CALL functionIdentity(ExecState*);
615static EncodedJSValue JSC_HOST_CALL functionMakeMasquerader(ExecState*);
616static EncodedJSValue JSC_HOST_CALL functionHasCustomProperties(ExecState*);
617static EncodedJSValue JSC_HOST_CALL functionDumpTypesForAllVariables(ExecState*);
618static EncodedJSValue JSC_HOST_CALL functionFindTypeForExpression(ExecState*);
619static EncodedJSValue JSC_HOST_CALL functionReturnTypeFor(ExecState*);
620static EncodedJSValue JSC_HOST_CALL functionDumpBasicBlockExecutionRanges(ExecState*);
621static EncodedJSValue JSC_HOST_CALL functionHasBasicBlockExecuted(ExecState*);
622static EncodedJSValue JSC_HOST_CALL functionBasicBlockExecutionCount(ExecState*);
623static EncodedJSValue JSC_HOST_CALL functionEnableExceptionFuzz(ExecState*);
624static EncodedJSValue JSC_HOST_CALL functionDrainMicrotasks(ExecState*);
625static EncodedJSValue JSC_HOST_CALL functionIs32BitPlatform(ExecState*);
626static EncodedJSValue JSC_HOST_CALL functionLoadModule(ExecState*);
627static EncodedJSValue JSC_HOST_CALL functionCheckModuleSyntax(ExecState*);
628static EncodedJSValue JSC_HOST_CALL functionPlatformSupportsSamplingProfiler(ExecState*);
629static EncodedJSValue JSC_HOST_CALL functionGenerateHeapSnapshot(ExecState*);
630#if ENABLE(SAMPLING_PROFILER)
631static EncodedJSValue JSC_HOST_CALL functionStartSamplingProfiler(ExecState*);
632static EncodedJSValue JSC_HOST_CALL functionSamplingProfilerStackTraces(ExecState*);
633#endif
634
635#if ENABLE(SAMPLING_FLAGS)
636static EncodedJSValue JSC_HOST_CALL functionSetSamplingFlags(ExecState*);
637static EncodedJSValue JSC_HOST_CALL functionClearSamplingFlags(ExecState*);
638#endif
639
640static EncodedJSValue JSC_HOST_CALL functionShadowChickenFunctionsOnStack(ExecState*);
641static EncodedJSValue JSC_HOST_CALL functionSetGlobalConstRedeclarationShouldNotThrow(ExecState*);
642
643struct Script {
644 enum class StrictMode {
645 Strict,
646 Sloppy
647 };
648
649 enum class ScriptType {
650 Script,
651 Module
652 };
653
654 enum class CodeSource {
655 File,
656 CommandLine
657 };
658
659 StrictMode strictMode;
660 CodeSource codeSource;
661 ScriptType scriptType;
662 char* argument;
663
664 Script(StrictMode strictMode, CodeSource codeSource, ScriptType scriptType, char *argument)
665 : strictMode(strictMode)
666 , codeSource(codeSource)
667 , scriptType(scriptType)
668 , argument(argument)
669 {
670 if (strictMode == StrictMode::Strict)
671 ASSERT(codeSource == CodeSource::File);
672 }
673};
674
675class CommandLine {
676public:
677 CommandLine(int argc, char** argv)
678 {
679 parseArguments(argc, argv);
680 }
681
682 bool m_interactive { false };
683 bool m_dump { false };
684 bool m_module { false };
685 bool m_exitCode { false };
686 Vector<Script> m_scripts;
687 Vector<String> m_arguments;
688 bool m_profile { false };
689 String m_profilerOutput;
690 String m_uncaughtExceptionName;
691 bool m_dumpSamplingProfilerData { false };
692
693 void parseArguments(int, char**);
694};
695
696static const char interactivePrompt[] = ">>> ";
697
698class StopWatch {
699public:
700 void start();
701 void stop();
702 long getElapsedMS(); // call stop() first
703
704private:
705 double m_startTime;
706 double m_stopTime;
707};
708
709void StopWatch::start()
710{
711 m_startTime = monotonicallyIncreasingTime();
712}
713
714void StopWatch::stop()
715{
716 m_stopTime = monotonicallyIncreasingTime();
717}
718
719long StopWatch::getElapsedMS()
720{
721 return static_cast<long>((m_stopTime - m_startTime) * 1000);
722}
723
724template<typename Vector>
725static inline String stringFromUTF(const Vector& utf8)
726{
727 return String::fromUTF8WithLatin1Fallback(utf8.data(), utf8.size());
728}
729
730template<typename Vector>
731static inline SourceCode jscSource(const Vector& utf8, const String& filename)
732{
733 String str = stringFromUTF(utf8);
734 return makeSource(str, filename);
735}
736
737class GlobalObject : public JSGlobalObject {
738private:
739 GlobalObject(VM&, Structure*);
740
741public:
742 typedef JSGlobalObject Base;
743
744 static GlobalObject* create(VM& vm, Structure* structure, const Vector<String>& arguments)
745 {
746 GlobalObject* object = new (NotNull, allocateCell<GlobalObject>(vm.heap)) GlobalObject(vm, structure);
747 object->finishCreation(vm, arguments);
748 vm.heap.addFinalizer(object, destroy);
749 return object;
750 }
751
752 static const bool needsDestruction = false;
753
754 DECLARE_INFO;
755 static const GlobalObjectMethodTable s_globalObjectMethodTable;
756
757 static Structure* createStructure(VM& vm, JSValue prototype)
758 {
759 return Structure::create(vm, 0, prototype, TypeInfo(GlobalObjectType, StructureFlags), info());
760 }
761
762 static RuntimeFlags javaScriptRuntimeFlags(const JSGlobalObject*) { return RuntimeFlags::createAllEnabled(); }
763
764protected:
765 void finishCreation(VM& vm, const Vector<String>& arguments)
766 {
767 Base::finishCreation(vm);
768
769 addFunction(vm, "debug", functionDebug, 1);
770 addFunction(vm, "describe", functionDescribe, 1);
771 addFunction(vm, "describeArray", functionDescribeArray, 1);
772 addFunction(vm, "print", functionPrint, 1);
773 addFunction(vm, "quit", functionQuit, 0);
774 addFunction(vm, "abort", functionAbort, 0);
775 addFunction(vm, "gc", functionGCAndSweep, 0);
776 addFunction(vm, "fullGC", functionFullGC, 0);
777 addFunction(vm, "edenGC", functionEdenGC, 0);
778 addFunction(vm, "forceGCSlowPaths", functionForceGCSlowPaths, 0);
779 addFunction(vm, "gcHeapSize", functionHeapSize, 0);
780 addFunction(vm, "addressOf", functionAddressOf, 1);
781 addFunction(vm, "getGetterSetter", functionGetGetterSetter, 2);
782#ifndef NDEBUG
783 addFunction(vm, "dumpCallFrame", functionDumpCallFrame, 0);
784#endif
785 addFunction(vm, "version", functionVersion, 1);
786 addFunction(vm, "run", functionRun, 1);
787 addFunction(vm, "load", functionLoad, 1);
788 addFunction(vm, "loadString", functionLoadString, 1);
789 addFunction(vm, "readFile", functionReadFile, 1);
790 addFunction(vm, "checkSyntax", functionCheckSyntax, 1);
791 addFunction(vm, "jscStack", functionJSCStack, 1);
792 addFunction(vm, "readline", functionReadline, 0);
793 addFunction(vm, "preciseTime", functionPreciseTime, 0);
794 addFunction(vm, "neverInlineFunction", functionNeverInlineFunction, 1);
795 addFunction(vm, "noInline", functionNeverInlineFunction, 1);
796 addFunction(vm, "noDFG", functionNoDFG, 1);
797 addFunction(vm, "noFTL", functionNoFTL, 1);
798 addFunction(vm, "numberOfDFGCompiles", functionNumberOfDFGCompiles, 1);
799 addFunction(vm, "optimizeNextInvocation", functionOptimizeNextInvocation, 1);
800 addFunction(vm, "reoptimizationRetryCount", functionReoptimizationRetryCount, 1);
801 addFunction(vm, "transferArrayBuffer", functionTransferArrayBuffer, 1);
802 addFunction(vm, "failNextNewCodeBlock", functionFailNextNewCodeBlock, 1);
803#if ENABLE(SAMPLING_FLAGS)
804 addFunction(vm, "setSamplingFlags", functionSetSamplingFlags, 1);
805 addFunction(vm, "clearSamplingFlags", functionClearSamplingFlags, 1);
806#endif
807 addFunction(vm, "shadowChickenFunctionsOnStack", functionShadowChickenFunctionsOnStack, 0);
808 addFunction(vm, "setGlobalConstRedeclarationShouldNotThrow", functionSetGlobalConstRedeclarationShouldNotThrow, 0);
809 addConstructableFunction(vm, "Root", functionCreateRoot, 0);
810 addConstructableFunction(vm, "Element", functionCreateElement, 1);
811 addFunction(vm, "getElement", functionGetElement, 1);
812 addFunction(vm, "setElementRoot", functionSetElementRoot, 2);
813
814 addConstructableFunction(vm, "SimpleObject", functionCreateSimpleObject, 0);
815 addFunction(vm, "getHiddenValue", functionGetHiddenValue, 1);
816 addFunction(vm, "setHiddenValue", functionSetHiddenValue, 2);
817
818 putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "DFGTrue"), 0, functionFalse1, DFGTrueIntrinsic, DontEnum);
819 putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "OSRExit"), 0, functionUndefined1, OSRExitIntrinsic, DontEnum);
820 putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "isFinalTier"), 0, functionFalse2, IsFinalTierIntrinsic, DontEnum);
821 putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "predictInt32"), 0, functionUndefined2, SetInt32HeapPredictionIntrinsic, DontEnum);
822 putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "isInt32"), 0, functionIsInt32, CheckInt32Intrinsic, DontEnum);
823 putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "fiatInt52"), 0, functionIdentity, FiatInt52Intrinsic, DontEnum);
824
825 addFunction(vm, "effectful42", functionEffectful42, 0);
826 addFunction(vm, "makeMasquerader", functionMakeMasquerader, 0);
827 addFunction(vm, "hasCustomProperties", functionHasCustomProperties, 0);
828
829 addFunction(vm, "createProxy", functionCreateProxy, 1);
830 addFunction(vm, "createRuntimeArray", functionCreateRuntimeArray, 0);
831
832 addFunction(vm, "createImpureGetter", functionCreateImpureGetter, 1);
833 addFunction(vm, "createCustomGetterObject", functionCreateCustomGetterObject, 0);
834 addFunction(vm, "createBuiltin", functionCreateBuiltin, 2);
835 addFunction(vm, "createGlobalObject", functionCreateGlobalObject, 0);
836 addFunction(vm, "setImpureGetterDelegate", functionSetImpureGetterDelegate, 2);
837
838 addFunction(vm, "dumpTypesForAllVariables", functionDumpTypesForAllVariables , 0);
839 addFunction(vm, "findTypeForExpression", functionFindTypeForExpression, 2);
840 addFunction(vm, "returnTypeFor", functionReturnTypeFor, 1);
841
842 addFunction(vm, "dumpBasicBlockExecutionRanges", functionDumpBasicBlockExecutionRanges , 0);
843 addFunction(vm, "hasBasicBlockExecuted", functionHasBasicBlockExecuted, 2);
844 addFunction(vm, "basicBlockExecutionCount", functionBasicBlockExecutionCount, 2);
845
846 addFunction(vm, "enableExceptionFuzz", functionEnableExceptionFuzz, 0);
847
848 addFunction(vm, "drainMicrotasks", functionDrainMicrotasks, 0);
849
850 addFunction(vm, "is32BitPlatform", functionIs32BitPlatform, 0);
851
852 addFunction(vm, "loadModule", functionLoadModule, 1);
853 addFunction(vm, "checkModuleSyntax", functionCheckModuleSyntax, 1);
854
855 addFunction(vm, "platformSupportsSamplingProfiler", functionPlatformSupportsSamplingProfiler, 0);
856 addFunction(vm, "generateHeapSnapshot", functionGenerateHeapSnapshot, 0);
857#if ENABLE(SAMPLING_PROFILER)
858 addFunction(vm, "startSamplingProfiler", functionStartSamplingProfiler, 0);
859 addFunction(vm, "samplingProfilerStackTraces", functionSamplingProfilerStackTraces, 0);
860#endif
861
862 if (!arguments.isEmpty()) {
863 JSArray* array = constructEmptyArray(globalExec(), 0);
864 for (size_t i = 0; i < arguments.size(); ++i)
865 array->putDirectIndex(globalExec(), i, jsString(globalExec(), arguments[i]));
866 putDirect(vm, Identifier::fromString(globalExec(), "arguments"), array);
867 }
868
869 putDirect(vm, Identifier::fromString(globalExec(), "console"), jsUndefined());
870 }
871
872 void addFunction(VM& vm, const char* name, NativeFunction function, unsigned arguments)
873 {
874 Identifier identifier = Identifier::fromString(&vm, name);
875 putDirect(vm, identifier, JSFunction::create(vm, this, arguments, identifier.string(), function));
876 }
877
878 void addConstructableFunction(VM& vm, const char* name, NativeFunction function, unsigned arguments)
879 {
880 Identifier identifier = Identifier::fromString(&vm, name);
881 putDirect(vm, identifier, JSFunction::create(vm, this, arguments, identifier.string(), function, NoIntrinsic, function));
882 }
883
884 static JSInternalPromise* moduleLoaderResolve(JSGlobalObject*, ExecState*, JSModuleLoader*, JSValue, JSValue);
885 static JSInternalPromise* moduleLoaderFetch(JSGlobalObject*, ExecState*, JSModuleLoader*, JSValue);
886};
887
888const ClassInfo GlobalObject::s_info = { "global", &JSGlobalObject::s_info, nullptr, CREATE_METHOD_TABLE(GlobalObject) };
889const GlobalObjectMethodTable GlobalObject::s_globalObjectMethodTable = { &allowsAccessFrom, &supportsRichSourceInfo, &shouldInterruptScript, &javaScriptRuntimeFlags, 0, &shouldInterruptScriptBeforeTimeout, &moduleLoaderResolve, &moduleLoaderFetch, nullptr, nullptr, nullptr, nullptr };
890
891
892GlobalObject::GlobalObject(VM& vm, Structure* structure)
893 : JSGlobalObject(vm, structure, &s_globalObjectMethodTable)
894{
895}
896
897static UChar pathSeparator()
898{
899#if OS(WINDOWS)
900 return '\\';
901#else
902 return '/';
903#endif
904}
905
906struct DirectoryName {
907 // In unix, it is "/". In Windows, it becomes a drive letter like "C:\"
908 String rootName;
909
910 // If the directory name is "/home/WebKit", this becomes "home/WebKit". If the directory name is "/", this becomes "".
911 String queryName;
912};
913
914struct ModuleName {
915 ModuleName(const String& moduleName);
916
917 bool startsWithRoot() const
918 {
919 return !queries.isEmpty() && queries[0].isEmpty();
920 }
921
922 Vector<String> queries;
923};
924
925ModuleName::ModuleName(const String& moduleName)
926{
927 // A module name given from code is represented as the UNIX style path. Like, `./A/B.js`.
928 moduleName.split('/', true, queries);
929}
930
931static bool extractDirectoryName(const String& absolutePathToFile, DirectoryName& directoryName)
932{
933 size_t firstSeparatorPosition = absolutePathToFile.find(pathSeparator());
934 if (firstSeparatorPosition == notFound)
935 return false;
936 directoryName.rootName = absolutePathToFile.substring(0, firstSeparatorPosition + 1); // Include the separator.
937 size_t lastSeparatorPosition = absolutePathToFile.reverseFind(pathSeparator());
938 ASSERT_WITH_MESSAGE(lastSeparatorPosition != notFound, "If the separator is not found, this function already returns when performing the forward search.");
939 if (firstSeparatorPosition == lastSeparatorPosition)
940 directoryName.queryName = StringImpl::empty();
941 else {
942 size_t queryStartPosition = firstSeparatorPosition + 1;
943 size_t queryLength = lastSeparatorPosition - queryStartPosition; // Not include the last separator.
944 directoryName.queryName = absolutePathToFile.substring(queryStartPosition, queryLength);
945 }
946 return true;
947}
948
949static bool currentWorkingDirectory(DirectoryName& directoryName)
950{
951#if OS(WINDOWS)
952 // https://msdn.microsoft.com/en-us/library/windows/desktop/aa364934.aspx
953 // https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247.aspx#maxpath
954 // The _MAX_PATH in Windows is 260. If the path of the current working directory is longer than that, _getcwd truncates the result.
955 // And other I/O functions taking a path name also truncate it. To avoid this situation,
956 //
957 // (1). When opening the file in Windows for modules, we always use the abosolute path and add "\\?\" prefix to the path name.
958 // (2). When retrieving the current working directory, use GetCurrentDirectory instead of _getcwd.
959 //
960 // In the path utility functions inside the JSC shell, we does not handle the UNC and UNCW including the network host name.
961 DWORD bufferLength = ::GetCurrentDirectoryW(0, nullptr);
962 if (!bufferLength)
963 return false;
964 // In Windows, wchar_t is the UTF-16LE.
965 // https://msdn.microsoft.com/en-us/library/dd374081.aspx
966 // https://msdn.microsoft.com/en-us/library/windows/desktop/ff381407.aspx
967 auto buffer = std::make_unique<wchar_t[]>(bufferLength);
968 DWORD lengthNotIncludingNull = ::GetCurrentDirectoryW(bufferLength, buffer.get());
969 static_assert(sizeof(wchar_t) == sizeof(UChar), "In Windows, both are UTF-16LE");
970 String directoryString = String(reinterpret_cast<UChar*>(buffer.get()));
971 // We don't support network path like \\host\share\<path name>.
972 if (directoryString.startsWith("\\\\"))
973 return false;
974#else
975 auto buffer = std::make_unique<char[]>(PATH_MAX);
976 if (!getcwd(buffer.get(), PATH_MAX))
977 return false;
978 String directoryString = String::fromUTF8(buffer.get());
979#endif
980 if (directoryString.isEmpty())
981 return false;
982
983 if (directoryString[directoryString.length() - 1] == pathSeparator())
984 return extractDirectoryName(directoryString, directoryName);
985 // Append the seperator to represents the file name. extractDirectoryName only accepts the absolute file name.
986 return extractDirectoryName(makeString(directoryString, pathSeparator()), directoryName);
987}
988
989static String resolvePath(const DirectoryName& directoryName, const ModuleName& moduleName)
990{
991 Vector<String> directoryPieces;
992 directoryName.queryName.split(pathSeparator(), false, directoryPieces);
993
994 // Only first '/' is recognized as the path from the root.
995 if (moduleName.startsWithRoot())
996 directoryPieces.clear();
997
998 for (const auto& query : moduleName.queries) {
999 if (query == String(ASCIILiteral(".."))) {
1000 if (!directoryPieces.isEmpty())
1001 directoryPieces.removeLast();
1002 } else if (!query.isEmpty() && query != String(ASCIILiteral(".")))
1003 directoryPieces.append(query);
1004 }
1005
1006 StringBuilder builder;
1007 builder.append(directoryName.rootName);
1008 for (size_t i = 0; i < directoryPieces.size(); ++i) {
1009 builder.append(directoryPieces[i]);
1010 if (i + 1 != directoryPieces.size())
1011 builder.append(pathSeparator());
1012 }
1013 return builder.toString();
1014}
1015
1016JSInternalPromise* GlobalObject::moduleLoaderResolve(JSGlobalObject* globalObject, ExecState* exec, JSModuleLoader*, JSValue keyValue, JSValue referrerValue)
1017{
1018 JSInternalPromiseDeferred* deferred = JSInternalPromiseDeferred::create(exec, globalObject);
1019 const Identifier key = keyValue.toPropertyKey(exec);
1020 if (exec->hadException()) {
1021 JSValue exception = exec->exception();
1022 exec->clearException();
1023 return deferred->reject(exec, exception);
1024 }
1025
1026 if (key.isSymbol())
1027 return deferred->resolve(exec, keyValue);
1028
1029 DirectoryName directoryName;
1030 if (referrerValue.isUndefined()) {
1031 if (!currentWorkingDirectory(directoryName))
1032 return deferred->reject(exec, createError(exec, ASCIILiteral("Could not resolve the current working directory.")));
1033 } else {
1034 const Identifier referrer = referrerValue.toPropertyKey(exec);
1035 if (exec->hadException()) {
1036 JSValue exception = exec->exception();
1037 exec->clearException();
1038 return deferred->reject(exec, exception);
1039 }
1040 if (referrer.isSymbol()) {
1041 if (!currentWorkingDirectory(directoryName))
1042 return deferred->reject(exec, createError(exec, ASCIILiteral("Could not resolve the current working directory.")));
1043 } else {
1044 // If the referrer exists, we assume that the referrer is the correct absolute path.
1045 if (!extractDirectoryName(referrer.impl(), directoryName))
1046 return deferred->reject(exec, createError(exec, makeString("Could not resolve the referrer name '", String(referrer.impl()), "'.")));
1047 }
1048 }
1049
1050 return deferred->resolve(exec, jsString(exec, resolvePath(directoryName, ModuleName(key.impl()))));
1051}
1052
1053static void convertShebangToJSComment(Vector<char>& buffer)
1054{
1055 if (buffer.size() >= 2) {
1056 if (buffer[0] == '#' && buffer[1] == '!')
1057 buffer[0] = buffer[1] = '/';
1058 }
1059}
1060
1061static bool fillBufferWithContentsOfFile(FILE* file, Vector<char>& buffer)
1062{
1063 // We might have injected "use strict"; at the top.
1064 size_t initialSize = buffer.size();
1065 fseek(file, 0, SEEK_END);
1066 size_t bufferCapacity = ftell(file);
1067 fseek(file, 0, SEEK_SET);
1068 buffer.resize(bufferCapacity + initialSize);
1069 size_t readSize = fread(buffer.data() + initialSize, 1, buffer.size(), file);
1070 return readSize == buffer.size() - initialSize;
1071}
1072
1073static bool fillBufferWithContentsOfFile(const String& fileName, Vector<char>& buffer)
1074{
1075 FILE* f = fopen(fileName.utf8().data(), "rb");
1076 if (!f) {
1077 fprintf(stderr, "Could not open file: %s\n", fileName.utf8().data());
1078 return false;
1079 }
1080
1081 bool result = fillBufferWithContentsOfFile(f, buffer);
1082 fclose(f);
1083
1084 return result;
1085}
1086
1087static bool fetchScriptFromLocalFileSystem(const String& fileName, Vector<char>& buffer)
1088{
1089 if (!fillBufferWithContentsOfFile(fileName, buffer))
1090 return false;
1091 convertShebangToJSComment(buffer);
1092 return true;
1093}
1094
1095static bool fetchModuleFromLocalFileSystem(const String& fileName, Vector<char>& buffer)
1096{
1097 // We assume that fileName is always an absolute path.
1098#if OS(WINDOWS)
1099 // https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247.aspx#maxpath
1100 // Use long UNC to pass the long path name to the Windows APIs.
1101 String longUNCPathName = WTF::makeString("\\\\?\\", fileName);
1102 static_assert(sizeof(wchar_t) == sizeof(UChar), "In Windows, both are UTF-16LE");
1103 auto utf16Vector = longUNCPathName.charactersWithNullTermination();
1104 FILE* f = _wfopen(reinterpret_cast<wchar_t*>(utf16Vector.data()), L"rb");
1105#else
1106 FILE* f = fopen(fileName.utf8().data(), "r");
1107#endif
1108 if (!f) {
1109 fprintf(stderr, "Could not open file: %s\n", fileName.utf8().data());
1110 return false;
1111 }
1112
1113 bool result = fillBufferWithContentsOfFile(f, buffer);
1114 if (result)
1115 convertShebangToJSComment(buffer);
1116 fclose(f);
1117
1118 return result;
1119}
1120
1121JSInternalPromise* GlobalObject::moduleLoaderFetch(JSGlobalObject* globalObject, ExecState* exec, JSModuleLoader*, JSValue key)
1122{
1123 JSInternalPromiseDeferred* deferred = JSInternalPromiseDeferred::create(exec, globalObject);
1124 String moduleKey = key.toWTFString(exec);
1125 if (exec->hadException()) {
1126 JSValue exception = exec->exception();
1127 exec->clearException();
1128 return deferred->reject(exec, exception);
1129 }
1130
1131 // Here, now we consider moduleKey as the fileName.
1132 Vector<char> utf8;
1133 if (!fetchModuleFromLocalFileSystem(moduleKey, utf8))
1134 return deferred->reject(exec, createError(exec, makeString("Could not open file '", moduleKey, "'.")));
1135
1136 return deferred->resolve(exec, jsString(exec, stringFromUTF(utf8)));
1137}
1138
1139
1140EncodedJSValue JSC_HOST_CALL functionPrint(ExecState* exec)
1141{
1142 if (test262AsyncTest) {
1143 JSValue value = exec->argument(0);
1144 if (value.isString() && WTF::equal(asString(value)->value(exec).impl(), "Test262:AsyncTestComplete"))
1145 test262AsyncPassed = true;
1146 return JSValue::encode(jsUndefined());
1147 }
1148
1149 for (unsigned i = 0; i < exec->argumentCount(); ++i) {
1150 if (i)
1151 putchar(' ');
1152
1153 printf("%s", exec->uncheckedArgument(i).toString(exec)->view(exec).get().utf8().data());
1154 }
1155
1156 putchar('\n');
1157 fflush(stdout);
1158 return JSValue::encode(jsUndefined());
1159}
1160
1161#ifndef NDEBUG
1162EncodedJSValue JSC_HOST_CALL functionDumpCallFrame(ExecState* exec)
1163{
1164 VMEntryFrame* topVMEntryFrame = exec->vm().topVMEntryFrame;
1165 ExecState* callerFrame = exec->callerFrame(topVMEntryFrame);
1166 if (callerFrame)
1167 exec->vm().interpreter->dumpCallFrame(callerFrame);
1168 return JSValue::encode(jsUndefined());
1169}
1170#endif
1171
1172EncodedJSValue JSC_HOST_CALL functionDebug(ExecState* exec)
1173{
1174 fprintf(stderr, "--> %s\n", exec->argument(0).toString(exec)->view(exec).get().utf8().data());
1175 return JSValue::encode(jsUndefined());
1176}
1177
1178EncodedJSValue JSC_HOST_CALL functionDescribe(ExecState* exec)
1179{
1180 if (exec->argumentCount() < 1)
1181 return JSValue::encode(jsUndefined());
1182 return JSValue::encode(jsString(exec, toString(exec->argument(0))));
1183}
1184
1185EncodedJSValue JSC_HOST_CALL functionDescribeArray(ExecState* exec)
1186{
1187 if (exec->argumentCount() < 1)
1188 return JSValue::encode(jsUndefined());
1189 JSObject* object = jsDynamicCast<JSObject*>(exec->argument(0));
1190 if (!object)
1191 return JSValue::encode(jsNontrivialString(exec, ASCIILiteral("<not object>")));
1192 return JSValue::encode(jsNontrivialString(exec, toString("<Public length: ", object->getArrayLength(), "; vector length: ", object->getVectorLength(), ">")));
1193}
1194
1195class FunctionJSCStackFunctor {
1196public:
1197 FunctionJSCStackFunctor(StringBuilder& trace)
1198 : m_trace(trace)
1199 {
1200 }
1201
1202 StackVisitor::Status operator()(StackVisitor& visitor) const
1203 {
1204 m_trace.append(String::format(" %zu %s\n", visitor->index(), visitor->toString().utf8().data()));
1205 return StackVisitor::Continue;
1206 }
1207
1208private:
1209 StringBuilder& m_trace;
1210};
1211
1212EncodedJSValue JSC_HOST_CALL functionJSCStack(ExecState* exec)
1213{
1214 StringBuilder trace;
1215 trace.appendLiteral("--> Stack trace:\n");
1216
1217 FunctionJSCStackFunctor functor(trace);
1218 exec->iterate(functor);
1219 fprintf(stderr, "%s", trace.toString().utf8().data());
1220 return JSValue::encode(jsUndefined());
1221}
1222
1223EncodedJSValue JSC_HOST_CALL functionCreateRoot(ExecState* exec)
1224{
1225 JSLockHolder lock(exec);
1226 return JSValue::encode(Root::create(exec->vm(), exec->lexicalGlobalObject()));
1227}
1228
1229EncodedJSValue JSC_HOST_CALL functionCreateElement(ExecState* exec)
1230{
1231 JSLockHolder lock(exec);
1232 Root* root = jsDynamicCast<Root*>(exec->argument(0));
1233 if (!root)
1234 return JSValue::encode(jsUndefined());
1235 return JSValue::encode(Element::create(exec->vm(), exec->lexicalGlobalObject(), root));
1236}
1237
1238EncodedJSValue JSC_HOST_CALL functionGetElement(ExecState* exec)
1239{
1240 JSLockHolder lock(exec);
1241 Root* root = jsDynamicCast<Root*>(exec->argument(0));
1242 if (!root)
1243 return JSValue::encode(jsUndefined());
1244 Element* result = root->element();
1245 return JSValue::encode(result ? result : jsUndefined());
1246}
1247
1248EncodedJSValue JSC_HOST_CALL functionSetElementRoot(ExecState* exec)
1249{
1250 JSLockHolder lock(exec);
1251 Element* element = jsDynamicCast<Element*>(exec->argument(0));
1252 Root* root = jsDynamicCast<Root*>(exec->argument(1));
1253 if (element && root)
1254 element->setRoot(exec->vm(), root);
1255 return JSValue::encode(jsUndefined());
1256}
1257
1258EncodedJSValue JSC_HOST_CALL functionCreateSimpleObject(ExecState* exec)
1259{
1260 JSLockHolder lock(exec);
1261 return JSValue::encode(SimpleObject::create(exec->vm(), exec->lexicalGlobalObject()));
1262}
1263
1264EncodedJSValue JSC_HOST_CALL functionGetHiddenValue(ExecState* exec)
1265{
1266 JSLockHolder lock(exec);
1267 SimpleObject* simpleObject = jsCast<SimpleObject*>(exec->argument(0).asCell());
1268 return JSValue::encode(simpleObject->hiddenValue());
1269}
1270
1271EncodedJSValue JSC_HOST_CALL functionSetHiddenValue(ExecState* exec)
1272{
1273 JSLockHolder lock(exec);
1274 SimpleObject* simpleObject = jsCast<SimpleObject*>(exec->argument(0).asCell());
1275 JSValue value = exec->argument(1);
1276 simpleObject->setHiddenValue(exec->vm(), value);
1277 return JSValue::encode(jsUndefined());
1278}
1279
1280EncodedJSValue JSC_HOST_CALL functionCreateProxy(ExecState* exec)
1281{
1282 JSLockHolder lock(exec);
1283 JSValue target = exec->argument(0);
1284 if (!target.isObject())
1285 return JSValue::encode(jsUndefined());
1286 JSObject* jsTarget = asObject(target.asCell());
1287 Structure* structure = JSProxy::createStructure(exec->vm(), exec->lexicalGlobalObject(), jsTarget->getPrototypeDirect(), ImpureProxyType);
1288 JSProxy* proxy = JSProxy::create(exec->vm(), structure, jsTarget);
1289 return JSValue::encode(proxy);
1290}
1291
1292EncodedJSValue JSC_HOST_CALL functionCreateRuntimeArray(ExecState* exec)
1293{
1294 JSLockHolder lock(exec);
1295 RuntimeArray* array = RuntimeArray::create(exec);
1296 return JSValue::encode(array);
1297}
1298
1299EncodedJSValue JSC_HOST_CALL functionCreateImpureGetter(ExecState* exec)
1300{
1301 JSLockHolder lock(exec);
1302 JSValue target = exec->argument(0);
1303 JSObject* delegate = nullptr;
1304 if (target.isObject())
1305 delegate = asObject(target.asCell());
1306 Structure* structure = ImpureGetter::createStructure(exec->vm(), exec->lexicalGlobalObject(), jsNull());
1307 ImpureGetter* result = ImpureGetter::create(exec->vm(), structure, delegate);
1308 return JSValue::encode(result);
1309}
1310
1311EncodedJSValue JSC_HOST_CALL functionCreateCustomGetterObject(ExecState* exec)
1312{
1313 JSLockHolder lock(exec);
1314 Structure* structure = CustomGetter::createStructure(exec->vm(), exec->lexicalGlobalObject(), jsNull());
1315 CustomGetter* result = CustomGetter::create(exec->vm(), structure);
1316 return JSValue::encode(result);
1317}
1318
1319EncodedJSValue JSC_HOST_CALL functionSetImpureGetterDelegate(ExecState* exec)
1320{
1321 JSLockHolder lock(exec);
1322 JSValue base = exec->argument(0);
1323 if (!base.isObject())
1324 return JSValue::encode(jsUndefined());
1325 JSValue delegate = exec->argument(1);
1326 if (!delegate.isObject())
1327 return JSValue::encode(jsUndefined());
1328 ImpureGetter* impureGetter = jsCast<ImpureGetter*>(asObject(base.asCell()));
1329 impureGetter->setDelegate(exec->vm(), asObject(delegate.asCell()));
1330 return JSValue::encode(jsUndefined());
1331}
1332
1333EncodedJSValue JSC_HOST_CALL functionGCAndSweep(ExecState* exec)
1334{
1335 JSLockHolder lock(exec);
1336 exec->heap()->collectAllGarbage();
1337 return JSValue::encode(jsNumber(exec->heap()->sizeAfterLastFullCollection()));
1338}
1339
1340EncodedJSValue JSC_HOST_CALL functionFullGC(ExecState* exec)
1341{
1342 JSLockHolder lock(exec);
1343 exec->heap()->collect(FullCollection);
1344 return JSValue::encode(jsNumber(exec->heap()->sizeAfterLastFullCollection()));
1345}
1346
1347EncodedJSValue JSC_HOST_CALL functionEdenGC(ExecState* exec)
1348{
1349 JSLockHolder lock(exec);
1350 exec->heap()->collect(EdenCollection);
1351 return JSValue::encode(jsNumber(exec->heap()->sizeAfterLastEdenCollection()));
1352}
1353
1354EncodedJSValue JSC_HOST_CALL functionForceGCSlowPaths(ExecState*)
1355{
1356 // It's best for this to be the first thing called in the
1357 // JS program so the option is set to true before we JIT.
1358 Options::forceGCSlowPaths() = true;
1359 return JSValue::encode(jsUndefined());
1360}
1361
1362EncodedJSValue JSC_HOST_CALL functionHeapSize(ExecState* exec)
1363{
1364 JSLockHolder lock(exec);
1365 return JSValue::encode(jsNumber(exec->heap()->size()));
1366}
1367
1368// This function is not generally very helpful in 64-bit code as the tag and payload
1369// share a register. But in 32-bit JITed code the tag may not be checked if an
1370// optimization removes type checking requirements, such as in ===.
1371EncodedJSValue JSC_HOST_CALL functionAddressOf(ExecState* exec)
1372{
1373 JSValue value = exec->argument(0);
1374 if (!value.isCell())
1375 return JSValue::encode(jsUndefined());
1376 // Need to cast to uint64_t so bitwise_cast will play along.
1377 uint64_t asNumber = reinterpret_cast<uint64_t>(value.asCell());
1378 EncodedJSValue returnValue = JSValue::encode(jsNumber(bitwise_cast<double>(asNumber)));
1379 return returnValue;
1380}
1381
1382static EncodedJSValue JSC_HOST_CALL functionGetGetterSetter(ExecState* exec)
1383{
1384 JSValue value = exec->argument(0);
1385 if (!value.isObject())
1386 return JSValue::encode(jsUndefined());
1387
1388 JSValue property = exec->argument(1);
1389 if (!property.isString())
1390 return JSValue::encode(jsUndefined());
1391
1392 Identifier ident = Identifier::fromString(&exec->vm(), property.toWTFString(exec));
1393
1394 PropertySlot slot(value, PropertySlot::InternalMethodType::VMInquiry);
1395 value.getPropertySlot(exec, ident, slot);
1396
1397 JSValue result;
1398 if (slot.isCacheableGetter())
1399 result = slot.getterSetter();
1400 else
1401 result = jsNull();
1402
1403 return JSValue::encode(result);
1404}
1405
1406EncodedJSValue JSC_HOST_CALL functionVersion(ExecState*)
1407{
1408 // We need this function for compatibility with the Mozilla JS tests but for now
1409 // we don't actually do any version-specific handling
1410 return JSValue::encode(jsUndefined());
1411}
1412
1413EncodedJSValue JSC_HOST_CALL functionRun(ExecState* exec)
1414{
1415 String fileName = exec->argument(0).toWTFString(exec);
1416 if (exec->hadException())
1417 return JSValue::encode(jsUndefined());
1418 Vector<char> script;
1419 if (!fetchScriptFromLocalFileSystem(fileName, script))
1420 return JSValue::encode(exec->vm().throwException(exec, createError(exec, ASCIILiteral("Could not open file."))));
1421
1422 GlobalObject* globalObject = GlobalObject::create(exec->vm(), GlobalObject::createStructure(exec->vm(), jsNull()), Vector<String>());
1423
1424 JSArray* array = constructEmptyArray(globalObject->globalExec(), 0);
1425 for (unsigned i = 1; i < exec->argumentCount(); ++i)
1426 array->putDirectIndex(globalObject->globalExec(), i - 1, exec->uncheckedArgument(i));
1427 globalObject->putDirect(
1428 exec->vm(), Identifier::fromString(globalObject->globalExec(), "arguments"), array);
1429
1430 NakedPtr<Exception> exception;
1431 StopWatch stopWatch;
1432 stopWatch.start();
1433 evaluate(globalObject->globalExec(), jscSource(script, fileName), JSValue(), exception);
1434 stopWatch.stop();
1435
1436 if (exception) {
1437 exec->vm().throwException(globalObject->globalExec(), exception);
1438 return JSValue::encode(jsUndefined());
1439 }
1440
1441 return JSValue::encode(jsNumber(stopWatch.getElapsedMS()));
1442}
1443
1444EncodedJSValue JSC_HOST_CALL functionLoad(ExecState* exec)
1445{
1446 String fileName = exec->argument(0).toWTFString(exec);
1447 if (exec->hadException())
1448 return JSValue::encode(jsUndefined());
1449 Vector<char> script;
1450 if (!fetchScriptFromLocalFileSystem(fileName, script))
1451 return JSValue::encode(exec->vm().throwException(exec, createError(exec, ASCIILiteral("Could not open file."))));
1452
1453 JSGlobalObject* globalObject = exec->lexicalGlobalObject();
1454
1455 NakedPtr<Exception> evaluationException;
1456 JSValue result = evaluate(globalObject->globalExec(), jscSource(script, fileName), JSValue(), evaluationException);
1457 if (evaluationException)
1458 exec->vm().throwException(exec, evaluationException);
1459 return JSValue::encode(result);
1460}
1461
1462EncodedJSValue JSC_HOST_CALL functionLoadString(ExecState* exec)
1463{
1464 String sourceCode = exec->argument(0).toWTFString(exec);
1465 if (exec->hadException())
1466 return JSValue::encode(jsUndefined());
1467 JSGlobalObject* globalObject = exec->lexicalGlobalObject();
1468
1469 NakedPtr<Exception> evaluationException;
1470 JSValue result = evaluate(globalObject->globalExec(), makeSource(sourceCode), JSValue(), evaluationException);
1471 if (evaluationException)
1472 exec->vm().throwException(exec, evaluationException);
1473 return JSValue::encode(result);
1474}
1475
1476EncodedJSValue JSC_HOST_CALL functionReadFile(ExecState* exec)
1477{
1478 String fileName = exec->argument(0).toWTFString(exec);
1479 if (exec->hadException())
1480 return JSValue::encode(jsUndefined());
1481 Vector<char> script;
1482 if (!fillBufferWithContentsOfFile(fileName, script))
1483 return JSValue::encode(exec->vm().throwException(exec, createError(exec, ASCIILiteral("Could not open file."))));
1484
1485 return JSValue::encode(jsString(exec, stringFromUTF(script)));
1486}
1487
1488EncodedJSValue JSC_HOST_CALL functionCheckSyntax(ExecState* exec)
1489{
1490 String fileName = exec->argument(0).toWTFString(exec);
1491 if (exec->hadException())
1492 return JSValue::encode(jsUndefined());
1493 Vector<char> script;
1494 if (!fetchScriptFromLocalFileSystem(fileName, script))
1495 return JSValue::encode(exec->vm().throwException(exec, createError(exec, ASCIILiteral("Could not open file."))));
1496
1497 JSGlobalObject* globalObject = exec->lexicalGlobalObject();
1498
1499 StopWatch stopWatch;
1500 stopWatch.start();
1501
1502 JSValue syntaxException;
1503 bool validSyntax = checkSyntax(globalObject->globalExec(), jscSource(script, fileName), &syntaxException);
1504 stopWatch.stop();
1505
1506 if (!validSyntax)
1507 exec->vm().throwException(exec, syntaxException);
1508 return JSValue::encode(jsNumber(stopWatch.getElapsedMS()));
1509}
1510
1511#if ENABLE(SAMPLING_FLAGS)
1512EncodedJSValue JSC_HOST_CALL functionSetSamplingFlags(ExecState* exec)
1513{
1514 for (unsigned i = 0; i < exec->argumentCount(); ++i) {
1515 unsigned flag = static_cast<unsigned>(exec->uncheckedArgument(i).toNumber(exec));
1516 if ((flag >= 1) && (flag <= 32))
1517 SamplingFlags::setFlag(flag);
1518 }
1519 return JSValue::encode(jsNull());
1520}
1521
1522EncodedJSValue JSC_HOST_CALL functionClearSamplingFlags(ExecState* exec)
1523{
1524 for (unsigned i = 0; i < exec->argumentCount(); ++i) {
1525 unsigned flag = static_cast<unsigned>(exec->uncheckedArgument(i).toNumber(exec));
1526 if ((flag >= 1) && (flag <= 32))
1527 SamplingFlags::clearFlag(flag);
1528 }
1529 return JSValue::encode(jsNull());
1530}
1531#endif
1532
1533EncodedJSValue JSC_HOST_CALL functionShadowChickenFunctionsOnStack(ExecState* exec)
1534{
1535 return JSValue::encode(exec->vm().shadowChicken().functionsOnStack(exec));
1536}
1537
1538EncodedJSValue JSC_HOST_CALL functionSetGlobalConstRedeclarationShouldNotThrow(ExecState* exec)
1539{
1540 exec->vm().setGlobalConstRedeclarationShouldThrow(false);
1541 return JSValue::encode(jsUndefined());
1542}
1543
1544EncodedJSValue JSC_HOST_CALL functionReadline(ExecState* exec)
1545{
1546 Vector<char, 256> line;
1547 int c;
1548 while ((c = getchar()) != EOF) {
1549 // FIXME: Should we also break on \r?
1550 if (c == '\n')
1551 break;
1552 line.append(c);
1553 }
1554 line.append('\0');
1555 return JSValue::encode(jsString(exec, line.data()));
1556}
1557
1558EncodedJSValue JSC_HOST_CALL functionPreciseTime(ExecState*)
1559{
1560 return JSValue::encode(jsNumber(currentTime()));
1561}
1562
1563EncodedJSValue JSC_HOST_CALL functionNeverInlineFunction(ExecState* exec)
1564{
1565 return JSValue::encode(setNeverInline(exec));
1566}
1567
1568EncodedJSValue JSC_HOST_CALL functionNoDFG(ExecState* exec)
1569{
1570 return JSValue::encode(setNeverOptimize(exec));
1571}
1572
1573EncodedJSValue JSC_HOST_CALL functionNoFTL(ExecState* exec)
1574{
1575 if (JSFunction* function = jsDynamicCast<JSFunction*>(exec->argument(0))) {
1576 FunctionExecutable* executable = function->jsExecutable();
1577 executable->setNeverFTLOptimize(true);
1578 }
1579
1580 return JSValue::encode(jsUndefined());
1581}
1582
1583EncodedJSValue JSC_HOST_CALL functionOptimizeNextInvocation(ExecState* exec)
1584{
1585 return JSValue::encode(optimizeNextInvocation(exec));
1586}
1587
1588EncodedJSValue JSC_HOST_CALL functionNumberOfDFGCompiles(ExecState* exec)
1589{
1590 return JSValue::encode(numberOfDFGCompiles(exec));
1591}
1592
1593EncodedJSValue JSC_HOST_CALL functionReoptimizationRetryCount(ExecState* exec)
1594{
1595 if (exec->argumentCount() < 1)
1596 return JSValue::encode(jsUndefined());
1597
1598 CodeBlock* block = getSomeBaselineCodeBlockForFunction(exec->argument(0));
1599 if (!block)
1600 return JSValue::encode(jsNumber(0));
1601
1602 return JSValue::encode(jsNumber(block->reoptimizationRetryCounter()));
1603}
1604
1605EncodedJSValue JSC_HOST_CALL functionTransferArrayBuffer(ExecState* exec)
1606{
1607 if (exec->argumentCount() < 1)
1608 return JSValue::encode(exec->vm().throwException(exec, createError(exec, ASCIILiteral("Not enough arguments"))));
1609
1610 JSArrayBuffer* buffer = jsDynamicCast<JSArrayBuffer*>(exec->argument(0));
1611 if (!buffer)
1612 return JSValue::encode(exec->vm().throwException(exec, createError(exec, ASCIILiteral("Expected an array buffer"))));
1613
1614 ArrayBufferContents dummyContents;
1615 buffer->impl()->transfer(dummyContents);
1616
1617 return JSValue::encode(jsUndefined());
1618}
1619
1620EncodedJSValue JSC_HOST_CALL functionFailNextNewCodeBlock(ExecState* exec)
1621{
1622 exec->vm().setFailNextNewCodeBlock();
1623 return JSValue::encode(jsUndefined());
1624}
1625
1626EncodedJSValue JSC_HOST_CALL functionQuit(ExecState*)
1627{
1628 jscExit(EXIT_SUCCESS);
1629
1630#if COMPILER(MSVC)
1631 // Without this, Visual Studio will complain that this method does not return a value.
1632 return JSValue::encode(jsUndefined());
1633#endif
1634}
1635
1636EncodedJSValue JSC_HOST_CALL functionAbort(ExecState*)
1637{
1638 CRASH();
1639}
1640
1641EncodedJSValue JSC_HOST_CALL functionFalse1(ExecState*) { return JSValue::encode(jsBoolean(false)); }
1642EncodedJSValue JSC_HOST_CALL functionFalse2(ExecState*) { return JSValue::encode(jsBoolean(false)); }
1643
1644EncodedJSValue JSC_HOST_CALL functionUndefined1(ExecState*) { return JSValue::encode(jsUndefined()); }
1645EncodedJSValue JSC_HOST_CALL functionUndefined2(ExecState*) { return JSValue::encode(jsUndefined()); }
1646EncodedJSValue JSC_HOST_CALL functionIsInt32(ExecState* exec)
1647{
1648 for (size_t i = 0; i < exec->argumentCount(); ++i) {
1649 if (!exec->argument(i).isInt32())
1650 return JSValue::encode(jsBoolean(false));
1651 }
1652 return JSValue::encode(jsBoolean(true));
1653}
1654
1655EncodedJSValue JSC_HOST_CALL functionIdentity(ExecState* exec) { return JSValue::encode(exec->argument(0)); }
1656
1657EncodedJSValue JSC_HOST_CALL functionEffectful42(ExecState*)
1658{
1659 return JSValue::encode(jsNumber(42));
1660}
1661
1662EncodedJSValue JSC_HOST_CALL functionMakeMasquerader(ExecState* exec)
1663{
1664 return JSValue::encode(Masquerader::create(exec->vm(), exec->lexicalGlobalObject()));
1665}
1666
1667EncodedJSValue JSC_HOST_CALL functionHasCustomProperties(ExecState* exec)
1668{
1669 JSValue value = exec->argument(0);
1670 if (value.isObject())
1671 return JSValue::encode(jsBoolean(asObject(value)->hasCustomProperties()));
1672 return JSValue::encode(jsBoolean(false));
1673}
1674
1675EncodedJSValue JSC_HOST_CALL functionDumpTypesForAllVariables(ExecState* exec)
1676{
1677 exec->vm().dumpTypeProfilerData();
1678 return JSValue::encode(jsUndefined());
1679}
1680
1681EncodedJSValue JSC_HOST_CALL functionFindTypeForExpression(ExecState* exec)
1682{
1683 RELEASE_ASSERT(exec->vm().typeProfiler());
1684 exec->vm().typeProfilerLog()->processLogEntries(ASCIILiteral("jsc Testing API: functionFindTypeForExpression"));
1685
1686 JSValue functionValue = exec->argument(0);
1687 RELEASE_ASSERT(functionValue.isFunction());
1688 FunctionExecutable* executable = (jsDynamicCast<JSFunction*>(functionValue.asCell()->getObject()))->jsExecutable();
1689
1690 RELEASE_ASSERT(exec->argument(1).isString());
1691 String substring = exec->argument(1).getString(exec);
1692 String sourceCodeText = executable->source().view().toString();
1693 unsigned offset = static_cast<unsigned>(sourceCodeText.find(substring) + executable->source().startOffset());
1694
1695 String jsonString = exec->vm().typeProfiler()->typeInformationForExpressionAtOffset(TypeProfilerSearchDescriptorNormal, offset, executable->sourceID(), exec->vm());
1696 return JSValue::encode(JSONParse(exec, jsonString));
1697}
1698
1699EncodedJSValue JSC_HOST_CALL functionReturnTypeFor(ExecState* exec)
1700{
1701 RELEASE_ASSERT(exec->vm().typeProfiler());
1702 exec->vm().typeProfilerLog()->processLogEntries(ASCIILiteral("jsc Testing API: functionReturnTypeFor"));
1703
1704 JSValue functionValue = exec->argument(0);
1705 RELEASE_ASSERT(functionValue.isFunction());
1706 FunctionExecutable* executable = (jsDynamicCast<JSFunction*>(functionValue.asCell()->getObject()))->jsExecutable();
1707
1708 unsigned offset = executable->typeProfilingStartOffset();
1709 String jsonString = exec->vm().typeProfiler()->typeInformationForExpressionAtOffset(TypeProfilerSearchDescriptorFunctionReturn, offset, executable->sourceID(), exec->vm());
1710 return JSValue::encode(JSONParse(exec, jsonString));
1711}
1712
1713EncodedJSValue JSC_HOST_CALL functionDumpBasicBlockExecutionRanges(ExecState* exec)
1714{
1715 RELEASE_ASSERT(exec->vm().controlFlowProfiler());
1716 exec->vm().controlFlowProfiler()->dumpData();
1717 return JSValue::encode(jsUndefined());
1718}
1719
1720EncodedJSValue JSC_HOST_CALL functionHasBasicBlockExecuted(ExecState* exec)
1721{
1722 RELEASE_ASSERT(exec->vm().controlFlowProfiler());
1723
1724 JSValue functionValue = exec->argument(0);
1725 RELEASE_ASSERT(functionValue.isFunction());
1726 FunctionExecutable* executable = (jsDynamicCast<JSFunction*>(functionValue.asCell()->getObject()))->jsExecutable();
1727
1728 RELEASE_ASSERT(exec->argument(1).isString());
1729 String substring = exec->argument(1).getString(exec);
1730 String sourceCodeText = executable->source().view().toString();
1731 RELEASE_ASSERT(sourceCodeText.contains(substring));
1732 int offset = sourceCodeText.find(substring) + executable->source().startOffset();
1733
1734 bool hasExecuted = exec->vm().controlFlowProfiler()->hasBasicBlockAtTextOffsetBeenExecuted(offset, executable->sourceID(), exec->vm());
1735 return JSValue::encode(jsBoolean(hasExecuted));
1736}
1737
1738EncodedJSValue JSC_HOST_CALL functionBasicBlockExecutionCount(ExecState* exec)
1739{
1740 RELEASE_ASSERT(exec->vm().controlFlowProfiler());
1741
1742 JSValue functionValue = exec->argument(0);
1743 RELEASE_ASSERT(functionValue.isFunction());
1744 FunctionExecutable* executable = (jsDynamicCast<JSFunction*>(functionValue.asCell()->getObject()))->jsExecutable();
1745
1746 RELEASE_ASSERT(exec->argument(1).isString());
1747 String substring = exec->argument(1).getString(exec);
1748 String sourceCodeText = executable->source().view().toString();
1749 RELEASE_ASSERT(sourceCodeText.contains(substring));
1750 int offset = sourceCodeText.find(substring) + executable->source().startOffset();
1751
1752 size_t executionCount = exec->vm().controlFlowProfiler()->basicBlockExecutionCountAtTextOffset(offset, executable->sourceID(), exec->vm());
1753 return JSValue::encode(JSValue(executionCount));
1754}
1755
1756EncodedJSValue JSC_HOST_CALL functionEnableExceptionFuzz(ExecState*)
1757{
1758 Options::useExceptionFuzz() = true;
1759 return JSValue::encode(jsUndefined());
1760}
1761
1762EncodedJSValue JSC_HOST_CALL functionDrainMicrotasks(ExecState* exec)
1763{
1764 exec->vm().drainMicrotasks();
1765 return JSValue::encode(jsUndefined());
1766}
1767
1768EncodedJSValue JSC_HOST_CALL functionIs32BitPlatform(ExecState*)
1769{
1770#if USE(JSVALUE64)
1771 return JSValue::encode(JSValue(JSC::JSValue::JSFalse));
1772#else
1773 return JSValue::encode(JSValue(JSC::JSValue::JSTrue));
1774#endif
1775}
1776
1777EncodedJSValue JSC_HOST_CALL functionLoadModule(ExecState* exec)
1778{
1779 String fileName = exec->argument(0).toWTFString(exec);
1780 if (exec->hadException())
1781 return JSValue::encode(jsUndefined());
1782 Vector<char> script;
1783 if (!fetchScriptFromLocalFileSystem(fileName, script))
1784 return JSValue::encode(exec->vm().throwException(exec, createError(exec, ASCIILiteral("Could not open file."))));
1785
1786 JSInternalPromise* promise = loadAndEvaluateModule(exec, fileName);
1787 if (exec->hadException())
1788 return JSValue::encode(jsUndefined());
1789
1790 JSValue error;
1791 JSFunction* errorHandler = JSNativeStdFunction::create(exec->vm(), exec->lexicalGlobalObject(), 1, String(), [&](ExecState* exec) {
1792 error = exec->argument(0);
1793 return JSValue::encode(jsUndefined());
1794 });
1795
1796 promise->then(exec, nullptr, errorHandler);
1797 exec->vm().drainMicrotasks();
1798 if (error)
1799 return JSValue::encode(exec->vm().throwException(exec, error));
1800 return JSValue::encode(jsUndefined());
1801}
1802
1803EncodedJSValue JSC_HOST_CALL functionCreateBuiltin(ExecState* exec)
1804{
1805 if (exec->argumentCount() < 1 || !exec->argument(0).isString())
1806 return JSValue::encode(jsUndefined());
1807
1808 String functionText = exec->argument(0).toWTFString(exec);
1809 if (exec->hadException())
1810 return JSValue::encode(JSValue());
1811
1812 VM& vm = exec->vm();
1813 const SourceCode& source = makeSource(functionText);
1814 JSFunction* func = JSFunction::createBuiltinFunction(vm, createBuiltinExecutable(vm, source, Identifier::fromString(&vm, "foo"), ConstructorKind::None, ConstructAbility::CannotConstruct)->link(vm, source), exec->lexicalGlobalObject());
1815
1816 return JSValue::encode(func);
1817}
1818
1819EncodedJSValue JSC_HOST_CALL functionCreateGlobalObject(ExecState* exec)
1820{
1821 VM& vm = exec->vm();
1822 return JSValue::encode(GlobalObject::create(vm, GlobalObject::createStructure(vm, jsNull()), Vector<String>()));
1823}
1824
1825EncodedJSValue JSC_HOST_CALL functionCheckModuleSyntax(ExecState* exec)
1826{
1827 String source = exec->argument(0).toWTFString(exec);
1828 if (exec->hadException())
1829 return JSValue::encode(jsUndefined());
1830
1831 StopWatch stopWatch;
1832 stopWatch.start();
1833
1834 ParserError error;
1835 bool validSyntax = checkModuleSyntax(exec, makeSource(source), error);
1836 stopWatch.stop();
1837
1838 if (!validSyntax)
1839 exec->vm().throwException(exec, jsNontrivialString(exec, toString("SyntaxError: ", error.message(), ":", error.line())));
1840 return JSValue::encode(jsNumber(stopWatch.getElapsedMS()));
1841}
1842
1843EncodedJSValue JSC_HOST_CALL functionPlatformSupportsSamplingProfiler(ExecState*)
1844{
1845#if ENABLE(SAMPLING_PROFILER)
1846 return JSValue::encode(JSValue(JSC::JSValue::JSTrue));
1847#else
1848 return JSValue::encode(JSValue(JSC::JSValue::JSFalse));
1849#endif
1850}
1851
1852EncodedJSValue JSC_HOST_CALL functionGenerateHeapSnapshot(ExecState* exec)
1853{
1854 JSLockHolder lock(exec);
1855
1856 HeapSnapshotBuilder snapshotBuilder(exec->vm().ensureHeapProfiler());
1857 snapshotBuilder.buildSnapshot();
1858
1859 String jsonString = snapshotBuilder.json();
1860 EncodedJSValue result = JSValue::encode(JSONParse(exec, jsonString));
1861 RELEASE_ASSERT(!exec->hadException());
1862 return result;
1863}
1864
1865#if ENABLE(SAMPLING_PROFILER)
1866EncodedJSValue JSC_HOST_CALL functionStartSamplingProfiler(ExecState* exec)
1867{
1868 SamplingProfiler& samplingProfiler = exec->vm().ensureSamplingProfiler(WTF::Stopwatch::create());
1869 samplingProfiler.noticeCurrentThreadAsJSCExecutionThread();
1870 samplingProfiler.start();
1871 return JSValue::encode(jsUndefined());
1872}
1873
1874EncodedJSValue JSC_HOST_CALL functionSamplingProfilerStackTraces(ExecState* exec)
1875{
1876 if (!exec->vm().samplingProfiler())
1877 return JSValue::encode(exec->vm().throwException(exec, createError(exec, ASCIILiteral("Sampling profiler was never started"))));
1878
1879 String jsonString = exec->vm().samplingProfiler()->stackTracesAsJSON();
1880 EncodedJSValue result = JSValue::encode(JSONParse(exec, jsonString));
1881 RELEASE_ASSERT(!exec->hadException());
1882 return result;
1883}
1884#endif // ENABLE(SAMPLING_PROFILER)
1885
1886// Use SEH for Release builds only to get rid of the crash report dialog
1887// (luckily the same tests fail in Release and Debug builds so far). Need to
1888// be in a separate main function because the jscmain function requires object
1889// unwinding.
1890
1891#if COMPILER(MSVC) && !defined(_DEBUG)
1892#define TRY __try {
1893#define EXCEPT(x) } __except (EXCEPTION_EXECUTE_HANDLER) { x; }
1894#else
1895#define TRY
1896#define EXCEPT(x)
1897#endif
1898
1899int jscmain(int argc, char** argv);
1900
1901static double s_desiredTimeout;
1902
1903static NO_RETURN_DUE_TO_CRASH void timeoutThreadMain(void*)
1904{
1905 auto timeout = std::chrono::microseconds(static_cast<std::chrono::microseconds::rep>(s_desiredTimeout * 1000000));
1906 std::this_thread::sleep_for(timeout);
1907
1908 dataLog("Timed out after ", s_desiredTimeout, " seconds!\n");
1909 CRASH();
1910}
1911
1912int main(int argc, char** argv)
1913{
1914#if PLATFORM(IOS) && CPU(ARM_THUMB2)
1915 // Enabled IEEE754 denormal support.
1916 fenv_t env;
1917 fegetenv( &env );
1918 env.__fpscr &= ~0x01000000u;
1919 fesetenv( &env );
1920#endif
1921
1922#if OS(WINDOWS)
1923 // Cygwin calls ::SetErrorMode(SEM_FAILCRITICALERRORS), which we will inherit. This is bad for
1924 // testing/debugging, as it causes the post-mortem debugger not to be invoked. We reset the
1925 // error mode here to work around Cygwin's behavior. See <http://webkit.org/b/55222>.
1926 ::SetErrorMode(0);
1927
1928#if defined(_DEBUG)
1929 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
1930 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
1931 _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
1932 _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
1933 _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
1934 _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
1935#endif
1936
1937 timeBeginPeriod(1);
1938#endif
1939
1940#if PLATFORM(EFL)
1941 ecore_init();
1942#endif
1943
1944#if PLATFORM(GTK)
1945 if (!setlocale(LC_ALL, ""))
1946 WTFLogAlways("Locale not supported by C library.\n\tUsing the fallback 'C' locale.");
1947#endif
1948
1949 // Need to initialize WTF threading before we start any threads. Cannot initialize JSC
1950 // threading yet, since that would do somethings that we'd like to defer until after we
1951 // have a chance to parse options.
1952 WTF::initializeThreading();
1953
1954 if (char* timeoutString = getenv("JSCTEST_timeout")) {
1955 if (sscanf(timeoutString, "%lf", &s_desiredTimeout) != 1) {
1956 dataLog(
1957 "WARNING: timeout string is malformed, got ", timeoutString,
1958 " but expected a number. Not using a timeout.\n");
1959 } else
1960 createThread(timeoutThreadMain, 0, "jsc Timeout Thread");
1961 }
1962
1963#if PLATFORM(IOS)
1964 Options::crashIfCantAllocateJITMemory() = true;
1965#endif
1966
1967 // We can't use destructors in the following code because it uses Windows
1968 // Structured Exception Handling
1969 int res = 0;
1970 TRY
1971 res = jscmain(argc, argv);
1972 EXCEPT(res = 3)
1973 if (Options::logHeapStatisticsAtExit())
1974 HeapStatistics::reportSuccess();
1975 if (Options::reportLLIntStats())
1976 LLInt::Data::finalizeStats();
1977
1978#if PLATFORM(EFL)
1979 ecore_shutdown();
1980#endif
1981
1982 jscExit(res);
1983}
1984
1985static void dumpException(GlobalObject* globalObject, JSValue exception)
1986{
1987 printf("Exception: %s\n", exception.toWTFString(globalObject->globalExec()).utf8().data());
1988
1989 Identifier nameID = Identifier::fromString(globalObject->globalExec(), "name");
1990 Identifier fileNameID = Identifier::fromString(globalObject->globalExec(), "sourceURL");
1991 Identifier lineNumberID = Identifier::fromString(globalObject->globalExec(), "line");
1992 Identifier stackID = Identifier::fromString(globalObject->globalExec(), "stack");
1993
1994 JSValue nameValue = exception.get(globalObject->globalExec(), nameID);
1995 JSValue fileNameValue = exception.get(globalObject->globalExec(), fileNameID);
1996 JSValue lineNumberValue = exception.get(globalObject->globalExec(), lineNumberID);
1997 JSValue stackValue = exception.get(globalObject->globalExec(), stackID);
1998
1999 if (nameValue.toWTFString(globalObject->globalExec()) == "SyntaxError"
2000 && (!fileNameValue.isUndefinedOrNull() || !lineNumberValue.isUndefinedOrNull())) {
2001 printf(
2002 "at %s:%s\n",
2003 fileNameValue.toWTFString(globalObject->globalExec()).utf8().data(),
2004 lineNumberValue.toWTFString(globalObject->globalExec()).utf8().data());
2005 }
2006
2007 if (!stackValue.isUndefinedOrNull())
2008 printf("%s\n", stackValue.toWTFString(globalObject->globalExec()).utf8().data());
2009}
2010
2011static bool checkUncaughtException(VM& vm, GlobalObject* globalObject, JSValue exception, const String& expectedExceptionName)
2012{
2013 vm.clearException();
2014 if (!exception) {
2015 printf("Expected uncaught exception with name '%s' but none was thrown\n", expectedExceptionName.utf8().data());
2016 return false;
2017 }
2018
2019 ExecState* exec = globalObject->globalExec();
2020 JSValue exceptionClass = globalObject->get(exec, Identifier::fromString(exec, expectedExceptionName));
2021 if (!exceptionClass.isObject() || vm.exception()) {
2022 printf("Expected uncaught exception with name '%s' but given exception class is not defined\n", expectedExceptionName.utf8().data());
2023 return false;
2024 }
2025
2026 bool isInstanceOfExpectedException = jsCast<JSObject*>(exceptionClass)->hasInstance(exec, exception);
2027 if (vm.exception()) {
2028 printf("Expected uncaught exception with name '%s' but given exception class fails performing hasInstance\n", expectedExceptionName.utf8().data());
2029 return false;
2030 }
2031 if (isInstanceOfExpectedException)
2032 return true;
2033
2034 printf("Expected uncaught exception with name '%s' but exception value is not instance of this exception class\n", expectedExceptionName.utf8().data());
2035 dumpException(globalObject, exception);
2036 return false;
2037}
2038
2039static bool runWithScripts(GlobalObject* globalObject, const Vector<Script>& scripts, const String& uncaughtExceptionName, bool dump, bool module)
2040{
2041 String fileName;
2042 Vector<char> scriptBuffer;
2043
2044 if (dump)
2045 JSC::Options::dumpGeneratedBytecodes() = true;
2046
2047 VM& vm = globalObject->vm();
2048 bool success = true;
2049
2050 auto checkException = [&] (bool isLastFile, bool hasException, JSValue value) {
2051 if (!uncaughtExceptionName || !isLastFile) {
2052 success = success && !hasException;
2053 if (dump && !hasException)
2054 printf("End: %s\n", value.toWTFString(globalObject->globalExec()).utf8().data());
2055 if (hasException)
2056 dumpException(globalObject, value);
2057 } else
2058 success = success && checkUncaughtException(vm, globalObject, (hasException) ? value : JSValue(), uncaughtExceptionName);
2059 };
2060
2061#if ENABLE(SAMPLING_FLAGS)
2062 SamplingFlags::start();
2063#endif
2064
2065 for (size_t i = 0; i < scripts.size(); i++) {
2066 JSInternalPromise* promise = nullptr;
2067 bool isModule = module || scripts[i].scriptType == Script::ScriptType::Module;
2068 if (scripts[i].codeSource == Script::CodeSource::File) {
2069 fileName = scripts[i].argument;
2070 if (scripts[i].strictMode == Script::StrictMode::Strict)
2071 scriptBuffer.append("\"use strict\";\n", strlen("\"use strict\";\n"));
2072
2073 if (isModule)
2074 promise = loadAndEvaluateModule(globalObject->globalExec(), fileName);
2075 else {
2076 if (!fetchScriptFromLocalFileSystem(fileName, scriptBuffer))
2077 return false; // fail early so we can catch missing files
2078 }
2079 } else {
2080 size_t commandLineLength = strlen(scripts[i].argument);
2081 scriptBuffer.resize(commandLineLength);
2082 std::copy(scripts[i].argument, scripts[i].argument + commandLineLength, scriptBuffer.begin());
2083 fileName = ASCIILiteral("[Command Line]");
2084 }
2085
2086 bool isLastFile = i == scripts.size() - 1;
2087 if (isModule) {
2088 if (!promise)
2089 promise = loadAndEvaluateModule(globalObject->globalExec(), jscSource(scriptBuffer, fileName));
2090 vm.clearException();
2091
2092 JSFunction* fulfillHandler = JSNativeStdFunction::create(vm, globalObject, 1, String(), [&, isLastFile](ExecState* exec) {
2093 checkException(isLastFile, false, exec->argument(0));
2094 return JSValue::encode(jsUndefined());
2095 });
2096
2097 JSFunction* rejectHandler = JSNativeStdFunction::create(vm, globalObject, 1, String(), [&, isLastFile](ExecState* exec) {
2098 checkException(isLastFile, true, exec->argument(0));
2099 return JSValue::encode(jsUndefined());
2100 });
2101
2102 promise->then(globalObject->globalExec(), fulfillHandler, rejectHandler);
2103 vm.drainMicrotasks();
2104 } else {
2105 NakedPtr<Exception> evaluationException;
2106 JSValue returnValue = evaluate(globalObject->globalExec(), jscSource(scriptBuffer, fileName), JSValue(), evaluationException);
2107 if (evaluationException)
2108 returnValue = evaluationException->value();
2109 checkException(isLastFile, evaluationException, returnValue);
2110 }
2111
2112 scriptBuffer.clear();
2113 vm.clearException();
2114 }
2115
2116#if ENABLE(REGEXP_TRACING)
2117 vm.dumpRegExpTrace();
2118#endif
2119 return success;
2120}
2121
2122#define RUNNING_FROM_XCODE 0
2123
2124static void runInteractive(GlobalObject* globalObject)
2125{
2126 String interpreterName(ASCIILiteral("Interpreter"));
2127
2128 bool shouldQuit = false;
2129 while (!shouldQuit) {
2130#if HAVE(READLINE) && !RUNNING_FROM_XCODE
2131 ParserError error;
2132 String source;
2133 do {
2134 error = ParserError();
2135 char* line = readline(source.isEmpty() ? interactivePrompt : "... ");
2136 shouldQuit = !line;
2137 if (!line)
2138 break;
2139 source = source + line;
2140 source = source + '\n';
2141 checkSyntax(globalObject->vm(), makeSource(source, interpreterName), error);
2142 if (!line[0])
2143 break;
2144 add_history(line);
2145 } while (error.syntaxErrorType() == ParserError::SyntaxErrorRecoverable);
2146
2147 if (error.isValid()) {
2148 printf("%s:%d\n", error.message().utf8().data(), error.line());
2149 continue;
2150 }
2151
2152
2153 NakedPtr<Exception> evaluationException;
2154 JSValue returnValue = evaluate(globalObject->globalExec(), makeSource(source, interpreterName), JSValue(), evaluationException);
2155#else
2156 printf("%s", interactivePrompt);
2157 Vector<char, 256> line;
2158 int c;
2159 while ((c = getchar()) != EOF) {
2160 // FIXME: Should we also break on \r?
2161 if (c == '\n')
2162 break;
2163 line.append(c);
2164 }
2165 if (line.isEmpty())
2166 break;
2167
2168 NakedPtr<Exception> evaluationException;
2169 JSValue returnValue = evaluate(globalObject->globalExec(), jscSource(line, interpreterName), JSValue(), evaluationException);
2170#endif
2171 if (evaluationException)
2172 printf("Exception: %s\n", evaluationException->value().toWTFString(globalObject->globalExec()).utf8().data());
2173 else
2174 printf("%s\n", returnValue.toWTFString(globalObject->globalExec()).utf8().data());
2175
2176 globalObject->globalExec()->clearException();
2177 globalObject->vm().drainMicrotasks();
2178 }
2179 printf("\n");
2180}
2181
2182static NO_RETURN void printUsageStatement(bool help = false)
2183{
2184 fprintf(stderr, "Usage: jsc [options] [files] [-- arguments]\n");
2185 fprintf(stderr, " -d Dumps bytecode (debug builds only)\n");
2186 fprintf(stderr, " -e Evaluate argument as script code\n");
2187 fprintf(stderr, " -f Specifies a source file (deprecated)\n");
2188 fprintf(stderr, " -h|--help Prints this help message\n");
2189 fprintf(stderr, " -i Enables interactive mode (default if no files are specified)\n");
2190 fprintf(stderr, " -m Execute as a module\n");
2191#if HAVE(SIGNAL_H)
2192 fprintf(stderr, " -s Installs signal handlers that exit on a crash (Unix platforms only)\n");
2193#endif
2194 fprintf(stderr, " -p <file> Outputs profiling data to a file\n");
2195 fprintf(stderr, " -x Output exit code before terminating\n");
2196 fprintf(stderr, "\n");
2197 fprintf(stderr, " --sample Collects and outputs sampling profiler data\n");
2198 fprintf(stderr, " --test262-async Check that some script calls the print function with the string 'Test262:AsyncTestComplete'\n");
2199 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");
2200 fprintf(stderr, " --module-file=<file> Parse and evaluate the given file as module (this option may be passed more than once)\n");
2201 fprintf(stderr, " --exception=<name> Check the last script exits with an uncaught exception with the specified name\n");
2202 fprintf(stderr, " --options Dumps all JSC VM options and exits\n");
2203 fprintf(stderr, " --dumpOptions Dumps all non-default JSC VM options before continuing\n");
2204 fprintf(stderr, " --<jsc VM option>=<value> Sets the specified JSC VM option\n");
2205 fprintf(stderr, "\n");
2206
2207 jscExit(help ? EXIT_SUCCESS : EXIT_FAILURE);
2208}
2209
2210void CommandLine::parseArguments(int argc, char** argv)
2211{
2212 Options::initialize();
2213
2214 int i = 1;
2215 JSC::Options::DumpLevel dumpOptionsLevel = JSC::Options::DumpLevel::None;
2216 bool needToExit = false;
2217
2218 bool hasBadJSCOptions = false;
2219 for (; i < argc; ++i) {
2220 const char* arg = argv[i];
2221 if (!strcmp(arg, "-f")) {
2222 if (++i == argc)
2223 printUsageStatement();
2224 m_scripts.append(Script(Script::StrictMode::Sloppy, Script::CodeSource::File, Script::ScriptType::Script, argv[i]));
2225 continue;
2226 }
2227 if (!strcmp(arg, "-e")) {
2228 if (++i == argc)
2229 printUsageStatement();
2230 m_scripts.append(Script(Script::StrictMode::Sloppy, Script::CodeSource::CommandLine, Script::ScriptType::Script, argv[i]));
2231 continue;
2232 }
2233 if (!strcmp(arg, "-i")) {
2234 m_interactive = true;
2235 continue;
2236 }
2237 if (!strcmp(arg, "-d")) {
2238 m_dump = true;
2239 continue;
2240 }
2241 if (!strcmp(arg, "-p")) {
2242 if (++i == argc)
2243 printUsageStatement();
2244 m_profile = true;
2245 m_profilerOutput = argv[i];
2246 continue;
2247 }
2248 if (!strcmp(arg, "-m")) {
2249 m_module = true;
2250 continue;
2251 }
2252 if (!strcmp(arg, "-s")) {
2253#if HAVE(SIGNAL_H)
2254 signal(SIGILL, _exit);
2255 signal(SIGFPE, _exit);
2256 signal(SIGBUS, _exit);
2257 signal(SIGSEGV, _exit);
2258#endif
2259 continue;
2260 }
2261 if (!strcmp(arg, "-x")) {
2262 m_exitCode = true;
2263 continue;
2264 }
2265 if (!strcmp(arg, "--")) {
2266 ++i;
2267 break;
2268 }
2269 if (!strcmp(arg, "-h") || !strcmp(arg, "--help"))
2270 printUsageStatement(true);
2271
2272 if (!strcmp(arg, "--options")) {
2273 dumpOptionsLevel = JSC::Options::DumpLevel::Verbose;
2274 needToExit = true;
2275 continue;
2276 }
2277 if (!strcmp(arg, "--dumpOptions")) {
2278 dumpOptionsLevel = JSC::Options::DumpLevel::Overridden;
2279 continue;
2280 }
2281 if (!strcmp(arg, "--sample")) {
2282 JSC::Options::useSamplingProfiler() = true;
2283 JSC::Options::collectSamplingProfilerDataForJSCShell() = true;
2284 m_dumpSamplingProfilerData = true;
2285 continue;
2286 }
2287
2288 if (!strcmp(arg, "--test262-async")) {
2289 test262AsyncTest = true;
2290 continue;
2291 }
2292
2293 static const unsigned strictFileStrLength = strlen("--strict-file=");
2294 if (!strncmp(arg, "--strict-file=", strictFileStrLength)) {
2295 m_scripts.append(Script(Script::StrictMode::Strict, Script::CodeSource::File, Script::ScriptType::Script, argv[i] + strictFileStrLength));
2296 continue;
2297 }
2298
2299 static const unsigned moduleFileStrLength = strlen("--module-file=");
2300 if (!strncmp(arg, "--module-file=", moduleFileStrLength)) {
2301 m_scripts.append(Script(Script::StrictMode::Sloppy, Script::CodeSource::File, Script::ScriptType::Module, argv[i] + moduleFileStrLength));
2302 continue;
2303 }
2304
2305 static const unsigned exceptionStrLength = strlen("--exception=");
2306 if (!strncmp(arg, "--exception=", exceptionStrLength)) {
2307 m_uncaughtExceptionName = String(arg + exceptionStrLength);
2308 continue;
2309 }
2310
2311 // See if the -- option is a JSC VM option.
2312 if (strstr(arg, "--") == arg) {
2313 if (!JSC::Options::setOption(&arg[2])) {
2314 hasBadJSCOptions = true;
2315 dataLog("ERROR: invalid option: ", arg, "\n");
2316 }
2317 continue;
2318 }
2319
2320 // This arg is not recognized by the VM nor by jsc. Pass it on to the
2321 // script.
2322 m_scripts.append(Script(Script::StrictMode::Sloppy, Script::CodeSource::File, Script::ScriptType::Script, argv[i]));
2323 }
2324
2325 if (hasBadJSCOptions && JSC::Options::validateOptions())
2326 CRASH();
2327
2328 if (m_scripts.isEmpty())
2329 m_interactive = true;
2330
2331 for (; i < argc; ++i)
2332 m_arguments.append(argv[i]);
2333
2334 if (dumpOptionsLevel != JSC::Options::DumpLevel::None) {
2335 const char* optionsTitle = (dumpOptionsLevel == JSC::Options::DumpLevel::Overridden)
2336 ? "Modified JSC runtime options:"
2337 : "All JSC runtime options:";
2338 JSC::Options::dumpAllOptions(stderr, dumpOptionsLevel, optionsTitle);
2339 }
2340 JSC::Options::ensureOptionsAreCoherent();
2341 if (needToExit)
2342 jscExit(EXIT_SUCCESS);
2343}
2344
2345// We make this function no inline so that globalObject won't be on the stack if we do a GC in jscmain.
2346static int NEVER_INLINE runJSC(VM* vm, CommandLine options)
2347{
2348 JSLockHolder locker(vm);
2349
2350 int result;
2351 if (options.m_profile && !vm->m_perBytecodeProfiler)
2352 vm->m_perBytecodeProfiler = std::make_unique<Profiler::Database>(*vm);
2353
2354 GlobalObject* globalObject = GlobalObject::create(*vm, GlobalObject::createStructure(*vm, jsNull()), options.m_arguments);
2355 bool success = runWithScripts(globalObject, options.m_scripts, options.m_uncaughtExceptionName, options.m_dump, options.m_module);
2356 if (options.m_interactive && success)
2357 runInteractive(globalObject);
2358
2359 vm->drainMicrotasks();
2360 result = success && (test262AsyncTest == test262AsyncPassed) ? 0 : 3;
2361
2362 if (options.m_exitCode)
2363 printf("jsc exiting %d\n", result);
2364
2365 if (options.m_profile) {
2366 if (!vm->m_perBytecodeProfiler->save(options.m_profilerOutput.utf8().data()))
2367 fprintf(stderr, "could not save profiler output.\n");
2368 }
2369
2370#if ENABLE(JIT)
2371 if (Options::useExceptionFuzz())
2372 printf("JSC EXCEPTION FUZZ: encountered %u checks.\n", numberOfExceptionFuzzChecks());
2373 bool fireAtEnabled =
2374 Options::fireExecutableAllocationFuzzAt() || Options::fireExecutableAllocationFuzzAtOrAfter();
2375 if (Options::useExecutableAllocationFuzz() && (!fireAtEnabled || Options::verboseExecutableAllocationFuzz()))
2376 printf("JSC EXECUTABLE ALLOCATION FUZZ: encountered %u checks.\n", numberOfExecutableAllocationFuzzChecks());
2377 if (Options::useOSRExitFuzz()) {
2378 printf("JSC OSR EXIT FUZZ: encountered %u static checks.\n", numberOfStaticOSRExitFuzzChecks());
2379 printf("JSC OSR EXIT FUZZ: encountered %u dynamic checks.\n", numberOfOSRExitFuzzChecks());
2380 }
2381
2382 auto compileTimeStats = JIT::compileTimeStats();
2383 Vector<CString> compileTimeKeys;
2384 for (auto& entry : compileTimeStats)
2385 compileTimeKeys.append(entry.key);
2386 std::sort(compileTimeKeys.begin(), compileTimeKeys.end());
2387 for (CString key : compileTimeKeys)
2388 printf("%40s: %.3lf ms\n", key.data(), compileTimeStats.get(key));
2389#endif
2390
2391 return result;
2392}
2393
2394int jscmain(int argc, char** argv)
2395{
2396 // Note that the options parsing can affect VM creation, and thus
2397 // comes first.
2398 CommandLine options(argc, argv);
2399
2400 // Initialize JSC before getting VM.
2401#if ENABLE(SAMPLING_REGIONS)
2402 WTF::initializeMainThread();
2403#endif
2404 JSC::initializeThreading();
2405
2406 VM* vm = &VM::create(LargeHeap).leakRef();
2407 int result;
2408 result = runJSC(vm, options);
2409
2410 if (Options::gcAtEnd()) {
2411 // We need to hold the API lock to do a GC.
2412 JSLockHolder locker(vm);
2413 vm->heap.collectAllGarbage();
2414 }
2415
2416 if (options.m_dumpSamplingProfilerData) {
2417#if ENABLE(SAMPLING_PROFILER)
2418 JSLockHolder locker(vm);
2419 vm->samplingProfiler()->reportTopFunctions();
2420 vm->samplingProfiler()->reportTopBytecodes();
2421#else
2422 dataLog("Sampling profiler is not enabled on this platform\n");
2423#endif
2424 }
2425
2426 printSuperSamplerState();
2427
2428 return result;
2429}
2430
2431#if OS(WINDOWS)
2432extern "C" __declspec(dllexport) int WINAPI dllLauncherEntryPoint(int argc, const char* argv[])
2433{
2434 return main(argc, const_cast<char**>(argv));
2435}
2436#endif
Note: See TracBrowser for help on using the repository browser.