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

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

Replace JSC::UString by WTF::String
https://bugs.webkit.org/show_bug.cgi?id=95271

Patch by Benjamin Poulain <[email protected]> on 2012-08-30
Reviewed by Geoffrey Garen.

Source/JavaScriptCore:

Having JSC::UString and WTF::String increase the complexity of working on WebKit, and
add useless conversions in the bindings. It also cause some code bloat.

The performance advantages of UString have been ported over in previous patches. This patch
is the last step: getting rid of UString.

In addition to the simplified code, this also reduce the binary size by 15kb on x86_64.

  • API/OpaqueJSString.cpp:

(OpaqueJSString::ustring):

  • runtime/Identifier.h:

(JSC::Identifier::ustring):
To avoid changing everything at once, the function named ustring() were kept as is. They
will be renamed in a follow up patch.

  • runtime/JSString.h:

(JSC::JSString::string):
(JSC::JSValue::toWTFString):
(JSC::inlineJSValueNotStringtoString):
(JSC::JSValue::toWTFStringInline):
Since JSValue::toString() already exist (and return the JSString), the direct accessor is renamed
to ::toWTFString(). We may change ::string() to ::jsString() and ::toWTFString() to ::toString()
in the future.

  • runtime/StringPrototype.cpp:

(JSC::substituteBackreferencesSlow): Replace the use of UString::getCharacters<>() by String::getCharactersWithUpconvert<>().

Source/WebCore:

Update the code to use String instead of UString.

On x86_64, this reduces the binary size by 22kb.

Since it is no longer possible to differenciate JSC::jsString() and WebCore::jsString() by the input
types, WebCore::jsString() is renated to WebCore::jsStringWithCache().

Since the cache is using a PtrHash, JSC::jsString() is used in place of the old WebCore::jsString() when
the string is generated locally. This is because the cache can never match in those cases.

Source/WebKit/blackberry:

Replace UString by String.

  • WebCoreSupport/ClientExtension.cpp:
  • WebCoreSupport/PagePopupBlackBerry.cpp:

(WebCore::PagePopupBlackBerry::installDomFunction):

Source/WebKit/efl:

Replace UString by String.

  • WebCoreSupport/DumpRenderTreeSupportEfl.cpp:

(DumpRenderTreeSupportEfl::sendWebIntentResponse):

  • ewk/ewk_frame.cpp:

(ewk_frame_script_execute):

Source/WebKit/gtk:

Replace UString by String.

  • gdom/ConvertToGCharPrivate.h:

(copyAsGchar):

Source/WebKit/mac:

Get rid of UString, replace it by String, and simplify the code when possible.

On x86_64, this reduces the binary size by 7kb.

  • Plugins/Hosted/NetscapePluginHostProxy.mm:

(identifierFromIdentifierRep):

  • Plugins/Hosted/NetscapePluginInstanceProxy.mm:

(WebKit::NetscapePluginInstanceProxy::addValueToArray):
(WebKit::NetscapePluginInstanceProxy::moveGlobalExceptionToExecState):

  • Plugins/Hosted/ProxyInstance.mm:

(WebKit::ProxyRuntimeMethod::create):
(WebKit::ProxyRuntimeMethod::finishCreation):
(WebKit::ProxyInstance::getPropertyNames):
(WebKit::ProxyInstance::methodsNamed):
(WebKit::ProxyInstance::fieldNamed):

  • WebView/WebFrame.mm:

(-[WebFrame _stringByEvaluatingJavaScriptFromString:forceUserGesture:]):
(-[WebFrame _stringByEvaluatingJavaScriptFromString:withGlobalObject:inScriptWorld:]):

  • WebView/WebScriptDebugDelegate.mm:

(-[WebScriptCallFrame functionName]):
(-[WebScriptCallFrame evaluateWebScript:]):

  • WebView/WebScriptDebugger.h:

(WTF):
(JSC):
(WebScriptDebugger):

  • WebView/WebScriptDebugger.mm:

(toNSURL):
(WebScriptDebugger::sourceParsed):

  • WebView/WebView.mm:

(aeDescFromJSValue):

Source/WebKit/qt:

Replace UString by String.

  • Api/qwebelement.cpp:

(QWebElement::evaluateJavaScript):

Source/WebKit/win:

Replace UString by String.

  • WebFrame.cpp:

(WebFrame::stringByEvaluatingJavaScriptInScriptWorld):

  • WebView.cpp:

(WebView::stringByEvaluatingJavaScriptFromString):

Source/WebKit/wx:

Update the #includes to use the correct types.

  • WebFrame.cpp:
  • WebView.cpp:

Source/WebKit2:

Update to code to switch from UString to String.

  • WebProcess/Plugins/Netscape/JSNPMethod.cpp:

(WebKit::JSNPMethod::finishCreation):

  • WebProcess/Plugins/Netscape/JSNPMethod.h:

(WebKit::JSNPMethod::create):
(JSNPMethod):

  • WebProcess/Plugins/Netscape/JSNPObject.cpp:

(WebKit::npIdentifierFromIdentifier):

  • WebProcess/Plugins/Netscape/NPRuntimeObjectMap.cpp:

(WebKit::NPRuntimeObjectMap::evaluate):
(WebKit::NPRuntimeObjectMap::moveGlobalExceptionToExecState):

Source/WTF:

  • wtf/Platform.h: Useless edit to force a full build. This is needed for some bots for some reason.
  • wtf/text/WTFString.h: Export a symbol that was exported on UString and needed in WebCore.

Add String::getCharactersWithUpconvert<>(), which is similar to String::getCharacters<>() but with the same
behaviors as UString::getCharacters<>().

String::getCharactersWithUpconvert<>() is useful when manipulating multiple strings, it allow writting code
using 16bits characters if any of the input String is not 8bit.

Tools:

Get rid of UString.

  • DumpRenderTree/efl/WorkQueueItemEfl.cpp:
  • gdb/webkit.py:

(WTFStringPrinter.to_string):
(JSCIdentifierPrinter.to_string):
(JSCJSStringPrinter.to_string):
(add_pretty_printers):

Websites/webkit.org:

Update the coding style to avoid mentioning a class that no longer exist.

  • coding/coding-style.html:
  • Property svn:eol-style set to native
