source: webkit/trunk/Source/JavaScriptCore/testRegExp.cpp@ 253443

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

[JSC] Lock-down JSGlobalObject and derived classes in IsoSubspace
https://bugs.webkit.org/show_bug.cgi?id=205108

Reviewed by Mark Lam.

Source/JavaScriptCore:

This patch puts JSGlobalLexicalEnvironment and JSGlobalObject (and its derived classes including JSDOMWindow etc.) in IsoSubspace.
We were using addFinalizer feature to call destructors for these objects since they do not inherit JSDestructibleObject. But now
each derived classes has its IsoSubspace. So we do not need to use finalizer feature: just setting specialized HeapCellType works.

  • API/JSAPIGlobalObject.h:
  • API/JSCallbackObject.cpp:
  • API/glib/JSAPIWrapperGlobalObject.cpp:
  • JavaScriptCore.xcodeproj/project.pbxproj:
  • bytecode/SuperSampler.h:
  • heap/CellAttributes.h:
  • heap/FreeList.h:
  • heap/IsoHeapCellType.cpp:

(JSC::IsoHeapCellType::IsoHeapCellType):

  • heap/IsoHeapCellType.h:
  • heap/MarkedBlock.cpp:

(JSC::MarkedBlock::Handle::setIsFreeListed): Deleted.

  • heap/MarkedBlockInlines.h:

(JSC::MarkedBlock::Handle::setIsFreeListed):

  • jsc.cpp:

(GlobalObject::create): Deleted.
(GlobalObject::createStructure): Deleted.
(GlobalObject::javaScriptRuntimeFlags): Deleted.
(GlobalObject::finishCreation): Deleted.
(GlobalObject::addFunction): Deleted.

  • runtime/JSGlobalLexicalEnvironment.h:
  • runtime/JSGlobalObject.h:

(JSC::JSGlobalObject::subspaceFor):

  • runtime/JSSegmentedVariableObject.cpp:

(JSC::JSSegmentedVariableObject::JSSegmentedVariableObject):
(JSC::JSSegmentedVariableObject::finishCreation):
(JSC::JSSegmentedVariableObject::destroy): Deleted.

  • runtime/JSSegmentedVariableObject.h:

(JSC::JSSegmentedVariableObject::subspaceFor):
(JSC::JSSegmentedVariableObject::classInfo const): Deleted.

  • runtime/VM.cpp:

(JSC::VM::VM):

  • runtime/VM.h:
  • testRegExp.cpp:

(GlobalObject::create): Deleted.
(GlobalObject::createStructure): Deleted.
(GlobalObject::finishCreation): Deleted.

Source/WebCore:

We put derived classes of JSGlobalObject in IsoSubspace in WebCore side too.

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

(WebCore::globalObjectOutputConstraintSubspaceFor): Deleted.

  • bindings/js/JSDOMWrapper.h:
  • bindings/js/JSRemoteDOMWindowBase.h:
  • bindings/js/JSWindowProxy.h:
  • bindings/js/JSWorkerGlobalScopeBase.h:

(WebCore::JSWorkerGlobalScopeBase::subspaceFor):

  • bindings/js/JSWorkletGlobalScopeBase.h:

(WebCore::JSWorkletGlobalScopeBase::subspaceFor):

  • bindings/js/WebCoreJSClientData.cpp:

(WebCore::JSVMClientData::JSVMClientData):

  • bindings/js/WebCoreJSClientData.h:

(WebCore::JSVMClientData::subspaceForJSDOMWindow):
(WebCore::JSVMClientData::subspaceForJSDedicatedWorkerGlobalScope):
(WebCore::JSVMClientData::subspaceForJSRemoteDOMWindow):
(WebCore::JSVMClientData::subspaceForJSWorkerGlobalScope):
(WebCore::JSVMClientData::subspaceForJSServiceWorkerGlobalScope):
(WebCore::JSVMClientData::subspaceForJSPaintWorkletGlobalScope):
(WebCore::JSVMClientData::subspaceForJSWorkletGlobalScope):
(WebCore::JSVMClientData::forEachOutputConstraintSpace):
(WebCore::JSVMClientData::globalObjectOutputConstraintSpace): Deleted.

  • bindings/scripts/CodeGeneratorJS.pm:

