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

Last change on this file since 202280 was 202280, checked in by [email protected], 9 years ago

It should be easy to add a private global helper function for builtins
https://bugs.webkit.org/show_bug.cgi?id=158893

Reviewed by Mark Lam.

Source/JavaScriptCore:

This patch does two things. First it moves all the builtin names
out of CommonIdentifiers and into BuiltinNames. This means that
adding a new function to the Builtins does not require rebuilding
all of JavaScriptCore. This patch also adds a new decorator to our
builtins @privateGlobal that will automatically put the function
on the global object. The name of the property will be the same as
the private name of the function.

This patch, also, removes the JSArrayIterator.h/.cpp files
as they no longer appear to be used in any real way. Finally,
the builtins tests have been rebaselined. It appears this has
not been done for a while so the expected files contain other
changes.

  • CMakeLists.txt:
  • JavaScriptCore.xcodeproj/project.pbxproj:
  • Scripts/builtins/builtins_generate_combined_header.py:

(BuiltinsCombinedHeaderGenerator.generate_output):
(generate_section_for_code_name_macro):
(generate_section_for_global_private_code_name_macro):

  • Scripts/builtins/builtins_model.py:

(BuiltinFunction.init):
(BuiltinFunction.fromString):

  • Scripts/tests/builtins/expected/JavaScriptCore-Builtin.Promise-Combined.js-result:
  • Scripts/tests/builtins/expected/JavaScriptCore-Builtin.Promise-Separate.js-result:
  • Scripts/tests/builtins/expected/JavaScriptCore-Builtin.prototype-Combined.js-result:
  • Scripts/tests/builtins/expected/JavaScriptCore-Builtin.prototype-Separate.js-result:
  • Scripts/tests/builtins/expected/JavaScriptCore-BuiltinConstructor-Combined.js-result:
  • Scripts/tests/builtins/expected/JavaScriptCore-BuiltinConstructor-Separate.js-result:
  • Scripts/tests/builtins/expected/JavaScriptCore-InternalClashingNames-Combined.js-result:
  • Scripts/tests/builtins/expected/WebCore-ArbitraryConditionalGuard-Separate.js-result:
  • Scripts/tests/builtins/expected/WebCore-GuardedBuiltin-Separate.js-result:
  • Scripts/tests/builtins/expected/WebCore-GuardedInternalBuiltin-Separate.js-result:
  • Scripts/tests/builtins/expected/WebCore-UnguardedBuiltin-Separate.js-result:
  • Scripts/tests/builtins/expected/WebCore-xmlCasingTest-Separate.js-result:
  • builtins/ArrayIteratorPrototype.js:
  • builtins/ArrayPrototype.js:
  • builtins/BuiltinNames.h:
  • builtins/GeneratorPrototype.js:
  • builtins/GlobalObject.js:
  • builtins/PromiseOperations.js:
  • builtins/RegExpPrototype.js:
  • builtins/StringPrototype.js:
  • bytecode/BytecodeIntrinsicRegistry.cpp:
  • bytecompiler/BytecodeGenerator.cpp:

(JSC::BytecodeGenerator::initializeArrowFunctionContextScopeIfNeeded):
(JSC::BytecodeGenerator::expectedFunctionForIdentifier):
(JSC::BytecodeGenerator::emitGetTemplateObject):
(JSC::BytecodeGenerator::emitLoadNewTargetFromArrowFunctionLexicalEnvironment):
(JSC::BytecodeGenerator::emitLoadDerivedConstructorFromArrowFunctionLexicalEnvironment):
(JSC::BytecodeGenerator::emitPutNewTargetToArrowFunctionContextScope):
(JSC::BytecodeGenerator::emitPutDerivedConstructorToArrowFunctionContextScope):
(JSC::BytecodeGenerator::emitGeneratorStateChange):

  • bytecompiler/NodesCodegen.cpp:

(JSC::emitHomeObjectForCallee):
(JSC::emitPutHomeObject):
(JSC::FunctionNode::emitBytecode):

  • dfg/DFGOperations.cpp:
  • inspector/JSInjectedScriptHost.cpp:

(Inspector::JSInjectedScriptHost::subtype):
(Inspector::JSInjectedScriptHost::getInternalProperties): Deleted.

  • parser/Lexer.cpp:

(JSC::Lexer<LChar>::parseIdentifier):
(JSC::Lexer<UChar>::parseIdentifier):

  • parser/Nodes.h:
  • parser/Parser.cpp:

(JSC::Parser<LexerType>::createGeneratorParameters):
(JSC::Parser<LexerType>::parseExportDeclaration):

  • runtime/ArrayIteratorPrototype.cpp:
  • runtime/ArrayIteratorPrototype.h:
  • runtime/ArrayPrototype.cpp:
  • runtime/CommonIdentifiers.cpp:

(JSC::CommonIdentifiers::CommonIdentifiers): Deleted.

  • runtime/CommonIdentifiers.h:
  • runtime/CommonSlowPaths.cpp:

(JSC::SLOW_PATH_DECL):

  • runtime/IntlDateTimeFormat.cpp:
  • runtime/IntlDateTimeFormatPrototype.cpp:

(JSC::IntlDateTimeFormatPrototypeGetterFormat):
(JSC::IntlDateTimeFormatPrototypeFuncResolvedOptions):

  • runtime/IntlNumberFormatPrototype.cpp:

(JSC::IntlNumberFormatPrototypeGetterFormat):
(JSC::IntlNumberFormatPrototypeFuncResolvedOptions):

  • runtime/IntlObjectInlines.h:

(JSC::constructIntlInstanceWithWorkaroundForLegacyIntlConstructor):

  • runtime/JSArrayIterator.cpp: Removed.

(JSC::JSArrayIterator::finishCreation): Deleted.
(JSC::JSArrayIterator::kind): Deleted.
(JSC::JSArrayIterator::iteratedValue): Deleted.

  • runtime/JSArrayIterator.h: Removed.

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

  • runtime/JSGenericTypedArrayViewConstructorInlines.h:

(JSC::JSGenericTypedArrayViewConstructor<ViewClass>::finishCreation):

  • runtime/JSGenericTypedArrayViewPrototypeFunctions.h:
  • runtime/JSGlobalObject.cpp:

(JSC::JSGlobalObject::init):

  • runtime/JSInternalPromise.cpp:
  • runtime/JSInternalPromiseDeferred.cpp:

(JSC::JSInternalPromiseDeferred::create):

  • runtime/JSPromise.cpp:

(JSC::JSPromise::finishCreation):
(JSC::JSPromise::result):

  • runtime/JSPromiseDeferred.cpp:

(JSC::JSPromiseDeferred::create):

  • runtime/JSStringIterator.cpp:

(JSC::JSStringIterator::finishCreation):
(JSC::JSStringIterator::iteratedValue):
(JSC::JSStringIterator::clone):

  • runtime/MapPrototype.cpp:

(JSC::MapPrototype::finishCreation):

  • runtime/ObjectConstructor.cpp:

(JSC::ObjectConstructor::finishCreation):

  • runtime/ReflectObject.cpp:

(JSC::ReflectObject::finishCreation):

  • runtime/StringPrototype.cpp:

(JSC::StringPrototype::finishCreation):

  • runtime/TypedArrayInlines.h:

Source/WebCore:

Add JSCJSValueInlines.h to fix build issues.

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