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

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

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

Reviewed by Geoffrey Garen.

Source/JavaScriptCore:

Completed the sixth 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 fifth 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/JSCallbackFunction.cpp:

(JSC::JSCallbackFunction::JSCallbackFunction):

  • API/JSCallbackFunction.h:

(JSC::JSCallbackFunction::create):

  • jsc.cpp:

(GlobalObject::create):
(GlobalObject::GlobalObject):

  • runtime/ArrayConstructor.cpp:

(JSC::ArrayConstructor::ArrayConstructor):

  • runtime/ArrayConstructor.h:

(JSC::ArrayConstructor::create):

  • runtime/BooleanConstructor.cpp:

(JSC::BooleanConstructor::BooleanConstructor):

  • runtime/BooleanConstructor.h:

(JSC::BooleanConstructor::create):

  • runtime/BooleanPrototype.cpp:

(JSC::BooleanPrototype::BooleanPrototype):

  • runtime/BooleanPrototype.h:

(JSC::BooleanPrototype::create):

  • runtime/DateConstructor.cpp:

(JSC::DateConstructor::DateConstructor):

  • runtime/DateConstructor.h:

(JSC::DateConstructor::create):

  • runtime/DatePrototype.cpp:

(JSC::DatePrototype::DatePrototype):

  • runtime/DatePrototype.h:

(JSC::DatePrototype::create):

  • runtime/Error.cpp:

(JSC::StrictModeTypeErrorFunction::StrictModeTypeErrorFunction):
(JSC::StrictModeTypeErrorFunction::create):

  • runtime/ErrorConstructor.cpp:

(JSC::ErrorConstructor::ErrorConstructor):

  • runtime/ErrorConstructor.h:

(JSC::ErrorConstructor::create):

  • runtime/FunctionConstructor.cpp:

(JSC::FunctionConstructor::FunctionConstructor):

  • runtime/FunctionConstructor.h:

(JSC::FunctionConstructor::create):

  • runtime/FunctionPrototype.cpp:

(JSC::FunctionPrototype::FunctionPrototype):

  • runtime/FunctionPrototype.h:

(JSC::FunctionPrototype::create):

  • runtime/NativeErrorConstructor.cpp:

(JSC::NativeErrorConstructor::NativeErrorConstructor):

  • runtime/NativeErrorConstructor.h:

(JSC::NativeErrorConstructor::create):

  • runtime/NativeErrorPrototype.cpp:

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

  • runtime/NativeErrorPrototype.h:

(JSC::NativeErrorPrototype::create):

  • runtime/NumberConstructor.cpp:

(JSC::NumberConstructor::NumberConstructor):

  • runtime/NumberConstructor.h:

(JSC::NumberConstructor::create):

  • runtime/NumberPrototype.cpp:

(JSC::NumberPrototype::NumberPrototype):

  • runtime/NumberPrototype.h:

(JSC::NumberPrototype::create):

  • runtime/ObjectConstructor.cpp:

(JSC::ObjectConstructor::ObjectConstructor):

  • runtime/ObjectConstructor.h:

(JSC::ObjectConstructor::create):

  • runtime/RegExpConstructor.cpp:

(JSC::RegExpConstructor::RegExpConstructor):

  • runtime/RegExpConstructor.h:

(JSC::RegExpConstructor::create):

  • runtime/RegExpPrototype.cpp:

(JSC::RegExpPrototype::RegExpPrototype):

  • runtime/RegExpPrototype.h:

(JSC::RegExpPrototype::create):

  • runtime/StringConstructor.cpp:

(JSC::StringConstructor::StringConstructor):

  • runtime/StringConstructor.h:

(JSC::StringConstructor::create):

  • runtime/StringObjectThatMasqueradesAsUndefined.h:

(JSC::StringObjectThatMasqueradesAsUndefined::create):
(JSC::StringObjectThatMasqueradesAsUndefined::StringObjectThatMasqueradesAsUndefined):

  • runtime/StringPrototype.cpp:

(JSC::StringPrototype::StringPrototype):

  • runtime/StringPrototype.h:

(JSC::StringPrototype::create):

Source/JavaScriptGlue:

Completed the sixth 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 fifth 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):

  • JSRun.h:

(JSGlueGlobalObject::create):

Source/WebCore:

No new tests.

Completed the sixth 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 fifth 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):
(WebCore::DOMConstructorWithDocument::DOMConstructorWithDocument):
(WebCore::DOMConstructorWithDocument::finishCreation):

  • bindings/js/JSDOMGlobalObject.cpp:

(WebCore::JSDOMGlobalObject::JSDOMGlobalObject):

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

(WebCore::JSDOMWindowBase::JSDOMWindowBase):
(WebCore::JSDOMWindowBase::finishCreation):

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

(WebCore::JSWorkerContextBase::JSWorkerContextBase):
(WebCore::JSWorkerContextBase::finishCreation):

  • bindings/js/JSWorkerContextBase.h:
  • bindings/scripts/CodeGeneratorJS.pm:

Added a finishCreation declaration and Moved the finishCreation call into the
create method for all classes except for subclasses of JSWorkerContextBase and
JSDOMWindowBase because those classes are on the next level, and it's easier
to do all of these classes in one fell swoop rather than level by level.
(GenerateHeader):
Added the implementation of the finishCreation method for the classes described above.
(GenerateImplementation):
Also added the finishCreation calls to the autogenerated DOM constructor classes.
(GenerateConstructorDeclaration):
(GenerateConstructorDefinition):

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

(WebCore::JSTestInterfaceConstructor::create):
(WebCore::JSTestInterfaceConstructor::JSTestInterfaceConstructor):
(WebCore::JSTestInterfaceConstructor::finishCreation):
(WebCore::JSTestInterface::JSTestInterface):
(WebCore::JSTestInterface::finishCreation):

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

(WebCore::JSTestInterface::create):
(WebCore::JSTestInterfacePrototype::create):
(WebCore::JSTestInterfacePrototype::JSTestInterfacePrototype):

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

(WebCore::JSTestMediaQueryListListenerConstructor::create):
(WebCore::JSTestMediaQueryListListenerConstructor::JSTestMediaQueryListListenerConstructor):
(WebCore::JSTestMediaQueryListListenerConstructor::finishCreation):
(WebCore::JSTestMediaQueryListListener::JSTestMediaQueryListListener):
(WebCore::JSTestMediaQueryListListener::finishCreation):

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

(WebCore::JSTestMediaQueryListListener::create):
(WebCore::JSTestMediaQueryListListenerPrototype::create):
(WebCore::JSTestMediaQueryListListenerPrototype::JSTestMediaQueryListListenerPrototype):

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

(WebCore::JSTestObjConstructor::create):
(WebCore::JSTestObjConstructor::JSTestObjConstructor):
(WebCore::JSTestObjConstructor::finishCreation):
(WebCore::JSTestObj::JSTestObj):
(WebCore::JSTestObj::finishCreation):

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

(WebCore::JSTestObj::create):
(WebCore::JSTestObjPrototype::create):
(WebCore::JSTestObjPrototype::JSTestObjPrototype):

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

(WebCore::JSTestSerializedScriptValueInterfaceConstructor::create):
(WebCore::JSTestSerializedScriptValueInterfaceConstructor::JSTestSerializedScriptValueInterfaceConstructor):
(WebCore::JSTestSerializedScriptValueInterfaceConstructor::finishCreation):
(WebCore::JSTestSerializedScriptValueInterface::JSTestSerializedScriptValueInterface):
(WebCore::JSTestSerializedScriptValueInterface::finishCreation):

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

(WebCore::JSTestSerializedScriptValueInterface::create):
(WebCore::JSTestSerializedScriptValueInterfacePrototype::create):
(WebCore::JSTestSerializedScriptValueInterfacePrototype::JSTestSerializedScriptValueInterfacePrototype):

  • bridge/c/CRuntimeObject.cpp:

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

  • bridge/c/CRuntimeObject.h:

(JSC::Bindings::CRuntimeObject::create):

  • bridge/c/c_instance.cpp:

(JSC::Bindings::CRuntimeMethod::CRuntimeMethod):
(JSC::Bindings::CRuntimeMethod::finishCreation):

  • bridge/jni/jsc/JavaInstanceJSC.cpp:

(JavaRuntimeMethod::JavaRuntimeMethod):
(JavaRuntimeMethod::finishCreation):

  • bridge/jni/jsc/JavaRuntimeObject.cpp:

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

  • bridge/jni/jsc/JavaRuntimeObject.h:

(JSC::Bindings::JavaRuntimeObject::create):

  • bridge/objc/ObjCRuntimeObject.h:

(JSC::Bindings::ObjCRuntimeObject::create):

  • bridge/objc/ObjCRuntimeObject.mm:

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

  • bridge/objc/objc_instance.mm:

(ObjCRuntimeMethod::ObjCRuntimeMethod):
(ObjCRuntimeMethod::finishCreation):

  • bridge/qt/qt_instance.cpp:

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

  • bridge/qt/qt_pixmapruntime.cpp:

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

  • bridge/qt/qt_runtime.cpp:

(JSC::Bindings::QtRuntimeMethod::QtRuntimeMethod):
(JSC::Bindings::QtRuntimeMetaMethod::QtRuntimeMetaMethod):
(JSC::Bindings::QtRuntimeMetaMethod::finishCreation):
(JSC::Bindings::QtRuntimeConnectionMethod::QtRuntimeConnectionMethod):
(JSC::Bindings::QtRuntimeConnectionMethod::finishCreation):

  • bridge/qt/qt_runtime.h:

(JSC::Bindings::QtRuntimeMetaMethod::create):

  • bridge/runtime_method.cpp:

(JSC::RuntimeMethod::RuntimeMethod):

  • bridge/runtime_method.h:

(JSC::RuntimeMethod::create):

Source/WebKit/mac:

Completed the sixth 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 fifth 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/ProxyInstance.mm:

(WebKit::ProxyRuntimeMethod::ProxyRuntimeMethod):
(WebKit::ProxyRuntimeMethod::finishCreation):

Source/WebKit2:

Completed the sixth 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 fifth 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):

  • WebProcess/Plugins/Netscape/JSNPMethod.h:

(WebKit::JSNPMethod::create):

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