(GenerateHeader):
(GenerateImplementation):
(GeneratePrototypeDeclaration):

  • bindings/scripts/test/JS/JSInterfaceName.cpp:
  • bindings/scripts/test/JS/JSMapLike.cpp:
  • bindings/scripts/test/JS/JSReadOnlyMapLike.cpp:
  • bindings/scripts/test/JS/JSReadOnlySetLike.cpp:
  • bindings/scripts/test/JS/JSSetLike.cpp:
  • bindings/scripts/test/JS/JSTestActiveDOMObject.cpp:
  • bindings/scripts/test/JS/JSTestCEReactions.cpp:
  • bindings/scripts/test/JS/JSTestCEReactionsStringifier.cpp:
  • bindings/scripts/test/JS/JSTestCallTracer.cpp:
  • bindings/scripts/test/JS/JSTestClassWithJSBuiltinConstructor.cpp:
  • bindings/scripts/test/JS/JSTestDOMJIT.cpp:
  • bindings/scripts/test/JS/JSTestEnabledBySetting.cpp:
  • bindings/scripts/test/JS/JSTestEnabledForContext.cpp:
  • bindings/scripts/test/JS/JSTestEventConstructor.cpp:
  • bindings/scripts/test/JS/JSTestEventTarget.cpp:
  • bindings/scripts/test/JS/JSTestException.cpp:
  • bindings/scripts/test/JS/JSTestGenerateIsReachable.cpp:
  • bindings/scripts/test/JS/JSTestGlobalObject.cpp:

(WebCore::JSTestGlobalObject::subspaceForImpl):

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

(WebCore::JSTestGlobalObject::subspaceFor):

  • bindings/scripts/test/JS/JSTestIndexedSetterNoIdentifier.cpp:
  • bindings/scripts/test/JS/JSTestIndexedSetterThrowingException.cpp:
  • bindings/scripts/test/JS/JSTestIndexedSetterWithIdentifier.cpp:
  • bindings/scripts/test/JS/JSTestInterface.cpp:
  • bindings/scripts/test/JS/JSTestInterfaceLeadingUnderscore.cpp:
  • bindings/scripts/test/JS/JSTestIterable.cpp:
  • bindings/scripts/test/JS/JSTestJSBuiltinConstructor.cpp:
  • bindings/scripts/test/JS/JSTestMediaQueryListListener.cpp:
  • bindings/scripts/test/JS/JSTestNamedAndIndexedSetterNoIdentifier.cpp:
  • bindings/scripts/test/JS/JSTestNamedAndIndexedSetterThrowingException.cpp:
  • bindings/scripts/test/JS/JSTestNamedAndIndexedSetterWithIdentifier.cpp:
  • bindings/scripts/test/JS/JSTestNamedConstructor.cpp:
  • bindings/scripts/test/JS/JSTestNamedDeleterNoIdentifier.cpp:
  • bindings/scripts/test/JS/JSTestNamedDeleterThrowingException.cpp:
  • bindings/scripts/test/JS/JSTestNamedDeleterWithIdentifier.cpp:
  • bindings/scripts/test/JS/JSTestNamedDeleterWithIndexedGetter.cpp:
  • bindings/scripts/test/JS/JSTestNamedGetterCallWith.cpp:
  • bindings/scripts/test/JS/JSTestNamedGetterNoIdentifier.cpp:
  • bindings/scripts/test/JS/JSTestNamedGetterWithIdentifier.cpp:
  • bindings/scripts/test/JS/JSTestNamedSetterNoIdentifier.cpp:
  • bindings/scripts/test/JS/JSTestNamedSetterThrowingException.cpp:
  • bindings/scripts/test/JS/JSTestNamedSetterWithIdentifier.cpp:
  • bindings/scripts/test/JS/JSTestNamedSetterWithIndexedGetter.cpp:
  • bindings/scripts/test/JS/JSTestNamedSetterWithIndexedGetterAndSetter.cpp:
  • bindings/scripts/test/JS/JSTestNamedSetterWithOverrideBuiltins.cpp:
  • bindings/scripts/test/JS/JSTestNamedSetterWithUnforgableProperties.cpp:
  • bindings/scripts/test/JS/JSTestNamedSetterWithUnforgablePropertiesAndOverrideBuiltins.cpp:
  • bindings/scripts/test/JS/JSTestNode.cpp:
  • bindings/scripts/test/JS/JSTestObj.cpp:
  • bindings/scripts/test/JS/JSTestOverloadedConstructors.cpp:
  • bindings/scripts/test/JS/JSTestOverloadedConstructorsWithSequence.cpp:
  • bindings/scripts/test/JS/JSTestOverrideBuiltins.cpp:
  • bindings/scripts/test/JS/JSTestPluginInterface.cpp:
  • bindings/scripts/test/JS/JSTestPromiseRejectionEvent.cpp:
  • bindings/scripts/test/JS/JSTestSerialization.cpp:
  • bindings/scripts/test/JS/JSTestSerializationIndirectInheritance.cpp:
  • bindings/scripts/test/JS/JSTestSerializationInherit.cpp:
  • bindings/scripts/test/JS/JSTestSerializationInheritFinal.cpp:
  • bindings/scripts/test/JS/JSTestSerializedScriptValueInterface.cpp:
  • bindings/scripts/test/JS/JSTestStringifier.cpp:
  • bindings/scripts/test/JS/JSTestStringifierAnonymousOperation.cpp:
  • bindings/scripts/test/JS/JSTestStringifierNamedOperation.cpp:
  • bindings/scripts/test/JS/JSTestStringifierOperationImplementedAs.cpp:
  • bindings/scripts/test/JS/JSTestStringifierOperationNamedToString.cpp:
  • bindings/scripts/test/JS/JSTestStringifierReadOnlyAttribute.cpp:
  • bindings/scripts/test/JS/JSTestStringifierReadWriteAttribute.cpp:
  • bindings/scripts/test/JS/JSTestTypedefs.cpp:
  • bridge/runtime_method.h:
  • Property svn:eol-style set to native
