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

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

Unzip initialization lists and constructors in JSCell hierarchy (5/7)
https://bugs.webkit.org/show_bug.cgi?id=67420

Patch by Mark Hahnenberg <[email protected]> on 2011-09-06
Reviewed by Geoffrey Garen.

Source/JavaScriptCore:

Completed the fifth level of the refactoring to add finishCreation()
methods to all classes within the JSCell hierarchy with non-trivial
constructor bodies.

This primarily consists of pushing the calls to finishCreation() down
into the constructors of the subclasses of the second level of the hierarchy
as well as pulling the finishCreation() calls out into the class's corresponding
create() method if it has one. Doing both simultaneously allows us to
maintain the invariant that the finishCreation() method chain is called exactly
once during the creation of an object, since calling it any other number of
times (0, 2, or more) will cause an assertion failure.

  • API/JSCallbackConstructor.cpp:

(JSC::JSCallbackConstructor::JSCallbackConstructor):

  • API/JSCallbackConstructor.h:

(JSC::JSCallbackConstructor::create):

  • API/JSCallbackFunction.cpp:

(JSC::JSCallbackFunction::JSCallbackFunction):
(JSC::JSCallbackFunction::finishCreation):

  • API/JSCallbackFunction.h:
  • JavaScriptCore.exp:
  • JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def:
  • debugger/DebuggerActivation.cpp:
  • debugger/DebuggerActivation.h:

(JSC::DebuggerActivation::create):

  • jsc.cpp:

(GlobalObject::finishCreation):
(GlobalObject::GlobalObject):

  • runtime/ArrayConstructor.cpp:

(JSC::ArrayConstructor::ArrayConstructor):
(JSC::ArrayConstructor::finishCreation):

  • runtime/ArrayConstructor.h:
  • runtime/ArrayPrototype.cpp:

(JSC::ArrayPrototype::ArrayPrototype):

  • runtime/ArrayPrototype.h:

(JSC::ArrayPrototype::create):

  • runtime/BooleanConstructor.cpp:

(JSC::BooleanConstructor::BooleanConstructor):
(JSC::BooleanConstructor::finishCreation):

  • runtime/BooleanConstructor.h:
  • runtime/BooleanObject.cpp:

(JSC::BooleanObject::BooleanObject):

  • runtime/BooleanObject.h:

(JSC::BooleanObject::create):

  • runtime/BooleanPrototype.cpp:

(JSC::BooleanPrototype::BooleanPrototype):
(JSC::BooleanPrototype::finishCreation):

  • runtime/BooleanPrototype.h:
  • runtime/DateConstructor.cpp:

(JSC::DateConstructor::DateConstructor):
(JSC::DateConstructor::finishCreation):

  • runtime/DateConstructor.h:
  • runtime/DateInstance.cpp:

(JSC::DateInstance::DateInstance):

  • runtime/DateInstance.h:

(JSC::DateInstance::create):

  • runtime/DatePrototype.cpp:

(JSC::DatePrototype::DatePrototype):
(JSC::DatePrototype::finishCreation):

  • runtime/DatePrototype.h:
  • runtime/Error.cpp:

(JSC::StrictModeTypeErrorFunction::StrictModeTypeErrorFunction):

  • runtime/ErrorConstructor.cpp:

(JSC::ErrorConstructor::ErrorConstructor):
(JSC::ErrorConstructor::finishCreation):

  • runtime/ErrorConstructor.h:
  • runtime/ErrorPrototype.cpp:

(JSC::ErrorPrototype::ErrorPrototype):

  • runtime/ErrorPrototype.h:

(JSC::ErrorPrototype::create):

  • runtime/FunctionConstructor.cpp:

(JSC::FunctionConstructor::FunctionConstructor):
(JSC::FunctionConstructor::finishCreation):

  • runtime/FunctionConstructor.h:
  • runtime/FunctionPrototype.cpp:

(JSC::FunctionPrototype::FunctionPrototype):
(JSC::FunctionPrototype::finishCreation):

  • runtime/FunctionPrototype.h:
  • runtime/InternalFunction.cpp:

(JSC::InternalFunction::InternalFunction):

  • runtime/InternalFunction.h:
  • runtime/JSActivation.cpp:

(JSC::JSActivation::JSActivation):

  • runtime/JSActivation.h:

(JSC::JSActivation::create):

  • runtime/JSGlobalObject.h:

(JSC::JSGlobalObject::create):
(JSC::JSGlobalObject::JSGlobalObject):

  • runtime/JSONObject.cpp:

(JSC::JSONObject::JSONObject):

  • runtime/JSONObject.h:

(JSC::JSONObject::create):

  • runtime/JSStaticScopeObject.h:

