Changeset 30555 in webkit for trunk/JavaScriptCore/kjs/testkjs.cpp
- Timestamp:
- Feb 24, 2008, 9:29:20 PM (17 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/kjs/testkjs.cpp
r30553 r30555 1 // -*- c-basic-offset: 2 -*-2 1 /* 3 2 * Copyright (C) 1999-2000 Harri Porten ([email protected]) 4 * Copyright (C) 2004 -2007 Apple Inc.3 * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. 5 4 * Copyright (C) 2006 Bjoern Graf ([email protected]) 6 5 * … … 29 28 #include "array_object.h" 30 29 #include "collector.h" 30 #include "function.h" 31 31 #include "interpreter.h" 32 32 #include "nodes.h" … … 57 57 static bool fillBufferWithContentsOfFile(const UString& fileName, Vector<char>& buffer); 58 58 59 class StopWatch 60 { 59 static JSValue* functionPrint(ExecState*, JSObject*, const List&); 60 static JSValue* functionDebug(ExecState*, JSObject*, const List&); 61 static JSValue* functionGC(ExecState*, JSObject*, const List&); 62 static JSValue* functionVersion(ExecState*, JSObject*, const List&); 63 static JSValue* functionRun(ExecState*, JSObject*, const List&); 64 static JSValue* functionLoad(ExecState*, JSObject*, const List&); 65 static JSValue* functionQuit(ExecState*, JSObject*, const List&); 66 67 class StopWatch { 61 68 public: 62 69 void start(); 63 70 void stop(); 64 71 long getElapsedMS(); // call stop() first 65 72 66 73 private: 67 74 #if PLATFORM(QT) … … 109 116 timeval elapsedTime; 110 117 timersub(&m_stopTime, &m_startTime, &elapsedTime); 111 118 112 119 return elapsedTime.tv_sec * 1000 + lroundf(elapsedTime.tv_usec / 1000.0f); 113 120 #endif 114 121 } 115 122 116 class Global Imp: public JSGlobalObject {123 class GlobalObject : public JSGlobalObject { 117 124 public: 118 virtual UString className() const { return "global"; } 125 GlobalObject(Vector<UString>& arguments); 126 virtual UString className() const { return "global"; } 119 127 }; 120 COMPILE_ASSERT(!IsInteger<GlobalImp>::value, WTF_IsInteger_GlobalImp_false); 121 122 class TestFunctionImp : public JSObject { 123 public: 124 enum TestFunctionType { Print, Debug, Quit, GC, Version, Run, Load }; 125 126 TestFunctionImp(TestFunctionType i, int length); 127 virtual bool implementsCall() const { return true; } 128 virtual JSValue* callAsFunction(ExecState* exec, JSObject* thisObj, const List &args); 129 130 private: 131 TestFunctionType m_type; 132 }; 133 134 TestFunctionImp::TestFunctionImp(TestFunctionType i, int length) 135 : JSObject() 136 , m_type(i) 137 { 138 putDirect(Identifier("length"), length, DontDelete | ReadOnly | DontEnum); 139 } 140 141 JSValue* TestFunctionImp::callAsFunction(ExecState* exec, JSObject*, const List &args) 142 { 143 switch (m_type) { 144 case Print: 145 printf("%s\n", args[0]->toString(exec).UTF8String().c_str()); 146 return jsUndefined(); 147 case Debug: 148 fprintf(stderr, "--> %s\n", args[0]->toString(exec).UTF8String().c_str()); 149 return jsUndefined(); 150 case GC: 151 { 152 JSLock lock; 153 Collector::collect(); 154 return jsUndefined(); 155 } 156 case Version: 157 // We need this function for compatibility with the Mozilla JS tests but for now 158 // we don't actually do any version-specific handling 159 return jsUndefined(); 160 case Run: 161 { 162 StopWatch stopWatch; 163 UString fileName = args[0]->toString(exec); 164 Vector<char> script; 165 if (!fillBufferWithContentsOfFile(fileName, script)) 128 COMPILE_ASSERT(!IsInteger<GlobalObject>::value, WTF_IsInteger_GlobalObject_false); 129 130 GlobalObject::GlobalObject(Vector<UString>& arguments) 131 { 132 putDirectFunction(new PrototypeFunction(globalExec(), functionPrototype(), 1, "debug", functionDebug)); 133 putDirectFunction(new PrototypeFunction(globalExec(), functionPrototype(), 1, "print", functionPrint)); 134 putDirectFunction(new PrototypeFunction(globalExec(), functionPrototype(), 0, "quit", functionQuit)); 135 putDirectFunction(new PrototypeFunction(globalExec(), functionPrototype(), 0, "gc", functionGC)); 136 putDirectFunction(new PrototypeFunction(globalExec(), functionPrototype(), 1, "version", functionVersion)); 137 putDirectFunction(new PrototypeFunction(globalExec(), functionPrototype(), 1, "run", functionRun)); 138 putDirectFunction(new PrototypeFunction(globalExec(), functionPrototype(), 1, "load", functionLoad)); 139 140 JSObject* array = arrayConstructor()->construct(globalExec(), globalExec()->emptyList()); 141 for (size_t i = 0; i < arguments.size(); ++i) 142 array->put(globalExec(), i, jsString(arguments[i])); 143 putDirect("arguments", array); 144 145 Interpreter::setShouldPrintExceptions(true); 146 } 147 148 JSValue* functionPrint(ExecState* exec, JSObject*, const List& args) 149 { 150 printf("%s\n", args[0]->toString(exec).UTF8String().c_str()); 151 return jsUndefined(); 152 } 153 154 JSValue* functionDebug(ExecState* exec, JSObject*, const List& args) 155 { 156 fprintf(stderr, "--> %s\n", args[0]->toString(exec).UTF8String().c_str()); 157 return jsUndefined(); 158 } 159 160 JSValue* functionGC(ExecState*, JSObject*, const List&) 161 { 162 JSLock lock; 163 Collector::collect(); 164 return jsUndefined(); 165 } 166 167 JSValue* functionVersion(ExecState*, JSObject*, const List&) 168 { 169 // We need this function for compatibility with the Mozilla JS tests but for now 170 // we don't actually do any version-specific handling 171 return jsUndefined(); 172 } 173 174 JSValue* functionRun(ExecState* exec, JSObject*, const List& args) 175 { 176 StopWatch stopWatch; 177 UString fileName = args[0]->toString(exec); 178 Vector<char> script; 179 if (!fillBufferWithContentsOfFile(fileName, script)) 166 180 return throwError(exec, GeneralError, "Could not open file."); 167 181 168 stopWatch.start(); 169 Interpreter::evaluate(exec->dynamicGlobalObject()->globalExec(), fileName, 0, script.data()); 170 stopWatch.stop(); 171 172 return jsNumber(stopWatch.getElapsedMS()); 173 } 174 case Load: 175 { 176 UString fileName = args[0]->toString(exec); 177 Vector<char> script; 178 if (!fillBufferWithContentsOfFile(fileName, script)) 182 stopWatch.start(); 183 Interpreter::evaluate(exec->dynamicGlobalObject()->globalExec(), fileName, 0, script.data()); 184 stopWatch.stop(); 185 186 return jsNumber(stopWatch.getElapsedMS()); 187 } 188 189 JSValue* functionLoad(ExecState* exec, JSObject*, const List& args) 190 { 191 UString fileName = args[0]->toString(exec); 192 Vector<char> script; 193 if (!fillBufferWithContentsOfFile(fileName, script)) 179 194 return throwError(exec, GeneralError, "Could not open file."); 180 195 181 Interpreter::evaluate(exec->dynamicGlobalObject()->globalExec(), fileName, 0, script.data()); 182 183 return jsUndefined(); 184 } 185 case Quit: 186 exit(0); 187 default: 188 abort(); 189 } 190 return 0; 196 Interpreter::evaluate(exec->dynamicGlobalObject()->globalExec(), fileName, 0, script.data()); 197 198 return jsUndefined(); 199 } 200 201 JSValue* functionQuit(ExecState*, JSObject*, const List&) 202 { 203 exit(0); 204 return jsUndefined(); 191 205 } 192 206 … … 224 238 } 225 239 226 static GlobalImp* createGlobalObject(Vector<UString>& arguments)227 {228 GlobalImp* global = new GlobalImp;229 230 // add debug() function231 global->put(global->globalExec(), "debug", new TestFunctionImp(TestFunctionImp::Debug, 1));232 // add "print" for compatibility with the mozilla js shell233 global->put(global->globalExec(), "print", new TestFunctionImp(TestFunctionImp::Print, 1));234 // add "quit" for compatibility with the mozilla js shell235 global->put(global->globalExec(), "quit", new TestFunctionImp(TestFunctionImp::Quit, 0));236 // add "gc" for compatibility with the mozilla js shell237 global->put(global->globalExec(), "gc", new TestFunctionImp(TestFunctionImp::GC, 0));238 // add "version" for compatibility with the mozilla js shell239 global->put(global->globalExec(), "version", new TestFunctionImp(TestFunctionImp::Version, 1));240 global->put(global->globalExec(), "run", new TestFunctionImp(TestFunctionImp::Run, 1));241 global->put(global->globalExec(), "load", new TestFunctionImp(TestFunctionImp::Load, 1));242 243 JSObject* array = global->arrayConstructor()->construct(global->globalExec(), global->globalExec()->emptyList());244 for (size_t i = 0; i < arguments.size(); ++i)245 array->put(global->globalExec(), i, jsString(arguments[i]));246 global->put(global->globalExec(), "arguments", array);247 248 Interpreter::setShouldPrintExceptions(true);249 return global;250 }251 252 240 static bool prettyPrintScript(const UString& fileName, const Vector<char>& script) 253 241 { 254 int errLine = 0;255 UString errMsg;256 UString scriptUString(script.data());257 RefPtr<ProgramNode> programNode = parser().parse<ProgramNode>(fileName, 0, scriptUString.data(), scriptUString.size(), 0, &errLine, &errMsg);258 if (!programNode) {259 fprintf(stderr, "%s:%d: %s.\n", fileName.UTF8String().c_str(), errLine, errMsg.UTF8String().c_str());260 return false;261 }262 263 printf("%s\n", programNode->toString().UTF8String().c_str());264 return true;242 int errLine = 0; 243 UString errMsg; 244 UString scriptUString(script.data()); 245 RefPtr<ProgramNode> programNode = parser().parse<ProgramNode>(fileName, 0, scriptUString.data(), scriptUString.size(), 0, &errLine, &errMsg); 246 if (!programNode) { 247 fprintf(stderr, "%s:%d: %s.\n", fileName.UTF8String().c_str(), errLine, errMsg.UTF8String().c_str()); 248 return false; 249 } 250 251 printf("%s\n", programNode->toString().UTF8String().c_str()); 252 return true; 265 253 } 266 254 267 255 static bool runWithScripts(const Vector<UString>& fileNames, Vector<UString>& arguments, bool prettyPrint) 268 256 { 269 GlobalImp* globalObject = createGlobalObject(arguments);270 Vector<char> script;271 272 bool success = true;273 274 for (size_t i = 0; i < fileNames.size(); i++) {275 UString fileName = fileNames[i];276 277 if (!fillBufferWithContentsOfFile(fileName, script))278 return false; // fail early so we can catch missing files279 280 if (prettyPrint)281 prettyPrintScript(fileName, script);282 else {283 Completion completion = Interpreter::evaluate(globalObject->globalExec(), fileName, 0, script.data());284 success = success && completion.complType() != Throw;285 }286 }287 return success;257 GlobalObject* globalObject = new GlobalObject(arguments); 258 Vector<char> script; 259 260 bool success = true; 261 262 for (size_t i = 0; i < fileNames.size(); i++) { 263 UString fileName = fileNames[i]; 264 265 if (!fillBufferWithContentsOfFile(fileName, script)) 266 return false; // fail early so we can catch missing files 267 268 if (prettyPrint) 269 prettyPrintScript(fileName, script); 270 else { 271 Completion completion = Interpreter::evaluate(globalObject->globalExec(), fileName, 0, script.data()); 272 success = success && completion.complType() != Throw; 273 } 274 } 275 return success; 288 276 } 289 277 … … 296 284 static void parseArguments(int argc, char** argv, Vector<UString>& fileNames, Vector<UString>& arguments, bool& prettyPrint) 297 285 { 298 if (argc < 3) 299 printUsageStatement(); 300 301 int i = 1; 302 for (; i < argc; ++i) { 303 const char* arg = argv[i]; 304 if (strcmp(arg, "-f") == 0) { 305 if (++i == argc) 286 if (argc < 3) 306 287 printUsageStatement(); 307 fileNames.append(argv[i]); 308 continue; 309 } 310 if (strcmp(arg, "-p") == 0) { 311 prettyPrint = true; 312 continue; 313 } 314 if (strcmp(arg, "--") == 0) { 315 ++i; 316 break; 317 } 318 break; 319 } 320 321 for (; i < argc; ++i) 322 arguments.append(argv[i]); 288 289 int i = 1; 290 for (; i < argc; ++i) { 291 const char* arg = argv[i]; 292 if (strcmp(arg, "-f") == 0) { 293 if (++i == argc) 294 printUsageStatement(); 295 fileNames.append(argv[i]); 296 continue; 297 } 298 if (strcmp(arg, "-p") == 0) { 299 prettyPrint = true; 300 continue; 301 } 302 if (strcmp(arg, "--") == 0) { 303 ++i; 304 break; 305 } 306 break; 307 } 308 309 for (; i < argc; ++i) 310 arguments.append(argv[i]); 323 311 } 324 312 325 313 int kjsmain(int argc, char** argv) 326 314 { 327 JSLock lock;328 329 bool prettyPrint = false;330 Vector<UString> fileNames;331 Vector<UString> arguments;332 parseArguments(argc, argv, fileNames, arguments, prettyPrint);333 334 bool success = runWithScripts(fileNames, arguments, prettyPrint);315 JSLock lock; 316 317 bool prettyPrint = false; 318 Vector<UString> fileNames; 319 Vector<UString> arguments; 320 parseArguments(argc, argv, fileNames, arguments, prettyPrint); 321 322 bool success = runWithScripts(fileNames, arguments, prettyPrint); 335 323 336 324 #ifndef NDEBUG 337 Collector::collect();338 #endif 339 340 return success ? 0 : 3;325 Collector::collect(); 326 #endif 327 328 return success ? 0 : 3; 341 329 } 342 330 343 331 static bool fillBufferWithContentsOfFile(const UString& fileName, Vector<char>& buffer) 344 332 { 345 FILE* f = fopen(fileName.UTF8String().c_str(), "r");346 if (!f) {347 fprintf(stderr, "Could not open file: %s\n", fileName.UTF8String().c_str());348 return false;349 }350 351 size_t buffer_size = 0;352 size_t buffer_capacity = 1024;353 354 buffer.resize(buffer_capacity);355 356 while (!feof(f) && !ferror(f)) {357 buffer_size += fread(buffer.data() + buffer_size, 1, buffer_capacity - buffer_size, f);358 if (buffer_size == buffer_capacity) { // guarantees space for trailing '\0'359 buffer_capacity *= 2;360 buffer.resize(buffer_capacity);361 }362 }363 fclose(f);364 buffer[buffer_size] = '\0';365 366 return true;367 } 333 FILE* f = fopen(fileName.UTF8String().c_str(), "r"); 334 if (!f) { 335 fprintf(stderr, "Could not open file: %s\n", fileName.UTF8String().c_str()); 336 return false; 337 } 338 339 size_t buffer_size = 0; 340 size_t buffer_capacity = 1024; 341 342 buffer.resize(buffer_capacity); 343 344 while (!feof(f) && !ferror(f)) { 345 buffer_size += fread(buffer.data() + buffer_size, 1, buffer_capacity - buffer_size, f); 346 if (buffer_size == buffer_capacity) { // guarantees space for trailing '\0' 347 buffer_capacity *= 2; 348 buffer.resize(buffer_capacity); 349 } 350 } 351 fclose(f); 352 buffer[buffer_size] = '\0'; 353 354 return true; 355 }
Note:
See TracChangeset
for help on using the changeset viewer.