File size: 14.0 KB
Line 
1/*
2 * Copyright (C) 2011 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 <wtf/CurrentTime.h>
25#include "InitializeThreading.h"
26#include "JSGlobalObject.h"
27#include <errno.h>
28#include <stdio.h>
29#include <stdlib.h>
30#include <string.h>
31#include <wtf/text/StringBuilder.h>
32
33#if !OS(WINDOWS)
34#include <unistd.h>
35#endif
36
37#if HAVE(SYS_TIME_H)
38#include <sys/time.h>
39#endif
40
41#if COMPILER(MSVC) && !OS(WINCE)
42#include <crtdbg.h>
43#include <mmsystem.h>
44#include <windows.h>
45#endif
46
47#if PLATFORM(QT)
48#include <QCoreApplication>
49#include <QDateTime>
50#endif
51
52const int MaxLineLength = 100 * 1024;
53
54using namespace JSC;
55using namespace WTF;
56
57struct CommandLine {
58 CommandLine()
59 : interactive(false)
60 , verbose(false)
61 {
62 }
63
64 bool interactive;
65 bool verbose;
66 Vector<String> arguments;
67 Vector<String> files;
68};
69
70class StopWatch {
71public:
72 void start();
73 void stop();
74 long getElapsedMS(); // call stop() first
75
76private:
77 double m_startTime;
78 double m_stopTime;
79};
80
81void StopWatch::start()
82{
83 m_startTime = currentTime();
84}
85
86void StopWatch::stop()
87{
88 m_stopTime = currentTime();
89}
90
91long StopWatch::getElapsedMS()
92{
93 return static_cast<long>((m_stopTime - m_startTime) * 1000);
94}
95
96struct RegExpTest {
97 RegExpTest()
98 : offset(0)
99 , result(0)
100 {
101 }
102
103 String subject;
104 int offset;
105 int result;
106 Vector<int, 32> expectVector;
107};
108
109class GlobalObject : public JSGlobalObject {
110private:
111 GlobalObject(JSGlobalData&, Structure*, const Vector<String>& arguments);
112
113public:
114 typedef JSGlobalObject Base;
115
116 static GlobalObject* create(JSGlobalData& globalData, Structure* structure, const Vector<String>& arguments)
117 {
118 return new (NotNull, allocateCell<GlobalObject>(globalData.heap)) GlobalObject(globalData, structure, arguments);
119 }
120
121 static const ClassInfo s_info;
122
123 static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
124 {
125 return Structure::create(globalData, 0, prototype, TypeInfo(GlobalObjectType, StructureFlags), &s_info);
126 }
127
128protected:
129 void finishCreation(JSGlobalData& globalData, const Vector<String>& arguments)
130 {
131 Base::finishCreation(globalData);
132 UNUSED_PARAM(arguments);
133 }
134};
135
136COMPILE_ASSERT(!IsInteger<GlobalObject>::value, WTF_IsInteger_GlobalObject_false);
137ASSERT_CLASS_FITS_IN_CELL(GlobalObject);
138
139const ClassInfo GlobalObject::s_info = { "global", &JSGlobalObject::s_info, 0, ExecState::globalObjectTable, CREATE_METHOD_TABLE(GlobalObject) };
140
141GlobalObject::GlobalObject(JSGlobalData& globalData, Structure* structure, const Vector<String>& arguments)
142 : JSGlobalObject(globalData, structure)
143{
144 finishCreation(globalData, arguments);
145}
146
147// Use SEH for Release builds only to get rid of the crash report dialog
148// (luckily the same tests fail in Release and Debug builds so far). Need to
149// be in a separate main function because the realMain function requires object
150// unwinding.
151
152#if COMPILER(MSVC) && !COMPILER(INTEL) && !defined(_DEBUG) && !OS(WINCE)
153#define TRY __try {
154#define EXCEPT(x) } __except (EXCEPTION_EXECUTE_HANDLER) { x; }
155#else
156#define TRY
157#define EXCEPT(x)
158#endif
159
160int realMain(int argc, char** argv);
161
162int main(int argc, char** argv)
163{
164#if OS(WINDOWS)
165#if !OS(WINCE)
166 // Cygwin calls ::SetErrorMode(SEM_FAILCRITICALERRORS), which we will inherit. This is bad for
167 // testing/debugging, as it causes the post-mortem debugger not to be invoked. We reset the
168 // error mode here to work around Cygwin's behavior. See <http://webkit.org/b/55222>.
169 ::SetErrorMode(0);
170#endif
171
172#if defined(_DEBUG)
173 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
174 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
175 _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
176 _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
177 _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
178 _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
179#endif
180
181 timeBeginPeriod(1);
182#endif
183
184#if PLATFORM(QT)
185 QCoreApplication app(argc, argv);
186#endif
187
188 // Initialize JSC before getting JSGlobalData.
189 JSC::initializeThreading();
190
191 // We can't use destructors in the following code because it uses Windows
192 // Structured Exception Handling
193 int res = 0;
194 TRY
195 res = realMain(argc, argv);
196 EXCEPT(res = 3)
197 return res;
198}
199
200static bool testOneRegExp(JSGlobalData& globalData, RegExp* regexp, RegExpTest* regExpTest, bool verbose, unsigned int lineNumber)
201{
202 bool result = true;
203 Vector<int, 32> outVector;
204 outVector.resize(regExpTest->expectVector.size());
205 int matchResult = regexp->match(globalData, regExpTest->subject, regExpTest->offset, outVector);
206
207 if (matchResult != regExpTest->result) {
208 result = false;
209 if (verbose)
210 printf("Line %d: results mismatch - expected %d got %d\n", lineNumber, regExpTest->result, matchResult);
211 } else if (matchResult != -1) {
212 if (outVector.size() != regExpTest->expectVector.size()) {
213 result = false;
214 if (verbose)
215 printf("Line %d: output vector size mismatch - expected %lu got %lu\n", lineNumber, regExpTest->expectVector.size(), outVector.size());
216 } else if (outVector.size() % 2) {
217 result = false;
218 if (verbose)
219 printf("Line %d: output vector size is odd (%lu), should be even\n", lineNumber, outVector.size());
220 } else {
221 // Check in pairs since the first value of the pair could be -1 in which case the second doesn't matter.
222 size_t pairCount = outVector.size() / 2;
223 for (size_t i = 0; i < pairCount; ++i) {
224 size_t startIndex = i*2;
225 if (outVector[startIndex] != regExpTest->expectVector[startIndex]) {
226 result = false;
227 if (verbose)
228 printf("Line %d: output vector mismatch at index %lu - expected %d got %d\n", lineNumber, startIndex, regExpTest->expectVector[startIndex], outVector[startIndex]);
229 }
230 if ((i > 0) && (regExpTest->expectVector[startIndex] != -1) && (outVector[startIndex+1] != regExpTest->expectVector[startIndex+1])) {
231 result = false;
232 if (verbose)
233 printf("Line %d: output vector mismatch at index %lu - expected %d got %d\n", lineNumber, startIndex+1, regExpTest->expectVector[startIndex+1], outVector[startIndex+1]);
234 }
235 }
236 }
237 }
238
239 return result;
240}
241
242static int scanString(char* buffer, int bufferLength, StringBuilder& builder, char termChar)
243{
244 bool escape = false;
245
246 for (int i = 0; i < bufferLength; ++i) {
247 UChar c = buffer[i];
248
249 if (escape) {
250 switch (c) {
251 case '0':
252 c = '\0';
253 break;
254 case 'a':
255 c = '\a';
256 break;
257 case 'b':
258 c = '\b';
259 break;
260 case 'f':
261 c = '\f';
262 break;
263 case 'n':
264 c = '\n';
265 break;
266 case 'r':
267 c = '\r';
268 break;
269 case 't':
270 c = '\t';
271 break;
272 case 'v':
273 c = '\v';
274 break;
275 case '\\':
276 c = '\\';
277 break;
278 case '?':
279 c = '\?';
280 break;
281 case 'u':
282 if ((i + 4) >= bufferLength)
283 return -1;
284 unsigned int charValue;
285 if (sscanf(buffer+i+1, "%04x", &charValue) != 1)
286 return -1;
287 c = static_cast<UChar>(charValue);
288 i += 4;
289 break;
290 }
291
292 builder.append(c);
293 escape = false;
294 } else {
295 if (c == termChar)
296 return i;
297
298 if (c == '\\')
299 escape = true;
300 else
301 builder.append(c);
302 }
303 }
304
305 return -1;
306}
307
308static RegExp* parseRegExpLine(JSGlobalData& globalData, char* line, int lineLength)
309{
310 StringBuilder pattern;
311
312 if (line[0] != '/')
313 return 0;
314
315 int i = scanString(line + 1, lineLength - 1, pattern, '/') + 1;
316
317 if ((i >= lineLength) || (line[i] != '/'))
318 return 0;
319
320 ++i;
321
322 return RegExp::create(globalData, pattern.toString(), regExpFlags(line + i));
323}
324
325static RegExpTest* parseTestLine(char* line, int lineLength)
326{
327 StringBuilder subjectString;
328
329 if ((line[0] != ' ') || (line[1] != '"'))
330 return 0;
331
332 int i = scanString(line + 2, lineLength - 2, subjectString, '"') + 2;
333
334 if ((i >= (lineLength - 2)) || (line[i] != '"') || (line[i+1] != ',') || (line[i+2] != ' '))
335 return 0;
336
337 i += 3;
338
339 int offset;
340
341 if (sscanf(line + i, "%d, ", &offset) != 1)
342 return 0;
343
344 while (line[i] && line[i] != ' ')
345 ++i;
346
347 ++i;
348
349 int matchResult;
350
351 if (sscanf(line + i, "%d, ", &matchResult) != 1)
352 return 0;
353
354 while (line[i] && line[i] != ' ')
355 ++i;
356
357 ++i;
358
359 if (line[i++] != '(')
360 return 0;
361
362 int start, end;
363
364 RegExpTest* result = new RegExpTest();
365
366 result->subject = subjectString.toString();
367 result->offset = offset;
368 result->result = matchResult;
369
370 while (line[i] && line[i] != ')') {
371 if (sscanf(line + i, "%d, %d", &start, &end) != 2) {
372 delete result;
373 return 0;
374 }
375
376 result->expectVector.append(start);
377 result->expectVector.append(end);
378
379 while (line[i] && (line[i] != ',') && (line[i] != ')'))
380 i++;
381 i++;
382 while (line[i] && (line[i] != ',') && (line[i] != ')'))
383 i++;
384
385 if (line[i] == ')')
386 break;
387 if (!line[i] || (line[i] != ',')) {
388 delete result;
389 return 0;
390 }
391 i++;
392 }
393
394 return result;
395}
396
397static bool runFromFiles(GlobalObject* globalObject, const Vector<String>& files, bool verbose)
398{
399 String script;
400 String fileName;
401 Vector<char> scriptBuffer;
402 unsigned tests = 0;
403 unsigned failures = 0;
404 char* lineBuffer = new char[MaxLineLength + 1];
405
406 JSGlobalData& globalData = globalObject->globalData();
407
408 bool success = true;
409 for (size_t i = 0; i < files.size(); i++) {
410 FILE* testCasesFile = fopen(files[i].utf8().data(), "rb");
411
412 if (!testCasesFile) {
413 printf("Unable to open test data file \"%s\"\n", files[i].utf8().data());
414 continue;
415 }
416
417 RegExp* regexp = 0;
418 size_t lineLength = 0;
419 char* linePtr = 0;
420 unsigned int lineNumber = 0;
421
422 while ((linePtr = fgets(&lineBuffer[0], MaxLineLength, testCasesFile))) {
423 lineLength = strlen(linePtr);
424 if (linePtr[lineLength - 1] == '\n') {
425 linePtr[lineLength - 1] = '\0';
426 --lineLength;
427 }
428 ++lineNumber;
429
430 if (linePtr[0] == '#')
431 continue;
432
433 if (linePtr[0] == '/') {
434 regexp = parseRegExpLine(globalData, linePtr, lineLength);
435 } else if (linePtr[0] == ' ') {
436 RegExpTest* regExpTest = parseTestLine(linePtr, lineLength);
437
438 if (regexp && regExpTest) {
439 ++tests;
440 if (!testOneRegExp(globalData, regexp, regExpTest, verbose, lineNumber)) {
441 failures++;
442 printf("Failure on line %u\n", lineNumber);
443 }
444 }
445
446 if (regExpTest)
447 delete regExpTest;
448 }
449 }
450
451 fclose(testCasesFile);
452 }
453
454 if (failures)
455 printf("%u tests run, %u failures\n", tests, failures);
456 else
457 printf("%u tests passed\n", tests);
458
459 delete[] lineBuffer;
460
461 globalData.dumpSampleData(globalObject->globalExec());
462#if ENABLE(REGEXP_TRACING)
463 globalData.dumpRegExpTrace();
464#endif
465 return success;
466}
467
468#define RUNNING_FROM_XCODE 0
469
470static NO_RETURN void printUsageStatement(bool help = false)
471{
472 fprintf(stderr, "Usage: regexp_test [options] file\n");
473 fprintf(stderr, " -h|--help Prints this help message\n");
474 fprintf(stderr, " -v|--verbose Verbose output\n");
475
476 exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
477}
478
479static void parseArguments(int argc, char** argv, CommandLine& options)
480{
481 int i = 1;
482 for (; i < argc; ++i) {
483 const char* arg = argv[i];
484 if (!strcmp(arg, "-h") || !strcmp(arg, "--help"))
485 printUsageStatement(true);
486 if (!strcmp(arg, "-v") || !strcmp(arg, "--verbose"))
487 options.verbose = true;
488 else
489 options.files.append(argv[i]);
490 }
491
492 for (; i < argc; ++i)
493 options.arguments.append(argv[i]);
494}
495
496int realMain(int argc, char** argv)
497{
498 RefPtr<JSGlobalData> globalData = JSGlobalData::create(ThreadStackTypeLarge, LargeHeap);
499 JSLockHolder lock(globalData.get());
500
501 CommandLine options;
502 parseArguments(argc, argv, options);
503
504 GlobalObject* globalObject = GlobalObject::create(*globalData, GlobalObject::createStructure(*globalData, jsNull()), options.arguments);
505 bool success = runFromFiles(globalObject, options.files, options.verbose);
506
507 return success ? 0 : 3;
508}
Note: See TracBrowser for help on using the repository browser.