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