(JSC::JSStaticScopeObject::create):
(JSC::JSStaticScopeObject::JSStaticScopeObject):

  • runtime/JSString.cpp:

(JSC::StringObject::create):

  • runtime/MathObject.cpp:

(JSC::MathObject::MathObject):

  • runtime/MathObject.h:

(JSC::MathObject::create):

  • runtime/NativeErrorConstructor.cpp:

(JSC::NativeErrorConstructor::NativeErrorConstructor):

  • runtime/NativeErrorConstructor.h:

(JSC::NativeErrorConstructor::finishCreation):

  • runtime/NativeErrorPrototype.cpp:

(JSC::NativeErrorPrototype::NativeErrorPrototype):
(JSC::NativeErrorPrototype::finishCreation):

  • runtime/NativeErrorPrototype.h:
  • runtime/NumberConstructor.cpp:

(JSC::NumberConstructor::NumberConstructor):
(JSC::NumberConstructor::finishCreation):

  • runtime/NumberConstructor.h:
  • runtime/NumberObject.cpp:

(JSC::NumberObject::NumberObject):

  • runtime/NumberObject.h:

(JSC::NumberObject::create):

  • runtime/NumberPrototype.cpp:

(JSC::NumberPrototype::NumberPrototype):
(JSC::NumberPrototype::finishCreation):

  • runtime/NumberPrototype.h:
  • runtime/ObjectConstructor.cpp:

(JSC::ObjectConstructor::ObjectConstructor):
(JSC::ObjectConstructor::finishCreation):

  • runtime/ObjectConstructor.h:
  • runtime/RegExpConstructor.cpp:

(JSC::RegExpConstructor::RegExpConstructor):
(JSC::RegExpConstructor::finishCreation):
(JSC::RegExpMatchesArray::RegExpMatchesArray):

  • runtime/RegExpConstructor.h:
  • runtime/RegExpMatchesArray.h:

(JSC::RegExpMatchesArray::create):

  • runtime/RegExpObject.cpp:

(JSC::RegExpObject::RegExpObject):

  • runtime/RegExpObject.h:

(JSC::RegExpObject::create):

  • runtime/RegExpPrototype.cpp:

(JSC::RegExpPrototype::RegExpPrototype):

  • runtime/StringConstructor.cpp:

(JSC::StringConstructor::StringConstructor):
(JSC::StringConstructor::finishCreation):

  • runtime/StringConstructor.h:
  • runtime/StringObject.cpp:

(JSC::StringObject::StringObject):

  • runtime/StringObject.h:

(JSC::StringObject::create):

  • runtime/StringObjectThatMasqueradesAsUndefined.h:

(JSC::StringObjectThatMasqueradesAsUndefined::StringObjectThatMasqueradesAsUndefined):

  • runtime/StringPrototype.cpp:

(JSC::StringPrototype::StringPrototype):
(JSC::StringPrototype::finishCreation):

  • runtime/StringPrototype.h:

Source/JavaScriptGlue:

Completed the fifth level of the refactoring to add finishCreation()
methods to all classes within the JSCell hierarchy with non-trivial
constructor bodies.

This primarily consists of pushing the calls to finishCreation() down
into the constructors of the subclasses of the second level of the hierarchy
as well as pulling the finishCreation() calls out into the class's corresponding
create() method if it has one. Doing both simultaneously allows us to
maintain the invariant that the finishCreation() method chain is called exactly
once during the creation of an object, since calling it any other number of
times (0, 2, or more) will cause an assertion failure.

  • JSRun.cpp:

(JSGlueGlobalObject::JSGlueGlobalObject):

Source/WebCore:

No new tests.

Completed the fifth level of the refactoring to add finishCreation()
methods to all classes within the JSCell hierarchy with non-trivial
constructor bodies.

This primarily consists of pushing the calls to finishCreation() down
into the constructors of the subclasses of the second level of the hierarchy
as well as pulling the finishCreation() calls out into the class's corresponding
create() method if it has one. Doing both simultaneously allows us to
maintain the invariant that the finishCreation() method chain is called exactly
once during the creation of an object, since calling it any other number of
times (0, 2, or more) will cause an assertion failure.

  • WebCore.exp.in:
  • bindings/js/JSDOMBinding.h:

(WebCore::DOMConstructorObject::DOMConstructorObject):

  • bindings/js/JSDOMGlobalObject.cpp:

(WebCore::JSDOMGlobalObject::JSDOMGlobalObject):
(WebCore::JSDOMGlobalObject::finishCreation):

  • bindings/js/JSDOMGlobalObject.h:
  • bindings/js/JSDOMWindowShell.cpp:
  • bindings/js/JSDOMWindowShell.h:

(WebCore::JSDOMWindowShell::create):

  • bindings/js/JSDOMWrapper.h:

(WebCore::JSDOMWrapper::JSDOMWrapper):

  • bindings/scripts/CodeGeneratorJS.pm:

(GenerateImplementation):

  • bindings/scripts/test/JS/JSTestInterface.cpp:

(WebCore::JSTestInterface::JSTestInterface):

  • bindings/scripts/test/JS/JSTestMediaQueryListListener.cpp:

(WebCore::JSTestMediaQueryListListener::JSTestMediaQueryListListener):

  • bindings/scripts/test/JS/JSTestObj.cpp:

(WebCore::JSTestObj::JSTestObj):

  • bindings/scripts/test/JS/JSTestSerializedScriptValueInterface.cpp:

(WebCore::JSTestSerializedScriptValueInterface::JSTestSerializedScriptValueInterface):

  • bridge/c/CRuntimeObject.cpp:

(JSC::Bindings::CRuntimeObject::CRuntimeObject):
(JSC::Bindings::CRuntimeObject::finishCreation):

  • bridge/c/CRuntimeObject.h:
  • bridge/jni/jsc/JavaRuntimeObject.cpp:

(JSC::Bindings::JavaRuntimeObject::JavaRuntimeObject):
(JSC::Bindings::JavaRuntimeObject::finishCreation):

  • bridge/jni/jsc/JavaRuntimeObject.h:
  • bridge/objc/ObjCRuntimeObject.h:
  • bridge/objc/ObjCRuntimeObject.mm:

(JSC::Bindings::ObjCRuntimeObject::ObjCRuntimeObject):
(JSC::Bindings::ObjCRuntimeObject::finishCreation):

  • bridge/objc/objc_runtime.h:

(JSC::Bindings::ObjcFallbackObjectImp::create):

  • bridge/objc/objc_runtime.mm:

(JSC::Bindings::ObjcFallbackObjectImp::ObjcFallbackObjectImp):

  • bridge/qt/qt_instance.cpp:

(JSC::Bindings::QtRuntimeObject::QtRuntimeObject):

  • bridge/qt/qt_pixmapruntime.cpp:

(JSC::Bindings::QtPixmapRuntimeObject::QtPixmapRuntimeObject):

  • bridge/qt/qt_runtime.cpp:

(JSC::Bindings::QtRuntimeMethod::QtRuntimeMethod):
(JSC::Bindings::QtRuntimeMethod::finishCreation):

  • bridge/qt/qt_runtime.h:
  • bridge/runtime_array.cpp:

(JSC::RuntimeArray::RuntimeArray):

  • bridge/runtime_array.h:

(JSC::RuntimeArray::create):

  • bridge/runtime_method.cpp:

(JSC::RuntimeMethod::RuntimeMethod):
(JSC::RuntimeMethod::finishCreation):

  • bridge/runtime_method.h:
  • bridge/runtime_object.cpp:

(JSC::Bindings::RuntimeObject::RuntimeObject):

  • bridge/runtime_object.h:

(JSC::Bindings::RuntimeObject::create):

Source/WebKit/mac:

Completed the fifth level of the refactoring to add finishCreation()
methods to all classes within the JSCell hierarchy with non-trivial
constructor bodies.

This primarily consists of pushing the calls to finishCreation() down
into the constructors of the subclasses of the second level of the hierarchy
as well as pulling the finishCreation() calls out into the class's corresponding
create() method if it has one. Doing both simultaneously allows us to
maintain the invariant that the finishCreation() method chain is called exactly
once during the creation of an object, since calling it any other number of
times (0, 2, or more) will cause an assertion failure.

  • Plugins/Hosted/ProxyRuntimeObject.h:
  • Plugins/Hosted/ProxyRuntimeObject.mm:

(WebKit::ProxyRuntimeObject::ProxyRuntimeObject):
(WebKit::ProxyRuntimeObject::finishCreation):

Source/WebKit2:

Completed the fifth level of the refactoring to add finishCreation()
methods to all classes within the JSCell hierarchy with non-trivial
constructor bodies.

This primarily consists of pushing the calls to finishCreation() down
into the constructors of the subclasses of the second level of the hierarchy
as well as pulling the finishCreation() calls out into the class's corresponding
create() method if it has one. Doing both simultaneously allows us to
maintain the invariant that the finishCreation() method chain is called exactly
once during the creation of an object, since calling it any other number of
times (0, 2, or more) will cause an assertion failure.

  • WebProcess/Plugins/Netscape/JSNPMethod.cpp:

(WebKit::JSNPMethod::JSNPMethod):
(WebKit::JSNPMethod::finishCreation):

  • WebProcess/Plugins/Netscape/JSNPMethod.h:

(WebKit::JSNPMethod::create):

  • WebProcess/Plugins/Netscape/JSNPObject.cpp:

(WebKit::JSNPObject::JSNPObject):

  • WebProcess/Plugins/Netscape/JSNPObject.h:

(WebKit::JSNPObject::create):

  • Property svn:eol-style set to native
File size: 20.2 KB
Line 
1/*
2 * Copyright (C) 1999-2000 Harri Porten ([email protected])
3 * Copyright (C) 2004, 2005, 2006, 2007, 2008 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 "BytecodeGenerator.h"
26#include "Completion.h"
27#include "CurrentTime.h"
28#include "ExceptionHelpers.h"
29#include "InitializeThreading.h"
30#include "JSArray.h"
31#include "JSFunction.h"
32#include "JSLock.h"
33#include "JSString.h"
34#include "SamplingTool.h"
35#include <math.h>
36#include <stdio.h>
37#include <stdlib.h>
38#include <string.h>
39
40#if !OS(WINDOWS)
41#include <unistd.h>
42#endif
43
44#if HAVE(READLINE)
45#include <readline/history.h>
46#include <readline/readline.h>
47#endif
48
49#if HAVE(SYS_TIME_H)
50#include <sys/time.h>
51#endif
52
53#if HAVE(SIGNAL_H)
54#include <signal.h>
55#endif
56
57#if COMPILER(MSVC) && !OS(WINCE)
58#include <crtdbg.h>
59#include <mmsystem.h>
60#include <windows.h>
61#endif
62
63#if PLATFORM(QT)
64#include <QCoreApplication>
65#include <QDateTime>
66#endif
67
68using namespace JSC;
69using namespace WTF;
70
71static void cleanupGlobalData(JSGlobalData*);
72static bool fillBufferWithContentsOfFile(const UString& fileName, Vector<char>& buffer);
73
74static EncodedJSValue JSC_HOST_CALL functionPrint(ExecState*);
75static EncodedJSValue JSC_HOST_CALL functionDebug(ExecState*);
76static EncodedJSValue JSC_HOST_CALL functionGC(ExecState*);
77#ifndef NDEBUG
78static EncodedJSValue JSC_HOST_CALL functionReleaseExecutableMemory(ExecState*);
79#endif
80static EncodedJSValue JSC_HOST_CALL functionVersion(ExecState*);
81static EncodedJSValue JSC_HOST_CALL functionRun(ExecState*);
82static EncodedJSValue JSC_HOST_CALL functionLoad(ExecState*);
83static EncodedJSValue JSC_HOST_CALL functionCheckSyntax(ExecState*);
84static EncodedJSValue JSC_HOST_CALL functionReadline(ExecState*);
85static EncodedJSValue JSC_HOST_CALL functionPreciseTime(ExecState*);
86static NO_RETURN_WITH_VALUE EncodedJSValue JSC_HOST_CALL functionQuit(ExecState*);
87
88#if ENABLE(SAMPLING_FLAGS)
89static EncodedJSValue JSC_HOST_CALL functionSetSamplingFlags(ExecState*);
90static EncodedJSValue JSC_HOST_CALL functionClearSamplingFlags(ExecState*);
91#endif
92
93struct Script {
94 bool isFile;
95 char* argument;
96
97 Script(bool isFile, char *argument)
98 : isFile(isFile)
99 , argument(argument)
100 {
101 }
102};
103
104struct Options {
105 Options()
106 : interactive(false)
107 , dump(false)
108 {
109 }
110
111 bool interactive;
112 bool dump;
113 Vector<Script> scripts;
114 Vector<UString> arguments;
115};
116
117static const char interactivePrompt[] = "> ";
118static const UString interpreterName("Interpreter");
119
120class StopWatch {
121public:
122 void start();
123 void stop();
124 long getElapsedMS(); // call stop() first
125
126private:
127 double m_startTime;
128 double m_stopTime;
129};
130
131void StopWatch::start()
132{
133 m_startTime = currentTime();
134}
135
136void StopWatch::stop()
137{
138 m_stopTime = currentTime();
139}
140
141long StopWatch::getElapsedMS()
142{
143 return static_cast<long>((m_stopTime - m_startTime) * 1000);
144}
145
146class GlobalObject : public JSGlobalObject {
147private:
148 GlobalObject(JSGlobalData&, Structure*, const Vector<UString>& arguments);
149
150public:
151 typedef JSGlobalObject Base;
152
153 static GlobalObject* create(JSGlobalData& globalData, Structure* structure, const Vector<UString>& arguments)
154 {
155 return new (allocateCell<GlobalObject>(globalData.heap)) GlobalObject(globalData, structure, arguments);
156 }
157 virtual UString className() const { return "global"; }
158
159protected:
160 void finishCreation(JSGlobalData& globalData, const Vector<UString>& arguments)
161 {
162 Base::finishCreation(globalData, this);
163 putDirectFunction(globalExec(), JSFunction::create(globalExec(), this, functionStructure(), 1, Identifier(globalExec(), "debug"), functionDebug));
164 putDirectFunction(globalExec(), JSFunction::create(globalExec(), this, functionStructure(), 1, Identifier(globalExec(), "print"), functionPrint));
165 putDirectFunction(globalExec(), JSFunction::create(globalExec(), this, functionStructure(), 0, Identifier(globalExec(), "quit"), functionQuit));
166 putDirectFunction(globalExec(), JSFunction::create(globalExec(), this, functionStructure(), 0, Identifier(globalExec(), "gc"), functionGC));
167#ifndef NDEBUG
168 putDirectFunction(globalExec(), JSFunction::create(globalExec(), this, functionStructure(), 0, Identifier(globalExec(), "releaseExecutableMemory"), functionReleaseExecutableMemory));
169#endif
170 putDirectFunction(globalExec(), JSFunction::create(globalExec(), this, functionStructure(), 1, Identifier(globalExec(), "version"), functionVersion));
171 putDirectFunction(globalExec(), JSFunction::create(globalExec(), this, functionStructure(), 1, Identifier(globalExec(), "run"), functionRun));
172 putDirectFunction(globalExec(), JSFunction::create(globalExec(), this, functionStructure(), 1, Identifier(globalExec(), "load"), functionLoad));
173 putDirectFunction(globalExec(), JSFunction::create(globalExec(), this, functionStructure(), 1, Identifier(globalExec(), "checkSyntax"), functionCheckSyntax));
174 putDirectFunction(globalExec(), JSFunction::create(globalExec(), this, functionStructure(), 0, Identifier(globalExec(), "readline"), functionReadline));
175 putDirectFunction(globalExec(), JSFunction::create(globalExec(), this, functionStructure(), 0, Identifier(globalExec(), "preciseTime"), functionPreciseTime));
176
177#if ENABLE(SAMPLING_FLAGS)
178 putDirectFunction(globalExec(), JSFunction::create(globalExec(), this, functionStructure(), 1, Identifier(globalExec(), "setSamplingFlags"), functionSetSamplingFlags));
179 putDirectFunction(globalExec(), JSFunction::create(globalExec(), this, functionStructure(), 1, Identifier(globalExec(), "clearSamplingFlags"), functionClearSamplingFlags));
180#endif
181
182 JSObject* array = constructEmptyArray(globalExec());
183 for (size_t i = 0; i < arguments.size(); ++i)
184 array->put(globalExec(), i, jsString(globalExec(), arguments[i]));
185 putDirect(globalExec()->globalData(), Identifier(globalExec(), "arguments"), array);
186 }
187};
188COMPILE_ASSERT(!IsInteger<GlobalObject>::value, WTF_IsInteger_GlobalObject_false);
189ASSERT_CLASS_FITS_IN_CELL(GlobalObject);
190
191GlobalObject::GlobalObject(JSGlobalData& globalData, Structure* structure, const Vector<UString>& arguments)
192 : JSGlobalObject(globalData, structure)
193{
194 finishCreation(globalData, arguments);
195}
196
197EncodedJSValue JSC_HOST_CALL functionPrint(ExecState* exec)
198{
199 for (unsigned i = 0; i < exec->argumentCount(); ++i) {
200 if (i)
201 putchar(' ');
202
203 printf("%s", exec->argument(i).toString(exec).utf8().data());
204 }
205
206 putchar('\n');
207 fflush(stdout);
208 return JSValue::encode(jsUndefined());
209}
210
211EncodedJSValue JSC_HOST_CALL functionDebug(ExecState* exec)
212{
213 fprintf(stderr, "--> %s\n", exec->argument(0).toString(exec).utf8().data());
214 return JSValue::encode(jsUndefined());
215}
216
217EncodedJSValue JSC_HOST_CALL functionGC(ExecState* exec)
218{
219 JSLock lock(SilenceAssertionsOnly);
220 exec->heap()->collectAllGarbage();
221 return JSValue::encode(jsUndefined());
222}
223
224#ifndef NDEBUG
225EncodedJSValue JSC_HOST_CALL functionReleaseExecutableMemory(ExecState* exec)
226{
227 JSLock lock(SilenceAssertionsOnly);
228 exec->globalData().releaseExecutableMemory();
229 return JSValue::encode(jsUndefined());
230}
231#endif
232
233EncodedJSValue JSC_HOST_CALL functionVersion(ExecState*)
234{
235 // We need this function for compatibility with the Mozilla JS tests but for now
236 // we don't actually do any version-specific handling
237 return JSValue::encode(jsUndefined());
238}
239
240EncodedJSValue JSC_HOST_CALL functionRun(ExecState* exec)
241{
242 UString fileName = exec->argument(0).toString(exec);
243 Vector<char> script;
244 if (!fillBufferWithContentsOfFile(fileName, script))
245 return JSValue::encode(throwError(exec, createError(exec, "Could not open file.")));
246
247 GlobalObject* globalObject = GlobalObject::create(exec->globalData(), GlobalObject::createStructure(exec->globalData(), jsNull()), Vector<UString>());
248
249 StopWatch stopWatch;
250 stopWatch.start();
251 evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), makeSource(script.data(), fileName));
252 stopWatch.stop();
253
254 return JSValue::encode(jsNumber(stopWatch.getElapsedMS()));
255}
256
257EncodedJSValue JSC_HOST_CALL functionLoad(ExecState* exec)
258{
259 UString fileName = exec->argument(0).toString(exec);
260 Vector<char> script;
261 if (!fillBufferWithContentsOfFile(fileName, script))
262 return JSValue::encode(throwError(exec, createError(exec, "Could not open file.")));
263
264 JSGlobalObject* globalObject = exec->lexicalGlobalObject();
265 Completion result = evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), makeSource(script.data(), fileName));
266 if (result.complType() == Throw)
267 throwError(exec, result.value());
268 return JSValue::encode(result.value());
269}
270
271EncodedJSValue JSC_HOST_CALL functionCheckSyntax(ExecState* exec)
272{
273 UString fileName = exec->argument(0).toString(exec);
274 Vector<char> script;
275 if (!fillBufferWithContentsOfFile(fileName, script))
276 return JSValue::encode(throwError(exec, createError(exec, "Could not open file.")));
277
278 JSGlobalObject* globalObject = exec->lexicalGlobalObject();
279
280 StopWatch stopWatch;
281 stopWatch.start();
282 Completion result = checkSyntax(globalObject->globalExec(), makeSource(script.data(), fileName));
283 stopWatch.stop();
284
285 if (result.complType() == Throw)
286 throwError(exec, result.value());
287 return JSValue::encode(jsNumber(stopWatch.getElapsedMS()));
288}
289
290#if ENABLE(SAMPLING_FLAGS)
291EncodedJSValue JSC_HOST_CALL functionSetSamplingFlags(ExecState* exec)
292{
293 for (unsigned i = 0; i < exec->argumentCount(); ++i) {
294 unsigned flag = static_cast<unsigned>(exec->argument(i).toNumber(exec));
295 if ((flag >= 1) && (flag <= 32))
296 SamplingFlags::setFlag(flag);
297 }
298 return JSValue::encode(jsNull());
299}
300
301EncodedJSValue JSC_HOST_CALL functionClearSamplingFlags(ExecState* exec)
302{
303 for (unsigned i = 0; i < exec->argumentCount(); ++i) {
304 unsigned flag = static_cast<unsigned>(exec->argument(i).toNumber(exec));
305 if ((flag >= 1) && (flag <= 32))
306 SamplingFlags::clearFlag(flag);
307 }
308 return JSValue::encode(jsNull());
309}
310#endif
311
312EncodedJSValue JSC_HOST_CALL functionReadline(ExecState* exec)
313{
314 Vector<char, 256> line;
315 int c;
316 while ((c = getchar()) != EOF) {
317 // FIXME: Should we also break on \r?
318 if (c == '\n')
319 break;
320 line.append(c);
321 }
322 line.append('\0');
323 return JSValue::encode(jsString(exec, line.data()));
324}
325
326EncodedJSValue JSC_HOST_CALL functionPreciseTime(ExecState*)
327{
328 return JSValue::encode(jsNumber(currentTime()));
329}
330
331EncodedJSValue JSC_HOST_CALL functionQuit(ExecState* exec)
332{
333 // Technically, destroying the heap in the middle of JS execution is a no-no,
334 // but we want to maintain compatibility with the Mozilla test suite, so
335 // we pretend that execution has terminated to avoid ASSERTs, then tear down the heap.
336 exec->globalData().dynamicGlobalObject = 0;
337
338 cleanupGlobalData(&exec->globalData());
339 exit(EXIT_SUCCESS);
340
341#if COMPILER(MSVC) && OS(WINCE)
342 // Without this, Visual Studio will complain that this method does not return a value.
343 return JSValue::encode(jsUndefined());
344#endif
345}
346
347// Use SEH for Release builds only to get rid of the crash report dialog
348// (luckily the same tests fail in Release and Debug builds so far). Need to
349// be in a separate main function because the jscmain function requires object
350// unwinding.
351
352#if COMPILER(MSVC) && !COMPILER(INTEL) && !defined(_DEBUG) && !OS(WINCE)
353#define TRY __try {
354#define EXCEPT(x) } __except (EXCEPTION_EXECUTE_HANDLER) { x; }
355#else
356#define TRY
357#define EXCEPT(x)
358#endif
359
360int jscmain(int argc, char** argv, JSGlobalData*);
361
362int main(int argc, char** argv)
363{
364#if OS(WINDOWS)
365#if !OS(WINCE)
366 // Cygwin calls ::SetErrorMode(SEM_FAILCRITICALERRORS), which we will inherit. This is bad for
367 // testing/debugging, as it causes the post-mortem debugger not to be invoked. We reset the
368 // error mode here to work around Cygwin's behavior. See <http://webkit.org/b/55222>.
369 ::SetErrorMode(0);
370#endif
371
372#if defined(_DEBUG)
373 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
374 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
375 _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
376 _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
377 _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
378 _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
379#endif
380
381 timeBeginPeriod(1);
382#endif
383
384#if PLATFORM(QT)
385 QCoreApplication app(argc, argv);
386#endif
387
388 // Initialize JSC before getting JSGlobalData.
389 JSC::initializeThreading();
390
391 // We can't use destructors in the following code because it uses Windows
392 // Structured Exception Handling
393 int res = 0;
394 JSGlobalData* globalData = JSGlobalData::create(ThreadStackTypeLarge, LargeHeap).leakRef();
395 TRY
396 res = jscmain(argc, argv, globalData);
397 EXCEPT(res = 3)
398
399 cleanupGlobalData(globalData);
400 return res;
401}
402
403static void cleanupGlobalData(JSGlobalData* globalData)
404{
405 JSLock lock(SilenceAssertionsOnly);
406 globalData->clearBuiltinStructures();
407 globalData->heap.destroy();
408 globalData->deref();
409}
410
411static bool runWithScripts(GlobalObject* globalObject, const Vector<Script>& scripts, bool dump)
412{
413 UString script;
414 UString fileName;
415 Vector<char> scriptBuffer;
416
417 if (dump)
418 BytecodeGenerator::setDumpsGeneratedCode(true);
419
420 JSGlobalData& globalData = globalObject->globalData();
421
422#if ENABLE(SAMPLING_FLAGS)
423 SamplingFlags::start();
424#endif
425
426 bool success = true;
427 for (size_t i = 0; i < scripts.size(); i++) {
428 if (scripts[i].isFile) {
429 fileName = scripts[i].argument;
430 if (!fillBufferWithContentsOfFile(fileName, scriptBuffer))
431 return false; // fail early so we can catch missing files
432 script = scriptBuffer.data();
433 } else {
434 script = scripts[i].argument;
435 fileName = "[Command Line]";
436 }
437
438 globalData.startSampling();
439
440 Completion completion = evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), makeSource(script, fileName));
441 success = success && completion.complType() != Throw;
442 if (dump) {
443 if (completion.complType() == Throw)
444 printf("Exception: %s\n", completion.value().toString(globalObject->globalExec()).utf8().data());
445 else
446 printf("End: %s\n", completion.value().toString(globalObject->globalExec()).utf8().data());
447 }
448
449 globalData.stopSampling();
450 globalObject->globalExec()->clearException();
451 }
452
453#if ENABLE(SAMPLING_FLAGS)
454 SamplingFlags::stop();
455#endif
456 globalData.dumpSampleData(globalObject->globalExec());
457#if ENABLE(SAMPLING_COUNTERS)
458 AbstractSamplingCounter::dump();
459#endif
460#if ENABLE(REGEXP_TRACING)
461 globalData.dumpRegExpTrace();
462#endif
463 return success;
464}
465
466#define RUNNING_FROM_XCODE 0
467
468static void runInteractive(GlobalObject* globalObject)
469{
470 while (true) {
471#if HAVE(READLINE) && !RUNNING_FROM_XCODE
472 char* line = readline(interactivePrompt);
473 if (!line)
474 break;
475 if (line[0])
476 add_history(line);
477 Completion completion = evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), makeSource(line, interpreterName));
478 free(line);
479#else
480 printf("%s", interactivePrompt);
481 Vector<char, 256> line;
482 int c;
483 while ((c = getchar()) != EOF) {
484 // FIXME: Should we also break on \r?
485 if (c == '\n')
486 break;
487 line.append(c);
488 }
489 if (line.isEmpty())
490 break;
491 line.append('\0');
492 Completion completion = evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), makeSource(line.data(), interpreterName));
493#endif
494 if (completion.complType() == Throw)
495 printf("Exception: %s\n", completion.value().toString(globalObject->globalExec()).utf8().data());
496 else
497 printf("%s\n", completion.value().toString(globalObject->globalExec()).utf8().data());
498
499 globalObject->globalExec()->clearException();
500 }
501 printf("\n");
502}
503
504static NO_RETURN void printUsageStatement(JSGlobalData* globalData, bool help = false)
505{
506 fprintf(stderr, "Usage: jsc [options] [files] [-- arguments]\n");
507 fprintf(stderr, " -d Dumps bytecode (debug builds only)\n");
508 fprintf(stderr, " -e Evaluate argument as script code\n");
509 fprintf(stderr, " -f Specifies a source file (deprecated)\n");
510 fprintf(stderr, " -h|--help Prints this help message\n");
511 fprintf(stderr, " -i Enables interactive mode (default if no files are specified)\n");
512#if HAVE(SIGNAL_H)
513 fprintf(stderr, " -s Installs signal handlers that exit on a crash (Unix platforms only)\n");
514#endif
515
516 cleanupGlobalData(globalData);
517 exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
518}
519
520static void parseArguments(int argc, char** argv, Options& options, JSGlobalData* globalData)
521{
522 int i = 1;
523 for (; i < argc; ++i) {
524 const char* arg = argv[i];
525 if (!strcmp(arg, "-f")) {
526 if (++i == argc)
527 printUsageStatement(globalData);
528 options.scripts.append(Script(true, argv[i]));
529 continue;
530 }
531 if (!strcmp(arg, "-e")) {
532 if (++i == argc)
533 printUsageStatement(globalData);
534 options.scripts.append(Script(false, argv[i]));
535 continue;
536 }
537 if (!strcmp(arg, "-i")) {
538 options.interactive = true;
539 continue;
540 }
541 if (!strcmp(arg, "-d")) {
542 options.dump = true;
543 continue;
544 }
545 if (!strcmp(arg, "-s")) {
546#if HAVE(SIGNAL_H)
547 signal(SIGILL, _exit);
548 signal(SIGFPE, _exit);
549 signal(SIGBUS, _exit);
550 signal(SIGSEGV, _exit);
551#endif
552 continue;
553 }
554 if (!strcmp(arg, "--")) {
555 ++i;
556 break;
557 }
558 if (!strcmp(arg, "-h") || !strcmp(arg, "--help"))
559 printUsageStatement(globalData, true);
560 options.scripts.append(Script(true, argv[i]));
561 }
562
563 if (options.scripts.isEmpty())
564 options.interactive = true;
565
566 for (; i < argc; ++i)
567 options.arguments.append(argv[i]);
568}
569
570int jscmain(int argc, char** argv, JSGlobalData* globalData)
571{
572 JSLock lock(SilenceAssertionsOnly);
573
574 Options options;
575 parseArguments(argc, argv, options, globalData);
576
577 GlobalObject* globalObject = GlobalObject::create(*globalData, GlobalObject::createStructure(*globalData, jsNull()), options.arguments);
578 bool success = runWithScripts(globalObject, options.scripts, options.dump);
579 if (options.interactive && success)
580 runInteractive(globalObject);
581
582 return success ? 0 : 3;
583}
584
585static bool fillBufferWithContentsOfFile(const UString& fileName, Vector<char>& buffer)
586{
587 FILE* f = fopen(fileName.utf8().data(), "r");
588 if (!f) {
589 fprintf(stderr, "Could not open file: %s\n", fileName.utf8().data());
590 return false;
591 }
592
593 size_t bufferSize = 0;
594 size_t bufferCapacity = 1024;
595
596 buffer.resize(bufferCapacity);
597
598 while (!feof(f) && !ferror(f)) {
599 bufferSize += fread(buffer.data() + bufferSize, 1, bufferCapacity - bufferSize, f);
600 if (bufferSize == bufferCapacity) { // guarantees space for trailing '\0'
601 bufferCapacity *= 2;
602 buffer.resize(bufferCapacity);
603 }
604 }
605 fclose(f);
606 buffer[bufferSize] = '\0';
607
608 if (buffer[0] == '#' && buffer[1] == '!')
609 buffer[0] = buffer[1] = '/';
610
611 return true;
612}
Note: See TracBrowser for help on using the repository browser.