File size: 15.5 KB
Line 
1/*
2 * Copyright (C) 2011-2019 Apple Inc. All rights reserved.
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public License
15 * along with this library; see the file COPYING.LIB. If not, write to
16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 *
19 */
20
21#include "config.h"
22#include "RegExp.h"
23
24#include "InitializeThreading.h"
25#include "JSCInlines.h"
26#include "JSGlobalObject.h"
27#include "YarrFlags.h"
28#include <errno.h>
29#include <stdio.h>
30#include <stdlib.h>
31#include <string.h>
32#include <wtf/Vector.h>
33#include <wtf/text/StringBuilder.h>
34
35#if !OS(WINDOWS)
36#include <unistd.h>
37#endif
38
39#if HAVE(SYS_TIME_H)
40#include <sys/time.h>
41#endif
42
43#if COMPILER(MSVC)
44#include <crtdbg.h>
45#include <mmsystem.h>
46#include <windows.h>
47#endif
48
49const int MaxLineLength = 100 * 1024;
50
51using namespace JSC;
52
53struct CommandLine {
54 CommandLine()
55 : interactive(false)
56 , verbose(false)
57 {
58 }
59
60 bool interactive;
61 bool verbose;
62 Vector<String> arguments;
63 Vector<String> files;
64};
65
66class StopWatch {
67public:
68 void start();
69 void stop();
70 long getElapsedMS(); // call stop() first
71
72private:
73 MonotonicTime m_startTime;
74 MonotonicTime m_stopTime;
75};
76
77void StopWatch::start()
78{
79 m_startTime = MonotonicTime::now();
80}
81
82void StopWatch::stop()
83{
84 m_stopTime = MonotonicTime::now();
85}
86
87long StopWatch::getElapsedMS()
88{
89 return (m_stopTime - m_startTime).millisecondsAs<long>();
90}
91
92struct RegExpTest {
93 RegExpTest()
94 : offset(0)
95 , result(0)
96 {
97 }
98
99 String subject;
100 int offset;
101 int result;
102 Vector<int, 32> expectVector;
103};
104
105class GlobalObject final : public JSGlobalObject {
106private:
107 GlobalObject(VM&, Structure*, const Vector<String>& arguments);
108
109public:
110 using Base = JSGlobalObject;
111
112 static GlobalObject* create(VM& vm, Structure* structure, const Vector<String>& arguments)
113 {
114 GlobalObject* globalObject = new (NotNull, allocateCell<GlobalObject>(vm.heap)) GlobalObject(vm, structure, arguments);
115 return globalObject;
116 }
117
118 DECLARE_INFO;
119
120 static constexpr bool needsDestructor = true;
121
122 static Structure* createStructure(VM& vm, JSValue prototype)
123 {
124 return Structure::create(vm, 0, prototype, TypeInfo(GlobalObjectType, StructureFlags), info());
125 }
126
127protected:
128 void finishCreation(VM& vm, const Vector<String>& arguments)
129 {
130 Base::finishCreation(vm);
131 UNUSED_PARAM(arguments);
132 }
133};
134STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(GlobalObject, JSGlobalObject);
135
136const ClassInfo GlobalObject::s_info = { "global", &JSGlobalObject::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(GlobalObject) };
137
138GlobalObject::GlobalObject(VM& vm, Structure* structure, const Vector<String>& arguments)
139 : JSGlobalObject(vm, structure)
140{
141 finishCreation(vm, arguments);
142}
143
144// Use SEH for Release builds only to get rid of the crash report dialog
145// (luckily the same tests fail in Release and Debug builds so far). Need to
146// be in a separate main function because the realMain function requires object
147// unwinding.
148
149#if COMPILER(MSVC) && !defined(_DEBUG)
150#define TRY __try {
151#define EXCEPT(x) } __except (EXCEPTION_EXECUTE_HANDLER) { x; }
152#else
153#define TRY
154#define EXCEPT(x)
155#endif
156
157int realMain(int argc, char** argv);
158
159int main(int argc, char** argv)
160{
161#if OS(WINDOWS)
162 // Cygwin calls ::SetErrorMode(SEM_FAILCRITICALERRORS), which we will inherit. This is bad for
163 // testing/debugging, as it causes the post-mortem debugger not to be invoked. We reset the
164 // error mode here to work around Cygwin's behavior. See <http://webkit.org/b/55222>.
165 ::SetErrorMode(0);
166
167#if defined(_DEBUG)
168 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
169 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
170 _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
171 _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
172 _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
173 _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
174#endif
175
176 timeBeginPeriod(1);
177#endif
178
179 // Initialize JSC before getting VM.
180 JSC::initializeThreading();
181
182 // We can't use destructors in the following code because it uses Windows
183 // Structured Exception Handling
184 int res = 0;
185 TRY
186 res = realMain(argc, argv);
187 EXCEPT(res = 3)
188 return res;
189}
190
191static bool testOneRegExp(VM& vm, RegExp* regexp, RegExpTest* regExpTest, bool verbose, unsigned int lineNumber)
192{
193 bool result = true;
194 Vector<int> outVector;
195 outVector.resize(regExpTest->expectVector.size());
196 int matchResult = regexp->match(vm, regExpTest->subject, regExpTest->offset, outVector);
197
198 if (matchResult != regExpTest->result) {
199 result = false;
200 if (verbose)
201 printf("Line %d: results mismatch - expected %d got %d\n", lineNumber, regExpTest->result, matchResult);
202 } else if (matchResult != -1) {
203 if (outVector.size() != regExpTest->expectVector.size()) {
204 result = false;
205 if (verbose) {
206#if OS(WINDOWS)
207 printf("Line %d: output vector size mismatch - expected %Iu got %Iu\n", lineNumber, regExpTest->expectVector.size(), outVector.size());
208#else
209 printf("Line %d: output vector size mismatch - expected %zu got %zu\n", lineNumber, regExpTest->expectVector.size(), outVector.size());
210#endif
211 }
212 } else if (outVector.size() % 2) {
213 result = false;
214 if (verbose) {
215#if OS(WINDOWS)
216 printf("Line %d: output vector size is odd (%Iu), should be even\n", lineNumber, outVector.size());
217#else
218 printf("Line %d: output vector size is odd (%zu), should be even\n", lineNumber, outVector.size());
219#endif
220 }
221 } else {
222 // Check in pairs since the first value of the pair could be -1 in which case the second doesn't matter.
223 size_t pairCount = outVector.size() / 2;
224 for (size_t i = 0; i < pairCount; ++i) {
225 size_t startIndex = i*2;
226 if (outVector[startIndex] != regExpTest->expectVector[startIndex]) {
227 result = false;
228 if (verbose) {
229#if OS(WINDOWS)
230 printf("Line %d: output vector mismatch at index %Iu - expected %d got %d\n", lineNumber, startIndex, regExpTest->expectVector[startIndex], outVector[startIndex]);
231#else
232 printf("Line %d: output vector mismatch at index %zu - expected %d got %d\n", lineNumber, startIndex, regExpTest->expectVector[startIndex], outVector[startIndex]);
233#endif
234 }
235 }
236 if ((i > 0) && (regExpTest->expectVector[startIndex] != -1) && (outVector[startIndex+1] != regExpTest->expectVector[startIndex+1])) {
237 result = false;
238 if (verbose) {
239#if OS(WINDOWS)
240 printf("Line %d: output vector mismatch at index %Iu - expected %d got %d\n", lineNumber, startIndex + 1, regExpTest->expectVector[startIndex + 1], outVector[startIndex + 1]);
241#else
242 printf("Line %d: output vector mismatch at index %zu - expected %d got %d\n", lineNumber, startIndex + 1, regExpTest->expectVector[startIndex + 1], outVector[startIndex + 1]);
243#endif
244 }
245 }
246 }
247 }
248 }
249
250 return result;
251}
252
253static int scanString(char* buffer, int bufferLength, StringBuilder& builder, char termChar)
254{
255 bool escape = false;
256
257 for (int i = 0; i < bufferLength; ++i) {
258 UChar c = buffer[i];
259
260 if (escape) {
261 switch (c) {
262 case '0':
263 c = '\0';
264 break;
265 case 'a':
266 c = '\a';
267 break;
268 case 'b':
269 c = '\b';
270 break;
271 case 'f':
272 c = '\f';
273 break;
274 case 'n':
275 c = '\n';
276 break;
277 case 'r':
278 c = '\r';
279 break;
280 case 't':
281 c = '\t';
282 break;
283 case 'v':
284 c = '\v';
285 break;
286 case '\\':
287 c = '\\';
288 break;
289 case '?':
290 c = '\?';
291 break;
292 case 'u':
293 if ((i + 4) >= bufferLength)
294 return -1;
295 unsigned int charValue;
296 if (sscanf(buffer+i+1, "%04x", &charValue) != 1)
297 return -1;
298 c = static_cast<UChar>(charValue);
299 i += 4;
300 break;
301 }
302
303 builder.append(c);
304 escape = false;
305 } else {
306 if (c == termChar)
307 return i;
308
309 if (c == '\\')
310 escape = true;
311 else
312 builder.append(c);
313 }
314 }
315
316 return -1;
317}
318
319static RegExp* parseRegExpLine(VM& vm, char* line, int lineLength, const char** regexpError)
320{
321 StringBuilder pattern;
322
323 if (line[0] != '/')
324 return 0;
325
326 int i = scanString(line + 1, lineLength - 1, pattern, '/') + 1;
327
328 if ((i >= lineLength) || (line[i] != '/'))
329 return 0;
330
331 ++i;
332
333 auto flags = Yarr::parseFlags(line + i);
334 if (!flags) {
335 *regexpError = Yarr::errorMessage(Yarr::ErrorCode::InvalidRegularExpressionFlags);
336 return nullptr;
337 }
338
339 RegExp* r = RegExp::create(vm, pattern.toString(), flags.value());
340 if (!r->isValid()) {
341 *regexpError = r->errorMessage();
342 return nullptr;
343 }
344
345 return r;
346}
347
348static RegExpTest* parseTestLine(char* line, int lineLength)
349{
350 StringBuilder subjectString;
351
352 if ((line[0] != ' ') || (line[1] != '"'))
353 return 0;
354
355 int i = scanString(line + 2, lineLength - 2, subjectString, '"') + 2;
356
357 if ((i >= (lineLength - 2)) || (line[i] != '"') || (line[i+1] != ',') || (line[i+2] != ' '))
358 return 0;
359
360 i += 3;
361
362 int offset;
363
364 if (sscanf(line + i, "%d, ", &offset) != 1)
365 return 0;
366
367 while (line[i] && line[i] != ' ')
368 ++i;
369
370 ++i;
371
372 int matchResult;
373
374 if (sscanf(line + i, "%d, ", &matchResult) != 1)
375 return 0;
376
377 while (line[i] && line[i] != ' ')
378 ++i;
379
380 ++i;
381
382 if (line[i++] != '(')
383 return 0;
384
385 int start, end;
386
387 RegExpTest* result = new RegExpTest();
388
389 result->subject = subjectString.toString();
390 result->offset = offset;
391 result->result = matchResult;
392
393 while (line[i] && line[i] != ')') {
394 if (sscanf(line + i, "%d, %d", &start, &end) != 2) {
395 delete result;
396 return 0;
397 }
398
399 result->expectVector.append(start);
400 result->expectVector.append(end);
401
402 while (line[i] && (line[i] != ',') && (line[i] != ')'))
403 i++;
404 i++;
405 while (line[i] && (line[i] != ',') && (line[i] != ')'))
406 i++;
407
408 if (line[i] == ')')
409 break;
410 if (!line[i] || (line[i] != ',')) {
411 delete result;
412 return 0;
413 }
414 i++;
415 }
416
417 return result;
418}
419
420static bool runFromFiles(GlobalObject* globalObject, const Vector<String>& files, bool verbose)
421{
422 String script;
423 String fileName;
424 Vector<char> scriptBuffer;
425 unsigned tests = 0;
426 unsigned failures = 0;
427 Vector<char> lineBuffer(MaxLineLength + 1);
428
429 VM& vm = globalObject->vm();
430
431 bool success = true;
432 for (size_t i = 0; i < files.size(); i++) {
433 FILE* testCasesFile = fopen(files[i].utf8().data(), "rb");
434
435 if (!testCasesFile) {
436 printf("Unable to open test data file \"%s\"\n", files[i].utf8().data());
437 continue;
438 }
439
440 RegExp* regexp = 0;
441 size_t lineLength = 0;
442 char* linePtr = 0;
443 unsigned int lineNumber = 0;
444 const char* regexpError = nullptr;
445
446 while ((linePtr = fgets(lineBuffer.data(), MaxLineLength, testCasesFile))) {
447 lineLength = strlen(linePtr);
448 if (linePtr[lineLength - 1] == '\n') {
449 linePtr[lineLength - 1] = '\0';
450 --lineLength;
451 }
452 ++lineNumber;
453
454 if (linePtr[0] == '#')
455 continue;
456
457 if (linePtr[0] == '/') {
458 regexp = parseRegExpLine(vm, linePtr, lineLength, &regexpError);
459 if (!regexp) {
460 failures++;
461 fprintf(stderr, "Failure on line %u. '%s' %s\n", lineNumber, linePtr, regexpError);
462 }
463 } else if (linePtr[0] == ' ') {
464 RegExpTest* regExpTest = parseTestLine(linePtr, lineLength);
465
466 if (regexp && regExpTest) {
467 ++tests;
468 if (!testOneRegExp(vm, regexp, regExpTest, verbose, lineNumber)) {
469 failures++;
470 printf("Failure on line %u\n", lineNumber);
471 }
472 }
473
474 if (regExpTest)
475 delete regExpTest;
476 } else if (linePtr[0] == '-') {
477 tests++;
478 regexp = 0; // Reset the live regexp to avoid confusing other subsequent tests
479 bool successfullyParsed = parseRegExpLine(vm, linePtr + 1, lineLength - 1, &regexpError);
480 if (successfullyParsed) {
481 failures++;
482 fprintf(stderr, "Failure on line %u. '%s' %s\n", lineNumber, linePtr + 1, regexpError);
483 }
484 }
485 }
486
487 fclose(testCasesFile);
488 }
489
490 if (failures)
491 printf("%u tests run, %u failures\n", tests, failures);
492 else
493 printf("%u tests passed\n", tests);
494
495#if ENABLE(REGEXP_TRACING)
496 vm.dumpRegExpTrace();
497#endif
498 return success;
499}
500
501#define RUNNING_FROM_XCODE 0
502
503static NO_RETURN void printUsageStatement(bool help = false)
504{
505 fprintf(stderr, "Usage: regexp_test [options] file\n");
506 fprintf(stderr, " -h|--help Prints this help message\n");
507 fprintf(stderr, " -v|--verbose Verbose output\n");
508
509 exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
510}
511
512static void parseArguments(int argc, char** argv, CommandLine& options)
513{
514 int i = 1;
515 for (; i < argc; ++i) {
516 const char* arg = argv[i];
517 if (!strcmp(arg, "-h") || !strcmp(arg, "--help"))
518 printUsageStatement(true);
519 if (!strcmp(arg, "-v") || !strcmp(arg, "--verbose"))
520 options.verbose = true;
521 else
522 options.files.append(argv[i]);
523 }
524
525 for (; i < argc; ++i)
526 options.arguments.append(argv[i]);
527}
528
529int realMain(int argc, char** argv)
530{
531 VM* vm = &VM::create(LargeHeap).leakRef();
532 JSLockHolder locker(vm);
533
534 CommandLine options;
535 parseArguments(argc, argv, options);
536
537 GlobalObject* globalObject = GlobalObject::create(*vm, GlobalObject::createStructure(*vm, jsNull()), options.arguments);
538 bool success = runFromFiles(globalObject, options.files, options.verbose);
539
540 return success ? 0 : 3;
541}
542
543#if OS(WINDOWS)
544extern "C" __declspec(dllexport) int WINAPI dllLauncherEntryPoint(int argc, const char* argv[])
545{
546 return main(argc, const_cast<char**>(argv));
547}
548#endif
Note: See TracBrowser for help on using the repository browser.