#include "Completion.h"
#include "InitializeThreading.h"
#include "JSArray.h"
+#include "JSFunction.h"
#include "JSLock.h"
#include "PrototypeFunction.h"
#include "SamplingTool.h"
#include <sys/time.h>
#endif
-#if PLATFORM(UNIX)
+#if HAVE(SIGNAL_H)
#include <signal.h>
#endif
-#if COMPILER(MSVC) && !PLATFORM(WIN_CE)
+#if COMPILER(MSVC) && !PLATFORM(WINCE)
#include <crtdbg.h>
#include <windows.h>
+#include <mmsystem.h>
#endif
#if PLATFORM(QT)
static void cleanupGlobalData(JSGlobalData*);
static bool fillBufferWithContentsOfFile(const UString& fileName, Vector<char>& buffer);
-static JSValuePtr functionPrint(ExecState*, JSObject*, JSValuePtr, const ArgList&);
-static JSValuePtr functionDebug(ExecState*, JSObject*, JSValuePtr, const ArgList&);
-static JSValuePtr functionGC(ExecState*, JSObject*, JSValuePtr, const ArgList&);
-static JSValuePtr functionVersion(ExecState*, JSObject*, JSValuePtr, const ArgList&);
-static JSValuePtr functionRun(ExecState*, JSObject*, JSValuePtr, const ArgList&);
-static JSValuePtr functionLoad(ExecState*, JSObject*, JSValuePtr, const ArgList&);
-static JSValuePtr functionReadline(ExecState*, JSObject*, JSValuePtr, const ArgList&);
-static NO_RETURN JSValuePtr functionQuit(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValue JSC_HOST_CALL functionPrint(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL functionDebug(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL functionGC(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL functionVersion(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL functionRun(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL functionLoad(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL functionCheckSyntax(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL functionReadline(ExecState*, JSObject*, JSValue, const ArgList&);
+static NO_RETURN JSValue JSC_HOST_CALL functionQuit(ExecState*, JSObject*, JSValue, const ArgList&);
+
+#if ENABLE(SAMPLING_FLAGS)
+static JSValue JSC_HOST_CALL functionSetSamplingFlags(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL functionClearSamplingFlags(ExecState*, JSObject*, JSValue, const ArgList&);
+#endif
+
+struct Script {
+ bool isFile;
+ char *argument;
+
+ Script(bool isFile, char *argument)
+ : isFile(isFile)
+ , argument(argument)
+ {
+ }
+};
struct Options {
Options()
bool interactive;
bool dump;
- Vector<UString> fileNames;
+ Vector<Script> scripts;
Vector<UString> arguments;
};
GlobalObject::GlobalObject(const Vector<UString>& arguments)
: JSGlobalObject()
{
- putDirectFunction(globalExec(), new (globalExec()) PrototypeFunction(globalExec(), prototypeFunctionStructure(), 1, Identifier(globalExec(), "debug"), functionDebug));
- putDirectFunction(globalExec(), new (globalExec()) PrototypeFunction(globalExec(), prototypeFunctionStructure(), 1, Identifier(globalExec(), "print"), functionPrint));
- putDirectFunction(globalExec(), new (globalExec()) PrototypeFunction(globalExec(), prototypeFunctionStructure(), 0, Identifier(globalExec(), "quit"), functionQuit));
- putDirectFunction(globalExec(), new (globalExec()) PrototypeFunction(globalExec(), prototypeFunctionStructure(), 0, Identifier(globalExec(), "gc"), functionGC));
- putDirectFunction(globalExec(), new (globalExec()) PrototypeFunction(globalExec(), prototypeFunctionStructure(), 1, Identifier(globalExec(), "version"), functionVersion));
- putDirectFunction(globalExec(), new (globalExec()) PrototypeFunction(globalExec(), prototypeFunctionStructure(), 1, Identifier(globalExec(), "run"), functionRun));
- putDirectFunction(globalExec(), new (globalExec()) PrototypeFunction(globalExec(), prototypeFunctionStructure(), 1, Identifier(globalExec(), "load"), functionLoad));
- putDirectFunction(globalExec(), new (globalExec()) PrototypeFunction(globalExec(), prototypeFunctionStructure(), 0, Identifier(globalExec(), "readline"), functionReadline));
+ putDirectFunction(globalExec(), new (globalExec()) NativeFunctionWrapper(globalExec(), prototypeFunctionStructure(), 1, Identifier(globalExec(), "debug"), functionDebug));
+ putDirectFunction(globalExec(), new (globalExec()) NativeFunctionWrapper(globalExec(), prototypeFunctionStructure(), 1, Identifier(globalExec(), "print"), functionPrint));
+ putDirectFunction(globalExec(), new (globalExec()) NativeFunctionWrapper(globalExec(), prototypeFunctionStructure(), 0, Identifier(globalExec(), "quit"), functionQuit));
+ putDirectFunction(globalExec(), new (globalExec()) NativeFunctionWrapper(globalExec(), prototypeFunctionStructure(), 0, Identifier(globalExec(), "gc"), functionGC));
+ putDirectFunction(globalExec(), new (globalExec()) NativeFunctionWrapper(globalExec(), prototypeFunctionStructure(), 1, Identifier(globalExec(), "version"), functionVersion));
+ putDirectFunction(globalExec(), new (globalExec()) NativeFunctionWrapper(globalExec(), prototypeFunctionStructure(), 1, Identifier(globalExec(), "run"), functionRun));
+ putDirectFunction(globalExec(), new (globalExec()) NativeFunctionWrapper(globalExec(), prototypeFunctionStructure(), 1, Identifier(globalExec(), "load"), functionLoad));
+ putDirectFunction(globalExec(), new (globalExec()) NativeFunctionWrapper(globalExec(), prototypeFunctionStructure(), 1, Identifier(globalExec(), "checkSyntax"), functionCheckSyntax));
+ putDirectFunction(globalExec(), new (globalExec()) NativeFunctionWrapper(globalExec(), prototypeFunctionStructure(), 0, Identifier(globalExec(), "readline"), functionReadline));
+
+#if ENABLE(SAMPLING_FLAGS)
+ putDirectFunction(globalExec(), new (globalExec()) NativeFunctionWrapper(globalExec(), prototypeFunctionStructure(), 1, Identifier(globalExec(), "setSamplingFlags"), functionSetSamplingFlags));
+ putDirectFunction(globalExec(), new (globalExec()) NativeFunctionWrapper(globalExec(), prototypeFunctionStructure(), 1, Identifier(globalExec(), "clearSamplingFlags"), functionClearSamplingFlags));
+#endif
JSObject* array = constructEmptyArray(globalExec());
for (size_t i = 0; i < arguments.size(); ++i)
putDirect(Identifier(globalExec(), "arguments"), array);
}
-JSValuePtr functionPrint(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+JSValue JSC_HOST_CALL functionPrint(ExecState* exec, JSObject*, JSValue, const ArgList& args)
{
for (unsigned i = 0; i < args.size(); ++i) {
if (i != 0)
putchar(' ');
- printf("%s", args.at(exec, i).toString(exec).UTF8String().c_str());
+ printf("%s", args.at(i).toString(exec).UTF8String().c_str());
}
putchar('\n');
return jsUndefined();
}
-JSValuePtr functionDebug(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+JSValue JSC_HOST_CALL functionDebug(ExecState* exec, JSObject*, JSValue, const ArgList& args)
{
- fprintf(stderr, "--> %s\n", args.at(exec, 0).toString(exec).UTF8String().c_str());
+ fprintf(stderr, "--> %s\n", args.at(0).toString(exec).UTF8String().c_str());
return jsUndefined();
}
-JSValuePtr functionGC(ExecState* exec, JSObject*, JSValuePtr, const ArgList&)
+JSValue JSC_HOST_CALL functionGC(ExecState* exec, JSObject*, JSValue, const ArgList&)
{
JSLock lock(false);
exec->heap()->collect();
return jsUndefined();
}
-JSValuePtr functionVersion(ExecState*, JSObject*, JSValuePtr, const ArgList&)
+JSValue JSC_HOST_CALL functionVersion(ExecState*, JSObject*, JSValue, const ArgList&)
{
// We need this function for compatibility with the Mozilla JS tests but for now
// we don't actually do any version-specific handling
return jsUndefined();
}
-JSValuePtr functionRun(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+JSValue JSC_HOST_CALL functionRun(ExecState* exec, JSObject*, JSValue, const ArgList& args)
{
StopWatch stopWatch;
- UString fileName = args.at(exec, 0).toString(exec);
+ UString fileName = args.at(0).toString(exec);
Vector<char> script;
if (!fillBufferWithContentsOfFile(fileName, script))
return throwError(exec, GeneralError, "Could not open file.");
return jsNumber(globalObject->globalExec(), stopWatch.getElapsedMS());
}
-JSValuePtr functionLoad(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+JSValue JSC_HOST_CALL functionLoad(ExecState* exec, JSObject* o, JSValue v, const ArgList& args)
{
- UString fileName = args.at(exec, 0).toString(exec);
+ UNUSED_PARAM(o);
+ UNUSED_PARAM(v);
+ UString fileName = args.at(0).toString(exec);
Vector<char> script;
if (!fillBufferWithContentsOfFile(fileName, script))
return throwError(exec, GeneralError, "Could not open file.");
JSGlobalObject* globalObject = exec->lexicalGlobalObject();
- evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), makeSource(script.data(), fileName));
+ Completion result = evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), makeSource(script.data(), fileName));
+ if (result.complType() == Throw)
+ exec->setException(result.value());
+ return result.value();
+}
- return jsUndefined();
+JSValue JSC_HOST_CALL functionCheckSyntax(ExecState* exec, JSObject* o, JSValue v, const ArgList& args)
+{
+ UNUSED_PARAM(o);
+ UNUSED_PARAM(v);
+ UString fileName = args.at(0).toString(exec);
+ Vector<char> script;
+ if (!fillBufferWithContentsOfFile(fileName, script))
+ return throwError(exec, GeneralError, "Could not open file.");
+
+ JSGlobalObject* globalObject = exec->lexicalGlobalObject();
+ Completion result = checkSyntax(globalObject->globalExec(), makeSource(script.data(), fileName));
+ if (result.complType() == Throw)
+ exec->setException(result.value());
+ return result.value();
}
-JSValuePtr functionReadline(ExecState* exec, JSObject*, JSValuePtr, const ArgList&)
+#if ENABLE(SAMPLING_FLAGS)
+JSValue JSC_HOST_CALL functionSetSamplingFlags(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+{
+ for (unsigned i = 0; i < args.size(); ++i) {
+ unsigned flag = static_cast<unsigned>(args.at(i).toNumber(exec));
+ if ((flag >= 1) && (flag <= 32))
+ SamplingFlags::setFlag(flag);
+ }
+ return jsNull();
+}
+
+JSValue JSC_HOST_CALL functionClearSamplingFlags(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+{
+ for (unsigned i = 0; i < args.size(); ++i) {
+ unsigned flag = static_cast<unsigned>(args.at(i).toNumber(exec));
+ if ((flag >= 1) && (flag <= 32))
+ SamplingFlags::clearFlag(flag);
+ }
+ return jsNull();
+}
+#endif
+
+JSValue JSC_HOST_CALL functionReadline(ExecState* exec, JSObject*, JSValue, const ArgList&)
{
Vector<char, 256> line;
int c;
return jsString(exec, line.data());
}
-JSValuePtr functionQuit(ExecState* exec, JSObject*, JSValuePtr, const ArgList&)
+JSValue JSC_HOST_CALL functionQuit(ExecState* exec, JSObject*, JSValue, const ArgList&)
{
cleanupGlobalData(&exec->globalData());
exit(EXIT_SUCCESS);
_CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
#endif
+#if COMPILER(MSVC) && !PLATFORM(WINCE)
+ timeBeginPeriod(1);
+#endif
+
#if PLATFORM(QT)
QCoreApplication app(argc, argv);
#endif
globalData->deref();
}
-static bool runWithScripts(GlobalObject* globalObject, const Vector<UString>& fileNames, bool dump)
+static bool runWithScripts(GlobalObject* globalObject, const Vector<Script>& scripts, bool dump)
{
- Vector<char> script;
+ UString script;
+ UString fileName;
+ Vector<char> scriptBuffer;
if (dump)
BytecodeGenerator::setDumpsGeneratedCode(true);
#if ENABLE(OPCODE_SAMPLING)
Interpreter* interpreter = globalObject->globalData()->interpreter;
interpreter->setSampler(new SamplingTool(interpreter));
+ interpreter->sampler()->setup();
+#endif
+#if ENABLE(SAMPLING_FLAGS)
+ SamplingFlags::start();
#endif
bool success = true;
- for (size_t i = 0; i < fileNames.size(); i++) {
- UString fileName = fileNames[i];
-
- if (!fillBufferWithContentsOfFile(fileName, script))
- return false; // fail early so we can catch missing files
+ for (size_t i = 0; i < scripts.size(); i++) {
+ if (scripts[i].isFile) {
+ fileName = scripts[i].argument;
+ if (!fillBufferWithContentsOfFile(fileName, scriptBuffer))
+ return false; // fail early so we can catch missing files
+ script = scriptBuffer.data();
+ } else {
+ script = scripts[i].argument;
+ fileName = "[Command Line]";
+ }
-#if ENABLE(OPCODE_SAMPLING)
- interpreter->sampler()->start();
+#if ENABLE(SAMPLING_THREAD)
+ SamplingThread::start();
#endif
- Completion completion = evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), makeSource(script.data(), fileName));
+
+ Completion completion = evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), makeSource(script, fileName));
success = success && completion.complType() != Throw;
if (dump) {
if (completion.complType() == Throw)
printf("End: %s\n", completion.value().toString(globalObject->globalExec()).ascii());
}
- globalObject->globalExec()->clearException();
-
-#if ENABLE(OPCODE_SAMPLING)
- interpreter->sampler()->stop();
+#if ENABLE(SAMPLING_THREAD)
+ SamplingThread::stop();
#endif
+
+ globalObject->globalExec()->clearException();
}
+#if ENABLE(SAMPLING_FLAGS)
+ SamplingFlags::stop();
+#endif
#if ENABLE(OPCODE_SAMPLING)
interpreter->sampler()->dump(globalObject->globalExec());
delete interpreter->sampler();
+#endif
+#if ENABLE(SAMPLING_COUNTERS)
+ AbstractSamplingCounter::dump();
#endif
return success;
}
+#define RUNNING_FROM_XCODE 0
+
static void runInteractive(GlobalObject* globalObject)
{
while (true) {
-#if HAVE(READLINE)
+#if HAVE(READLINE) && !RUNNING_FROM_XCODE
char* line = readline(interactivePrompt);
if (!line)
break;
Completion completion = evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), makeSource(line, interpreterName));
free(line);
#else
- puts(interactivePrompt);
+ printf("%s", interactivePrompt);
Vector<char, 256> line;
int c;
while ((c = getchar()) != EOF) {
break;
line.append(c);
}
+ if (line.isEmpty())
+ break;
line.append('\0');
Completion completion = evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), makeSource(line.data(), interpreterName));
#endif
printf("\n");
}
-static NO_RETURN void printUsageStatement()
+static NO_RETURN void printUsageStatement(JSGlobalData* globalData, bool help = false)
{
fprintf(stderr, "Usage: jsc [options] [files] [-- arguments]\n");
fprintf(stderr, " -d Dumps bytecode (debug builds only)\n");
+ fprintf(stderr, " -e Evaluate argument as script code\n");
fprintf(stderr, " -f Specifies a source file (deprecated)\n");
fprintf(stderr, " -h|--help Prints this help message\n");
fprintf(stderr, " -i Enables interactive mode (default if no files are specified)\n");
+#if HAVE(SIGNAL_H)
fprintf(stderr, " -s Installs signal handlers that exit on a crash (Unix platforms only)\n");
- exit(EXIT_FAILURE);
+#endif
+
+ cleanupGlobalData(globalData);
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
-static void parseArguments(int argc, char** argv, Options& options)
+static void parseArguments(int argc, char** argv, Options& options, JSGlobalData* globalData)
{
int i = 1;
for (; i < argc; ++i) {
const char* arg = argv[i];
if (strcmp(arg, "-f") == 0) {
if (++i == argc)
- printUsageStatement();
- options.fileNames.append(argv[i]);
+ printUsageStatement(globalData);
+ options.scripts.append(Script(true, argv[i]));
+ continue;
+ }
+ if (strcmp(arg, "-e") == 0) {
+ if (++i == argc)
+ printUsageStatement(globalData);
+ options.scripts.append(Script(false, argv[i]));
continue;
}
if (strcmp(arg, "-h") == 0 || strcmp(arg, "--help") == 0) {
- printUsageStatement();
+ printUsageStatement(globalData, true);
}
if (strcmp(arg, "-i") == 0) {
options.interactive = true;
continue;
}
if (strcmp(arg, "-s") == 0) {
-#if PLATFORM(UNIX)
+#if HAVE(SIGNAL_H)
signal(SIGILL, _exit);
signal(SIGFPE, _exit);
signal(SIGBUS, _exit);
++i;
break;
}
- options.fileNames.append(argv[i]);
+ options.scripts.append(Script(true, argv[i]));
}
- if (options.fileNames.isEmpty())
+ if (options.scripts.isEmpty())
options.interactive = true;
for (; i < argc; ++i)
JSLock lock(false);
Options options;
- parseArguments(argc, argv, options);
+ parseArguments(argc, argv, options, globalData);
GlobalObject* globalObject = new (globalData) GlobalObject(options.arguments);
- bool success = runWithScripts(globalObject, options.fileNames, options.dump);
+ bool success = runWithScripts(globalObject, options.scripts, options.dump);
if (options.interactive && success)
runInteractive(globalObject);