summaryrefslogtreecommitdiff
path: root/Tools
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@nokia.com>2012-02-09 14:16:12 +0100
committerSimon Hausmann <simon.hausmann@nokia.com>2012-02-09 14:16:12 +0100
commit03e12282df9aa1e1fb05a8b90f1cfc2e08764cec (patch)
tree52599cd0ab782b1768e23ad176f7618f98333cb6 /Tools
parentcd44dc59cdfc39534aef4d417e9f3c412e3be139 (diff)
downloadqtwebkit-03e12282df9aa1e1fb05a8b90f1cfc2e08764cec.tar.gz
Imported WebKit commit e09a82039aa4273ab318b71122e92d8e5f233525 (http://svn.webkit.org/repository/webkit/trunk@107223)
Diffstat (limited to 'Tools')
-rw-r--r--Tools/BuildSlaveSupport/build.webkit.org-config/config.json11
-rw-r--r--Tools/BuildSlaveSupport/build.webkit.org-config/master.cfg8
-rw-r--r--Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/base.js16
-rw-r--r--Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/config.js2
-rw-r--r--Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/controllers.js36
-rw-r--r--Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/garden-o-matic.js19
-rw-r--r--Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui.js21
-rw-r--r--Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui/failures.js20
-rw-r--r--Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui/notifications.js14
-rw-r--r--Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui/notifications_unittests.js4
-rw-r--r--Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/styles/failures.css22
-rw-r--r--Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/styles/onebar.css4
-rwxr-xr-xTools/BuildSlaveSupport/kill-old-processes7
-rw-r--r--Tools/ChangeLog1211
-rw-r--r--Tools/DumpRenderTree/blackberry/AccessibilityControllerBlackBerry.cpp80
-rw-r--r--Tools/DumpRenderTree/blackberry/AccessibilityUIElementBlackBerry.cpp612
-rw-r--r--Tools/DumpRenderTree/blackberry/DumpRenderTree.cpp820
-rw-r--r--Tools/DumpRenderTree/blackberry/DumpRenderTreeBlackBerry.h149
-rw-r--r--Tools/DumpRenderTree/blackberry/EventSender.cpp408
-rw-r--r--Tools/DumpRenderTree/blackberry/EventSender.h29
-rw-r--r--Tools/DumpRenderTree/blackberry/GCControllerBlackBerry.cpp39
-rw-r--r--Tools/DumpRenderTree/blackberry/WorkQueueItemBlackBerry.cpp89
-rw-r--r--Tools/DumpRenderTree/chromium/DumpRenderTree.cpp7
-rw-r--r--Tools/DumpRenderTree/chromium/MockWebSpeechInputController.cpp2
-rw-r--r--Tools/DumpRenderTree/chromium/TestShell.cpp5
-rw-r--r--Tools/DumpRenderTree/chromium/TestShell.h4
-rw-r--r--Tools/DumpRenderTree/chromium/WebPreferences.cpp4
-rw-r--r--Tools/DumpRenderTree/chromium/WebPreferences.h3
-rw-r--r--Tools/DumpRenderTree/chromium/WebViewHost.cpp5
-rw-r--r--Tools/DumpRenderTree/efl/CMakeLists.txt16
-rw-r--r--Tools/DumpRenderTree/mac/DumpRenderTree.mm5
-rw-r--r--Tools/DumpRenderTree/mac/EventSendingController.mm20
-rw-r--r--Tools/DumpRenderTree/qt/DumpRenderTreeQt.cpp10
-rw-r--r--Tools/DumpRenderTree/qt/DumpRenderTreeQt.h3
-rw-r--r--Tools/DumpRenderTree/qt/LayoutTestControllerQt.cpp10
-rw-r--r--Tools/DumpRenderTree/qt/LayoutTestControllerQt.h6
-rw-r--r--Tools/DumpRenderTree/qt/main.cpp17
-rw-r--r--Tools/EWebLauncher/CMakeLists.txt8
-rw-r--r--Tools/GNUmakefile.am2
-rw-r--r--Tools/MiniBrowser/gtk/BrowserWindow.c21
-rw-r--r--Tools/MiniBrowser/gtk/GNUmakefile.am11
-rw-r--r--Tools/MiniBrowser/qt/BrowserWindow.cpp6
-rw-r--r--Tools/MiniBrowser/qt/MiniBrowserApplication.cpp7
-rw-r--r--Tools/MiniBrowser/qt/MiniBrowserApplication.h5
-rw-r--r--Tools/MiniBrowser/qt/qml/BrowserWindow.qml2
-rw-r--r--Tools/MiniBrowser/qt/qml/MockTouchPoint.qml4
-rwxr-xr-xTools/Scripts/build-webkit6
-rwxr-xr-xTools/Scripts/run-launcher2
-rwxr-xr-xTools/Scripts/update-webkit-auxiliary-libs2
-rwxr-xr-xTools/Scripts/update-webkit-dependency4
-rwxr-xr-xTools/Scripts/update-webkit-support-libs6
-rwxr-xr-xTools/Scripts/webkitdirs.pm10
-rw-r--r--Tools/Scripts/webkitpy/common/checkout/changelog_unittest.py2
-rw-r--r--Tools/Scripts/webkitpy/common/checkout/checkout_unittest.py2
-rw-r--r--Tools/Scripts/webkitpy/common/checkout/scm/git.py5
-rw-r--r--Tools/Scripts/webkitpy/common/checkout/scm/scm.py3
-rw-r--r--Tools/Scripts/webkitpy/common/checkout/scm/scm_mock.py3
-rw-r--r--Tools/Scripts/webkitpy/common/checkout/scm/scm_unittest.py2
-rw-r--r--Tools/Scripts/webkitpy/common/checkout/scm/svn.py5
-rw-r--r--Tools/Scripts/webkitpy/common/config/committers.py4
-rw-r--r--Tools/Scripts/webkitpy/common/net/buildbot/buildbot.py9
-rw-r--r--Tools/Scripts/webkitpy/common/net/credentials_unittest.py2
-rw-r--r--Tools/Scripts/webkitpy/common/net/file_uploader.py2
-rw-r--r--Tools/Scripts/webkitpy/common/net/resultsjsonparser.py6
-rw-r--r--Tools/Scripts/webkitpy/common/newstringio_unittest.py2
-rwxr-xr-xTools/Scripts/webkitpy/common/system/autoinstall.py41
-rw-r--r--Tools/Scripts/webkitpy/common/system/crashlogs.py2
-rw-r--r--Tools/Scripts/webkitpy/common/system/deprecated_logging.py2
-rw-r--r--Tools/Scripts/webkitpy/common/system/fileset.py2
-rw-r--r--Tools/Scripts/webkitpy/common/system/filesystem.py6
-rw-r--r--Tools/Scripts/webkitpy/common/system/filesystem_mock.py31
-rw-r--r--Tools/Scripts/webkitpy/common/system/filesystem_unittest.py2
-rw-r--r--Tools/Scripts/webkitpy/common/system/ospath.py85
-rw-r--r--Tools/Scripts/webkitpy/common/system/ospath_unittest.py62
-rw-r--r--Tools/Scripts/webkitpy/common/system/outputcapture.py13
-rw-r--r--Tools/Scripts/webkitpy/common/system/path.py1
-rw-r--r--Tools/Scripts/webkitpy/common/thread/threadedmessagequeue.py2
-rw-r--r--Tools/Scripts/webkitpy/common/version_check.py4
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/controllers/manager.py18
-rwxr-xr-xTools/Scripts/webkitpy/layout_tests/controllers/manager_worker_broker.py76
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/controllers/manager_worker_broker_unittest.py18
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/controllers/single_test_runner.py3
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/controllers/test_expectations_editor.py7
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/controllers/worker.py3
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/layout_package/json_layout_results_generator.py2
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/layout_package/json_results_generator.py11
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/layout_package/json_results_generator_unittest.py7
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/models/result_summary.py10
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/models/test_configuration.py26
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/models/test_expectations.py74
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/models/test_expectations_unittest.py124
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/models/test_input.py3
-rwxr-xr-xTools/Scripts/webkitpy/layout_tests/port/base.py45
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/port/base_unittest.py11
-rwxr-xr-xTools/Scripts/webkitpy/layout_tests/port/chromium.py8
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/port/chromium_mac.py7
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/port/efl.py4
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/port/gtk.py4
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/port/mac.py6
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/port/mac_unittest.py11
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/port/mock_drt.py4
-rwxr-xr-xTools/Scripts/webkitpy/layout_tests/port/port_testcase.py13
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/port/test.py10
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/port/webkit.py5
-rwxr-xr-xTools/Scripts/webkitpy/layout_tests/port/webkit_unittest.py6
-rwxr-xr-xTools/Scripts/webkitpy/layout_tests/run_webkit_tests.py10
-rwxr-xr-xTools/Scripts/webkitpy/layout_tests/run_webkit_tests_integrationtest.py35
-rw-r--r--Tools/Scripts/webkitpy/performance_tests/perftestsrunner.py25
-rwxr-xr-xTools/Scripts/webkitpy/performance_tests/perftestsrunner_unittest.py50
-rw-r--r--Tools/Scripts/webkitpy/style/checker.py7
-rwxr-xr-xTools/Scripts/webkitpy/style/checker_unittest.py5
-rw-r--r--Tools/Scripts/webkitpy/style/checkers/cpp.py4
-rw-r--r--Tools/Scripts/webkitpy/style/checkers/jsonchecker.py7
-rw-r--r--Tools/Scripts/webkitpy/style/checkers/test_expectations.py48
-rw-r--r--Tools/Scripts/webkitpy/style/checkers/test_expectations_unittest.py27
-rw-r--r--Tools/Scripts/webkitpy/style/filereader_unittest.py4
-rw-r--r--Tools/Scripts/webkitpy/thirdparty/simplejson/LICENSE.txt19
-rw-r--r--Tools/Scripts/webkitpy/thirdparty/simplejson/README.txt11
-rw-r--r--Tools/Scripts/webkitpy/thirdparty/simplejson/__init__.py438
-rw-r--r--Tools/Scripts/webkitpy/thirdparty/simplejson/_speedups.c2652
-rw-r--r--Tools/Scripts/webkitpy/thirdparty/simplejson/decoder.py421
-rw-r--r--Tools/Scripts/webkitpy/thirdparty/simplejson/encoder.py503
-rw-r--r--Tools/Scripts/webkitpy/thirdparty/simplejson/jsonfilter.py40
-rw-r--r--Tools/Scripts/webkitpy/thirdparty/simplejson/ordered_dict.py119
-rw-r--r--Tools/Scripts/webkitpy/thirdparty/simplejson/scanner.py77
-rw-r--r--Tools/Scripts/webkitpy/thirdparty/simplejson/tool.py39
-rw-r--r--Tools/Scripts/webkitpy/to_be_moved/rebaseline_chromium_webkit_tests.py4
-rwxr-xr-xTools/Scripts/webkitpy/to_be_moved/update_webgl_conformance_tests.py2
-rw-r--r--Tools/Scripts/webkitpy/tool/bot/queueengine.py3
-rw-r--r--Tools/Scripts/webkitpy/tool/commands/abstractsequencedcommand.py2
-rw-r--r--Tools/Scripts/webkitpy/tool/commands/analyzechangelog.py2
-rw-r--r--Tools/Scripts/webkitpy/tool/commands/download.py6
-rw-r--r--Tools/Scripts/webkitpy/tool/commands/download_unittest.py6
-rw-r--r--Tools/Scripts/webkitpy/tool/commands/queues.py7
-rw-r--r--Tools/Scripts/webkitpy/tool/commands/queues_unittest.py6
-rw-r--r--Tools/Scripts/webkitpy/tool/commands/upload.py2
-rw-r--r--Tools/Scripts/webkitpy/tool/multicommandtool.py3
-rw-r--r--Tools/Scripts/webkitpy/tool/servers/gardeningserver_unittest.py7
-rw-r--r--Tools/Scripts/webkitpy/tool/servers/rebaselineserver_unittest.py8
-rw-r--r--Tools/Scripts/webkitpy/tool/servers/reflectionhandler.py9
-rw-r--r--Tools/Scripts/webkitpy/tool/steps/abstractstep.py5
-rw-r--r--Tools/Scripts/webkitpy/tool/steps/checkstyle.py2
-rw-r--r--Tools/Scripts/webkitpy/tool/steps/commit.py4
-rw-r--r--Tools/Scripts/webkitpy/tool/steps/confirmdiff.py2
-rw-r--r--Tools/Scripts/webkitpy/tool/steps/preparechangelogforrevert_unittest.py2
-rw-r--r--Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj40
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayout.cpp63
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFails.cpp84
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFails_Bundle.cpp53
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFrames.cpp88
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFrames_Bundle.cpp53
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayout_Bundle.cpp53
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/UserMessage.cpp157
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/UserMessage_Bundle.cpp52
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/WKPreferences.cpp14
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/lots-of-iframes.html35
-rw-r--r--Tools/TestWebKitAPI/Tests/mac/TypingStyleCrash.mm37
-rw-r--r--Tools/TestWebKitAPI/mac/PlatformWebViewMac.mm11
-rw-r--r--Tools/TestWebKitAPI/win/TestWebKitAPI.vcproj4
-rw-r--r--Tools/TestWebKitAPI/win/TestWebKitAPIInjectedBundle.vcproj4
-rw-r--r--Tools/Tools.pro4
-rw-r--r--Tools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp4
-rw-r--r--Tools/WebKitTestRunner/TestController.cpp8
-rw-r--r--Tools/WebKitTestRunner/TestController.h1
-rw-r--r--Tools/WebKitTestRunner/TestInvocation.cpp3
-rw-r--r--Tools/WebKitTestRunner/TestInvocation.h4
-rw-r--r--Tools/WebKitTestRunner/qt/PlatformWebViewQt.cpp1
-rw-r--r--Tools/WebKitTestRunner/qt/main.cpp2
-rw-r--r--Tools/gtk/common.py28
-rwxr-xr-xTools/gtk/generate-gtkdoc77
-rw-r--r--Tools/gtk/gtkdoc.py47
-rw-r--r--Tools/gtk/jhbuild.modules12
-rw-r--r--Tools/qmake/mkspecs/features/default_post.prf2
-rw-r--r--Tools/qmake/mkspecs/features/features.prf5
174 files changed, 5101 insertions, 5118 deletions
diff --git a/Tools/BuildSlaveSupport/build.webkit.org-config/config.json b/Tools/BuildSlaveSupport/build.webkit.org-config/config.json
index 8ef7c2968..85fbfec95 100644
--- a/Tools/BuildSlaveSupport/build.webkit.org-config/config.json
+++ b/Tools/BuildSlaveSupport/build.webkit.org-config/config.json
@@ -21,6 +21,7 @@
{ "name": "apple-xserve-2", "platform": "mac-lion" },
{ "name": "apple-xserve-3", "platform": "mac-lion" },
{ "name": "apple-xserve-10", "platform": "mac-lion" },
+ { "name": "apple-xserve-11", "platform": "mac-lion" },
{ "name": "apple-windows-1", "platform": "win"},
{ "name": "apple-windows-2", "platform": "win"},
@@ -110,7 +111,7 @@
},
{ "name": "Lion Intel Release (Build)", "type": "Build", "builddir": "lion-intel-release",
"platform": "mac-lion", "configuration": "release", "architectures": ["x86_64"],
- "triggers": ["lion-intel-release-tests", "lion-intel-release-tests-wk2"],
+ "triggers": ["lion-intel-release-tests", "lion-intel-release-tests-wk2", "lion-intel-release-perf"],
"slavenames": ["apple-xserve-3"]
},
{ "name": "Lion Intel Debug (Tests)", "type": "Test", "builddir": "lion-intel-debug-tests",
@@ -130,6 +131,11 @@
"slavenames": ["apple-macpro-6"]
},
{
+ "name": "Lion Intel Release (Perf)", "type": "DownloadAndPerfTest", "builddir": "lion-release-perf-tests",
+ "platform": "mac-lion", "configuration": "release", "architectures": ["x86_64"],
+ "slavenames": ["apple-xserve-11"]
+ },
+ {
"name": "Windows Release (Build)", "type": "Build", "builddir": "win-release",
"platform": "win", "configuration": "release", "architectures": ["i386"],
"triggers": ["win-release-tests", "win-release-tests-wk2"],
@@ -297,6 +303,9 @@
{ "type": "Triggerable", "name": "lion-intel-release-tests-wk2",
"builderNames": ["Lion Intel Release (WebKit2 Tests)"]
},
+ { "type": "Triggerable", "name": "lion-intel-release-perf",
+ "builderNames": ["Lion Intel Release (Perf)"]
+ },
{ "type": "Triggerable", "name": "lion-intel-debug-tests",
"builderNames": ["Lion Intel Debug (Tests)"]
},
diff --git a/Tools/BuildSlaveSupport/build.webkit.org-config/master.cfg b/Tools/BuildSlaveSupport/build.webkit.org-config/master.cfg
index a4daa7aa8..a1a01b285 100644
--- a/Tools/BuildSlaveSupport/build.webkit.org-config/master.cfg
+++ b/Tools/BuildSlaveSupport/build.webkit.org-config/master.cfg
@@ -775,6 +775,14 @@ class BuildAndPerfTestFactory(Factory):
self.addStep(CompileWebKit)
self.addStep(RunAndUploadPerfTests)
+class DownloadAndPerfTestFactory(Factory):
+ def __init__(self, platform, configuration, architectures, **kwargs):
+ Factory.__init__(self, platform, configuration, architectures, False, **kwargs)
+ self.addStep(CreateWebKitBuildDirectory)
+ self.addStep(DownloadBuiltProduct)
+ self.addStep(ExtractBuiltProduct)
+ self.addStep(RunAndUploadPerfTests)
+
class PlatformSpecificScheduler(AnyBranchScheduler):
def __init__(self, platform, branch, **kwargs):
self.platform = platform
diff --git a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/base.js b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/base.js
index 0c99efbf1..eae0315a5 100644
--- a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/base.js
+++ b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/base.js
@@ -171,12 +171,26 @@ base.filterTree = function(tree, isLeaf, predicate)
return filteredTree;
};
+base.forEachDirectory = function(pathList, callback)
+{
+ var pathsByDirectory = {};
+ pathList.forEach(function(path) {
+ var directory = base.dirName(path);
+ pathsByDirectory[directory] = pathsByDirectory[directory] || [];
+ pathsByDirectory[directory].push(path);
+ });
+ Object.keys(pathsByDirectory).sort().forEach(function(directory) {
+ var paths = pathsByDirectory[directory];
+ callback(directory + ' (' + paths.length + ' tests)', paths);
+ });
+};
+
base.parseJSONP = function(jsonp)
{
var startIndex = jsonp.indexOf('(') + 1;
var endIndex = jsonp.lastIndexOf(')');
return JSON.parse(jsonp.substr(startIndex, endIndex - startIndex));
-}
+};
base.RequestTracker = function(requestsInFlight, callback, args)
{
diff --git a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/config.js b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/config.js
index 4b3b7a087..bcb33801d 100644
--- a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/config.js
+++ b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/config.js
@@ -69,6 +69,6 @@ var kTenMinutesInMilliseconds = 10 * 60 * 1000;
config.kUpdateFrequency = kTenMinutesInMilliseconds;
config.kRelativeTimeUpdateFrequency = 1000 * 60;
-
+config.kExperimentalFeatures = window.location.search.search('enableExperiments=1') != -1;
})();
diff --git a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/controllers.js b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/controllers.js
index e161eaf65..458763110 100644
--- a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/controllers.js
+++ b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/controllers.js
@@ -94,6 +94,42 @@ controllers.ResultsDetails = base.extends(Object, {
}
});
+controllers.ExpectedFailures = base.extends(Object, {
+ init: function(model, view, delegate)
+ {
+ this._model = model;
+ this._view = view;
+ this._delegate = delegate;
+ },
+ update: function()
+ {
+ var expectedOrUnexpectedFailures = results.expectedOrUnexpectedFailuresByTest(this._model.resultsByBuilder);
+ var failingTestsList = Object.keys(expectedOrUnexpectedFailures);
+
+ $(this._view).empty();
+ base.forEachDirectory(failingTestsList, function(label, testsFailingInDirectory) {
+ var listItem = new ui.failures.ListItem(label, testsFailingInDirectory);
+ this._view.appendChild(listItem);
+ $(listItem).bind('examine', function() {
+ this.onExamine(testsFailingInDirectory);
+ }.bind(this));
+ }.bind(this));
+ },
+ onExamine: function(failingTestsList)
+ {
+ var resultsView = new ui.results.View({
+ fetchResultsURLs: results.fetchResultsURLs
+ });
+ var failuresByTest = base.filterDictionary(
+ results.expectedOrUnexpectedFailuresByTest(this._model.resultsByBuilder),
+ function(key) {
+ return failingTestsList.indexOf(key) != -1;
+ });
+ var controller = new controllers.ResultsDetails(resultsView, failuresByTest);
+ this._delegate.showResults(resultsView);
+ }
+});
+
var FailureStreamController = base.extends(Object, {
_resultsFilter: null,
_keyFor: function(failureAnalysis) { throw "Not implemented!"; },
diff --git a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/garden-o-matic.js b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/garden-o-matic.js
index 46cb86f67..f27189154 100644
--- a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/garden-o-matic.js
+++ b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/garden-o-matic.js
@@ -32,6 +32,7 @@ var g_updateTimerId = 0;
var g_buildersFailing = null;
var g_unexpectedFailuresController = null;
+var g_failuresController = null;
var g_losingTestCoverageBuilders = null;
@@ -49,6 +50,8 @@ function update()
builders.buildersFailingStepRequredForTestCoverage(g_losingTestCoverageBuilders.update.bind(g_losingTestCoverageBuilders));
base.callInParallel([model.updateRecentCommits, model.updateResultsByBuilder], function() {
+ if (g_failuresController)
+ g_failuresController.update();
updating.update('Analyzing test failures ...');
@@ -83,6 +86,7 @@ $(document).ready(function() {
showResults: function(resultsView)
{
var resultsContainer = onebar.results();
+ console.log(resultsContainer);
$(resultsContainer).empty().append(resultsView);
onebar.select('results');
}
@@ -99,10 +103,17 @@ $(document).ready(function() {
updateButton.addEventListener("click", update);
updateButton.textContent = 'update';
- var summary = onebar.summary();
- summary.appendChild(updateButton);
- summary.appendChild(g_info);
- summary.appendChild(unexpectedFailuresView);
+ var unexpected = onebar.unexpected();
+ unexpected.appendChild(updateButton);
+ unexpected.appendChild(g_info);
+ unexpected.appendChild(unexpectedFailuresView);
+
+ var failures = onebar.failures();
+ if (failures) {
+ var failuresView = new ui.failures.List();
+ g_failuresController = new controllers.ExpectedFailures(model.state, failuresView, onebarController);
+ failures.appendChild(failuresView);
+ }
update();
});
diff --git a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui.js b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui.js
index a77c4e7fe..e6e4fe5ca 100644
--- a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui.js
+++ b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui.js
@@ -63,18 +63,23 @@ ui.onebar = base.extends('div', {
this.id = 'onebar';
this.innerHTML =
'<ul>' +
- '<li><a href="#summary">Summary</a></li>' +
+ '<li><a href="#unexpected">Unexpected Failures</a></li>' +
'<li><a href="#results">Results</a></li>' +
'</ul>' +
- '<div id="summary"></div>' +
+ '<div id="unexpected"></div>' +
+ '<div id="failures"></div>' +
'<div id="results"></div>';
this._tabNames = [
- 'summary',
+ 'unexpected',
'results',
]
this._tabs = $(this).tabs({
disabled: [1],
});
+ if (config.kExperimentalFeatures) {
+ this._tabs.tabs('add', '#failures', 'All Failures (experimental)');
+ this._tabNames.push('failures');
+ }
},
attach: function()
{
@@ -82,6 +87,8 @@ ui.onebar = base.extends('div', {
},
tabNamed: function(tabName)
{
+ if (this._tabNames.indexOf(tabName) == -1)
+ return null;
tab = document.getElementById(tabName);
// We perform this sanity check below to make sure getElementById
// hasn't given us a node in some other unrelated part of the document.
@@ -91,9 +98,13 @@ ui.onebar = base.extends('div', {
return null;
return tab;
},
- summary: function()
+ unexpected: function()
+ {
+ return this.tabNamed('unexpected');
+ },
+ failures: function()
{
- return this.tabNamed('summary');
+ return this.tabNamed('failures');
},
results: function()
{
diff --git a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui/failures.js b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui/failures.js
index ff9652453..d3d631a66 100644
--- a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui/failures.js
+++ b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui/failures.js
@@ -127,4 +127,24 @@ ui.failures.FailureGrid = base.extends('table', {
}
});
+ui.failures.ListItem = base.extends('li', {
+ init: function(groupName, failingTestsList)
+ {
+ this._failingTestsList = failingTestsList;
+ this.appendChild(new ui.actions.List([
+ new ui.actions.Examine().makeDefault(),
+ ]));
+ var label = this.appendChild(document.createElement('label'))
+ label.textContent = failingTestsList.length == 1 ? failingTestsList[0] : groupName;
+ },
+});
+
+ui.failures.List = base.extends('ul', {
+ init: function()
+ {
+ this.className = 'failures';
+ this.textContent = 'Loading...';
+ }
+});
+
})();
diff --git a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui/notifications.js b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui/notifications.js
index 13ba105c0..ef713c264 100644
--- a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui/notifications.js
+++ b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui/notifications.js
@@ -182,21 +182,13 @@ ui.notifications.FailingTests = base.extends(ui.notifications.Failure, {
},
_forEachTestGroup: function(callback)
{
- var testsByDirectory = {};
- this._testNameList.forEach(function(testName) {
- var directory = base.dirName(testName);
- testsByDirectory[directory] = testsByDirectory[directory] || [];
- testsByDirectory[directory].push(testName);
- });
var individualTests = [];
- Object.keys(testsByDirectory).forEach(function(directory) {
- var testsInDirectory = testsByDirectory[directory];
- var count = testsInDirectory.length;
- if (count <= kMaxTestsPerGroup) {
+ base.forEachDirectory(this._testNameList, function(groupLabel, testsInDirectory) {
+ if (testsInDirectory.length <= kMaxTestsPerGroup) {
individualTests = individualTests.concat(testsInDirectory);
return;
}
- callback(directory + ' (' + count + ' tests)', testsInDirectory);
+ callback(groupLabel, testsInDirectory);
});
individualTests.forEach(function(testName) {
callback(testName, [testName]);
diff --git a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui/notifications_unittests.js b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui/notifications_unittests.js
index f5c292a82..b8b81c223 100644
--- a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui/notifications_unittests.js
+++ b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui/notifications_unittests.js
@@ -218,8 +218,8 @@ test('FailingTestsSummary', 12, function() {
'<div class="what">' +
'<div class="problem">' +
'<ul class="effects">' +
- '<li><a target="_blank" href="http://test-results.appspot.com/dashboards/flakiness_dashboard.html#tests=test">test</a></li>' +
'<li><a target="_blank" href="http://test-results.appspot.com/dashboards/flakiness_dashboard.html#tests=foo">foo</a></li>' +
+ '<li><a target="_blank" href="http://test-results.appspot.com/dashboards/flakiness_dashboard.html#tests=test">test</a></li>' +
'</ul>' +
'<ul class="actions">' +
'<li><button class="action default" title="Examine these failures in detail.">Examine</button></li>' +
@@ -263,8 +263,8 @@ test('FailingTestsSummary', 12, function() {
'<div class="what">' +
'<div class="problem">' +
'<ul class="effects">' +
- '<li><a target="_blank" href="http://test-results.appspot.com/dashboards/flakiness_dashboard.html#tests=test">test</a></li>' +
'<li><a target="_blank" href="http://test-results.appspot.com/dashboards/flakiness_dashboard.html#tests=foo">foo</a></li>' +
+ '<li><a target="_blank" href="http://test-results.appspot.com/dashboards/flakiness_dashboard.html#tests=test">test</a></li>' +
'</ul>' +
'<ul class="actions">' +
'<li><button class="action default" title="Examine these failures in detail.">Examine</button></li>' +
diff --git a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/styles/failures.css b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/styles/failures.css
index beb10836e..03c5c386b 100644
--- a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/styles/failures.css
+++ b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/styles/failures.css
@@ -51,3 +51,25 @@ a.failing-builder {
a.failing-builder>span.graphics {
padding: 0 2px;
}
+
+
+ul.failures {
+ padding: 0px;
+}
+
+ ul.failures>li {
+ display: -webkit-box;
+ }
+
+ ul.failures>li label {
+ margin-left: 10px;
+ }
+
+ ul.failures>li ul.actions {
+ padding: 0px;
+ visibility: hidden;
+ }
+
+ ul.failures>li:hover ul.actions {
+ visibility: visible;
+ }
diff --git a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/styles/onebar.css b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/styles/onebar.css
index d35e27e39..119c171c4 100644
--- a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/styles/onebar.css
+++ b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/styles/onebar.css
@@ -40,10 +40,10 @@
border-radius: 0px;
}
-#summary {
+#unexpected {
min-height: 550px;
}
-#onebar.partytime #summary {
+#onebar.partytime #unexpected {
background: url(../images/partytime.gif) center center no-repeat;
}
diff --git a/Tools/BuildSlaveSupport/kill-old-processes b/Tools/BuildSlaveSupport/kill-old-processes
index 8b7b494d7..f3a947ada 100755
--- a/Tools/BuildSlaveSupport/kill-old-processes
+++ b/Tools/BuildSlaveSupport/kill-old-processes
@@ -55,6 +55,12 @@ def main():
]
tasksToKillMac = [
+ "cc1plus",
+ "cc1objplus",
+ "clang",
+ "clang++",
+ "gcc-4.2",
+ "i686-apple-darwin10-gcc-4.2.1"
"jsc",
"make",
"per5.12",
@@ -71,6 +77,7 @@ def main():
"WebKitTestRunner Web Content",
"WebKitTestRunner",
"WebProcess",
+ "xcodebuild",
]
if sys.platform == 'darwin':
diff --git a/Tools/ChangeLog b/Tools/ChangeLog
index fc1b807d3..a4fb2d060 100644
--- a/Tools/ChangeLog
+++ b/Tools/ChangeLog
@@ -1,3 +1,1214 @@
+2012-02-09 Ryosuke Niwa <rniwa@webkit.org>
+
+ kill-old-processes should kill gcc and clang
+ https://bugs.webkit.org/show_bug.cgi?id=78189
+
+ Reviewed by Eric Seidel.
+
+ Added a bunch of processes names of gcc and clang to the list.
+
+ * BuildSlaveSupport/kill-old-processes:
+
+2012-02-07 MORITA Hajime <morrita@google.com>
+
+ Replacement text should be available from the marker.
+ https://bugs.webkit.org/show_bug.cgi?id=77934
+
+ Made the mock requestCheckingOfText() implementation to return
+ a replacement text for each misspelled word if available.
+
+ Reviewed by Kent Tamura.
+
+ * DumpRenderTree/chromium/WebViewHost.cpp:
+ (WebViewHost::finishLastTextCheck):
+
+2012-02-08 Jesus Sanchez-Palencia <jesus.palencia@openbossa.org>
+
+ [Qt][DRT] DumpRenderTreeQt should support --no-timeout and --timeout options
+ https://bugs.webkit.org/show_bug.cgi?id=78146
+
+ Reviewed by Ryosuke Niwa.
+
+ Our DumpRenderTree should support --no-timeout and --timeout options in order
+ to be able to use run-perf-tests and have a Performance Bot.
+ This patch adds setTimeout and setShouldTimeout functions to our LayoutTestController
+ and the necessary code to handle such command line arguments to our DumpRenderTree.
+
+ * DumpRenderTree/qt/DumpRenderTreeQt.cpp:
+ (WebCore::DumpRenderTree::setTimeout):
+ (WebCore):
+ (WebCore::DumpRenderTree::setShouldTimeout):
+ * DumpRenderTree/qt/DumpRenderTreeQt.h:
+ (DumpRenderTree):
+ * DumpRenderTree/qt/LayoutTestControllerQt.cpp:
+ (LayoutTestController::LayoutTestController):
+ (LayoutTestController::waitUntilDone):
+ (LayoutTestController::notifyDone):
+ * DumpRenderTree/qt/LayoutTestControllerQt.h:
+ (LayoutTestController::setTimeout):
+ (LayoutTestController::setShouldTimeout):
+ (LayoutTestController):
+ * DumpRenderTree/qt/main.cpp:
+ (isOption):
+ (printUsage):
+ (main):
+
+2012-02-08 Gustavo Noronha Silva <gns@gnome.org>
+
+ Rubber-stamped by Martin Robinson.
+
+ * gtk/common.py:
+ (get_build_path): Move test for current directory being a valid
+ directory up so it takes precedence over WebKitBuild/Release and
+ WebKitBuild/Debug when they exist as well.
+
+2012-02-08 Gustavo Noronha Silva <gns@gnome.org>
+
+ [GTK] doc rebasing does not respect DESTDIR
+ https://bugs.webkit.org/show_bug.cgi?id=78177
+
+ Reviewed by Martin Robinson.
+
+ * GNUmakefile.am: Pass DESTDIR on to generate-gtkdoc, when
+ calling it for rebasing.
+ * gtk/generate-gtkdoc:
+ (get_common_options): Handle the new --virtual-root option.
+ * gtk/gtkdoc.py:
+ (GTKDoc.rebase_installed_docs): If a virtual-root has been given, pass
+ it on to gtkdoc-rebase as dest-dir, and prefix the htmldir with it.
+
+2012-02-08 Adam Barth <abarth@webkit.org>
+
+ Remove Python 2.5 support from WebKit
+ https://bugs.webkit.org/show_bug.cgi?id=71593
+
+ Reviewed by Eric Seidel.
+
+ This is the last vestige of our Python 2.5 support.
+
+ * Scripts/webkitpy/tool/commands/queues_unittest.py:
+ (AbstractQueueTest.test_log_from_script_error_for_upload):
+
+2012-02-08 Adam Barth <abarth@webkit.org>
+
+ version_check.py should inform users that we don't support Python 2.5 anymore
+ https://bugs.webkit.org/show_bug.cgi?id=78179
+
+ Reviewed by Eric Seidel.
+
+ We don't support Python 2.5 anymore.
+
+ * Scripts/webkitpy/common/version_check.py:
+
+2012-02-08 Adam Barth <abarth@webkit.org>
+
+ test_configuration.py shouldn't re-implement itertools
+ https://bugs.webkit.org/show_bug.cgi?id=78178
+
+ Reviewed by Eric Seidel.
+
+ * Scripts/webkitpy/layout_tests/models/test_configuration.py:
+ (TestConfigurationConverter.to_specifiers_list):
+ (TestConfigurationConverter.to_specifiers_list.try_collapsing):
+ (TestConfigurationConverter.to_specifiers_list.try_abbreviating):
+ (TestConfigurationConverter):
+
+2012-02-08 Adam Barth <abarth@webkit.org>
+
+ webkitpy should reply upon the multiprocessing package existing
+ https://bugs.webkit.org/show_bug.cgi?id=78176
+
+ Reviewed by Eric Seidel.
+
+ Now that we don't support Python 2.5, this import can't fail.
+
+ * Scripts/webkitpy/layout_tests/controllers/manager_worker_broker.py:
+ (get):
+ (_Process):
+ (_Process.__init__):
+ (_Process.run):
+ * Scripts/webkitpy/layout_tests/controllers/manager_worker_broker_unittest.py:
+ (FunctionTests.test_get__processes):
+ (MultiProcessBrokerTests.setUp):
+ * Scripts/webkitpy/layout_tests/port/base.py:
+ (Port.__init__):
+ (Port.default_worker_model):
+ * Scripts/webkitpy/layout_tests/port/chromium_mac.py:
+ (ChromiumMacPort.check_build):
+ * Scripts/webkitpy/layout_tests/port/port_testcase.py:
+ (PortTestCase.test_default_worker_model):
+ * Scripts/webkitpy/layout_tests/run_webkit_tests_integrationtest.py:
+
+2012-02-08 Gustavo Noronha Silva <gns@gnome.org>
+
+ Unreviewed typo fix that makes docs build again for the gtk2-based
+ library.
+
+ * gtk/generate-gtkdoc:
+
+2012-02-08 Adam Barth <abarth@webkit.org>
+
+ Don't re-implement ZipFile.extractall
+ https://bugs.webkit.org/show_bug.cgi?id=78173
+
+ Reviewed by Eric Seidel.
+
+ We can use ZipFile.extractall now that we don't support Python 2.5.
+
+ * Scripts/webkitpy/common/system/autoinstall.py:
+ (AutoInstaller._extract_targz):
+ (AutoInstaller._unzip):
+
+2012-02-08 Adam Barth <abarth@webkit.org>
+
+ Remove the ospath compat shim from webkitpy
+ https://bugs.webkit.org/show_bug.cgi?id=78170
+
+ Reviewed by Eric Seidel.
+
+ We no longer need this compat shim now that we don't support Python 2.5.
+
+ * Scripts/webkitpy/common/checkout/scm/git.py:
+ * Scripts/webkitpy/common/checkout/scm/svn.py:
+ * Scripts/webkitpy/common/system/filesystem.py:
+ (FileSystem.relpath):
+ * Scripts/webkitpy/common/system/filesystem_mock.py:
+ (MockFileSystem.relpath):
+ * Scripts/webkitpy/common/system/ospath.py: Removed.
+ * Scripts/webkitpy/common/system/ospath_unittest.py: Removed.
+
+2012-02-08 Ryosuke Niwa <rniwa@webkit.org>
+
+ Build fix attempt after r107053.
+
+ * Scripts/webkitpy/performance_tests/perftestsrunner_unittest.py:
+ (test_collect_tests):
+
+2012-02-08 Adam Barth <abarth@webkit.org>
+
+ Remove simplejson because it's no longer used by webkitpy
+ https://bugs.webkit.org/show_bug.cgi?id=78164
+
+ Reviewed by Eric Seidel.
+
+ All the importers of this code were removed in a previous patch.
+
+ * Scripts/webkitpy/thirdparty/simplejson: Removed.
+ * Scripts/webkitpy/thirdparty/simplejson/LICENSE.txt: Removed.
+ * Scripts/webkitpy/thirdparty/simplejson/README.txt: Removed.
+ * Scripts/webkitpy/thirdparty/simplejson/__init__.py: Removed.
+ * Scripts/webkitpy/thirdparty/simplejson/_speedups.c: Removed.
+ * Scripts/webkitpy/thirdparty/simplejson/decoder.py: Removed.
+ * Scripts/webkitpy/thirdparty/simplejson/encoder.py: Removed.
+ * Scripts/webkitpy/thirdparty/simplejson/jsonfilter.py: Removed.
+ * Scripts/webkitpy/thirdparty/simplejson/ordered_dict.py: Removed.
+ * Scripts/webkitpy/thirdparty/simplejson/scanner.py: Removed.
+ * Scripts/webkitpy/thirdparty/simplejson/tool.py: Removed.
+
+2012-02-08 Adam Barth <abarth@webkit.org>
+
+ webkitpy still imports simplejson
+ https://bugs.webkit.org/show_bug.cgi?id=78161
+
+ Reviewed by Eric Seidel.
+
+ We no longer support Python 2.5, so we can rely upon Python's built-in
+ JSON package.
+
+ * Scripts/webkitpy/common/net/buildbot/buildbot.py:
+ * Scripts/webkitpy/common/net/resultsjsonparser.py:
+ * Scripts/webkitpy/layout_tests/controllers/test_expectations_editor.py:
+ * Scripts/webkitpy/layout_tests/layout_package/json_results_generator.py:
+ * Scripts/webkitpy/layout_tests/layout_package/json_results_generator_unittest.py:
+ * Scripts/webkitpy/layout_tests/models/test_expectations.py:
+ * Scripts/webkitpy/layout_tests/run_webkit_tests_integrationtest.py:
+ * Scripts/webkitpy/style/checkers/jsonchecker.py:
+ * Scripts/webkitpy/tool/servers/gardeningserver_unittest.py:
+ * Scripts/webkitpy/tool/servers/rebaselineserver_unittest.py:
+ * Scripts/webkitpy/tool/servers/reflectionhandler.py:
+
+2012-02-08 Gustavo Noronha Silva <gns@gnome.org>
+
+ [GTK] Fails to build docs with non-standard build directories
+ https://bugs.webkit.org/show_bug.cgi?id=78118
+
+ * gtk/common.py:
+ (get_build_path): add comment to document changes done in r107098,
+ as requested by the reviewer and forgotten by me.
+
+2012-02-08 Adam Barth <abarth@webkit.org>
+
+ Stop importing with_statement from the mysterious future
+ https://bugs.webkit.org/show_bug.cgi?id=78156
+
+ Reviewed by Eric Seidel.
+
+ The future is now! (Well, at least 2008, when Python 2.6 was released,
+ is no longer the __future__.)
+
+ * Scripts/webkitpy/common/checkout/changelog_unittest.py:
+ * Scripts/webkitpy/common/checkout/checkout_unittest.py:
+ * Scripts/webkitpy/common/checkout/scm/scm_unittest.py:
+ * Scripts/webkitpy/common/net/credentials_unittest.py:
+ * Scripts/webkitpy/common/net/file_uploader.py:
+ * Scripts/webkitpy/common/newstringio_unittest.py:
+ * Scripts/webkitpy/common/system/autoinstall.py:
+ * Scripts/webkitpy/common/system/crashlogs.py:
+ * Scripts/webkitpy/common/system/fileset.py:
+ * Scripts/webkitpy/common/system/filesystem.py:
+ * Scripts/webkitpy/common/system/filesystem_unittest.py:
+ * Scripts/webkitpy/common/system/path.py:
+ * Scripts/webkitpy/common/thread/threadedmessagequeue.py:
+ * Scripts/webkitpy/layout_tests/controllers/manager.py:
+ * Scripts/webkitpy/layout_tests/port/base.py:
+ (of):
+ * Scripts/webkitpy/layout_tests/port/gtk.py:
+ * Scripts/webkitpy/layout_tests/port/test.py:
+ * Scripts/webkitpy/layout_tests/run_webkit_tests_integrationtest.py:
+ * Scripts/webkitpy/style/filereader_unittest.py:
+ * Scripts/webkitpy/to_be_moved/rebaseline_chromium_webkit_tests.py:
+ * Scripts/webkitpy/to_be_moved/update_webgl_conformance_tests.py:
+ * Scripts/webkitpy/tool/commands/analyzechangelog.py:
+ * Scripts/webkitpy/tool/commands/queues.py:
+ * Scripts/webkitpy/tool/servers/reflectionhandler.py:
+ * Scripts/webkitpy/tool/steps/preparechangelogforrevert_unittest.py:
+
+2012-02-08 Rob Buis <rbuis@rim.com>
+
+ [BlackBerry] Upstream DumpRenderTreeBlackBerry
+ https://bugs.webkit.org/show_bug.cgi?id=78042
+
+ Reviewed by Antonio Gomes.
+
+ Upstream more parts of our DRT implementation.
+
+ * DumpRenderTree/blackberry/AccessibilityControllerBlackBerry.cpp: Added.
+ * DumpRenderTree/blackberry/AccessibilityUIElementBlackBerry.cpp: Added.
+ * DumpRenderTree/blackberry/EventSender.cpp: Added.
+ * DumpRenderTree/blackberry/EventSender.h: Added.
+ * DumpRenderTree/blackberry/GCControllerBlackBerry.cpp: Added.
+ * DumpRenderTree/blackberry/WorkQueueItemBlackBerry.cpp: Added.
+
+2012-02-08 Dirk Pranke <dpranke@chromium.org>
+
+ check-webkit-style failing with "Path does not exist."
+ https://bugs.webkit.org/show_bug.cgi?id=77873
+
+ Reviewed by Ojan Vafai.
+
+ This change fixes the way the style checker determines which
+ Port class to use for a given test_expectations.txt path; the
+ previous version used a heuristic that didn't really work in the
+ first place.
+
+ * Scripts/webkitpy/style/checkers/test_expectations.py:
+ (TestExpectationsChecker._determine_port_from_expectations_path):
+ (TestExpectationsChecker.__init__):
+ * Scripts/webkitpy/style/checkers/test_expectations_unittest.py:
+ (TestExpectationsTestCase._expect_port_for_expectations_path):
+ (TestExpectationsTestCase.test_determine_port_from_expectations_path):
+
+2012-02-08 Fehér Zsolt <feherzs@inf.u-szeged.hu>
+
+ nrwt: make --skip-pixel-test-if-no-baseline option
+ https://bugs.webkit.org/show_bug.cgi?id=70484
+
+ Reviewed by Dirk Pranke.
+
+ * Scripts/webkitpy/layout_tests/controllers/single_test_runner.py:
+ (SingleTestRunner.__init__):
+ (SingleTestRunner._should_fetch_expected_checksum):
+ * Scripts/webkitpy/layout_tests/controllers/worker.py:
+ (Worker.handle_test_list):
+ * Scripts/webkitpy/layout_tests/models/test_input.py:
+ (TestInput.__init__):
+ * Scripts/webkitpy/layout_tests/port/webkit.py:
+ (WebKitDriver.cmd_line):
+ * Scripts/webkitpy/layout_tests/run_webkit_tests.py:
+ (_set_up_derived_options):
+ (parse_args):
+ * Scripts/webkitpy/layout_tests/run_webkit_tests_integrationtest.py:
+ (MainTest.test_skip_pixel_test_if_no_baseline_option):
+ * WebKitTestRunner/TestController.cpp:
+ (WTR::TestController::TestController):
+ (WTR::TestController::initialize):
+ (WTR::TestController::runTest):
+ * WebKitTestRunner/TestController.h:
+ (TestController):
+ * WebKitTestRunner/TestInvocation.cpp:
+ (WTR::TestInvocation::TestInvocation):
+ (WTR::TestInvocation::setIsPixelTest):
+ * WebKitTestRunner/TestInvocation.h:
+ (WTR::TestInvocation::setSkipPixelTestOption):
+ (TestInvocation):
+
+2012-02-08 Rob Buis <rbuis@rim.com>
+
+ [BlackBerry] Upstream DumpRenderTreeBlackBerry
+ https://bugs.webkit.org/show_bug.cgi?id=78042
+
+ Reviewed by Antonio Gomes.
+
+ Add implementation for our DumpRenderTree solution.
+
+ * DumpRenderTree/blackberry/DumpRenderTree.cpp: Added.
+ * DumpRenderTree/blackberry/DumpRenderTreeBlackBerry.h: Added.
+
+2012-02-08 Antti Koivisto <antti@apple.com>
+
+ REGRESSION (r106681): Null check missing in [WebFrame(WebInternal) _typingStyle]
+ https://bugs.webkit.org/show_bug.cgi?id=78080
+
+ Reviewed by Andreas Kling, Darin Adler and Dan Bernstein.
+
+ Add API test.
+
+ * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+ * TestWebKitAPI/Tests/mac/TypingStyleCrash.mm: Added.
+ (TestWebKitAPI):
+ (TestWebKitAPI::TEST):
+
+2012-02-08 Gustavo Noronha Silva <gns@gnome.org>
+
+ [GTK] Fails to build docs with non-standard build directories
+ https://bugs.webkit.org/show_bug.cgi?id=78118
+
+ Reviewed by Martin Robinson.
+
+ * gtk/common.py:
+ (get_build_path): also try the current directory as a valid build
+ dir, which makes non-standard build directories such as build-2.0
+ and build-3.0 work
+
+2012-02-08 Carlos Garcia Campos <cgarcia@igalia.com>
+
+ [GTK] Open links in a new window when clicking with the middle button in MiniBrowser
+ https://bugs.webkit.org/show_bug.cgi?id=78099
+
+ Reviewed by Martin Robinson.
+
+ * MiniBrowser/gtk/BrowserWindow.c:
+ (webViewDecidePolicy): Check whether it's a link clicked with the
+ middle mouse button and load the request in a new window.
+ (browserWindowConstructed): Connect to
+ WebKitWebView::decide-policy signal.
+
+2012-02-08 Ryosuke Niwa <rniwa@webkit.org>
+
+ Revert a part of the change in r106687 as a build fix.
+
+ Since Chromium port doesn't checkout the entire WebKit trunk,
+ we can't run "svn info" on webkit_base.
+
+ * Scripts/webkitpy/layout_tests/port/base.py:
+ (Port.repository_paths):
+
+2012-02-07 Ryosuke Niwa <rniwa@webkit.org>
+
+ run-perf-tests doesn't recognize paths that start with PerformanceTests
+ https://bugs.webkit.org/show_bug.cgi?id=78012
+
+ Reviewed by Adam Barth.
+
+ Use resolve paths using filesystem.relpath before passing it to find_files.find.
+
+ * Scripts/webkitpy/performance_tests/perftestsrunner.py:
+ (PerfTestsRunner):
+ (PerfTestsRunner._collect_tests):
+ * Scripts/webkitpy/performance_tests/perftestsrunner_unittest.py:
+ (test_collect_tests):
+ (test_collect_tests.add_file):
+
+2012-02-07 Justin Novosad <junov@chromium.org>
+
+ [Chromium] add option for 2d canvas defered rendering to DumpRenderTree
+ https://bugs.webkit.org/show_bug.cgi?id=78039
+
+ Reviewed by Stephen White.
+
+ Adding the --enable-deferred-2d-canvas switch to DumpRenderTree
+
+ * DumpRenderTree/chromium/DumpRenderTree.cpp:
+ (main):
+ * DumpRenderTree/chromium/TestShell.cpp:
+ (TestShell::TestShell):
+ (TestShell::resetWebSettings):
+ (TestShell::runFileTest):
+ * DumpRenderTree/chromium/TestShell.h:
+ (TestShell::setDeferred2dCanvasEnabled):
+ (TestShell):
+ * DumpRenderTree/chromium/WebPreferences.cpp:
+ (WebPreferences::reset):
+ (WebPreferences::applyTo):
+ * DumpRenderTree/chromium/WebPreferences.h:
+ (WebPreferences):
+
+2012-02-07 Gyuyoung Kim <gyuyoung.kim@samsung.com>
+
+ [CMAKE] Use *bin* and *lib* directories for executable and libraries.
+ https://bugs.webkit.org/show_bug.cgi?id=77928
+
+ Reviewed by Daniel Bates.
+
+ CMake has used *Programs* directory for executable. In addition, shared libraries are being
+ built in source directory. It is better to set common places in order to maintain executable
+ and libraries. *bin* is for executable and *lib* is for library.
+
+ * DumpRenderTree/efl/CMakeLists.txt:
+ * EWebLauncher/CMakeLists.txt:
+ * Scripts/run-launcher:
+ * Scripts/webkitdirs.pm:
+ (jscProductDir):
+ * Scripts/webkitpy/layout_tests/port/efl.py:
+ (EflPort._path_to_driver):
+ (EflPort._path_to_image_diff):
+
+2012-02-07 Adam Klein <adamk@chromium.org>
+
+ Add JSC support for delivering mutations when the outermost script context exits
+ https://bugs.webkit.org/show_bug.cgi?id=70289
+
+ Reviewed by Eric Seidel.
+
+ * DumpRenderTree/mac/EventSendingController.mm: Add support for
+ eventSender.scheduleAsynchronousKeyDown.
+ (+[EventSendingController isSelectorExcludedFromWebScript:]):
+ (+[EventSendingController webScriptNameForSelector:]):
+ (-[EventSendingController keyDownWrapper:withModifiers:withLocation:]):
+ (-[EventSendingController scheduleAsynchronousKeyDown:withModifiers:withLocation:]):
+ * Scripts/build-webkit: Properly alphabetize --mutation-observers in the --help output.
+
+2012-02-07 Chris Rogers <crogers@google.com>
+
+ Add Chris Rogers to reviewers section
+ https://bugs.webkit.org/show_bug.cgi?id=78016
+
+ Reviewed by Adam Barth.
+
+ * Scripts/webkitpy/common/config/committers.py:
+
+2012-02-07 Nikolas Zimmermann <nzimmermann@rim.com>
+
+ layoutTestController.display() is flaky for SVG tests
+ https://bugs.webkit.org/show_bug.cgi?id=78021
+
+ Reviewed by Dan Bernstein.
+
+ Fix race condition in repaint rect tracking. When running a test using the repaint.js
+ harness right after a test starting with "svg/W3C-SVG-1.1" the repaint test will fail,
+ the gray overlay isn't contained in the pixel dump anymore. This is because of a specific
+ hack that forces 480x360 instead of 800x600 pixel test dumps for any test starting with
+ svg/W3C-SVG-1.1. The resizing of the web view was done when dumping the render tree, after
+ the repaint test already run, thus invalidating the previously tracked repaint rects.
+
+ * DumpRenderTree/mac/DumpRenderTree.mm:
+ (dump):
+ (runTest):
+
+2012-02-07 Hans Wennborg <hans@chromium.org>
+
+ Chromium: remove WebSpeechInputResult::set
+ https://bugs.webkit.org/show_bug.cgi?id=77977
+
+ Reviewed by Darin Fisher.
+
+ It was renamed to assign() in r106475.
+
+ * DumpRenderTree/chromium/MockWebSpeechInputController.cpp:
+ (makeRectResult):
+
+2012-02-07 Allan Sandfeld Jensen <allan.jensen@nokia.com>
+
+ [Qt] Give emulated touch-point a radius
+ https://bugs.webkit.org/show_bug.cgi?id=77985
+
+ Increase the radius of touch-point and show the actual size of the touch point in the touch-point mockup.
+
+ Reviewed by Kenneth Rohde Christiansen.
+
+ * MiniBrowser/qt/BrowserWindow.cpp:
+ (BrowserWindow::updateVisualMockTouchPoints):
+ * MiniBrowser/qt/MiniBrowserApplication.cpp:
+ (MiniBrowserApplication::notify):
+ * MiniBrowser/qt/qml/MockTouchPoint.qml:
+
+2012-02-07 Mario Sanchez Prada <msanchez@igalia.com>
+
+ [GTK] Include gdk-pixbuf in the jhbuild modules
+ https://bugs.webkit.org/show_bug.cgi?id=77980
+
+ Reviewed by Gustavo Noronha Silva.
+
+ * gtk/jhbuild.modules: Add gdk-pixbuf to the jhbuild moduleset.
+
+2012-02-07 Simon Hausmann <simon.hausmann@nokia.com>
+
+ [Qt] Prevent early test termination with newer Qt 5
+ https://bugs.webkit.org/show_bug.cgi?id=77945
+
+ Reviewed by Csaba Osztrogonác.
+
+ QTBUG-24120 tracks a regression in Qt that would make layout tests
+ terminate early. This patch works around it in a Qt 4 + 5 safe manner
+ by disabling the quitOnLastWindowClosed feature, which we don't want/need
+ for DRT anyway.
+
+ * DumpRenderTree/qt/main.cpp:
+ (main): Don't quit on last window closed.
+
+2012-02-06 Martin Robinson <mrobinson@igalia.com>
+
+ Fix some miscellaneous 'make dist' error for WebKitGTK+.
+
+ * MiniBrowser/gtk/GNUmakefile.am: The MiniBrowser generated
+ files should not be distributed.
+
+2012-02-02 Hajime Morrita <morrita@chromium.org>
+
+ [PerformanceTests] Each Dromaeo test needs its landing html.
+ https://bugs.webkit.org/show_bug.cgi?id=77504
+
+ Reviewed by Ryosuke Niwa.
+
+ Added an ignorable pattern which happens in some Dromaeo tests.
+
+ * Scripts/webkitpy/performance_tests/perftestsrunner.py:
+ (PerfTestsRunner):
+
+2012-02-06 Kalev Lember <kalevlember@gmail.com>
+
+ [GTK] Add missing pango include dir to fix build
+ https://bugs.webkit.org/show_bug.cgi?id=77832
+
+ Reviewed by Martin Robinson.
+
+ * GNUmakefile.am: Added $(PANGO_CFLAGS) to libWebCoreInternals_la_CPPFLAGS.
+
+2012-02-06 Martin Robinson <mrobinson@igalia.com>
+
+ [GTK] Fix remaining errors in GTK+ WebKit2 API
+ https://bugs.webkit.org/show_bug.cgi?id=77890
+
+ Reviewed by Gustavo Noronha Silva.
+
+ Verify that WebKit2 GTK+ test files are not skipped during style checks.
+ Skip soup_server_new when checking for NULL versus 0 usage.
+
+ * Scripts/webkitpy/style/checker_unittest.py:
+ (CheckerDispatcherSkipTest.test_should_skip_with_warning):
+ * Scripts/webkitpy/style/checkers/cpp.py:
+ (check_for_null):
+
+2012-02-06 Eric Seidel <eric@webkit.org>
+
+ webkit-patch apply-from-bug should be able to apply non-reviewed patches
+ https://bugs.webkit.org/show_bug.cgi?id=77883
+
+ Reviewed by Adam Barth.
+
+ This is very helpful if you use bugzilla as a replacement for git-stash.
+ Makes it simpler to re-apply the patch w/o having to look up the patch id.
+
+ * Scripts/webkitpy/tool/commands/download.py:
+ (ProcessBugsMixin._fetch_list_of_patches_to_process):
+ * Scripts/webkitpy/tool/commands/download_unittest.py:
+ (DownloadCommandsTest.test_apply_from_bug):
+
+2012-02-06 Philippe Normand <pnormand@igalia.com>
+
+ [webkitpy] cpp style-checker complains about readability/naming in GStreamer elements source files
+ https://bugs.webkit.org/show_bug.cgi?id=77866
+
+ Reviewed by Martin Robinson.
+
+ * Scripts/webkitpy/style/checker.py: Ignore readability/naming
+ errors in some gstreamer source code files defining new GStreamer elements.
+ * Scripts/webkitpy/style/checker_unittest.py:
+ (GlobalVariablesTest.test_path_rules_specifier):
+
+2012-02-06 Carlos Garcia Campos <cgarcia@igalia.com>
+
+ [GTK] Make sure html_dir exists before calling gtkdoc-rebase
+ https://bugs.webkit.org/show_bug.cgi?id=77869
+
+ Reviewed by Philippe Normand.
+
+ * gtk/gtkdoc.py:
+ (GTKDoc.rebase_installed_docs): Check html_dir exists.
+
+2012-02-03 Jocelyn Turcotte <jocelyn.turcotte@nokia.com>
+
+ [Qt] Don't version QtWebKit.experimental.
+ https://bugs.webkit.org/show_bug.cgi?id=77739
+
+ Reviewed by Tor Arne Vestbø.
+
+ * MiniBrowser/qt/qml/BrowserWindow.qml:
+
+2012-02-06 Carlos Garcia Campos <cgarcia@igalia.com>
+
+ [GTK] Fix several gtkdoc-fixxref warnings
+ https://bugs.webkit.org/show_bug.cgi?id=77613
+
+ Reviewed by Martin Robinson.
+
+ * gtk/generate-gtkdoc:
+ (get_webkit1_options): Add webkitspellcheckerenchant.* to the list
+ of ignored files, since it's private.
+ * gtk/gtkdoc.py:
+ (GTKDoc._ignored_files_basenames): Helper function that returns a
+ string with the list of ignored files basenames separated by a
+ spaces, as expected by several gtkdoc commands.
+ (GTKDoc._run_gtkdoc_scan): Use _ignored_files_basenames for
+ --ignore-headers option.
+ (GTKDoc._run_gtkdoc_mkdb): Use _ignored_files_basenames for
+ --ignore-files option.
+
+2012-02-06 Carlos Garcia Campos <cgarcia@igalia.com>
+
+ [GTK] Fix xrefs after installing API documentation
+ https://bugs.webkit.org/show_bug.cgi?id=77551
+
+ Reviewed by Martin Robinson.
+
+ * GNUmakefile.am: Call generate-gtkdoc --rebase after installing
+ api docs.
+ * gtk/common.py:
+ (prefix_of_pkg_config_file): Get the prefix variable of the given
+ pkg-config file.
+ (gtk_version_of_pkg_config_file): Get the gtk version required by
+ the given pkg-config file.
+ * gtk/generate-gtkdoc: Add --rebase command line option to rebase
+ installed documentation.
+ (get_gtkdoc_module_paths): Get paths where API doc is installed
+ for the dependencies of the given pkg-config file.
+ (get_common_xref_deps): Get API doc directories of dependencies
+ common to WebKit1 and WebKit2.
+ (get_webkit2_options): Add cross_reference_deps option.
+ (get_webkit1_options): Ditto
+ (rebase_installed_docs): Helper function to create a generator for
+ the given pkg-config file and options and call rebase_installed_docs.
+ * gtk/gtkdoc.py:
+ (GTKDoc.__init__): Initialize cross_reference_deps.
+ (GTKDoc._run_gtkdoc_fixxref): Add API doc directories of
+ dependencies.
+ (GTKDoc.rebase_installed_docs): Call gtkdoc-rebase to fix xref
+ links of installed documentation.
+ (PkgConfigGTKDoc.__init__): Get the prefix from the pkg-config
+ file.
+
+2012-02-06 Sergio Villar Senin <svillar@igalia.com>
+
+ Incorrect statistics shown when running run-webkit-tests with --repeat-each or --iterations
+ https://bugs.webkit.org/show_bug.cgi?id=77672
+
+ Reviewed by Dirk Pranke.
+
+ Test repetitions must be taken into account when working out
+ the statistics shown by run-webkit-tests.
+
+ * Scripts/webkitpy/layout_tests/controllers/manager.py:
+ (Manager.prepare_lists_and_print_output):
+ (Manager._print_result_summary):
+ * Scripts/webkitpy/layout_tests/models/result_summary.py:
+ (ResultSummary.__init__):
+ (ResultSummary.add):
+ * Scripts/webkitpy/layout_tests/run_webkit_tests_integrationtest.py:
+ (MainTest.test_repeat_each_iterations_num_tests):
+
+2012-02-05 Dan Bernstein <mitz@apple.com>
+
+ <rdar://problem/10809525> WebKit2’s WebFrameLoaderClient::shouldUseCredentialStorage() always returns true
+ https://bugs.webkit.org/show_bug.cgi?id=77823
+
+ Reviewed by Anders Carlsson.
+
+ * WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp:
+ (WTR::InjectedBundlePage::InjectedBundlePage): Updated for the additional callback.
+
+2012-02-04 Dan Bernstein <mitz@apple.com>
+
+ <rdar://problem/10660698> Clients cannot prevent caching of individual responses
+ https://bugs.webkit.org/show_bug.cgi?id=77822
+
+ Reviewed by Sam Weinig.
+
+ * WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp:
+ (WTR::InjectedBundlePage::InjectedBundlePage): Updated for the additional callback.
+
+2012-02-04 Sam Weinig <sam@webkit.org>
+
+ Add ability to send WKURLRequests in WebKit2 API user messages
+ https://bugs.webkit.org/show_bug.cgi?id=77819
+
+ Reviewed by Anders Carlsson.
+
+ Add testing for round-tripping WKTypes from the UIProcess,
+ to the WebProcess, and back.
+
+ - This commit adds a test fixture and tests for WKURLRequestRef, WKURLRef, and WKStringRef.
+ More can easily be added.
+
+ * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+ * TestWebKitAPI/Tests/WebKit2/UserMessage.cpp: Added.
+ (TestWebKitAPI):
+ (WebKit2UserMessageRoundTripTest):
+ (TestWebKitAPI::WebKit2UserMessageRoundTripTest::WebKit2UserMessageRoundTripTest):
+ (TestWebKitAPI::WebKit2UserMessageRoundTripTest::didReceiveMessageFromInjectedBundle):
+ (TestWebKitAPI::WebKit2UserMessageRoundTripTest::didFinishLoadForFrame):
+ (TestWebKitAPI::WebKit2UserMessageRoundTripTest::setInjectedBundleClient):
+ (TestWebKitAPI::WebKit2UserMessageRoundTripTest::setPageLoaderClient):
+ (TestWebKitAPI::WebKit2UserMessageRoundTripTest::SetUp):
+ (TestWebKitAPI::WebKit2UserMessageRoundTripTest::roundTrip):
+ (TestWebKitAPI::TEST_F):
+ * TestWebKitAPI/Tests/WebKit2/UserMessage_Bundle.cpp: Added.
+ (TestWebKitAPI):
+ (UserMessageTest):
+ (TestWebKitAPI::UserMessageTest::UserMessageTest):
+ (TestWebKitAPI::UserMessageTest::didReceiveMessage):
+ * TestWebKitAPI/mac/PlatformWebViewMac.mm:
+ (TestWebKitAPI::PlatformWebView::resizeTo):
+ (TestWebKitAPI):
+ * TestWebKitAPI/win/TestWebKitAPI.vcproj:
+ * TestWebKitAPI/win/TestWebKitAPIInjectedBundle.vcproj:
+
+2012-02-04 Dan Bernstein <mitz@apple.com>
+
+ <rdar://problem/10772406> WKPreferences instances cannot be copied
+ https://bugs.webkit.org/show_bug.cgi?id=77816
+
+ Reviewed by Sam Weinig.
+
+ * TestWebKitAPI/Tests/WebKit2/WKPreferences.cpp:
+ (TestWebKitAPI::TEST):
+
+2012-02-04 Adam Barth <abarth@webkit.org>
+
+ garden-o-matic's All Failure tab should let you examine and rebaseline expected failures
+ https://bugs.webkit.org/show_bug.cgi?id=77802
+
+ Reviewed by Eric Seidel.
+
+ This patch refactors our directory grouping code into base.js where it
+ can be shared between failures.js and notifications.js. It then adds
+ an Examine action to each group of failures that triggers the "results"
+ view.
+
+ * BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/base.js:
+ * BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/controllers.js:
+ * BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui/failures.js:
+ * BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui/notifications.js:
+ * BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui/notifications_unittests.js:
+ * BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/styles/failures.css:
+
+2012-02-04 Ojan Vafai <ojan@chromium.org>
+
+ check-webkit-style is throwing an exception
+ https://bugs.webkit.org/show_bug.cgi?id=77744
+
+ Reviewed by David Levin.
+
+ If the test_list is None, then we don't need to check for unsupported
+ feature tests to skip.
+
+ * Scripts/webkitpy/layout_tests/port/webkit.py:
+ (WebKitPort._has_test_in_directories):
+ * Scripts/webkitpy/layout_tests/port/webkit_unittest.py:
+ (test_skipped_tests_for_unsupported_features_empty_test_list):
+
+2012-02-03 Adam Barth <abarth@webkit.org>
+
+ List of all failures in garden-o-matic should actually list all the failures
+ https://bugs.webkit.org/show_bug.cgi?id=77796
+
+ Reviewed by Eric Seidel.
+
+ This patch wires a bit more data into the new "All Failures" tab. I've
+ also iterated on how we enable this experimental feature. The tab is
+ still just a dumb list, but we'll make it smarter.
+
+ * BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/controllers.js:
+ * BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/garden-o-matic.js:
+ * BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui.js:
+ * BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui/failures.js:
+
+2012-02-03 Ryosuke Niwa <rniwa@webkit.org>
+
+ Windows build fix after r106692.
+
+ * Scripts/webkitpy/layout_tests/port/base_unittest.py:
+ (PortTest.test_reference_files):
+
+2012-02-03 Beth Dakin <bdakin@apple.com>
+
+ https://bugs.webkit.org/show_bug.cgi?id=77782
+ WebPageProxy::didNewFirstVisuallyNonEmptyLayout should is called more than
+ once on some pages with frames
+ -and corresponding-
+ <rdar://problem/10798474>
+
+ Reviewed by Sam Weinig.
+
+ One new test.
+ * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+ * TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFrames.cpp: Added.
+ (TestWebKitAPI):
+ (TestWebKitAPI::didForceRepaint):
+ (TestWebKitAPI::didFinishLoadForFrame):
+ (TestWebKitAPI::didNewFirstVisuallyNonEmptyLayout):
+ (TestWebKitAPI::setPageLoaderClient):
+ (TestWebKitAPI::TEST):
+ * TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFrames_Bundle.cpp: Added.
+ (TestWebKitAPI):
+ (NewFirstVisuallyNonEmptyLayoutFramesTest):
+ (TestWebKitAPI::NewFirstVisuallyNonEmptyLayoutFramesTest::NewFirstVisuallyNonEmptyLayoutFramesTest):
+ (TestWebKitAPI::NewFirstVisuallyNonEmptyLayoutFramesTest::didCreatePage):
+ * TestWebKitAPI/Tests/WebKit2/lots-of-iframes.html: Added.
+
+2012-02-03 Dirk Pranke <dpranke@chromium.org>
+
+ webkitpy: change exit() calls to sys.exit(), fix a leak in outputcapture
+ https://bugs.webkit.org/show_bug.cgi?id=77781
+
+ Reviewed by Eric Seidel.
+
+ This change fixes a couple of issues discovered while debugging
+ test-webkitpy; both calling exit() instead of sys.exit() --
+ which is discouraged in program code instead of the interpreter
+ -- and a particular usage of outputcapture were stdin to get whacked
+ and preventing debugging.
+
+ This change introduces a couple of common _exit() methods that
+ will standardize how webkit-patch exit's, in case we need to do
+ something different in the future.
+
+ * Scripts/webkitpy/common/system/deprecated_logging.py:
+ (error):
+ * Scripts/webkitpy/common/system/outputcapture.py:
+ (OutputCapture.assert_outputs):
+ * Scripts/webkitpy/tool/bot/queueengine.py:
+ (QueueEngine.exit_after_handled_error):
+ * Scripts/webkitpy/tool/commands/abstractsequencedcommand.py:
+ (AbstractSequencedCommand.execute):
+ * Scripts/webkitpy/tool/commands/queues.py:
+ (StyleQueue.handle_script_error):
+ * Scripts/webkitpy/tool/commands/upload.py:
+ (MarkBugFixed.execute):
+ * Scripts/webkitpy/tool/multicommandtool.py:
+ (Command._exit):
+ * Scripts/webkitpy/tool/steps/abstractstep.py:
+ (AbstractStep._exit):
+ * Scripts/webkitpy/tool/steps/checkstyle.py:
+ (CheckStyle.run):
+ * Scripts/webkitpy/tool/steps/commit.py:
+ (Commit._check_test_expectations):
+ * Scripts/webkitpy/tool/steps/confirmdiff.py:
+ (ConfirmDiff.run):
+
+2012-02-03 Ryosuke Niwa <rniwa@webkit.org>
+
+ Perf bot build fix.
+
+ * Scripts/webkitpy/performance_tests/perftestsrunner.py:
+ (PerfTestsRunner._generate_json):
+
+2012-02-03 Adam Barth <abarth@webkit.org>
+
+ Add a blank "Expected Failures" tab to garden-o-matic
+ https://bugs.webkit.org/show_bug.cgi?id=77793
+
+ Reviewed by Eric Seidel.
+
+ This tab will help us explore and manage our expected failures. The
+ tab is hidden by default via a new "experimental features" flag.
+
+ * BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/config.js:
+ * BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/garden-o-matic.js:
+ * BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui.js:
+ * BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui/failures.js:
+ * BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/styles/onebar.css:
+ (#unexpected):
+ (#onebar.partytime #unexpected):
+
+2012-02-03 Lucas Forschler <lforschler@apple.com>
+
+ update-webkit-support-libraries is broken with the change from http to https on developer.apple.com
+ https://bugs.webkit.org/show_bug.cgi?id=77785
+
+ Fix the build bots.
+
+ Pass the -k and --sslv3 keys to make curl work with https on https://developer.apple.com
+
+ * Scripts/update-webkit-support-libs:
+ (downloadExpectedVersionNumber):
+
+2012-02-03 Lucas Forschler <lforschler@apple.com>
+
+ Add a Mac Lion Performance bot.
+ https://bugs.webkit.org/show_bug.cgi?id=77765
+
+ Reviewed by Adam Roben.
+
+ This will update the master configuration in the following ways:
+ Add a new performance slave (apple-xseve-11)
+ Add a new Factory to download a build and run perf tests.
+
+ * BuildSlaveSupport/build.webkit.org-config/config.json:
+ * BuildSlaveSupport/build.webkit.org-config/master.cfg:
+ (DownloadAndPerfTestFactory):
+ (DownloadAndPerfTestFactory.__init__):
+
+2012-02-03 Dirk Pranke <dpranke@chromium.org>
+
+ Extra TestWebKitAPI.gyp/TestWebKitAPI.target.chromium.mk in repository
+ https://bugs.webkit.org/show_bug.cgi?id=77752
+
+ Reviewed by James Robinson.
+
+ Delete unneeded file accidentally checked in in r106481.
+
+ * TestWebKitAPI/TestWebKitAPI.gyp/TestWebKitAPI.target.chromium.mk: Removed.
+
+2012-02-03 Ryosuke Niwa <rniwa@webkit.org>
+
+ Ref Tests should support plain SVG files
+ https://bugs.webkit.org/show_bug.cgi?id=77685
+
+ Reviewed by Tony Chang.
+
+ Don't assume reference files always use .html as the extension.
+ Instead, use the list of supported extension to look for -expected.* and -mismatch.*
+
+ Also fix various bugs in MockFileSystem and TestPort.
+
+ * Scripts/webkitpy/common/system/filesystem_mock.py:
+ (MockFileSystem.isdir):
+ * Scripts/webkitpy/layout_tests/port/base.py:
+ (Port.reference_files):
+ * Scripts/webkitpy/layout_tests/port/base_unittest.py:
+ (PortTest.test_is_test_file):
+ (PortTest.test_reference_files):
+ * Scripts/webkitpy/layout_tests/port/test.py:
+ (TestInstance.__init__):
+
+2012-02-03 Ryosuke Niwa <rniwa@webkit.org>
+
+ perf-o-matic should store chromium svn revision
+ https://bugs.webkit.org/show_bug.cgi?id=77725
+
+ Reviewed by Dirk Pranke.
+
+ Report both WebKit and Chromium revisions to the graph server. Renamed test_repository_paths to
+ repository_paths since it's nothing to do with tests. Also refactored scm so that head_svn_revision
+ is implemented in terms of newly added svn_revision.
+
+ * Scripts/webkitpy/common/checkout/scm/git.py:
+ (Git.svn_revision):
+ * Scripts/webkitpy/common/checkout/scm/scm.py:
+ (SCM.head_svn_revision):
+ (SCM):
+ (SCM.svn_revision):
+ * Scripts/webkitpy/common/checkout/scm/scm_mock.py:
+ (MockSCM.svn_revision):
+ * Scripts/webkitpy/common/checkout/scm/svn.py:
+ (SVN.svn_revision):
+ * Scripts/webkitpy/layout_tests/layout_package/json_layout_results_generator.py:
+ (JSONLayoutResultsGenerator.__init__):
+ * Scripts/webkitpy/layout_tests/layout_package/json_results_generator.py:
+ (JSONResultsGeneratorBase._insert_generic_metadata):
+ * Scripts/webkitpy/layout_tests/port/base.py:
+ (Port.repository_paths):
+ * Scripts/webkitpy/layout_tests/port/chromium.py:
+ (ChromiumPort.repository_paths):
+ * Scripts/webkitpy/performance_tests/perftestsrunner.py:
+ (PerfTestsRunner._generate_json):
+ * Scripts/webkitpy/performance_tests/perftestsrunner_unittest.py:
+ (test_run_test_set_with_json_output):
+ (test_run_test_set_with_json_source):
+ (test_run_test_set_with_multiple_repositories):
+
+2012-02-03 Jocelyn Turcotte <jocelyn.turcotte@nokia.com>
+
+ [Qt] Split QQuickWebViewPrivate in two classes, for desktop and touch behavior.
+ https://bugs.webkit.org/show_bug.cgi?id=77632
+
+ Reviewed by Kenneth Rohde Christiansen.
+
+ * MiniBrowser/qt/BrowserWindow.cpp:
+ (BrowserWindow::BrowserWindow):
+ * MiniBrowser/qt/MiniBrowserApplication.cpp:
+ (MiniBrowserApplication::sendTouchEvent):
+ (MiniBrowserApplication::handleUserOptions):
+ * MiniBrowser/qt/MiniBrowserApplication.h:
+ (WindowOptions):
+ (WindowOptions::WindowOptions):
+ * WebKitTestRunner/qt/PlatformWebViewQt.cpp:
+ (WTR::PlatformWebView::PlatformWebView):
+ * WebKitTestRunner/qt/main.cpp:
+ (main):
+ * qmake/mkspecs/features/default_post.prf:
+
+2012-02-03 Simon Hausmann <simon.hausmann@nokia.com>
+
+ [Qt] Replace GNU linker script for exports with export macros in WTF/JSC
+ https://bugs.webkit.org/show_bug.cgi?id=77723
+
+ Reviewed by Tor Arne Vestbø.
+
+ * Tools.pro: Compile WTR again on all platforms with WK2.
+
+2012-02-03 Sriram Neelakandan <sriram.neelakandan@gmail.com>
+
+ Ensure that inspector disabled build works
+ https://bugs.webkit.org/show_bug.cgi?id=77604
+
+ Reviewed by Tor Arne Vestbø.
+
+ * qmake/mkspecs/features/features.prf:
+
+2012-02-02 Jochen Eisinger <jochen@chromium.org>
+
+ [chromium] add support for --makeargs to the ninja-based build
+ https://bugs.webkit.org/show_bug.cgi?id=77688
+
+ Reviewed by Adam Barth.
+
+ * Scripts/webkitdirs.pm:
+ (buildChromiumNinja):
+
+2012-02-02 Eric Seidel <eric@webkit.org>
+
+ Run tests in serial on SnowLeopard to avoid CFURLCache crashes
+ https://bugs.webkit.org/show_bug.cgi?id=75145
+
+ Reviewed by Dirk Pranke.
+
+ * Scripts/webkitpy/layout_tests/port/mac.py:
+ (MacPort.default_child_processes):
+ * Scripts/webkitpy/layout_tests/port/mac_unittest.py:
+ (test_operating_system):
+ (test_default_child_processes):
+
+2012-02-02 Dirk Pranke <dpranke@chromium.org>
+
+ nrwt shouldn't blow up when there are errors in test_expectations.txt
+ https://bugs.webkit.org/show_bug.cgi?id=73603
+
+ Reviewed by Ojan Vafai.
+
+ This change removes the distinction between 'errors' and 'warnings'
+ in the test expectations parser. Now, any problem is a
+ 'warning', and if we are linting the file, warnings become fatal (errors).
+
+ This will allow a normal run-webkit-tests run to proceed even if
+ there are bad lines.
+
+ * Scripts/webkitpy/layout_tests/models/test_expectations.py:
+ (ParseError.__init__):
+ (ParseError.__str__):
+ (ParseError.__repr__):
+ (TestExpectationSerializer.to_string):
+ (TestExpectationParser._parse_modifiers):
+ (TestExpectationParser._parse_expectations):
+ (TestExpectationParser._check_modifiers_against_expectations):
+ (TestExpectationParser._tokenize):
+ (TestExpectationLine.__init__):
+ (TestExpectationLine.is_invalid):
+ (TestExpectationsModel.add_expectation_line):
+ (TestExpectationsModel._already_seen_better_match):
+ (TestExpectations.__init__):
+ (TestExpectations._report_warnings):
+ (TestExpectations.remove_rebaselined_tests.without_rebaseline_modifier):
+ * Scripts/webkitpy/layout_tests/models/test_expectations_unittest.py:
+ (assert_bad_expectations):
+ (test_parse_warning):
+ (test_overrides__duplicate):
+ (ExpectationSyntaxTests.test_missing_expectation):
+ (ExpectationSyntaxTests.test_missing_colon):
+ (ExpectationSyntaxTests.test_too_many_colons):
+ (ExpectationSyntaxTests.test_too_many_equals_signs):
+ (ExpectationSyntaxTests.test_unrecognized_expectation):
+ (SemanticTests.test_bug_format):
+ (SemanticTests.test_bad_bugid):
+ (SemanticTests.test_slow_and_timeout):
+ (test_ambiguous):
+ (test_more_modifiers):
+ (test_order_in_file):
+ (test_macro_overrides):
+ (RebaseliningTest.assertRemove):
+ (TestExpectationParserTests.test_tokenize_blank):
+ (TestExpectationParserTests.test_tokenize_missing_colon):
+ (TestExpectationParserTests.test_tokenize_extra_colon):
+ (TestExpectationParserTests.test_tokenize_empty_comment):
+ (TestExpectationParserTests.test_tokenize_comment):
+ (TestExpectationParserTests.test_tokenize_missing_equal):
+ (TestExpectationParserTests.test_tokenize_extra_equal):
+ (TestExpectationParserTests.test_tokenize_valid):
+ (TestExpectationParserTests.test_tokenize_valid_with_comment):
+ (TestExpectationParserTests.test_tokenize_valid_with_multiple_modifiers):
+ (TestExpectationSerializerTests.test_unparsed_to_string):
+ * Scripts/webkitpy/layout_tests/run_webkit_tests.py:
+ (lint):
+ * Scripts/webkitpy/style/checkers/test_expectations.py:
+ (TestExpectationsChecker.check_test_expectations):
+
+2012-02-02 Sheriff Bot <webkit.review.bot@gmail.com>
+
+ Unreviewed, rolling out r106543.
+ http://trac.webkit.org/changeset/106543
+ https://bugs.webkit.org/show_bug.cgi?id=77671
+
+ Made tests less stable (Requested by rniwa on #webkit).
+
+ * Scripts/webkitpy/performance_tests/perftestsrunner.py:
+ (PerfTestsRunner):
+ (PerfTestsRunner.__init__):
+ (PerfTestsRunner._run_tests_set):
+ (PerfTestsRunner._run_single_test):
+ * Scripts/webkitpy/performance_tests/perftestsrunner_unittest.py:
+ (MainTest.TestDriver.run_test):
+ (run_test):
+
+2012-02-02 Beth Dakin <bdakin@apple.com>
+
+ https://bugs.webkit.org/show_bug.cgi?id=77664
+ Add API tests for didNewFirstVisuallyNonEmptyLayout
+
+ Reviewed by Darin Adler.
+
+ Two new tests.
+ * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+ * TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayout.cpp: Added.
+ (TestWebKitAPI):
+ (TestWebKitAPI::didNewFirstVisuallyNonEmptyLayout):
+ (TestWebKitAPI::setPageLoaderClient):
+ (TestWebKitAPI::TEST):
+ * TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFails.cpp: Added.
+ (TestWebKitAPI):
+ (TestWebKitAPI::didForceRepaint):
+ (TestWebKitAPI::didFinishLoadForFrame):
+ (TestWebKitAPI::didNewFirstVisuallyNonEmptyLayout):
+ (TestWebKitAPI::setPageLoaderClient):
+ (TestWebKitAPI::TEST):
+ * TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFails_Bundle.cpp: Added.
+ (TestWebKitAPI):
+ (NewFirstVisuallyNonEmptyLayoutFailsTest):
+ (TestWebKitAPI::NewFirstVisuallyNonEmptyLayoutFailsTest::NewFirstVisuallyNonEmptyLayoutFailsTest):
+ (TestWebKitAPI::NewFirstVisuallyNonEmptyLayoutFailsTest::didCreatePage):
+ * TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayout_Bundle.cpp: Added.
+ (TestWebKitAPI):
+ (NewFirstVisuallyNonEmptyLayoutTest):
+ (TestWebKitAPI::NewFirstVisuallyNonEmptyLayoutTest::NewFirstVisuallyNonEmptyLayoutTest):
+ (TestWebKitAPI::NewFirstVisuallyNonEmptyLayoutTest::didCreatePage):
+
+2012-02-02 Michael Saboff <msaboff@apple.com>
+
+ Add Michael Saboff to reviewers list.
+
+ Rubber-stamped by Gavin Barraclough.
+
+ * Scripts/webkitpy/common/config/committers.py:
+
2012-02-02 Kristóf Kosztyó <kkristof@inf.u-szeged.hu>
Add myself as a committer
diff --git a/Tools/DumpRenderTree/blackberry/AccessibilityControllerBlackBerry.cpp b/Tools/DumpRenderTree/blackberry/AccessibilityControllerBlackBerry.cpp
new file mode 100644
index 000000000..1fe2ea85e
--- /dev/null
+++ b/Tools/DumpRenderTree/blackberry/AccessibilityControllerBlackBerry.cpp
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2010, 2012 Research In Motion Limited. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+#include "AccessibilityController.h"
+
+#include "AccessibilityUIElement.h"
+#include "NotImplemented.h"
+
+AccessibilityController::AccessibilityController()
+{
+}
+
+AccessibilityController::~AccessibilityController()
+{
+}
+
+AccessibilityUIElement AccessibilityController::focusedElement()
+{
+ notImplemented();
+ return 0;
+}
+
+AccessibilityUIElement AccessibilityController::rootElement()
+{
+ notImplemented();
+ return 0;
+}
+
+void AccessibilityController::setLogFocusEvents(bool)
+{
+ notImplemented();
+}
+
+void AccessibilityController::setLogScrollingStartEvents(bool)
+{
+ notImplemented();
+}
+
+void AccessibilityController::setLogValueChangeEvents(bool)
+{
+ notImplemented();
+}
+
+AccessibilityUIElement AccessibilityController::elementAtPoint(int, int)
+{
+ notImplemented();
+ return 0;
+}
+
+void AccessibilityController::setLogAccessibilityEvents(bool)
+{
+ notImplemented();
+}
+
+void AccessibilityController::addNotificationListener(PlatformUIElement, JSObjectRef)
+{
+ notImplemented();
+}
+
+void AccessibilityController::notificationReceived(PlatformUIElement, const std::string&)
+{
+ notImplemented();
+}
+
diff --git a/Tools/DumpRenderTree/blackberry/AccessibilityUIElementBlackBerry.cpp b/Tools/DumpRenderTree/blackberry/AccessibilityUIElementBlackBerry.cpp
new file mode 100644
index 000000000..d363e79cb
--- /dev/null
+++ b/Tools/DumpRenderTree/blackberry/AccessibilityUIElementBlackBerry.cpp
@@ -0,0 +1,612 @@
+/*
+ * Copyright (C) 2010, 2012 Research In Motion Limited. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+#include "AccessibilityUIElement.h"
+
+#include "NotImplemented.h"
+
+AccessibilityUIElement::AccessibilityUIElement(PlatformUIElement element)
+ : m_element(element)
+{
+}
+
+AccessibilityUIElement::AccessibilityUIElement(const AccessibilityUIElement& other)
+ : m_element(other.m_element)
+{
+}
+
+AccessibilityUIElement::~AccessibilityUIElement()
+{
+}
+
+void AccessibilityUIElement::getLinkedUIElements(Vector<AccessibilityUIElement>&)
+{
+ notImplemented();
+}
+
+void AccessibilityUIElement::getDocumentLinks(Vector<AccessibilityUIElement>&)
+{
+ notImplemented();
+}
+
+void AccessibilityUIElement::getChildren(Vector<AccessibilityUIElement>&)
+{
+ notImplemented();
+}
+
+void AccessibilityUIElement::getChildrenWithRange(Vector<AccessibilityUIElement>&, unsigned, unsigned)
+{
+ notImplemented();
+}
+
+int AccessibilityUIElement::childrenCount()
+{
+ notImplemented();
+ return 0;
+}
+
+AccessibilityUIElement AccessibilityUIElement::elementAtPoint(int, int)
+{
+ notImplemented();
+ return 0;
+}
+
+AccessibilityUIElement AccessibilityUIElement::getChildAtIndex(unsigned)
+{
+ notImplemented();
+ return 0;
+}
+
+AccessibilityUIElement AccessibilityUIElement::linkedUIElementAtIndex(unsigned)
+{
+ notImplemented();
+ return 0;
+}
+
+JSStringRef AccessibilityUIElement::allAttributes()
+{
+ notImplemented();
+ return 0;
+}
+
+JSStringRef AccessibilityUIElement::attributesOfLinkedUIElements()
+{
+ notImplemented();
+ return 0;
+}
+
+JSStringRef AccessibilityUIElement::attributesOfDocumentLinks()
+{
+ notImplemented();
+ return 0;
+}
+
+AccessibilityUIElement AccessibilityUIElement::titleUIElement()
+{
+ notImplemented();
+ return 0;
+}
+
+AccessibilityUIElement AccessibilityUIElement::parentElement()
+{
+ notImplemented();
+ return 0;
+}
+
+JSStringRef AccessibilityUIElement::attributesOfChildren()
+{
+ notImplemented();
+ return 0;
+}
+
+JSStringRef AccessibilityUIElement::parameterizedAttributeNames()
+{
+ notImplemented();
+ return 0;
+}
+
+JSStringRef AccessibilityUIElement::role()
+{
+ notImplemented();
+ return 0;
+}
+
+JSStringRef AccessibilityUIElement::subrole()
+{
+ notImplemented();
+ return 0;
+}
+
+JSStringRef AccessibilityUIElement::roleDescription()
+{
+ notImplemented();
+ return 0;
+}
+
+JSStringRef AccessibilityUIElement::title()
+{
+ notImplemented();
+ return 0;
+}
+
+JSStringRef AccessibilityUIElement::description()
+{
+ notImplemented();
+ return 0;
+}
+
+JSStringRef AccessibilityUIElement::stringValue()
+{
+ notImplemented();
+ return 0;
+}
+
+JSStringRef AccessibilityUIElement::language()
+{
+ notImplemented();
+ return 0;
+}
+
+double AccessibilityUIElement::x()
+{
+ notImplemented();
+ return 0;
+}
+
+double AccessibilityUIElement::y()
+{
+ notImplemented();
+ return 0;
+}
+
+double AccessibilityUIElement::width()
+{
+ notImplemented();
+ return 0;
+}
+
+double AccessibilityUIElement::height()
+{
+ notImplemented();
+ return 0;
+}
+
+double AccessibilityUIElement::clickPointX()
+{
+ notImplemented();
+ return 0;
+}
+
+double AccessibilityUIElement::clickPointY()
+{
+ notImplemented();
+ return 0;
+}
+
+JSStringRef AccessibilityUIElement::orientation() const
+{
+ notImplemented();
+ return 0;
+}
+
+double AccessibilityUIElement::minValue()
+{
+ notImplemented();
+ return 0;
+}
+
+double AccessibilityUIElement::maxValue()
+{
+ notImplemented();
+ return 0;
+}
+
+JSStringRef AccessibilityUIElement::valueDescription()
+{
+ notImplemented();
+ return 0;
+}
+
+bool AccessibilityUIElement::isEnabled()
+{
+ notImplemented();
+ return 0;
+}
+
+int AccessibilityUIElement::insertionPointLineNumber()
+{
+ notImplemented();
+ return 0;
+}
+
+bool AccessibilityUIElement::isActionSupported(JSStringRef)
+{
+ notImplemented();
+ return 0;
+}
+
+bool AccessibilityUIElement::isRequired() const
+{
+ notImplemented();
+ return 0;
+}
+
+bool AccessibilityUIElement::isSelected() const
+{
+ notImplemented();
+ return 0;
+}
+
+int AccessibilityUIElement::hierarchicalLevel() const
+{
+ notImplemented();
+ return 0;
+}
+
+bool AccessibilityUIElement::ariaIsGrabbed() const
+{
+ notImplemented();
+ return 0;
+}
+
+JSStringRef AccessibilityUIElement::ariaDropEffects() const
+{
+ notImplemented();
+ return 0;
+}
+
+bool AccessibilityUIElement::isExpanded() const
+{
+ notImplemented();
+ return 0;
+}
+
+JSStringRef AccessibilityUIElement::attributesOfColumnHeaders()
+{
+ notImplemented();
+ return 0;
+}
+
+JSStringRef AccessibilityUIElement::attributesOfRowHeaders()
+{
+ notImplemented();
+ return 0;
+}
+
+JSStringRef AccessibilityUIElement::attributesOfColumns()
+{
+ notImplemented();
+ return 0;
+}
+
+JSStringRef AccessibilityUIElement::attributesOfRows()
+{
+ notImplemented();
+ return 0;
+}
+
+JSStringRef AccessibilityUIElement::attributesOfVisibleCells()
+{
+ notImplemented();
+ return 0;
+}
+
+JSStringRef AccessibilityUIElement::attributesOfHeader()
+{
+ notImplemented();
+ return 0;
+}
+
+int AccessibilityUIElement::indexInTable()
+{
+ notImplemented();
+ return 0;
+}
+
+JSStringRef AccessibilityUIElement::rowIndexRange()
+{
+ notImplemented();
+ return 0;
+}
+
+JSStringRef AccessibilityUIElement::columnIndexRange()
+{
+ notImplemented();
+ return 0;
+}
+
+int AccessibilityUIElement::lineForIndex(int)
+{
+ notImplemented();
+ return 0;
+}
+
+JSStringRef AccessibilityUIElement::boundsForRange(unsigned, unsigned)
+{
+ notImplemented();
+ return 0;
+}
+
+JSStringRef AccessibilityUIElement::stringForRange(unsigned, unsigned)
+{
+ notImplemented();
+ return 0;
+}
+
+AccessibilityUIElement AccessibilityUIElement::uiElementForSearchPredicate(AccessibilityUIElement*, bool, JSStringRef, JSStringRef)
+{
+ notImplemented();
+ return 0;
+}
+
+AccessibilityUIElement AccessibilityUIElement::cellForColumnAndRow(unsigned, unsigned)
+{
+ notImplemented();
+ return 0;
+}
+
+JSStringRef AccessibilityUIElement::selectedTextRange()
+{
+ notImplemented();
+ return 0;
+}
+
+void AccessibilityUIElement::setSelectedTextRange(unsigned, unsigned)
+{
+ notImplemented();
+}
+
+bool AccessibilityUIElement::isAttributeSettable(JSStringRef)
+{
+ notImplemented();
+ return 0;
+}
+
+bool AccessibilityUIElement::isAttributeSupported(JSStringRef)
+{
+ notImplemented();
+ return 0;
+}
+
+void AccessibilityUIElement::increment()
+{
+ notImplemented();
+}
+
+void AccessibilityUIElement::decrement()
+{
+ notImplemented();
+}
+
+void AccessibilityUIElement::showMenu()
+{
+ notImplemented();
+}
+
+AccessibilityUIElement AccessibilityUIElement::disclosedRowAtIndex(unsigned)
+{
+ notImplemented();
+ return 0;
+}
+
+AccessibilityUIElement AccessibilityUIElement::ariaOwnsElementAtIndex(unsigned)
+{
+ notImplemented();
+ return 0;
+}
+
+AccessibilityUIElement AccessibilityUIElement::ariaFlowToElementAtIndex(unsigned)
+{
+ notImplemented();
+ return 0;
+}
+
+AccessibilityUIElement AccessibilityUIElement::selectedRowAtIndex(unsigned)
+{
+ notImplemented();
+ return 0;
+}
+
+AccessibilityUIElement AccessibilityUIElement::disclosedByRow()
+{
+ notImplemented();
+ return 0;
+}
+
+JSStringRef AccessibilityUIElement::accessibilityValue() const
+{
+ notImplemented();
+ return 0;
+}
+
+JSStringRef AccessibilityUIElement::documentEncoding()
+{
+ notImplemented();
+ return 0;
+}
+
+JSStringRef AccessibilityUIElement::documentURI()
+{
+ notImplemented();
+ return 0;
+}
+
+unsigned AccessibilityUIElement::indexOfChild(AccessibilityUIElement*)
+{
+ notImplemented();
+ return 0;
+}
+
+double AccessibilityUIElement::numberAttributeValue(JSStringRef)
+{
+ notImplemented();
+ return 0;
+}
+
+bool AccessibilityUIElement::boolAttributeValue(JSStringRef)
+{
+ notImplemented();
+ return 0;
+}
+
+JSStringRef AccessibilityUIElement::stringAttributeValue(JSStringRef)
+{
+ notImplemented();
+ return 0;
+}
+
+double AccessibilityUIElement::intValue() const
+{
+ notImplemented();
+ return 0;
+}
+
+bool AccessibilityUIElement::isChecked() const
+{
+ notImplemented();
+ return 0;
+}
+
+JSStringRef AccessibilityUIElement::url()
+{
+ notImplemented();
+ return 0;
+}
+
+
+bool AccessibilityUIElement::addNotificationListener(JSObjectRef)
+{
+ notImplemented();
+ return 0;
+}
+
+bool AccessibilityUIElement::isSelectable() const
+{
+ notImplemented();
+ return false;
+}
+
+bool AccessibilityUIElement::isMultiSelectable() const
+{
+ notImplemented();
+ return false;
+}
+
+bool AccessibilityUIElement::isVisible() const
+{
+ notImplemented();
+ return false;
+}
+
+bool AccessibilityUIElement::isOffScreen() const
+{
+ notImplemented();
+ return false;
+}
+
+bool AccessibilityUIElement::isCollapsed() const
+{
+ notImplemented();
+ return false;
+}
+
+bool AccessibilityUIElement::hasPopup() const
+{
+ notImplemented();
+ return false;
+}
+
+void AccessibilityUIElement::takeFocus()
+{
+ notImplemented();
+}
+
+void AccessibilityUIElement::takeSelection()
+{
+ notImplemented();
+}
+
+void AccessibilityUIElement::addSelection()
+{
+ notImplemented();
+}
+
+void AccessibilityUIElement::removeSelection()
+{
+ notImplemented();
+}
+
+int AccessibilityUIElement::columnCount()
+{
+ notImplemented();
+ return 0;
+}
+
+void AccessibilityUIElement::removeNotificationListener()
+{
+ notImplemented();
+}
+
+void AccessibilityUIElement::press()
+{
+ notImplemented();
+}
+
+int AccessibilityUIElement::rowCount()
+{
+ notImplemented();
+ return 0;
+}
+
+JSStringRef AccessibilityUIElement::helpText() const
+{
+ notImplemented();
+ return 0;
+}
+
+JSStringRef AccessibilityUIElement::attributedStringForRange(unsigned, unsigned)
+{
+ notImplemented();
+ return 0;
+}
+
+bool AccessibilityUIElement::attributedStringRangeIsMisspelled(unsigned, unsigned)
+{
+ notImplemented();
+ return 0;
+}
+
+bool AccessibilityUIElement::isIgnored() const
+{
+ notImplemented();
+ return false;
+}
+
+bool AccessibilityUIElement::isFocused() const
+{
+ notImplemented();
+ return false;
+}
+
+bool AccessibilityUIElement::isFocusable() const
+{
+ notImplemented();
+ return false;
+}
+
diff --git a/Tools/DumpRenderTree/blackberry/DumpRenderTree.cpp b/Tools/DumpRenderTree/blackberry/DumpRenderTree.cpp
new file mode 100644
index 000000000..fb52cfde9
--- /dev/null
+++ b/Tools/DumpRenderTree/blackberry/DumpRenderTree.cpp
@@ -0,0 +1,820 @@
+/*
+ * Copyright (C) 2009, 2010, 2011, 2012 Research In Motion Limited. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+#include "DumpRenderTree.h"
+
+#include "AccessibilityController.h"
+#include "BackForwardController.h"
+#include "BackForwardListImpl.h"
+#include "CString.h"
+#include "DatabaseTracker.h"
+#include "DocumentLoader.h"
+#include "DumpRenderTree/GCController.h"
+#include "DumpRenderTreeSupport.h"
+#include "EditingBehaviorTypes.h"
+#include "EditorClientBlackBerry.h"
+#include "EditorInsertAction.h"
+#include "Element.h"
+#include "EventSender.h"
+#include "Frame.h"
+#include "FrameLoaderTypes.h"
+#include "FrameTree.h"
+#include "FrameView.h"
+#include "HistoryItem.h"
+#include "IntSize.h"
+#include "LayoutTestController.h"
+#include "NotImplemented.h"
+#include "OwnArrayPtr.h"
+#include "Page.h"
+#include "PageGroup.h"
+#include "PixelDumpSupport.h"
+#include "PixelDumpSupportBlackBerry.h"
+#include "Range.h"
+#include "RenderTreeAsText.h"
+#include "ScriptController.h"
+#include "SecurityOrigin.h"
+#include "Settings.h"
+#include "TextAffinity.h"
+#include "Timer.h"
+#include "Vector.h"
+#include "WebCoreTestSupport.h"
+#include "WebPage.h"
+#include "WebPageClient.h"
+#include "WorkQueue.h"
+#include "WorkQueueItem.h"
+#include <WebSettings.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <wtf/NonCopyingSort.h>
+
+#define SDCARD_PATH "/developer"
+
+volatile bool testDone;
+
+RefPtr<LayoutTestController> gLayoutTestController;
+
+WebCore::Frame* mainFrame = 0;
+WebCore::Frame* topLoadingFrame = 0;
+bool waitForPolicy = false;
+
+// FIXME: Assuming LayoutTests has been copied to /developer/LayoutTests/
+static const char* const kSDCLayoutTestsURI = "file:///developer/LayoutTests/";
+static const char* httpTestSyntax = "http/tests/";
+static const char* httpPrefixURL = "http://127.0.0.1:8000/";
+
+using namespace std;
+
+static WTF::String drtAffinityDescription(WebCore::EAffinity affinity)
+{
+ if (affinity == WebCore::UPSTREAM)
+ return WTF::String("NSSelectionAffinityUpstream");
+ if (affinity == WebCore::DOWNSTREAM)
+ return WTF::String("NSSelectionAffinityDownstream");
+ return "";
+}
+
+static WTF::String drtDumpPath(WebCore::Node* node)
+{
+ WebCore::Node* parent = node->parentNode();
+ WTF::String str = WTF::String::format("%s", node->nodeName().utf8().data());
+ if (parent) {
+ str.append(" > ");
+ str.append(drtDumpPath(parent));
+ }
+ return str;
+}
+
+static WTF::String drtRangeDescription(WebCore::Range* range)
+{
+ if (!range)
+ return "(null)";
+ return WTF::String::format("range from %d of %s to %d of %s", range->startOffset(), drtDumpPath(range->startContainer()).utf8().data(), range->endOffset(), drtDumpPath(range->endContainer()).utf8().data());
+}
+
+static WTF::String drtFrameDescription(WebCore::Frame* frame)
+{
+ WTF::String name = frame->tree()->uniqueName().string();
+ if (frame == mainFrame) {
+ if (!name.isNull() && name.length())
+ return WTF::String::format("main frame \"%s\"", name.utf8().data());
+ return "main frame";
+ }
+ if (!name.isNull())
+ return WTF::String::format("frame \"%s\"", name.utf8().data());
+ return "frame (anonymous)";
+}
+
+static bool shouldLogFrameLoadDelegates(const WTF::String& url)
+{
+ return url.contains("loading/");
+}
+
+namespace BlackBerry {
+namespace WebKit {
+
+DumpRenderTree* DumpRenderTree::s_currentInstance = 0;
+bool DumpRenderTree::s_selectTrailingWhitespaceEnabled = false;
+
+static void createFile(const WTF::String& fileName)
+{
+ FILE* fd = fopen(fileName.utf8().data(), "wb");
+ fclose(fd);
+}
+
+DumpRenderTree::DumpRenderTree(BlackBerry::WebKit::WebPage* page)
+ : m_gcController(0)
+ , m_accessibilityController(0)
+ , m_page(page)
+ , m_dumpPixels(false)
+ , m_waitToDumpWatchdogTimer(this, &DumpRenderTree::waitToDumpWatchdogTimerFired)
+ , m_workTimer(this, &DumpRenderTree::processWork)
+ , m_acceptsEditing(true)
+{
+ WTF::String sdcardPath = SDCARD_PATH;
+ m_resultsDir = sdcardPath + "/results/";
+ m_indexFile = sdcardPath + "/index.drt";
+ m_doneFile = sdcardPath + "/done";
+ m_currentTestFile = sdcardPath + "/current.drt";
+ m_page->resetVirtualViewportOnCommitted(false);
+ m_page->setVirtualViewportSize(800, 600);
+ s_currentInstance = this;
+}
+
+DumpRenderTree::~DumpRenderTree()
+{
+ delete m_gcController;
+ delete m_accessibilityController;
+}
+
+void DumpRenderTree::runTest(const WTF::String& url)
+{
+ createFile(m_resultsDir + *m_currentTest + ".dump.crash");
+
+ mainFrame->loader()->stopForUserCancel();
+ resetToConsistentStateBeforeTesting();
+ if (shouldLogFrameLoadDelegates(url))
+ gLayoutTestController->setDumpFrameLoadCallbacks(true);
+ WTF::String stdoutFile = m_resultsDir + *m_currentTest + ".dump";
+ WTF::String stderrFile = m_resultsDir + *m_currentTest + ".stderr";
+
+ // FIXME: we should preserve the original stdout and stderr here but aren't doing
+ // that yet due to issues with dup, etc.
+ freopen(stdoutFile.utf8().data(), "wb", stdout);
+ freopen(stderrFile.utf8().data(), "wb", stderr);
+
+ FILE* current = fopen(m_currentTestFile.utf8().data(), "w");
+ fwrite(m_currentTest->utf8().data(), 1, m_currentTest->utf8().length(), current);
+ fclose(current);
+ m_page->load(url.utf8().data(), 0, false);
+}
+
+void DumpRenderTree::doneDrt()
+{
+ fclose(stdout);
+ fclose(stderr);
+
+ // Notify the external world that we're done.
+ createFile(m_doneFile);
+ (m_page->client())->notifyRunLayoutTestsFinished();
+}
+
+void DumpRenderTree::runRemainingTests()
+{
+ // FIXME: fflush should not be necessary but is temporarily required due to a bug in stdio output.
+ fflush(stdout);
+ fflush(stderr);
+
+ if (m_currentTest >= m_tests.end() - 1) {
+ doneDrt();
+ return;
+ }
+
+ m_currentTest++;
+ if (isHTTPTest(m_currentTest->utf8().data())) {
+ m_currentHttpTest = m_currentTest->utf8().data();
+ m_currentHttpTest.remove(0, strlen(httpTestSyntax));
+ runTest(httpPrefixURL + m_currentHttpTest);
+ } else
+ runTest(kSDCLayoutTestsURI + *m_currentTest);
+}
+
+void DumpRenderTree::resetToConsistentStateBeforeTesting()
+{
+ if (isHTTPTest(m_currentTest->utf8().data()))
+ gLayoutTestController = LayoutTestController::create(String(httpPrefixURL + *m_currentTest).utf8().data(), "");
+ else
+ gLayoutTestController = LayoutTestController::create(String(kSDCLayoutTestsURI + *m_currentTest).utf8().data(), "");
+
+ gLayoutTestController->setIconDatabaseEnabled(false);
+
+ DumpRenderTreeSupport::resetGeolocationMock(m_page);
+
+ topLoadingFrame = 0;
+ m_loadFinished = false;
+ s_selectTrailingWhitespaceEnabled = false;
+
+ testDone = false;
+ WorkQueue::shared()->clear();
+ WorkQueue::shared()->setFrozen(false);
+
+ WebSettings* settings = m_page->settings();
+
+ settings->setTextReflowMode(WebSettings::TextReflowDisabled);
+ settings->setJavaScriptEnabled(true);
+ settings->setLoadsImagesAutomatically(true);
+ settings->setJavaScriptOpenWindowsAutomatically(true);
+ settings->setZoomToFitOnLoad(false);
+ settings->setDefaultFontSize(16);
+ settings->setDefaultFixedFontSize(13);
+ settings->setMinimumFontSize(1);
+ settings->setSerifFontFamily("Times");
+ settings->setFixedFontFamily("Courier New");
+ settings->setSansSerifFontFamily("Arial");
+ settings->setStandardFontFamily("Times");
+ settings->setXSSAuditorEnabled(false);
+ settings->setFrameFlatteningEnabled(false);
+ settings->setMaximumPagesInCache(0);
+ settings->setPluginsEnabled(true);
+ settings->setUserScalable(true);
+ // Apply new settings to current page, see more in the destructor of WebSettingsTransaction.
+ WebSettingsTransaction webSettingTransaction(settings);
+
+ BlackBerry::WebKit::DumpRenderTree::currentInstance()->page()->clearBackForwardList(false);
+
+ setAcceptsEditing(true);
+ DumpRenderTreeSupport::setLinksIncludedInFocusChain(true);
+
+ m_page->setVirtualViewportSize(800, 600);
+ m_page->resetVirtualViewportOnCommitted(false);
+ m_page->setJavaScriptCanAccessClipboard(true);
+
+ mainFrame = m_page->mainFrame();
+ if (mainFrame) {
+ mainFrame->page()->setTabKeyCyclesThroughElements(true);
+ mainFrame->page()->settings()->setEditingBehaviorType(WebCore::EditingUnixBehavior);
+ mainFrame->page()->settings()->setDOMPasteAllowed(true);
+ mainFrame->page()->settings()->setValidationMessageTimerMagnification(-1);
+ mainFrame->page()->settings()->setInteractiveFormValidationEnabled(true);
+ mainFrame->page()->settings()->setAllowFileAccessFromFileURLs(true);
+ mainFrame->page()->settings()->setAllowUniversalAccessFromFileURLs(true);
+ mainFrame->page()->settings()->setAuthorAndUserStylesEnabled(true);
+ mainFrame->page()->settings()->setUsePreHTML5ParserQuirks(false);
+ mainFrame->tree()->clearName();
+ mainFrame->loader()->setOpener(0);
+ // FIXME: Other ports also clear history/backForwardList allong with visited links.
+ mainFrame->page()->group().removeVisitedLinks();
+ }
+
+ // For now we manually garbage collect between each test to make sure the device won't run out of memory due to lazy collection.
+ DumpRenderTreeSupport::garbageCollectorCollect();
+}
+
+void DumpRenderTree::runTests()
+{
+ m_gcController = new GCController();
+ m_accessibilityController = new AccessibilityController();
+ getTestsToRun();
+
+ mainFrame = m_page->mainFrame();
+
+ m_currentTest = m_tests.begin();
+
+ if (m_currentTest == m_tests.end()) {
+ doneDrt();
+ return;
+ }
+
+ if (isHTTPTest(m_currentTest->utf8().data())) {
+ m_currentHttpTest = m_currentTest->utf8().data();
+ m_currentHttpTest.remove(0, strlen(httpTestSyntax));
+ runTest(httpPrefixURL + m_currentHttpTest);
+ } else
+ runTest(kSDCLayoutTestsURI + *m_currentTest);
+}
+
+
+WTF::String DumpRenderTree::dumpFramesAsText(WebCore::Frame* frame)
+{
+ WTF::String s;
+ WebCore::Element* documentElement = frame->document()->documentElement();
+ if (!documentElement)
+ return s.utf8().data();
+
+ if (frame->tree()->parent())
+ s = WTF::String::format("\n--------\nFrame: '%s'\n--------\n", frame->tree()->uniqueName().string().utf8().data());
+
+ s += documentElement->innerText() + "\n";
+
+ if (gLayoutTestController->dumpChildFramesAsText()) {
+ WebCore::FrameTree* tree = frame->tree();
+ for (WebCore::Frame* child = tree->firstChild(); child; child = child->tree()->nextSibling())
+ s += dumpFramesAsText(child);
+ }
+ return s;
+}
+
+static void dumpToFile(const WTF::String& data)
+{
+ fwrite(data.utf8().data(), 1, data.utf8().length(), stdout);
+}
+
+bool DumpRenderTree::isHTTPTest(const WTF::String& test)
+{
+ if (test.length() < strlen(httpTestSyntax))
+ return false;
+ return test.lower().substring(0, strlen(httpTestSyntax)) == httpTestSyntax;
+}
+
+void DumpRenderTree::getTestsToRun()
+{
+ Vector<WTF::String> files;
+
+ FILE* fd = fopen(m_indexFile.utf8().data(), "r");
+ fseek(fd, 0, SEEK_END);
+ int size = ftell(fd);
+ fseek(fd, 0, SEEK_SET);
+ OwnArrayPtr<char> buf = adoptArrayPtr(new char[size]);
+ fread(buf.get(), 1, size, fd);
+ fclose(fd);
+ WTF::String s(buf.get(), size);
+ s.split("\n", files);
+
+ m_tests = files;
+}
+
+void DumpRenderTree::invalidateAnyPreviousWaitToDumpWatchdog()
+{
+ m_waitToDumpWatchdogTimer.stop();
+ waitForPolicy = false;
+}
+
+WTF::String DumpRenderTree::renderTreeDump() const
+{
+ if (mainFrame) {
+ if (mainFrame->view() && mainFrame->view()->layoutPending())
+ mainFrame->view()->layout();
+
+ return externalRepresentation(mainFrame);
+ }
+ return "";
+}
+
+static bool historyItemCompare(const RefPtr<WebCore::HistoryItem>& a, const RefPtr<WebCore::HistoryItem>& b)
+{
+ return codePointCompare(a->urlString(), b->urlString()) < 0;
+}
+
+static WTF::String dumpHistoryItem(PassRefPtr<WebCore::HistoryItem> item, int indent, bool current)
+{
+ WTF::String result;
+
+ int start = 0;
+ if (current) {
+ result += "curr->";
+ start = 6;
+ }
+ for (int i = start; i < indent; i++)
+ result += " ";
+
+ WTF::String url = item->urlString();
+ if (url.contains("file://")) {
+ static WTF::String layoutTestsString("/LayoutTests/");
+ static WTF::String fileTestString("(file test):");
+
+ WTF::String res = url.substring(url.find(layoutTestsString) + layoutTestsString.length());
+ if (res.isEmpty())
+ return result;
+
+ result += fileTestString;
+ result += res;
+ } else
+ result += url;
+
+ WTF::String target = item->target();
+ if (!target.isEmpty())
+ result += " (in frame \"" + target + "\")";
+
+ if (item->isTargetItem())
+ result += " **nav target**";
+ result += "\n";
+
+ WebCore::HistoryItemVector children = item->children();
+ // Must sort to eliminate arbitrary result ordering which defeats reproducible testing.
+ nonCopyingSort(children.begin(), children.end(), historyItemCompare);
+ unsigned resultSize = children.size();
+ for (unsigned i = 0; i < resultSize; ++i)
+ result += dumpHistoryItem(children[i], indent + 4, false);
+
+ return result;
+}
+
+static WTF::String dumpBackForwardListForWebView()
+{
+ WTF::String result = "\n============== Back Forward List ==============\n";
+ // FORMAT:
+ // " (file test):fast/loader/resources/click-fragment-link.html **nav target**"
+ // "curr-> (file test):fast/loader/resources/click-fragment-link.html#testfragment **nav target**"
+ WebCore::BackForwardListImpl* bfList = static_cast<WebCore::BackForwardListImpl*>(mainFrame->page()->backForward()->client());
+ int maxItems = bfList->capacity();
+ WebCore::HistoryItemVector entries;
+ bfList->backListWithLimit(maxItems, entries);
+ unsigned resultSize = entries.size();
+ for (unsigned i = 0; i < resultSize; ++i)
+ result += dumpHistoryItem(entries[i], 8, false);
+
+ result += dumpHistoryItem(bfList->currentItem(), 8, true);
+
+ bfList->forwardListWithLimit(maxItems, entries);
+ resultSize = entries.size();
+ for (unsigned i = 0; i < resultSize; ++i)
+ result += dumpHistoryItem(entries[i], 8, false);
+
+ result += "===============================================\n";
+
+ return result;
+}
+
+void DumpRenderTree::dump()
+{
+ invalidateAnyPreviousWaitToDumpWatchdog();
+
+ WTF::String dumpFile = m_resultsDir + *m_currentTest + ".dump";
+
+ WTF::String resultMimeType = "text/plain";
+ WTF::String responseMimeType = mainFrame->loader()->documentLoader()->responseMIMEType();
+
+ bool dumpAsText = gLayoutTestController->dumpAsText() || responseMimeType == "text/plain";
+ WTF::String data = dumpAsText ? dumpFramesAsText(mainFrame) : renderTreeDump();
+
+ if (gLayoutTestController->dumpBackForwardList())
+ data += dumpBackForwardListForWebView();
+
+ WTF::String result = "Content-Type: " + resultMimeType + "\n" + data;
+
+ dumpToFile(result);
+ if (m_dumpPixels && !dumpAsText && gLayoutTestController->generatePixelResults())
+ dumpWebViewAsPixelsAndCompareWithExpected(gLayoutTestController->expectedPixelHash());
+
+ WTF::String crashFile = dumpFile + ".crash";
+ unlink(crashFile.utf8().data());
+
+ testDone = true;
+ runRemainingTests();
+}
+
+void DumpRenderTree::setWaitToDumpWatchdog(double interval)
+{
+ invalidateAnyPreviousWaitToDumpWatchdog();
+ m_waitToDumpWatchdogTimer.startOneShot(interval);
+}
+
+void DumpRenderTree::waitToDumpWatchdogTimerFired(WebCore::Timer<DumpRenderTree>*)
+{
+ gLayoutTestController->waitToDumpWatchdogTimerFired();
+}
+
+void DumpRenderTree::processWork(WebCore::Timer<DumpRenderTree>*)
+{
+ if (topLoadingFrame)
+ return;
+
+ if (WorkQueue::shared()->processWork() && !gLayoutTestController->waitToDump())
+ dump();
+}
+
+void DumpRenderTree::locationChangeForFrame(WebCore::Frame* frame)
+{
+ if (frame != topLoadingFrame)
+ return;
+
+ topLoadingFrame = 0;
+ WorkQueue::shared()->setFrozen(true); // first complete load freezes the queue
+ if (gLayoutTestController->waitToDump())
+ return;
+
+ if (WorkQueue::shared()->count())
+ m_workTimer.startOneShot(0);
+ else
+ dump();
+}
+
+// FrameLoadClient delegates.
+void DumpRenderTree::didStartProvisionalLoadForFrame(WebCore::Frame* frame)
+{
+ if (!testDone && gLayoutTestController->dumpFrameLoadCallbacks())
+ printf("%s - didStartProvisionalLoadForFrame\n", drtFrameDescription(frame).utf8().data());
+
+ if (!testDone && gLayoutTestController->dumpUserGestureInFrameLoadCallbacks())
+ printf("Frame with user gesture \"%s\" - in didStartProvisionalLoadForFrame\n", WebCore::ScriptController::processingUserGesture() ? "true" : "false");
+
+ if (!topLoadingFrame && !testDone)
+ topLoadingFrame = frame;
+
+ if (!testDone && gLayoutTestController->stopProvisionalFrameLoads()) {
+ printf("%s - stopping load in didStartProvisionalLoadForFrame callback\n", drtFrameDescription(frame).utf8().data());
+ frame->loader()->stopForUserCancel();
+ }
+}
+
+void DumpRenderTree::didCommitLoadForFrame(WebCore::Frame* frame)
+{
+ if (!testDone && gLayoutTestController->dumpFrameLoadCallbacks())
+ printf("%s - didCommitLoadForFrame\n", drtFrameDescription(frame).utf8().data());
+
+ gLayoutTestController->setWindowIsKey(true);
+}
+
+void DumpRenderTree::didFailProvisionalLoadForFrame(WebCore::Frame* frame)
+{
+ if (!testDone && gLayoutTestController->dumpFrameLoadCallbacks())
+ printf("%s - didFailProvisionalLoadWithError\n", drtFrameDescription(frame).utf8().data());
+
+ locationChangeForFrame(frame);
+}
+
+void DumpRenderTree::didFailLoadForFrame(WebCore::Frame* frame)
+{
+ if (!testDone && gLayoutTestController->dumpFrameLoadCallbacks())
+ printf("%s - didFailLoadWithError\n", drtFrameDescription(frame).utf8().data());
+
+ locationChangeForFrame(frame);
+}
+
+void DumpRenderTree::didFinishLoadForFrame(WebCore::Frame* frame)
+{
+ if (!testDone && gLayoutTestController->dumpFrameLoadCallbacks())
+ printf("%s - didFinishLoadForFrame\n", drtFrameDescription(frame).utf8().data());
+
+ if (frame == topLoadingFrame)
+ m_loadFinished = true;
+ locationChangeForFrame(frame);
+}
+
+void DumpRenderTree::didFinishDocumentLoadForFrame(WebCore::Frame* frame)
+{
+ if (!testDone) {
+ if (gLayoutTestController->dumpFrameLoadCallbacks())
+ printf("%s - didFinishDocumentLoadForFrame\n", drtFrameDescription(frame).utf8().data());
+ else {
+ unsigned pendingFrameUnloadEvents = frame->domWindow()->pendingUnloadEventListeners();
+ if (pendingFrameUnloadEvents)
+ printf("%s - has %u onunload handler(s)\n", drtFrameDescription(frame).utf8().data(), pendingFrameUnloadEvents);
+ }
+ }
+}
+
+void DumpRenderTree::didClearWindowObjectInWorld(WebCore::DOMWrapperWorld*, JSGlobalContextRef context, JSObjectRef windowObject)
+{
+ JSValueRef exception = 0;
+
+ gLayoutTestController->makeWindowObject(context, windowObject, &exception);
+ ASSERT(!exception);
+
+ m_gcController->makeWindowObject(context, windowObject, &exception);
+ ASSERT(!exception);
+
+ m_accessibilityController->makeWindowObject(context, windowObject, &exception);
+ ASSERT(!exception);
+
+ JSStringRef eventSenderStr = JSStringCreateWithUTF8CString("eventSender");
+ JSValueRef eventSender = makeEventSender(context);
+ JSObjectSetProperty(context, windowObject, eventSenderStr, eventSender, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete, 0);
+ JSStringRelease(eventSenderStr);
+ WebCoreTestSupport::injectInternalsObject(context);
+}
+
+void DumpRenderTree::didReceiveTitleForFrame(const WTF::String& title, WebCore::Frame* frame)
+{
+ if (!testDone && gLayoutTestController->dumpFrameLoadCallbacks())
+ printf("%s - didReceiveTitle: %s\n", drtFrameDescription(frame).utf8().data(), title.utf8().data());
+
+ if (gLayoutTestController->dumpTitleChanges())
+ printf("TITLE CHANGED: %s\n", title.utf8().data());
+}
+
+// ChromeClient delegates.
+void DumpRenderTree::addMessageToConsole(const WTF::String& message, unsigned int lineNumber, const WTF::String& sourceID)
+{
+ printf("CONSOLE MESSAGE: line %d: %s\n", lineNumber, message.utf8().data());
+}
+
+void DumpRenderTree::runJavaScriptAlert(const WTF::String& message)
+{
+ if (!testDone)
+ printf("ALERT: %s\n", message.utf8().data());
+}
+
+bool DumpRenderTree::runJavaScriptConfirm(const WTF::String& message)
+{
+ if (!testDone)
+ printf("CONFIRM: %s\n", message.utf8().data());
+ return true;
+}
+
+WTF::String DumpRenderTree::runJavaScriptPrompt(const WTF::String& message, const WTF::String& defaultValue)
+{
+ if (!testDone)
+ printf("PROMPT: %s, default text: %s\n", message.utf8().data(), defaultValue.utf8().data());
+ return defaultValue;
+}
+
+bool DumpRenderTree::runBeforeUnloadConfirmPanel(const WTF::String& message)
+{
+ if (!testDone)
+ printf("CONFIRM NAVIGATION: %s\n", message.utf8().data());
+ return true;
+}
+
+void DumpRenderTree::setStatusText(const WTF::String& status)
+{
+ if (gLayoutTestController->dumpStatusCallbacks())
+ printf("UI DELEGATE STATUS CALLBACK: setStatusText:%s\n", status.utf8().data());
+}
+
+void DumpRenderTree::exceededDatabaseQuota(WebCore::SecurityOrigin* origin, const WTF::String& name)
+{
+ if (!testDone && gLayoutTestController->dumpDatabaseCallbacks())
+ printf("UI DELEGATE DATABASE CALLBACK: exceededDatabaseQuotaForSecurityOrigin:{%s, %s, %i} database:%s\n", origin->protocol().utf8().data(), origin->host().utf8().data(), origin->port(), name.utf8().data());
+
+ WebCore::DatabaseTracker::tracker().setQuota(mainFrame->document()->securityOrigin(), 5 * 1024 * 1024);
+}
+
+bool DumpRenderTree::allowsOpeningWindow()
+{
+ return gLayoutTestController->canOpenWindows();
+}
+
+void DumpRenderTree::windowCreated(BlackBerry::WebKit::WebPage* page)
+{
+ page->settings()->setJavaScriptOpenWindowsAutomatically(true);
+}
+
+// EditorClient delegates.
+void DumpRenderTree::didBeginEditing()
+{
+ if (!testDone && gLayoutTestController->dumpEditingCallbacks())
+ printf("EDITING DELEGATE: webViewDidBeginEditing:%s\n", "WebViewDidBeginEditingNotification");
+}
+
+void DumpRenderTree::didEndEditing()
+{
+ if (!testDone && gLayoutTestController->dumpEditingCallbacks())
+ printf("EDITING DELEGATE: webViewDidEndEditing:%s\n", "WebViewDidEndEditingNotification");
+}
+
+void DumpRenderTree::didChange()
+{
+ if (!testDone && gLayoutTestController->dumpEditingCallbacks())
+ printf("EDITING DELEGATE: webViewDidChange:%s\n", "WebViewDidChangeNotification");
+}
+
+void DumpRenderTree::didChangeSelection()
+{
+ if (!testDone && gLayoutTestController->dumpEditingCallbacks())
+ printf("EDITING DELEGATE: webViewDidChangeSelection:%s\n", "WebViewDidChangeSelectionNotification");
+}
+
+bool DumpRenderTree::findString(const WTF::String& string, WebCore::FindOptions options)
+{
+ WebCore::Page* page = mainFrame ? mainFrame->page() : 0;
+ return page && page->findString(string, options);
+}
+
+bool DumpRenderTree::shouldBeginEditingInDOMRange(WebCore::Range* range)
+{
+ if (!testDone && gLayoutTestController->dumpEditingCallbacks())
+ printf("EDITING DELEGATE: shouldBeginEditingInDOMRange:%s\n", drtRangeDescription(range).utf8().data());
+ return m_acceptsEditing;
+}
+
+bool DumpRenderTree::shouldEndEditingInDOMRange(WebCore::Range* range)
+{
+ if (!testDone && gLayoutTestController->dumpEditingCallbacks())
+ printf("EDITING DELEGATE: shouldEndEditingInDOMRange:%s\n", drtRangeDescription(range).utf8().data());
+ return m_acceptsEditing;
+}
+
+bool DumpRenderTree::shouldDeleteDOMRange(WebCore::Range* range)
+{
+ if (!testDone && gLayoutTestController->dumpEditingCallbacks())
+ printf("EDITING DELEGATE: shouldDeleteDOMRange:%s\n", drtRangeDescription(range).utf8().data());
+ return m_acceptsEditing;
+}
+
+bool DumpRenderTree::shouldChangeSelectedDOMRangeToDOMRangeAffinityStillSelecting(WebCore::Range* fromRange, WebCore::Range* toRange, int affinity, bool stillSelecting)
+{
+ if (!testDone && gLayoutTestController->dumpEditingCallbacks())
+ printf("EDITING DELEGATE: shouldChangeSelectedDOMRange:%s toDOMRange:%s affinity:%s stillSelecting:%s\n", drtRangeDescription(fromRange).utf8().data(), drtRangeDescription(toRange).utf8().data(), drtAffinityDescription(static_cast<WebCore::EAffinity>(affinity)).utf8().data(), stillSelecting ? "TRUE" : "FALSE");
+ return m_acceptsEditing;
+}
+
+static const char* insertActionString(WebCore::EditorInsertAction action)
+{
+ switch (action) {
+ case WebCore::EditorInsertActionTyped:
+ return "WebViewInsertActionTyped";
+ case WebCore::EditorInsertActionPasted:
+ return "WebViewInsertActionPasted";
+ case WebCore::EditorInsertActionDropped:
+ return "WebViewInsertActionDropped";
+ }
+ ASSERT_NOT_REACHED();
+ return "WebViewInsertActionTyped";
+}
+
+bool DumpRenderTree::shouldInsertNode(WebCore::Node* node, WebCore::Range* range, int action)
+{
+ if (!testDone && gLayoutTestController->dumpEditingCallbacks())
+ printf("EDITING DELEGATE: shouldInsertNode:%s replacingDOMRange:%s givenAction:%s\n", drtDumpPath(node).utf8().data(), drtRangeDescription(range).utf8().data(), insertActionString((WebCore::EditorInsertAction)action));
+ return m_acceptsEditing;
+}
+
+bool DumpRenderTree::shouldInsertText(const WTF::String& text, WebCore::Range* range, int action)
+{
+ if (!testDone && gLayoutTestController->dumpEditingCallbacks())
+ printf("EDITING DELEGATE: shouldInsertText:%s replacingDOMRange:%s givenAction:%s\n", text.utf8().data(), drtRangeDescription(range).utf8().data(), insertActionString((WebCore::EditorInsertAction)action));
+ return m_acceptsEditing;
+}
+
+void DumpRenderTree::didDecidePolicyForNavigationAction(const WebCore::NavigationAction& action, const WebCore::ResourceRequest& request)
+{
+ if (!waitForPolicy)
+ return;
+
+ const char* typeDescription;
+ switch (action.type()) {
+ case WebCore::NavigationTypeLinkClicked:
+ typeDescription = "link clicked";
+ break;
+ case WebCore::NavigationTypeFormSubmitted:
+ typeDescription = "form submitted";
+ break;
+ case WebCore::NavigationTypeBackForward:
+ typeDescription = "back/forward";
+ break;
+ case WebCore::NavigationTypeReload:
+ typeDescription = "reload";
+ break;
+ case WebCore::NavigationTypeFormResubmitted:
+ typeDescription = "form resubmitted";
+ break;
+ case WebCore::NavigationTypeOther:
+ typeDescription = "other";
+ break;
+ default:
+ typeDescription = "illegal value";
+ }
+
+ printf("Policy delegate: attempt to load %s with navigation type '%s'\n", request.url().string().utf8().data(), typeDescription);
+ // FIXME: do originating part.
+
+ gLayoutTestController->notifyDone();
+}
+
+void DumpRenderTree::didDispatchWillPerformClientRedirect()
+{
+ if (!testDone && gLayoutTestController->dumpUserGestureInFrameLoadCallbacks())
+ printf("Frame with user gesture \"%s\" - in willPerformClientRedirect\n", WebCore::ScriptController::processingUserGesture() ? "true" : "false");
+}
+
+void DumpRenderTree::didHandleOnloadEventsForFrame(WebCore::Frame* frame)
+{
+ if (!testDone && gLayoutTestController->dumpFrameLoadCallbacks())
+ printf("%s - didHandleOnloadEventsForFrame\n", drtFrameDescription(frame).utf8().data());
+}
+
+void DumpRenderTree::didReceiveResponseForFrame(WebCore::Frame* frame, const WebCore::ResourceResponse& response)
+{
+ if (!testDone && gLayoutTestController->dumpResourceResponseMIMETypes())
+ printf("%s has MIME type %s\n", response.url().lastPathComponent().utf8().data(), response.mimeType().utf8().data());
+}
+
+}
+}
+
+// Static dump() function required by cross-platform DRT code.
+void dump()
+{
+ BlackBerry::WebKit::DumpRenderTree* dumper = BlackBerry::WebKit::DumpRenderTree::currentInstance();
+ if (!dumper)
+ return;
+
+ dumper->dump();
+}
diff --git a/Tools/DumpRenderTree/blackberry/DumpRenderTreeBlackBerry.h b/Tools/DumpRenderTree/blackberry/DumpRenderTreeBlackBerry.h
new file mode 100644
index 000000000..db2f69a30
--- /dev/null
+++ b/Tools/DumpRenderTree/blackberry/DumpRenderTreeBlackBerry.h
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2009, 2010, 2011, 2012 Research In Motion Limited. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef DumpRenderTreeBlackBerry_h
+#define DumpRenderTreeBlackBerry_h
+
+#include "BlackBerryGlobal.h"
+
+#include "DumpRenderTreeClient.h"
+#include "PlatformString.h"
+#include "Timer.h"
+#include <FindOptions.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+class Frame;
+class DOMWrapperWorld;
+class Range;
+}
+
+extern WebCore::Frame* mainFrame;
+extern WebCore::Frame* topLoadingFrame;
+extern bool waitForPolicy;
+
+class AccessibilityController;
+class GCController;
+
+namespace BlackBerry {
+namespace WebKit {
+class WebPage;
+
+class DumpRenderTree : public BlackBerry::WebKit::DumpRenderTreeClient {
+public:
+ DumpRenderTree(WebPage*);
+ virtual ~DumpRenderTree();
+
+ static DumpRenderTree* currentInstance() { return s_currentInstance; }
+
+ void dump();
+
+ void setWaitToDumpWatchdog(double interval);
+
+ WebPage* page() { return m_page; }
+
+ bool loadFinished() const { return m_loadFinished; }
+
+ // FrameLoaderClient delegates
+ void didStartProvisionalLoadForFrame(WebCore::Frame*);
+ void didCommitLoadForFrame(WebCore::Frame*);
+ void didFailProvisionalLoadForFrame(WebCore::Frame*);
+ void didFailLoadForFrame(WebCore::Frame*);
+ void didFinishLoadForFrame(WebCore::Frame*);
+ void didFinishDocumentLoadForFrame(WebCore::Frame*);
+ void didClearWindowObjectInWorld(WebCore::DOMWrapperWorld*, JSGlobalContextRef, JSObjectRef windowObject);
+ void didReceiveTitleForFrame(const WTF::String& title, WebCore::Frame*);
+ void didDecidePolicyForNavigationAction(const WebCore::NavigationAction&, const WebCore::ResourceRequest&);
+ void didDispatchWillPerformClientRedirect();
+ void didHandleOnloadEventsForFrame(WebCore::Frame*);
+ void didReceiveResponseForFrame(WebCore::Frame*, const WebCore::ResourceResponse&);
+
+ // ChromeClient delegates
+ void addMessageToConsole(const WTF::String& message, unsigned int lineNumber, const WTF::String& sourceID);
+ void runJavaScriptAlert(const WTF::String& message);
+ bool runJavaScriptConfirm(const WTF::String& message);
+ WTF::String runJavaScriptPrompt(const WTF::String& message, const WTF::String& defaultValue);
+ bool runBeforeUnloadConfirmPanel(const WTF::String& message);
+ void setStatusText(const WTF::String&);
+ void exceededDatabaseQuota(WebCore::SecurityOrigin*, const WTF::String& name);
+ bool allowsOpeningWindow();
+ void windowCreated(WebPage*);
+
+ // EditorClient delegates
+ void setAcceptsEditing(bool acceptsEditing) { m_acceptsEditing = acceptsEditing; }
+
+ void didBeginEditing();
+ void didEndEditing();
+ void didChange();
+ void didChangeSelection();
+ bool findString(const WTF::String&, WebCore::FindOptions);
+ bool shouldBeginEditingInDOMRange(WebCore::Range*);
+ bool shouldEndEditingInDOMRange(WebCore::Range*);
+ bool shouldDeleteDOMRange(WebCore::Range*);
+ bool shouldChangeSelectedDOMRangeToDOMRangeAffinityStillSelecting(WebCore::Range* fromRange, WebCore::Range* toRange, int affinity, bool stillSelecting);
+ bool shouldInsertNode(WebCore::Node*, WebCore::Range*, int insertAction);
+ bool shouldInsertText(const WTF::String&, WebCore::Range*, int insertAction);
+
+ bool isSelectTrailingWhitespaceEnabled() const { return s_selectTrailingWhitespaceEnabled; }
+ void setSelectTrailingWhitespaceEnabled(bool enabled) { s_selectTrailingWhitespaceEnabled = enabled; }
+
+private:
+ void runTest(const WTF::String& url);
+ void runTests();
+
+ void processWork(WebCore::Timer<DumpRenderTree>*);
+
+private:
+ static DumpRenderTree* s_currentInstance;
+
+ WTF::String dumpFramesAsText(WebCore::Frame*);
+ void locationChangeForFrame(WebCore::Frame*);
+
+ void doneDrt();
+ void getTestsToRun();
+ bool isHTTPTest(const WTF::String& test);
+ WTF::String renderTreeDump() const;
+ void resetToConsistentStateBeforeTesting();
+ void runRemainingTests();
+ void invalidateAnyPreviousWaitToDumpWatchdog();
+ void waitToDumpWatchdogTimerFired(WebCore::Timer<DumpRenderTree>*);
+
+ Vector<WTF::String> m_tests;
+ Vector<WTF::String>::iterator m_currentTest;
+
+ WTF::String m_resultsDir;
+ WTF::String m_indexFile;
+ WTF::String m_doneFile;
+ WTF::String m_currentHttpTest;
+ WTF::String m_currentTestFile;
+
+ GCController* m_gcController;
+ AccessibilityController* m_accessibilityController;
+ WebPage* m_page;
+ bool m_dumpPixels;
+ WebCore::Timer<DumpRenderTree> m_waitToDumpWatchdogTimer;
+ WebCore::Timer<DumpRenderTree> m_workTimer;
+
+ bool m_acceptsEditing;
+ bool m_loadFinished;
+ static bool s_selectTrailingWhitespaceEnabled;
+};
+}
+}
+
+#endif // DumpRenderTreeBlackBerry_h
diff --git a/Tools/DumpRenderTree/blackberry/EventSender.cpp b/Tools/DumpRenderTree/blackberry/EventSender.cpp
new file mode 100644
index 000000000..1d5f0fe4d
--- /dev/null
+++ b/Tools/DumpRenderTree/blackberry/EventSender.cpp
@@ -0,0 +1,408 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2009 Torch Mobile Inc. http://www.torchmobile.com/
+ * Copyright (C) 2009, 2010, 2012 Research In Motion Limited. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+#include "EventSender.h"
+
+#include "DumpRenderTreeBlackBerry.h"
+#include "DumpRenderTreeSupport.h"
+#include "IntPoint.h"
+#include "NotImplemented.h"
+#include "WebPage.h"
+
+#include <BlackBerryPlatformKeyboardEvent.h>
+#include <BlackBerryPlatformMouseEvent.h>
+#include <BlackBerryPlatformTouchEvent.h>
+#include <JavaScriptCore/JSObjectRef.h>
+#include <JavaScriptCore/JSStringRef.h>
+#include <JavaScriptCore/JSValueRef.h>
+#include <wtf/Vector.h>
+
+using namespace WebCore;
+
+static IntPoint lastMousePosition;
+static Vector<BlackBerry::Platform::TouchPoint> touches;
+static bool touchActive = false;
+
+void sendTouchEvent(BlackBerry::Platform::TouchEvent::Type);
+
+// Callbacks
+
+static JSValueRef getDragModeCallback(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
+{
+ notImplemented();
+ return JSValueMakeUndefined(context);
+}
+
+static bool setDragModeCallback(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception)
+{
+ notImplemented();
+ return JSValueMakeUndefined(context);
+}
+
+static JSValueRef mouseWheelToCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ notImplemented();
+ return JSValueMakeUndefined(context);
+}
+
+static JSValueRef contextClickCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ notImplemented();
+ return JSValueMakeUndefined(context);
+}
+
+static JSValueRef mouseDownCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ BlackBerry::WebKit::WebPage* page = BlackBerry::WebKit::DumpRenderTree::currentInstance()->page();
+ page->mouseEvent(BlackBerry::Platform::MouseEvent(BlackBerry::Platform::MouseEvent::ScreenLeftMouseButton, 0, lastMousePosition, IntPoint::zero(), 0, 0));
+ return JSValueMakeUndefined(context);
+}
+
+static JSValueRef mouseUpCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ BlackBerry::WebKit::WebPage* page = BlackBerry::WebKit::DumpRenderTree::currentInstance()->page();
+ page->mouseEvent(BlackBerry::Platform::MouseEvent(0, BlackBerry::Platform::MouseEvent::ScreenLeftMouseButton, lastMousePosition, IntPoint::zero(), 0, 0));
+ return JSValueMakeUndefined(context);
+}
+
+static JSValueRef mouseMoveToCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ if (argumentCount < 2)
+ return JSValueMakeUndefined(context);
+
+ int x = static_cast<int>(JSValueToNumber(context, arguments[0], exception));
+ ASSERT(!exception || !*exception);
+ int y = static_cast<int>(JSValueToNumber(context, arguments[1], exception));
+ ASSERT(!exception || !*exception);
+
+ lastMousePosition = IntPoint(x, y);
+ BlackBerry::WebKit::WebPage* page = BlackBerry::WebKit::DumpRenderTree::currentInstance()->page();
+ page->mouseEvent(BlackBerry::Platform::MouseEvent(BlackBerry::Platform::MouseEvent::ScreenLeftMouseButton, BlackBerry::Platform::MouseEvent::ScreenLeftMouseButton, lastMousePosition, IntPoint::zero(), 0, 0));
+
+
+ return JSValueMakeUndefined(context);
+}
+
+static JSValueRef beginDragWithFilesCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ notImplemented();
+ return JSValueMakeUndefined(context);
+}
+
+static JSValueRef leapForwardCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ notImplemented();
+ return JSValueMakeUndefined(context);
+}
+
+static JSValueRef keyDownCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ if (argumentCount < 1)
+ return JSValueMakeUndefined(context);
+
+ JSStringRef character = JSValueToStringCopy(context, arguments[0], exception);
+ ASSERT(!*exception);
+ short charCode = 0;
+ bool needsShiftKeyModifier = false;
+ if (JSStringIsEqualToUTF8CString(character, "leftArrow"))
+ charCode = KEYCODE_LEFT;
+ else if (JSStringIsEqualToUTF8CString(character, "rightArrow"))
+ charCode = KEYCODE_RIGHT;
+ else if (JSStringIsEqualToUTF8CString(character, "upArrow"))
+ charCode = KEYCODE_UP;
+ else if (JSStringIsEqualToUTF8CString(character, "downArrow"))
+ charCode = KEYCODE_DOWN;
+ else if (JSStringIsEqualToUTF8CString(character, "pageUp")
+ || JSStringIsEqualToUTF8CString(character, "pageDown")
+ || JSStringIsEqualToUTF8CString(character, "home")
+ || JSStringIsEqualToUTF8CString(character, "end"))
+ return JSValueMakeUndefined(context);
+ else if (JSStringIsEqualToUTF8CString(character, "delete"))
+ charCode = KEYCODE_BACKSPACE;
+ else {
+ charCode = JSStringGetCharactersPtr(character)[0];
+ if (WTF::isASCIIUpper(charCode))
+ needsShiftKeyModifier = true;
+ }
+ JSStringRelease(character);
+
+ static const JSStringRef lengthProperty = JSStringCreateWithUTF8CString("length");
+ bool needsAltKeyModifier = false;
+ if (argumentCount > 1) {
+ if (JSObjectRef modifiersArray = JSValueToObject(context, arguments[1], 0)) {
+ int modifiersCount = JSValueToNumber(context, JSObjectGetProperty(context, modifiersArray, lengthProperty, 0), 0);
+ for (int i = 0; i < modifiersCount; ++i) {
+ JSStringRef string = JSValueToStringCopy(context, JSObjectGetPropertyAtIndex(context, modifiersArray, i, 0), 0);
+ if (JSStringIsEqualToUTF8CString(string, "shiftKey"))
+ needsShiftKeyModifier = true;
+ else if (JSStringIsEqualToUTF8CString(string, "altKey"))
+ needsAltKeyModifier = true;
+ JSStringRelease(string);
+ }
+ }
+ }
+
+ BlackBerry::WebKit::WebPage* page = BlackBerry::WebKit::DumpRenderTree::currentInstance()->page();
+
+ unsigned modifiers = 0;
+ if (needsShiftKeyModifier)
+ modifiers |= KEYMOD_SHIFT;
+ if (needsAltKeyModifier)
+ modifiers |= KEYMOD_ALT;
+
+ page->keyEvent(BlackBerry::Platform::KeyboardEvent(charCode, BlackBerry::Platform::KeyboardEvent::KeyChar, modifiers));
+
+ return JSValueMakeUndefined(context);
+}
+
+static JSValueRef textZoomInCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ notImplemented();
+ return JSValueMakeUndefined(context);
+}
+
+static JSValueRef textZoomOutCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ notImplemented();
+ return JSValueMakeUndefined(context);
+}
+
+static JSValueRef zoomPageInCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ notImplemented();
+ return JSValueMakeUndefined(context);
+}
+
+static JSValueRef zoomPageOutCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ notImplemented();
+ return JSValueMakeUndefined(context);
+}
+
+static JSValueRef addTouchPointCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ if (argumentCount < 2)
+ return JSValueMakeUndefined(context);
+
+ int x = static_cast<int>(JSValueToNumber(context, arguments[0], exception));
+ ASSERT(!exception || !*exception);
+ int y = static_cast<int>(JSValueToNumber(context, arguments[1], exception));
+ ASSERT(!exception || !*exception);
+
+ BlackBerry::Platform::TouchPoint touch;
+ touch.m_id = touches.isEmpty() ? 0 : touches.last().m_id + 1;
+ IntPoint pos(x, y);
+ touch.m_pos = pos;
+ touch.m_screenPos = pos;
+ touch.m_state = BlackBerry::Platform::TouchPoint::TouchPressed;
+
+ touches.append(touch);
+
+ return JSValueMakeUndefined(context);
+}
+
+static JSValueRef updateTouchPointCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ if (argumentCount < 3)
+ return JSValueMakeUndefined(context);
+
+ int index = static_cast<int>(JSValueToNumber(context, arguments[0], exception));
+ ASSERT(!exception || !*exception);
+ int x = static_cast<int>(JSValueToNumber(context, arguments[1], exception));
+ ASSERT(!exception || !*exception);
+ int y = static_cast<int>(JSValueToNumber(context, arguments[2], exception));
+ ASSERT(!exception || !*exception);
+
+ if (index < 0 || index >= (int)touches.size())
+ return JSValueMakeUndefined(context);
+
+ BlackBerry::Platform::TouchPoint& touch = touches[index];
+ IntPoint pos(x, y);
+ touch.m_pos = pos;
+ touch.m_screenPos = pos;
+ touch.m_state = BlackBerry::Platform::TouchPoint::TouchMoved;
+
+ return JSValueMakeUndefined(context);
+}
+
+static JSValueRef setTouchModifierCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ notImplemented();
+ return JSValueMakeUndefined(context);
+}
+
+static JSValueRef touchStartCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ if (!touchActive) {
+ sendTouchEvent(BlackBerry::Platform::TouchEvent::TouchStart);
+ touchActive = true;
+ } else
+ sendTouchEvent(BlackBerry::Platform::TouchEvent::TouchMove);
+ return JSValueMakeUndefined(context);
+}
+
+static JSValueRef touchCancelCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ notImplemented();
+ return JSValueMakeUndefined(context);
+}
+
+static JSValueRef touchMoveCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ sendTouchEvent(BlackBerry::Platform::TouchEvent::TouchMove);
+ return JSValueMakeUndefined(context);
+}
+
+static JSValueRef touchEndCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ for (unsigned i = 0; i < touches.size(); ++i)
+ if (touches[i].m_state != BlackBerry::Platform::TouchPoint::TouchReleased) {
+ sendTouchEvent(BlackBerry::Platform::TouchEvent::TouchMove);
+ return JSValueMakeUndefined(context);
+ }
+ sendTouchEvent(BlackBerry::Platform::TouchEvent::TouchEnd);
+ touchActive = false;
+ return JSValueMakeUndefined(context);
+}
+
+static JSValueRef clearTouchPointsCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ touches.clear();
+ touchActive = false;
+ return JSValueMakeUndefined(context);
+}
+
+static JSValueRef cancelTouchPointCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ notImplemented();
+ return JSValueMakeUndefined(context);
+}
+
+static JSValueRef releaseTouchPointCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ if (argumentCount < 1)
+ return JSValueMakeUndefined(context);
+
+ int index = static_cast<int>(JSValueToNumber(context, arguments[0], exception));
+ ASSERT(!exception || !*exception);
+ if (index < 0 || index >= (int)touches.size())
+ return JSValueMakeUndefined(context);
+
+ touches[index].m_state = BlackBerry::Platform::TouchPoint::TouchReleased;
+ return JSValueMakeUndefined(context);
+}
+
+void sendTouchEvent(BlackBerry::Platform::TouchEvent::Type type)
+{
+ BlackBerry::Platform::TouchEvent event;
+ event.m_type = type;
+ event.m_points.assign(touches.begin(), touches.end());
+ BlackBerry::WebKit::DumpRenderTree::currentInstance()->page()->touchEvent(event);
+
+ Vector<BlackBerry::Platform::TouchPoint> t;
+
+ for (Vector<BlackBerry::Platform::TouchPoint>::iterator it = touches.begin(); it != touches.end(); ++it) {
+ if (it->m_state != BlackBerry::Platform::TouchPoint::TouchReleased) {
+ it->m_state = BlackBerry::Platform::TouchPoint::TouchStationary;
+ t.append(*it);
+ }
+ }
+ touches = t;
+}
+
+static JSValueRef scalePageByCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ if (argumentCount < 3)
+ return JSValueMakeUndefined(context);
+
+ float scaleFactor = JSValueToNumber(context, arguments[0], exception);
+ float x = JSValueToNumber(context, arguments[1], exception);
+ float y = JSValueToNumber(context, arguments[2], exception);
+
+ BlackBerry::WebKit::WebPage* page = BlackBerry::WebKit::DumpRenderTree::currentInstance()->page();
+ if (!page)
+ return JSValueMakeUndefined(context);
+
+ DumpRenderTreeSupport::scalePageBy(page, scaleFactor, x, y);
+
+ return JSValueMakeUndefined(context);
+}
+
+static JSStaticFunction staticFunctions[] = {
+ { "mouseWheelTo", mouseWheelToCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "contextClick", contextClickCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "mouseDown", mouseDownCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "mouseUp", mouseUpCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "mouseMoveTo", mouseMoveToCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "beginDragWithFiles", beginDragWithFilesCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "leapForward", leapForwardCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "keyDown", keyDownCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "textZoomIn", textZoomInCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "textZoomOut", textZoomOutCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "addTouchPoint", addTouchPointCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "cancelTouchPoint", cancelTouchPointCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "clearTouchPoints", clearTouchPointsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "releaseTouchPoint", releaseTouchPointCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "scalePageBy", scalePageByCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "setTouchModifier", setTouchModifierCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "touchCancel", touchCancelCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "touchEnd", touchEndCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "touchMove", touchMoveCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "touchStart", touchStartCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "updateTouchPoint", updateTouchPointCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "zoomPageIn", zoomPageInCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "zoomPageOut", zoomPageOutCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { 0, 0, 0 }
+};
+
+static JSStaticValue staticValues[] = {
+ { "dragMode", getDragModeCallback, setDragModeCallback, kJSPropertyAttributeNone },
+ { 0, 0, 0, 0 }
+};
+
+static JSClassRef getClass(JSContextRef context)
+{
+ static JSClassRef eventSenderClass = 0;
+
+ if (!eventSenderClass) {
+ JSClassDefinition classDefinition = {
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ classDefinition.staticFunctions = staticFunctions;
+ classDefinition.staticValues = staticValues;
+
+ eventSenderClass = JSClassCreate(&classDefinition);
+ }
+
+ return eventSenderClass;
+}
+
+void replaySavedEvents()
+{
+ notImplemented();
+}
+
+JSObjectRef makeEventSender(JSContextRef context)
+{
+ return JSObjectMake(context, getClass(context), 0);
+}
+
diff --git a/Tools/DumpRenderTree/blackberry/EventSender.h b/Tools/DumpRenderTree/blackberry/EventSender.h
new file mode 100644
index 000000000..66f719629
--- /dev/null
+++ b/Tools/DumpRenderTree/blackberry/EventSender.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2009, 2012 Research In Motion Limited. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef EventSender_h
+#define EventSender_h
+
+typedef const struct OpaqueJSContext* JSContextRef;
+typedef struct OpaqueJSValue* JSObjectRef;
+
+JSObjectRef makeEventSender(JSContextRef);
+void replaySavedEvents();
+
+#endif
diff --git a/Tools/DumpRenderTree/blackberry/GCControllerBlackBerry.cpp b/Tools/DumpRenderTree/blackberry/GCControllerBlackBerry.cpp
new file mode 100644
index 000000000..8e8bd965b
--- /dev/null
+++ b/Tools/DumpRenderTree/blackberry/GCControllerBlackBerry.cpp
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2009, 2010, 2012 Research In Motion Limited. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+#include "DumpRenderTree/GCController.h"
+
+#include "DumpRenderTreeSupport.h"
+
+void GCController::collect() const
+{
+ DumpRenderTreeSupport::garbageCollectorCollect();
+}
+
+void GCController::collectOnAlternateThread(bool waitUntilDone) const
+{
+ DumpRenderTreeSupport::garbageCollectorCollectOnAlternateThread(waitUntilDone);
+}
+
+size_t GCController::getJSObjectCount() const
+{
+ return DumpRenderTreeSupport::javaScriptObjectsCount();
+}
+
diff --git a/Tools/DumpRenderTree/blackberry/WorkQueueItemBlackBerry.cpp b/Tools/DumpRenderTree/blackberry/WorkQueueItemBlackBerry.cpp
new file mode 100644
index 000000000..4c80bfb9b
--- /dev/null
+++ b/Tools/DumpRenderTree/blackberry/WorkQueueItemBlackBerry.cpp
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2009, 2010, 2012 Research In Motion Limited. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+#include "WorkQueueItem.h"
+
+#include "DumpRenderTreeBlackBerry.h"
+#include "Frame.h"
+#include "KURL.h"
+#include "OwnArrayPtr.h"
+#include "WebPage.h"
+
+using namespace WebCore;
+
+bool LoadItem::invoke() const
+{
+ size_t targetArrSize = JSStringGetMaximumUTF8CStringSize(m_target.get());
+ size_t urlArrSize = JSStringGetMaximumUTF8CStringSize(m_url.get());
+ OwnArrayPtr<char> target = adoptArrayPtr(new char[targetArrSize]);
+ OwnArrayPtr<char> url = adoptArrayPtr(new char[urlArrSize]);
+ size_t targetLen = JSStringGetUTF8CString(m_target.get(), target.get(), targetArrSize) - 1;
+ JSStringGetUTF8CString(m_url.get(), url.get(), urlArrSize);
+
+ Frame* frame;
+ if (target && targetLen)
+ frame = mainFrame->tree()->find(target.get());
+ else
+ frame = mainFrame;
+
+ if (!frame)
+ return false;
+
+ KURL kurl = KURL(KURL(), url.get());
+ frame->loader()->load(kurl, false);
+ return true;
+}
+
+bool LoadHTMLStringItem::invoke() const
+{
+ size_t contentSize = JSStringGetMaximumUTF8CStringSize(m_content.get());
+ size_t baseURLSize = JSStringGetMaximumUTF8CStringSize(m_baseURL.get());
+ size_t unreachableURLSize = JSStringGetMaximumUTF8CStringSize(m_unreachableURL.get());
+ OwnArrayPtr<char> content = adoptArrayPtr(new char[contentSize]);
+ OwnArrayPtr<char> baseURL = adoptArrayPtr(new char[baseURLSize]);
+ OwnArrayPtr<char> unreachableURL = adoptArrayPtr(new char[unreachableURLSize]);
+ JSStringGetUTF8CString(m_content.get(), content.get(), contentSize);
+ JSStringGetUTF8CString(m_baseURL.get(), baseURL.get(), baseURLSize);
+ JSStringGetUTF8CString(m_unreachableURL.get(), unreachableURL.get(), unreachableURLSize);
+ BlackBerry::WebKit::DumpRenderTree::currentInstance()->page()->loadString(content.get(), baseURL.get(), "text/html", unreachableURLSize ? unreachableURL.get() : 0);
+ return true;
+}
+
+bool ReloadItem::invoke() const
+{
+ mainFrame->loader()->reload(true);
+ return true;
+}
+
+bool ScriptItem::invoke() const
+{
+ BlackBerry::WebKit::JavaScriptDataType type;
+ BlackBerry::WebKit::WebString result;
+ size_t scriptArrSize = JSStringGetMaximumUTF8CStringSize(m_script.get());
+ OwnArrayPtr<char> script = adoptArrayPtr(new char[scriptArrSize]);
+ JSStringGetUTF8CString(m_script.get(), script.get(), scriptArrSize);
+ BlackBerry::WebKit::DumpRenderTree::currentInstance()->page()->executeJavaScript(script.get(), type, result);
+ return true;
+}
+
+bool BackForwardItem::invoke() const
+{
+ return BlackBerry::WebKit::DumpRenderTree::currentInstance()->page()->goBackOrForward(m_howFar);
+}
+
diff --git a/Tools/DumpRenderTree/chromium/DumpRenderTree.cpp b/Tools/DumpRenderTree/chromium/DumpRenderTree.cpp
index 24cbf5871..aac357636 100644
--- a/Tools/DumpRenderTree/chromium/DumpRenderTree.cpp
+++ b/Tools/DumpRenderTree/chromium/DumpRenderTree.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Google Inc. All rights reserved.
+ * Copyright (C) 2012 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -56,6 +56,7 @@ static const char optionHardwareAcceleratedGL[] = "--enable-hardware-gpu";
static const char optionEnableThreadedCompositing[] = "--enable-threaded-compositing";
static const char optionForceCompositingMode[] = "--force-compositing-mode";
static const char optionEnableAccelerated2DCanvas[] = "--enable-accelerated-2d-canvas";
+static const char optionEnableDeferred2DCanvas[] = "--enable-deferred-2d-canvas";
static const char optionEnableAcceleratedPainting[] = "--enable-accelerated-painting";
static const char optionEnableAcceleratedCompositingForVideo[] = "--enable-accelerated-video";
static const char optionEnableCompositeToTexture[] = "--enable-composite-to-texture";
@@ -143,6 +144,7 @@ int main(int argc, char* argv[])
bool compositeToTexture = false;
bool forceCompositingMode = false;
bool accelerated2DCanvasEnabled = false;
+ bool deferred2DCanvasEnabled = false;
bool acceleratedPaintingEnabled = false;
bool perTilePaintingEnabled = false;
bool stressOpt = false;
@@ -186,6 +188,8 @@ int main(int argc, char* argv[])
forceCompositingMode = true;
else if (argument == optionEnableAccelerated2DCanvas)
accelerated2DCanvasEnabled = true;
+ else if (argument == optionEnableDeferred2DCanvas)
+ deferred2DCanvasEnabled = true;
else if (argument == optionEnableAcceleratedPainting)
acceleratedPaintingEnabled = true;
else if (!argument.find(optionUseGraphicsContext3DImplementation)) {
@@ -236,6 +240,7 @@ int main(int argc, char* argv[])
shell.setCompositeToTexture(compositeToTexture);
shell.setForceCompositingMode(forceCompositingMode);
shell.setAccelerated2dCanvasEnabled(accelerated2DCanvasEnabled);
+ shell.setDeferred2dCanvasEnabled(deferred2DCanvasEnabled);
shell.setAcceleratedPaintingEnabled(acceleratedPaintingEnabled);
shell.setPerTilePaintingEnabled(perTilePaintingEnabled);
shell.setJavaScriptFlags(javaScriptFlags);
diff --git a/Tools/DumpRenderTree/chromium/MockWebSpeechInputController.cpp b/Tools/DumpRenderTree/chromium/MockWebSpeechInputController.cpp
index 0bea45b35..a5fe3eda6 100644
--- a/Tools/DumpRenderTree/chromium/MockWebSpeechInputController.cpp
+++ b/Tools/DumpRenderTree/chromium/MockWebSpeechInputController.cpp
@@ -124,7 +124,7 @@ static WebSpeechInputResultArray makeRectResult(const WebRect& rect)
sb.append(String::number(rect.height));
WebSpeechInputResult res;
- res.set(WebString(sb.characters(), sb.length()), 1.0);
+ res.assign(WebString(sb.characters(), sb.length()), 1.0);
WebSpeechInputResultArray results;
results.assign(&res, 1);
diff --git a/Tools/DumpRenderTree/chromium/TestShell.cpp b/Tools/DumpRenderTree/chromium/TestShell.cpp
index 501e78b7a..f576d2417 100644
--- a/Tools/DumpRenderTree/chromium/TestShell.cpp
+++ b/Tools/DumpRenderTree/chromium/TestShell.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Google Inc. All rights reserved.
+ * Copyright (C) 2012 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -110,6 +110,7 @@ TestShell::TestShell(bool testShellMode)
, m_compositeToTexture(false)
, m_forceCompositingMode(false)
, m_accelerated2dCanvasEnabled(false)
+ , m_deferred2dCanvasEnabled(false)
, m_acceleratedPaintingEnabled(false)
, m_perTilePaintingEnabled(false)
, m_stressOpt(false)
@@ -218,6 +219,7 @@ void TestShell::resetWebSettings(WebView& webView)
m_prefs.compositeToTexture = m_compositeToTexture;
m_prefs.forceCompositingMode = m_forceCompositingMode;
m_prefs.accelerated2dCanvasEnabled = m_accelerated2dCanvasEnabled;
+ m_prefs.deferred2dCanvasEnabled = m_deferred2dCanvasEnabled;
m_prefs.acceleratedPaintingEnabled = m_acceleratedPaintingEnabled;
m_prefs.perTilePaintingEnabled = m_perTilePaintingEnabled;
m_prefs.applyTo(&webView);
@@ -237,6 +239,7 @@ void TestShell::runFileTest(const TestParams& params)
if (testUrl.find("compositing/") != string::npos || testUrl.find("compositing\\") != string::npos) {
m_prefs.acceleratedCompositingForVideoEnabled = true;
m_prefs.accelerated2dCanvasEnabled = true;
+ m_prefs.deferred2dCanvasEnabled = true;
m_prefs.applyTo(m_webView);
}
diff --git a/Tools/DumpRenderTree/chromium/TestShell.h b/Tools/DumpRenderTree/chromium/TestShell.h
index 406fa7459..1ee5ce9a1 100644
--- a/Tools/DumpRenderTree/chromium/TestShell.h
+++ b/Tools/DumpRenderTree/chromium/TestShell.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Google Inc. All rights reserved.
+ * Copyright (C) 2012 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -136,6 +136,7 @@ public:
void setCompositeToTexture(bool enabled) { m_compositeToTexture = enabled; }
void setForceCompositingMode(bool enabled) { m_forceCompositingMode = enabled; }
void setAccelerated2dCanvasEnabled(bool enabled) { m_accelerated2dCanvasEnabled = enabled; }
+ void setDeferred2dCanvasEnabled(bool enabled) { m_deferred2dCanvasEnabled = enabled; }
void setAcceleratedPaintingEnabled(bool enabled) { m_acceleratedPaintingEnabled = enabled; }
void setPerTilePaintingEnabled(bool enabled) { m_perTilePaintingEnabled = enabled; }
#if defined(OS_WIN)
@@ -225,6 +226,7 @@ private:
bool m_compositeToTexture;
bool m_forceCompositingMode;
bool m_accelerated2dCanvasEnabled;
+ bool m_deferred2dCanvasEnabled;
bool m_acceleratedPaintingEnabled;
bool m_perTilePaintingEnabled;
WebPreferences m_prefs;
diff --git a/Tools/DumpRenderTree/chromium/WebPreferences.cpp b/Tools/DumpRenderTree/chromium/WebPreferences.cpp
index f90a1d070..872ebfb4a 100644
--- a/Tools/DumpRenderTree/chromium/WebPreferences.cpp
+++ b/Tools/DumpRenderTree/chromium/WebPreferences.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Google Inc. All rights reserved.
+ * Copyright (C) 2012 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -112,6 +112,7 @@ void WebPreferences::reset()
acceleratedCompositingEnabled = false;
compositeToTexture = false;
accelerated2dCanvasEnabled = false;
+ deferred2dCanvasEnabled = false;
acceleratedPaintingEnabled = false;
forceCompositingMode = false;
hixie76WebSocketProtocolEnabled = true;
@@ -217,6 +218,7 @@ void WebPreferences::applyTo(WebView* webView)
settings->setCompositeToTextureEnabled(compositeToTexture);
settings->setForceCompositingMode(forceCompositingMode);
settings->setAccelerated2dCanvasEnabled(accelerated2dCanvasEnabled);
+ settings->setDeferred2dCanvasEnabled(deferred2dCanvasEnabled);
settings->setAcceleratedPaintingEnabled(acceleratedPaintingEnabled);
settings->setHixie76WebSocketProtocolEnabled(hixie76WebSocketProtocolEnabled);
settings->setPerTilePaintingEnabled(perTilePaintingEnabled);
diff --git a/Tools/DumpRenderTree/chromium/WebPreferences.h b/Tools/DumpRenderTree/chromium/WebPreferences.h
index d39abfb6c..ee04a2094 100644
--- a/Tools/DumpRenderTree/chromium/WebPreferences.h
+++ b/Tools/DumpRenderTree/chromium/WebPreferences.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Google Inc. All rights reserved.
+ * Copyright (C) 2012 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -106,6 +106,7 @@ struct WebPreferences {
bool compositeToTexture;
bool forceCompositingMode;
bool accelerated2dCanvasEnabled;
+ bool deferred2dCanvasEnabled;
bool acceleratedPaintingEnabled;
bool hixie76WebSocketProtocolEnabled;
bool perTilePaintingEnabled;
diff --git a/Tools/DumpRenderTree/chromium/WebViewHost.cpp b/Tools/DumpRenderTree/chromium/WebViewHost.cpp
index 32b20dbf0..befa3b718 100644
--- a/Tools/DumpRenderTree/chromium/WebViewHost.cpp
+++ b/Tools/DumpRenderTree/chromium/WebViewHost.cpp
@@ -471,7 +471,10 @@ void WebViewHost::finishLastTextCheck()
m_spellcheck.spellCheckWord(WebString(text.characters(), text.length()), &misspelledPosition, &misspelledLength);
if (!misspelledLength)
break;
- results.append(WebTextCheckingResult(WebTextCheckingResult::ErrorSpelling, offset + misspelledPosition, misspelledLength));
+ Vector<WebString> suggestions;
+ m_spellcheck.fillSuggestionList(WebString(text.characters() + misspelledPosition, misspelledLength), &suggestions);
+ results.append(WebTextCheckingResult(WebTextCheckingTypeSpelling, offset + misspelledPosition, misspelledLength,
+ suggestions.isEmpty() ? WebString() : suggestions[0]));
text = text.substring(misspelledPosition + misspelledLength);
offset += misspelledPosition + misspelledLength;
}
diff --git a/Tools/DumpRenderTree/efl/CMakeLists.txt b/Tools/DumpRenderTree/efl/CMakeLists.txt
index 0dae16879..09726f628 100644
--- a/Tools/DumpRenderTree/efl/CMakeLists.txt
+++ b/Tools/DumpRenderTree/efl/CMakeLists.txt
@@ -123,12 +123,12 @@ ADD_DEFINITIONS(-DFONTS_CONF_DIR="${TOOLS_DIR}/DumpRenderTree/gtk/fonts"
INCLUDE_DIRECTORIES(${DumpRenderTree_INCLUDE_DIRECTORIES})
-ADD_EXECUTABLE(Programs/DumpRenderTree ${DumpRenderTree_SOURCES})
-TARGET_LINK_LIBRARIES(Programs/DumpRenderTree ${DumpRenderTree_LIBRARIES})
-ADD_TARGET_PROPERTIES(Programs/DumpRenderTree LINK_FLAGS "${DumpRenderTree_LINK_FLAGS}")
-SET_TARGET_PROPERTIES(Programs/DumpRenderTree PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}")
+ADD_EXECUTABLE(bin/DumpRenderTree ${DumpRenderTree_SOURCES})
+TARGET_LINK_LIBRARIES(bin/DumpRenderTree ${DumpRenderTree_LIBRARIES})
+ADD_TARGET_PROPERTIES(bin/DumpRenderTree LINK_FLAGS "${DumpRenderTree_LINK_FLAGS}")
+SET_TARGET_PROPERTIES(bin/DumpRenderTree PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}")
-ADD_EXECUTABLE(Programs/ImageDiff ${ImageDiff_SOURCES})
-TARGET_LINK_LIBRARIES(Programs/ImageDiff ${DumpRenderTree_LIBRARIES})
-ADD_TARGET_PROPERTIES(Programs/ImageDiff LINK_FLAGS "${DumpRenderTree_LINK_FLAGS}")
-SET_TARGET_PROPERTIES(Programs/ImageDiff PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}")
+ADD_EXECUTABLE(bin/ImageDiff ${ImageDiff_SOURCES})
+TARGET_LINK_LIBRARIES(bin/ImageDiff ${DumpRenderTree_LIBRARIES})
+ADD_TARGET_PROPERTIES(bin/ImageDiff LINK_FLAGS "${DumpRenderTree_LINK_FLAGS}")
+SET_TARGET_PROPERTIES(bin/ImageDiff PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}")
diff --git a/Tools/DumpRenderTree/mac/DumpRenderTree.mm b/Tools/DumpRenderTree/mac/DumpRenderTree.mm
index b735a965b..3012a70d8 100644
--- a/Tools/DumpRenderTree/mac/DumpRenderTree.mm
+++ b/Tools/DumpRenderTree/mac/DumpRenderTree.mm
@@ -1146,10 +1146,8 @@ void dump()
WebArchive *webArchive = [[mainFrame dataSource] webArchive];
resultString = HardAutorelease(createXMLStringFromWebArchiveData((CFDataRef)[webArchive data]));
resultMimeType = @"application/x-webarchive";
- } else {
- sizeWebViewForCurrentTest();
+ } else
resultString = [mainFrame renderTreeAsExternalRepresentationForPrinting:gLayoutTestController->isPrinting()];
- }
if (resultString && !resultData)
resultData = [resultString dataUsingEncoding:NSUTF8StringEncoding];
@@ -1303,6 +1301,7 @@ static void runTest(const string& testPathOrURL)
releaseAndZero(&draggingInfo);
done = NO;
+ sizeWebViewForCurrentTest();
gLayoutTestController->setIconDatabaseEnabled(false);
if (disallowedURLs)
diff --git a/Tools/DumpRenderTree/mac/EventSendingController.mm b/Tools/DumpRenderTree/mac/EventSendingController.mm
index 1c651f270..76ac69267 100644
--- a/Tools/DumpRenderTree/mac/EventSendingController.mm
+++ b/Tools/DumpRenderTree/mac/EventSendingController.mm
@@ -131,6 +131,7 @@ BOOL replayingSavedEvents;
|| aSelector == @selector(mouseMoveToX:Y:)
|| aSelector == @selector(mouseUp:withModifiers:)
|| aSelector == @selector(scheduleAsynchronousClick)
+ || aSelector == @selector(scheduleAsynchronousKeyDown:withModifiers:withLocation:)
|| aSelector == @selector(textZoomIn)
|| aSelector == @selector(textZoomOut)
|| aSelector == @selector(zoomPageIn)
@@ -161,6 +162,8 @@ BOOL replayingSavedEvents;
return @"fireKeyboardEventsToElement";
if (aSelector == @selector(keyDown:withModifiers:withLocation:))
return @"keyDown";
+ if (aSelector == @selector(scheduleAsynchronousKeyDown:withModifiers:withLocation:))
+ return @"scheduleAsynchronousKeyDown";
if (aSelector == @selector(leapForward:))
return @"leapForward";
if (aSelector == @selector(mouseDown:withModifiers:))
@@ -722,6 +725,23 @@ static int buildModifierFlags(const WebScriptObject* modifiers)
[[[[mainFrame webView] window] firstResponder] keyUp:event];
}
+- (void)keyDownWrapper:(NSString *)character withModifiers:(WebScriptObject *)modifiers withLocation:(unsigned long)keyLocation
+{
+ [self keyDown:character withModifiers:modifiers withLocation:keyLocation];
+}
+
+- (void)scheduleAsynchronousKeyDown:(NSString *)character withModifiers:(WebScriptObject *)modifiers withLocation:(unsigned long)keyLocation
+{
+ NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[EventSendingController instanceMethodSignatureForSelector:@selector(keyDownWrapper:withModifiers:withLocation:)]];
+ [invocation retainArguments];
+ [invocation setTarget:self];
+ [invocation setSelector:@selector(keyDownWrapper:withModifiers:withLocation:)];
+ [invocation setArgument:&character atIndex:2];
+ [invocation setArgument:&modifiers atIndex:3];
+ [invocation setArgument:&keyLocation atIndex:4];
+ [invocation performSelector:@selector(invoke) withObject:nil afterDelay:0];
+}
+
- (void)enableDOMUIEventLogging:(WebScriptObject *)node
{
NSEnumerator *eventEnumerator = [webkitDomEventNames objectEnumerator];
diff --git a/Tools/DumpRenderTree/qt/DumpRenderTreeQt.cpp b/Tools/DumpRenderTree/qt/DumpRenderTreeQt.cpp
index 21da8d04b..d5463867a 100644
--- a/Tools/DumpRenderTree/qt/DumpRenderTreeQt.cpp
+++ b/Tools/DumpRenderTree/qt/DumpRenderTreeQt.cpp
@@ -1138,4 +1138,14 @@ QList<WebPage*> DumpRenderTree::getAllPages() const
return pages;
}
+void DumpRenderTree::setTimeout(int timeout)
+{
+ m_controller->setTimeout(timeout);
+}
+
+void DumpRenderTree::setShouldTimeout(bool flag)
+{
+ m_controller->setShouldTimeout(flag);
+}
+
}
diff --git a/Tools/DumpRenderTree/qt/DumpRenderTreeQt.h b/Tools/DumpRenderTree/qt/DumpRenderTreeQt.h
index 5e1d6b4b2..1de1cb94c 100644
--- a/Tools/DumpRenderTree/qt/DumpRenderTreeQt.h
+++ b/Tools/DumpRenderTree/qt/DumpRenderTreeQt.h
@@ -106,6 +106,9 @@ public:
void setRedirectOutputFileName(const QString& fileName) { m_redirectOutputFileName = fileName; }
void setRedirectErrorFileName(const QString& fileName) { m_redirectErrorFileName = fileName; }
+ void setTimeout(int);
+ void setShouldTimeout(bool flag);
+
public Q_SLOTS:
void initJSObjects();
diff --git a/Tools/DumpRenderTree/qt/LayoutTestControllerQt.cpp b/Tools/DumpRenderTree/qt/LayoutTestControllerQt.cpp
index 722bf770f..037668034 100644
--- a/Tools/DumpRenderTree/qt/LayoutTestControllerQt.cpp
+++ b/Tools/DumpRenderTree/qt/LayoutTestControllerQt.cpp
@@ -41,6 +41,8 @@
LayoutTestController::LayoutTestController(WebCore::DumpRenderTree* drt)
: QObject()
, m_drt(drt)
+ , m_shouldTimeout(true)
+ , m_timeout(30000)
{
reset();
DumpRenderTreeSupportQt::dumpNotification(true);
@@ -146,7 +148,11 @@ void LayoutTestController::waitUntilDone()
{
//qDebug() << ">>>>waitForDone";
m_waitForDone = true;
- m_timeoutTimer.start(30000, this);
+
+ if (!m_shouldTimeout)
+ return;
+
+ m_timeoutTimer.start(m_timeout, this);
}
QString LayoutTestController::counterValueForElementById(const QString& id)
@@ -178,7 +184,7 @@ void LayoutTestController::notifyDone()
{
qDebug() << ">>>>notifyDone";
- if (!m_timeoutTimer.isActive())
+ if (m_shouldTimeout && !m_timeoutTimer.isActive())
return;
m_timeoutTimer.stop();
diff --git a/Tools/DumpRenderTree/qt/LayoutTestControllerQt.h b/Tools/DumpRenderTree/qt/LayoutTestControllerQt.h
index a543e4519..8c5d6e280 100644
--- a/Tools/DumpRenderTree/qt/LayoutTestControllerQt.h
+++ b/Tools/DumpRenderTree/qt/LayoutTestControllerQt.h
@@ -80,6 +80,9 @@ public:
static const unsigned int maxViewWidth;
static const unsigned int maxViewHeight;
+ void setTimeout(int timeout) { m_timeout = timeout; }
+ void setShouldTimeout(bool flag) { m_shouldTimeout = flag; }
+
protected:
void timerEvent(QTimerEvent*);
@@ -317,6 +320,9 @@ private:
QWebHistory* m_webHistory;
QStringList m_desktopNotificationAllowedOrigins;
bool m_ignoreDesktopNotification;
+
+ bool m_shouldTimeout;
+ int m_timeout;
};
#endif // LayoutTestControllerQt_h
diff --git a/Tools/DumpRenderTree/qt/main.cpp b/Tools/DumpRenderTree/qt/main.cpp
index bf5bcf31e..b562108c8 100644
--- a/Tools/DumpRenderTree/qt/main.cpp
+++ b/Tools/DumpRenderTree/qt/main.cpp
@@ -73,6 +73,7 @@ bool isOption(const QString& str)
{
return str == QString("-v") || str == QString("--pixel-tests")
|| str == QString("--stdout") || str == QString("--stderr")
+ || str == QString("--timeout") || str == QString("--no-timeout")
|| str == QString("-");
}
@@ -89,7 +90,7 @@ QString takeOptionValue(QStringList& arguments, int index)
void printUsage()
{
- fprintf(stderr, "Usage: DumpRenderTree [-v|--pixel-tests] [--stdout output_filename] [-stderr error_filename] filename [filename2..n]\n");
+ fprintf(stderr, "Usage: DumpRenderTree [-v|--pixel-tests] [--stdout output_filename] [-stderr error_filename] [--no-timeout] [--timeout timeout_MS] filename [filename2..n]\n");
fprintf(stderr, "Or folder containing test files: DumpRenderTree [-v|--pixel-tests] dirpath\n");
fflush(stderr);
}
@@ -149,6 +150,7 @@ int main(int argc, char* argv[])
QApplication::setStyle(new QWindowsStyle);
QApplication app(argc, argv);
+ app.setQuitOnLastWindowClosed(false);
#if QT_VERSION <= QT_VERSION_CHECK(5, 0, 0) // FIXME: need a way to port this to Qt5.
#ifdef Q_WS_X11
@@ -212,6 +214,19 @@ int main(int argc, char* argv[])
}
QWebDatabase::removeAllDatabases();
+ index = args.indexOf(QLatin1String("--timeout"));
+ if (index != -1) {
+ int timeout = takeOptionValue(args, index).toInt();
+ dumper.setTimeout(timeout);
+ args.removeAt(index);
+ }
+
+ index = args.indexOf(QLatin1String("--no-timeout"));
+ if (index != -1) {
+ dumper.setShouldTimeout(false);
+ args.removeAt(index);
+ }
+
index = args.indexOf(QLatin1String("-"));
if (index != -1) {
args.removeAt(index);
diff --git a/Tools/EWebLauncher/CMakeLists.txt b/Tools/EWebLauncher/CMakeLists.txt
index 69ac7bf4f..c2da94039 100644
--- a/Tools/EWebLauncher/CMakeLists.txt
+++ b/Tools/EWebLauncher/CMakeLists.txt
@@ -52,7 +52,7 @@ ENDIF ()
ADD_DEFINITIONS(-DDATA_DIR=\"${THEME_BINARY_DIR}\")
INCLUDE_DIRECTORIES(${EWebLauncher_INCLUDE_DIRECTORIES})
-ADD_EXECUTABLE(Programs/EWebLauncher ${EWebLauncher_SOURCES})
-TARGET_LINK_LIBRARIES(Programs/EWebLauncher ${EWebLauncher_LIBRARIES})
-ADD_TARGET_PROPERTIES(Programs/EWebLauncher LINK_FLAGS "${EWebLauncher_LINK_FLAGS}")
-SET_TARGET_PROPERTIES(Programs/EWebLauncher PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}")
+ADD_EXECUTABLE(bin/EWebLauncher ${EWebLauncher_SOURCES})
+TARGET_LINK_LIBRARIES(bin/EWebLauncher ${EWebLauncher_LIBRARIES})
+ADD_TARGET_PROPERTIES(bin/EWebLauncher LINK_FLAGS "${EWebLauncher_LINK_FLAGS}")
+SET_TARGET_PROPERTIES(bin/EWebLauncher PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}")
diff --git a/Tools/GNUmakefile.am b/Tools/GNUmakefile.am
index a91964926..fc8ed6be0 100644
--- a/Tools/GNUmakefile.am
+++ b/Tools/GNUmakefile.am
@@ -65,6 +65,7 @@ libWebCoreInternals_la_CPPFLAGS = \
$(javascriptcore_cppflags) \
$(CAIRO_CFLAGS) \
$(LIBSOUP_CFLAGS) \
+ $(PANGO_CFLAGS) \
-I$(top_builddir)/DerivedSources \
-I$(top_builddir)/DerivedSources/WebCore
@@ -325,6 +326,7 @@ if ENABLE_WEBKIT2
fi; \
fi
endif
+ $(srcdir)/Tools/gtk/generate-gtkdoc --rebase --virtual-root=$${DESTDIR}
uninstall-local:
@DOC_MODULE_VERSION=`cat ./Documentation/webkitgtk/version.xml`; \
diff --git a/Tools/MiniBrowser/gtk/BrowserWindow.c b/Tools/MiniBrowser/gtk/BrowserWindow.c
index e04ab0b06..4d6bde488 100644
--- a/Tools/MiniBrowser/gtk/BrowserWindow.c
+++ b/Tools/MiniBrowser/gtk/BrowserWindow.c
@@ -235,6 +235,26 @@ static gboolean webViewLoadFailed(WebKitWebView *webView, WebKitLoadEvent loadEv
return FALSE;
}
+static gboolean webViewDecidePolicy(WebKitWebView *webView, WebKitPolicyDecision *decision, WebKitPolicyDecisionType decisionType, BrowserWindow *window)
+{
+ if (decisionType != WEBKIT_POLICY_DECISION_TYPE_NAVIGATION_ACTION)
+ return FALSE;
+
+ WebKitNavigationPolicyDecision *navigationDecision = WEBKIT_NAVIGATION_POLICY_DECISION(decision);
+ if (webkit_navigation_policy_decision_get_navigation_type(navigationDecision) != WEBKIT_NAVIGATION_TYPE_LINK_CLICKED
+ || webkit_navigation_policy_decision_get_mouse_button(navigationDecision) != 2)
+ return FALSE;
+
+ WebKitWebView *newWebView = WEBKIT_WEB_VIEW(webkit_web_view_new_with_context(webkit_web_view_get_context(webView)));
+ webkit_web_view_set_settings(newWebView, webkit_web_view_get_settings(webView));
+ GtkWidget *newWindow = browser_window_new(newWebView);
+ webkit_web_view_load_request(newWebView, webkit_navigation_policy_decision_get_request(navigationDecision));
+ gtk_widget_show(newWindow);
+
+ webkit_policy_decision_ignore(decision);
+ return TRUE;
+}
+
static void browserWindowFinalize(GObject *gObject)
{
G_OBJECT_CLASS(browser_window_parent_class)->finalize(gObject);
@@ -333,6 +353,7 @@ static void browserWindowConstructed(GObject *gObject)
g_signal_connect(window->webView, "notify::title", G_CALLBACK(webViewTitleChanged), window);
g_signal_connect(window->webView, "create", G_CALLBACK(webViewCreate), window);
g_signal_connect(window->webView, "load-failed", G_CALLBACK(webViewLoadFailed), window);
+ g_signal_connect(window->webView, "decide-policy", G_CALLBACK(webViewDecidePolicy), window);
WebKitBackForwardList *backForwadlist = webkit_web_view_get_back_forward_list(window->webView);
g_signal_connect(backForwadlist, "changed", G_CALLBACK(backForwadlistChanged), window);
diff --git a/Tools/MiniBrowser/gtk/GNUmakefile.am b/Tools/MiniBrowser/gtk/GNUmakefile.am
index 8a3b87e0f..2a020f6e5 100644
--- a/Tools/MiniBrowser/gtk/GNUmakefile.am
+++ b/Tools/MiniBrowser/gtk/GNUmakefile.am
@@ -1,10 +1,6 @@
noinst_PROGRAMS += \
Programs/MiniBrowser
-minibrowser_built_sources += \
- DerivedSources/WebKit2/BrowserMarshal.h \
- DerivedSources/WebKit2/BrowserMarshal.c
-
Programs_MiniBrowser_CPPFLAGS = \
-I$(srcdir)/Source \
-I$(top_builddir)/DerivedSources/WebKit2 \
@@ -16,7 +12,6 @@ Programs_MiniBrowser_CPPFLAGS = \
$(GTK_CFLAGS)
Programs_MiniBrowser_SOURCES = \
- $(minibrowser_built_sources) \
Tools/MiniBrowser/gtk/BrowserCellRendererVariant.h \
Tools/MiniBrowser/gtk/BrowserCellRendererVariant.c \
Tools/MiniBrowser/gtk/BrowserSettingsDialog.h \
@@ -25,6 +20,12 @@ Programs_MiniBrowser_SOURCES = \
Tools/MiniBrowser/gtk/BrowserWindow.c \
Tools/MiniBrowser/gtk/main.c
+minibrowser_built_sources += \
+ DerivedSources/WebKit2/BrowserMarshal.h \
+ DerivedSources/WebKit2/BrowserMarshal.c
+nodist_Programs_MiniBrowser_SOURCES = \
+ $(minibrowser_built_sources)
+
Programs_MiniBrowser_LDADD = \
libwebkit2gtk-@WEBKITGTK_API_MAJOR_VERSION@.@WEBKITGTK_API_MINOR_VERSION@.la \
$(GLIB_LIBS) \
diff --git a/Tools/MiniBrowser/qt/BrowserWindow.cpp b/Tools/MiniBrowser/qt/BrowserWindow.cpp
index a768581dc..639cd4f0e 100644
--- a/Tools/MiniBrowser/qt/BrowserWindow.cpp
+++ b/Tools/MiniBrowser/qt/BrowserWindow.cpp
@@ -54,8 +54,6 @@ BrowserWindow::BrowserWindow(WindowOptions* options)
setSource(QUrl("qrc:/qml/BrowserWindow.qml"));
connect(rootObject(), SIGNAL(pageTitleChanged(QString)), this, SLOT(setWindowTitle(QString)));
connect(rootObject(), SIGNAL(newWindow(QString)), this, SLOT(newWindow(QString)));
- if (options->useTraditionalDesktopBehavior())
- webView()->experimental()->setUseTraditionalDesktopBehaviour(true);
if (options->startFullScreen())
showFullScreen();
else {
@@ -110,12 +108,14 @@ void BrowserWindow::updateVisualMockTouchPoints(const QList<QWindowSystemInterfa
mockTouchPointItem->setParentItem(rootObject());
}
- QPointF position = touchPoint.area.topLeft();
+ QPointF position = touchPoint.area.center();
position.rx() -= geometry().x();
position.ry() -= geometry().y();
mockTouchPointItem->setX(position.x());
mockTouchPointItem->setY(position.y());
+ mockTouchPointItem->setWidth(touchPoint.area.width());
+ mockTouchPointItem->setHeight(touchPoint.area.height());
mockTouchPointItem->setProperty("pressed", QVariant(touchPoint.state != Qt::TouchPointReleased));
}
}
diff --git a/Tools/MiniBrowser/qt/MiniBrowserApplication.cpp b/Tools/MiniBrowser/qt/MiniBrowserApplication.cpp
index 88260b8cc..57a55928b 100644
--- a/Tools/MiniBrowser/qt/MiniBrowserApplication.cpp
+++ b/Tools/MiniBrowser/qt/MiniBrowserApplication.cpp
@@ -29,6 +29,7 @@
#include "MiniBrowserApplication.h"
#include "BrowserWindow.h"
+#include "qquickwebview_p.h"
#include "utils.h"
#include <QRegExp>
#include <QEvent>
@@ -124,7 +125,7 @@ bool MiniBrowserApplication::notify(QObject* target, QEvent* event)
const QMouseEvent* const mouseEvent = static_cast<QMouseEvent*>(event);
QWindowSystemInterface::TouchPoint touchPoint;
- touchPoint.area = QRectF(mouseEvent->globalPos(), QSizeF(1, 1));
+ touchPoint.area = QRectF(mouseEvent->globalPos() - QPointF(30, 40), QSizeF(60, 80));
touchPoint.pressure = 1;
switch (mouseEvent->type()) {
@@ -182,7 +183,7 @@ void MiniBrowserApplication::sendTouchEvent(BrowserWindow* browserWindow)
QWindowSystemInterface::handleTouchEvent(browserWindow, device, m_touchPoints.values());
bool holdingControl = QApplication::keyboardModifiers().testFlag(Qt::ControlModifier);
- if (!m_windowOptions.useTraditionalDesktopBehavior())
+ if (QQuickWebViewExperimental::flickableViewportEnabled())
browserWindow->updateVisualMockTouchPoints(holdingControl ? m_touchPoints.values() : QList<QWindowSystemInterface::TouchPoint>());
// Get rid of touch-points that are no longer valid
@@ -220,9 +221,9 @@ void MiniBrowserApplication::handleUserOptions()
}
const bool useDesktopBehavior = takeOptionFlag(&args, "--desktop");
+ QQuickWebViewExperimental::setFlickableViewportEnabled(!useDesktopBehavior);
if (!useDesktopBehavior)
qputenv("QT_WEBKIT_USE_MOBILE_THEME", QByteArray("1"));
- m_windowOptions.setUseTraditionalDesktopBehavior(useDesktopBehavior);
m_windowOptions.setPrintLoadedUrls(takeOptionFlag(&args, "-v"));
m_windowOptions.setStartMaximized(takeOptionFlag(&args, "--maximize"));
m_windowOptions.setStartFullScreen(takeOptionFlag(&args, "-f"));
diff --git a/Tools/MiniBrowser/qt/MiniBrowserApplication.h b/Tools/MiniBrowser/qt/MiniBrowserApplication.h
index 43f83cfe1..b5565855e 100644
--- a/Tools/MiniBrowser/qt/MiniBrowserApplication.h
+++ b/Tools/MiniBrowser/qt/MiniBrowserApplication.h
@@ -43,7 +43,6 @@ class BrowserWindow;
class WindowOptions : public QObject {
Q_OBJECT
Q_PROPERTY(bool printLoadedUrls READ printLoadedUrls)
- Q_PROPERTY(bool useTraditionalDesktopBehavior READ useTraditionalDesktopBehavior)
Q_PROPERTY(bool startMaximized READ startMaximized)
Q_PROPERTY(bool touchMockingEnabled READ touchMockingEnabled WRITE setTouchMockingEnabled NOTIFY touchMockingEnabledChanged)
@@ -51,7 +50,6 @@ public:
WindowOptions(QObject* parent = 0)
: QObject(parent)
, m_printLoadedUrls(false)
- , m_useTraditionalDesktopBehavior(false)
, m_startMaximized(false)
, m_touchMockingEnabled(true)
, m_windowSize(QSize(980, 735))
@@ -60,8 +58,6 @@ public:
void setPrintLoadedUrls(bool enabled) { m_printLoadedUrls = enabled; }
bool printLoadedUrls() const { return m_printLoadedUrls; }
- void setUseTraditionalDesktopBehavior(bool enabled) { m_useTraditionalDesktopBehavior = enabled; }
- bool useTraditionalDesktopBehavior() const { return m_useTraditionalDesktopBehavior; }
void setStartMaximized(bool enabled) { m_startMaximized = enabled; }
bool startMaximized() const { return m_startMaximized; }
void setStartFullScreen(bool enabled) { m_startFullScreen = enabled; }
@@ -82,7 +78,6 @@ signals:
private:
bool m_printLoadedUrls;
- bool m_useTraditionalDesktopBehavior;
bool m_startMaximized;
bool m_startFullScreen;
bool m_touchMockingEnabled;
diff --git a/Tools/MiniBrowser/qt/qml/BrowserWindow.qml b/Tools/MiniBrowser/qt/qml/BrowserWindow.qml
index c080ed3ea..65999dd32 100644
--- a/Tools/MiniBrowser/qt/qml/BrowserWindow.qml
+++ b/Tools/MiniBrowser/qt/qml/BrowserWindow.qml
@@ -28,7 +28,7 @@
import QtQuick 2.0
import QtWebKit 3.0
-import QtWebKit.experimental 3.0
+import QtWebKit.experimental 1.0
Rectangle {
// Do not define anchors or an initial size here! This would mess up with QSGView::SizeRootObjectToView.
diff --git a/Tools/MiniBrowser/qt/qml/MockTouchPoint.qml b/Tools/MiniBrowser/qt/qml/MockTouchPoint.qml
index fd05156da..4cc5c2c66 100644
--- a/Tools/MiniBrowser/qt/qml/MockTouchPoint.qml
+++ b/Tools/MiniBrowser/qt/qml/MockTouchPoint.qml
@@ -37,7 +37,9 @@ Item {
source: "../icons/touchpoint.png"
x: -(width / 2)
y: -(height / 2)
- opacity: parent.pressed ? 0.8 : 0.0
+ height: parent.height
+ width: parent.width
+ opacity: parent.pressed ? 0.6 : 0.0
Behavior on opacity {
NumberAnimation { duration: 200 }
diff --git a/Tools/Scripts/build-webkit b/Tools/Scripts/build-webkit
index 27a084ee2..021a0bb82 100755
--- a/Tools/Scripts/build-webkit
+++ b/Tools/Scripts/build-webkit
@@ -195,9 +195,6 @@ my @features = (
{ option => "directory-upload", desc => "Toogle Directory upload support",
define => "ENABLE_DIRECTORY_UPLOAD", default => 0, value => \$directoryUploadSupport },
- { option => "mutation-observers", desc => "Toggle DOM mutation observer support",
- define => "ENABLE_MUTATION_OBSERVERS", default => 0, value => \$mutationObserversSupport },
-
{ option => "file-system", desc => "Toggle FileSystem support",
define => "ENABLE_FILE_SYSTEM", default => 0, value => \$fileSystemSupport },
@@ -273,6 +270,9 @@ my @features = (
{ option => "microdata", desc => "Toggle Microdata support",
define => "ENABLE_MICRODATA", default => 0, value => \$microdataSupport },
+ { option => "mutation-observers", desc => "Toggle DOM mutation observer support",
+ define => "ENABLE_MUTATION_OBSERVERS", default => 0, value => \$mutationObserversSupport },
+
{ option => "netscape-plugin", desc => "Netscape Plugin support",
define => "ENABLE_NETSCAPE_PLUGIN_API", default => !isEfl(), value => \$netscapePluginSupport },
diff --git a/Tools/Scripts/run-launcher b/Tools/Scripts/run-launcher
index 15bd0093f..c2a47dd1f 100755
--- a/Tools/Scripts/run-launcher
+++ b/Tools/Scripts/run-launcher
@@ -72,7 +72,7 @@ if (isQt()) {
}
if (isEfl()) {
- $launcherPath = catdir($launcherPath, "Programs", "EWebLauncher");
+ $launcherPath = catdir($launcherPath, "bin", "EWebLauncher");
}
if (isWx()) {
diff --git a/Tools/Scripts/update-webkit-auxiliary-libs b/Tools/Scripts/update-webkit-auxiliary-libs
index d301938e4..1bb99d5f6 100755
--- a/Tools/Scripts/update-webkit-auxiliary-libs
+++ b/Tools/Scripts/update-webkit-auxiliary-libs
@@ -34,7 +34,7 @@ use FindBin;
my $file = "WebKitAuxiliaryLibrary";
my $zipFile = "$file.zip";
-my $auxiliaryLibsURL = "http://developer.apple.com/opensource/internet/$zipFile";
+my $auxiliaryLibsURL = "https://developer.apple.com/opensource/internet/$zipFile";
my $command = "$FindBin::Bin/update-webkit-dependency";
system("perl", $command, $auxiliaryLibsURL, "win") == 0 or die;
diff --git a/Tools/Scripts/update-webkit-dependency b/Tools/Scripts/update-webkit-dependency
index 1ad4d6dc7..075691229 100755
--- a/Tools/Scripts/update-webkit-dependency
+++ b/Tools/Scripts/update-webkit-dependency
@@ -73,7 +73,7 @@ my $tmpAbsDir = File::Spec->rel2abs($tmpRelativeDir);
print "Checking Last-Modified date of $zipFile...\n";
-my $result = system "curl -s -I $libsURL | grep Last-Modified > \"$tmpAbsDir/$file.headers\"";
+my $result = system "curl -s -I -k --sslv3 $libsURL | grep Last-Modified > \"$tmpAbsDir/$file.headers\"";
if (WEXITSTATUS($result)) {
print STDERR "Couldn't check Last-Modified date of new $zipFile.\n";
@@ -103,7 +103,7 @@ if (open NEW, "$tmpAbsDir/$file.headers") {
}
print "Downloading $zipFile...\n\n";
-$result = system "curl -o \"$tmpAbsDir/$zipFile\" $libsURL";
+$result = system "curl -k --sslv3 -o \"$tmpAbsDir/$zipFile\" $libsURL";
die "Couldn't download $zipFile!" if $result;
$result = system "unzip", "-q", "-d", $tmpAbsDir, "$tmpAbsDir/$zipFile";
diff --git a/Tools/Scripts/update-webkit-support-libs b/Tools/Scripts/update-webkit-support-libs
index 8484f84fd..afced1d28 100755
--- a/Tools/Scripts/update-webkit-support-libs
+++ b/Tools/Scripts/update-webkit-support-libs
@@ -51,7 +51,7 @@ my $versionFile = $file . "Version";
my $pathToVersionFile = File::Spec->catfile($webkitLibrariesDir, $versionFile);
my $tmpRelativeDir = File::Temp::tempdir("webkitlibsXXXXXXX", TMPDIR => 1, CLEANUP => 1);
my $tmpAbsDir = File::Spec->rel2abs($tmpRelativeDir);
-my $versionFileURL = "http://developer.apple.com/opensource/internet/$versionFile";
+my $versionFileURL = "https://developer.apple.com/opensource/internet/$versionFile";
my $extractedVersion = extractedVersion();
@@ -114,7 +114,7 @@ sub extractedVersion
sub downloadExpectedVersionNumber
{
- chomp(my $expectedVersion = `curl -s $versionFileURL`);
+ chomp(my $expectedVersion = `curl -s --sslv3 -k $versionFileURL`);
return WEXITSTATUS($?) ? NOTAVERSION : $expectedVersion;
}
@@ -135,7 +135,7 @@ sub dieAndInstructToDownload
$message
Please download $zipFile from:
- http://developer.apple.com/opensource/internet/webkit_sptlib_agree.html
+ https://developer.apple.com/opensource/internet/webkit_sptlib_agree.html
and place it in:
diff --git a/Tools/Scripts/webkitdirs.pm b/Tools/Scripts/webkitdirs.pm
index 92271199d..eda2b205f 100755
--- a/Tools/Scripts/webkitdirs.pm
+++ b/Tools/Scripts/webkitdirs.pm
@@ -453,8 +453,8 @@ sub productDir
sub jscProductDir
{
my $productDir = productDir();
- $productDir .= "/bin" if isQt();
- $productDir .= "/Programs" if (isGtk() || isEfl());
+ $productDir .= "/bin" if (isQt() || isEfl());
+ $productDir .= "/Programs" if isGtk();
return $productDir;
}
@@ -2309,9 +2309,13 @@ sub buildChromiumNinja($$@)
# rm -rf out requires rerunning gyp, so don't support --clean for now.
my ($target, @options) = @_;
my $config = configuration();
+ my $makeArgs;
+ for (@options) {
+ $makeArgs = $1 if /^--makeargs=(.*)/i;
+ }
my $command = "";
- $command .= "ninja -C out/$config $target";
+ $command .= "ninja -C out/$config $target $makeArgs";
print "$command\n";
return system $command;
diff --git a/Tools/Scripts/webkitpy/common/checkout/changelog_unittest.py b/Tools/Scripts/webkitpy/common/checkout/changelog_unittest.py
index 0221bcee9..db4a55b06 100644
--- a/Tools/Scripts/webkitpy/common/checkout/changelog_unittest.py
+++ b/Tools/Scripts/webkitpy/common/checkout/changelog_unittest.py
@@ -26,8 +26,6 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-from __future__ import with_statement
-
import codecs
import os
import tempfile
diff --git a/Tools/Scripts/webkitpy/common/checkout/checkout_unittest.py b/Tools/Scripts/webkitpy/common/checkout/checkout_unittest.py
index 3b0943247..78d25cb31 100644
--- a/Tools/Scripts/webkitpy/common/checkout/checkout_unittest.py
+++ b/Tools/Scripts/webkitpy/common/checkout/checkout_unittest.py
@@ -26,8 +26,6 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-from __future__ import with_statement
-
import codecs
import os
import shutil
diff --git a/Tools/Scripts/webkitpy/common/checkout/scm/git.py b/Tools/Scripts/webkitpy/common/checkout/scm/git.py
index 866b24cc4..ab96b8fa7 100644
--- a/Tools/Scripts/webkitpy/common/checkout/scm/git.py
+++ b/Tools/Scripts/webkitpy/common/checkout/scm/git.py
@@ -34,7 +34,6 @@ import re
from webkitpy.common.memoized import memoized
from webkitpy.common.system.deprecated_logging import log
from webkitpy.common.system.executive import Executive, ScriptError
-from webkitpy.common.system import ospath
from .commitmessage import CommitMessage
from .scm import AuthenticationError, SCM, commit_error_handler
@@ -229,9 +228,9 @@ class Git(SCM, SVNRepository):
def display_name(self):
return "git"
- def head_svn_revision(self):
+ def svn_revision(self, path):
_log.debug('Running git.head_svn_revision... (Temporary logging message)')
- git_log = self.run(['git', 'log', '-25'])
+ git_log = self.run(['git', 'log', '-25', path])
match = re.search("^\s*git-svn-id:.*@(?P<svn_revision>\d+)\ ", git_log, re.MULTILINE)
if not match:
return ""
diff --git a/Tools/Scripts/webkitpy/common/checkout/scm/scm.py b/Tools/Scripts/webkitpy/common/checkout/scm/scm.py
index 4b581b17f..432d6ca99 100644
--- a/Tools/Scripts/webkitpy/common/checkout/scm/scm.py
+++ b/Tools/Scripts/webkitpy/common/checkout/scm/scm.py
@@ -182,6 +182,9 @@ class SCM:
self._subclass_must_implement()
def head_svn_revision(self):
+ return self.svn_revision(self.checkout_root)
+
+ def svn_revision(self, path):
self._subclass_must_implement()
def create_patch(self, git_commit=None, changed_files=None):
diff --git a/Tools/Scripts/webkitpy/common/checkout/scm/scm_mock.py b/Tools/Scripts/webkitpy/common/checkout/scm/scm_mock.py
index 78af67c98..f203cfa1a 100644
--- a/Tools/Scripts/webkitpy/common/checkout/scm/scm_mock.py
+++ b/Tools/Scripts/webkitpy/common/checkout/scm/scm_mock.py
@@ -68,6 +68,9 @@ class MockSCM(object):
def head_svn_revision(self):
return 1234
+ def svn_revision(self, path):
+ return 5678
+
def create_patch(self, git_commit, changed_files=None):
return "Patch1"
diff --git a/Tools/Scripts/webkitpy/common/checkout/scm/scm_unittest.py b/Tools/Scripts/webkitpy/common/checkout/scm/scm_unittest.py
index 209bd3510..b835cdf67 100644
--- a/Tools/Scripts/webkitpy/common/checkout/scm/scm_unittest.py
+++ b/Tools/Scripts/webkitpy/common/checkout/scm/scm_unittest.py
@@ -28,8 +28,6 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-from __future__ import with_statement
-
import atexit
import base64
import codecs
diff --git a/Tools/Scripts/webkitpy/common/checkout/scm/svn.py b/Tools/Scripts/webkitpy/common/checkout/scm/svn.py
index 3f583a7d3..edeee30ae 100644
--- a/Tools/Scripts/webkitpy/common/checkout/scm/svn.py
+++ b/Tools/Scripts/webkitpy/common/checkout/scm/svn.py
@@ -36,7 +36,6 @@ import sys
from webkitpy.common.memoized import memoized
from webkitpy.common.system.deprecated_logging import log
from webkitpy.common.system.executive import Executive, ScriptError
-from webkitpy.common.system import ospath
from .scm import AuthenticationError, SCM, commit_error_handler
@@ -237,8 +236,8 @@ class SVN(SCM, SVNRepository):
def display_name(self):
return "svn"
- def head_svn_revision(self):
- return self.value_from_svn_info(self.checkout_root, 'Revision')
+ def svn_revision(self, path):
+ return self.value_from_svn_info(path, 'Revision')
# FIXME: This method should be on Checkout.
def create_patch(self, git_commit=None, changed_files=None):
diff --git a/Tools/Scripts/webkitpy/common/config/committers.py b/Tools/Scripts/webkitpy/common/config/committers.py
index 6e7399ecb..43a9c68c1 100644
--- a/Tools/Scripts/webkitpy/common/config/committers.py
+++ b/Tools/Scripts/webkitpy/common/config/committers.py
@@ -199,7 +199,6 @@ committers_unable_to_review = [
Committer("Chris Evans", ["cevans@google.com", "cevans@chromium.org"]),
Committer("Chris Guillory", ["ctguil@chromium.org", "chris.guillory@google.com"], "ctguil"),
Committer("Chris Petersen", "cpetersen@apple.com", "cpetersen"),
- Committer("Chris Rogers", "crogers@google.com", "crogers"),
Committer("Christian Dywan", ["christian@twotoasts.de", "christian@webkit.org", "christian@lanedo.com"]),
Committer("Collin Jackson", "collinj@webkit.org", "collinjackson"),
Committer("Cris Neckar", "cdn@chromium.org", "cneckar"),
@@ -295,7 +294,6 @@ committers_unable_to_review = [
Committer("Maxime Britto", ["maxime.britto@gmail.com", "britto@apple.com"]),
Committer("Maxime Simon", ["simon.maxime@gmail.com", "maxime.simon@webkit.org"], "maxime.simon"),
Committer("Michael Nordman", "michaeln@google.com", "michaeln"),
- Committer("Michael Saboff", "msaboff@apple.com"),
Committer("Michelangelo De Simone", "michelangelo@webkit.org", "michelangelo"),
Committer("Mihnea Ovidenie", "mihnea@adobe.com", "mihnea"),
Committer("Mike Belshe", ["mbelshe@chromium.org", "mike@belshe.com"]),
@@ -395,6 +393,7 @@ reviewers_list = [
Reviewer("Chris Marrin", "cmarrin@apple.com", "cmarrin"),
Reviewer("Chris Fleizach", "cfleizach@apple.com", "cfleizach"),
Reviewer("Chris Jerdonek", "cjerdonek@webkit.org", "cjerdonek"),
+ Reviewer("Chris Rogers", "crogers@google.com", "crogers"),
Reviewer(u"Csaba Osztrogon\u00e1c", "ossy@webkit.org", "ossy"),
Reviewer("Dan Bernstein", ["mitz@webkit.org", "mitz@apple.com"], "mitzpettel"),
Reviewer("Daniel Bates", ["dbates@webkit.org", "dbates@rim.com"], "dydz"),
@@ -444,6 +443,7 @@ reviewers_list = [
Reviewer("Maciej Stachowiak", "mjs@apple.com", "othermaciej"),
Reviewer("Mark Rowe", "mrowe@apple.com", "bdash"),
Reviewer("Martin Robinson", ["mrobinson@webkit.org", "mrobinson@igalia.com", "martin.james.robinson@gmail.com"], "mrobinson"),
+ Reviewer("Michael Saboff", "msaboff@apple.com", "msaboff"),
Reviewer("Mihai Parparita", "mihaip@chromium.org", "mihaip"),
Reviewer("Nate Chapin", "japhet@chromium.org", ["japhet", "natechapin"]),
Reviewer("Nikolas Zimmermann", ["zimmermann@kde.org", "zimmermann@physik.rwth-aachen.de", "zimmermann@webkit.org", "nzimmermann@rim.com"], "wildfox"),
diff --git a/Tools/Scripts/webkitpy/common/net/buildbot/buildbot.py b/Tools/Scripts/webkitpy/common/net/buildbot/buildbot.py
index e84fcbffd..1cb2bddf9 100644
--- a/Tools/Scripts/webkitpy/common/net/buildbot/buildbot.py
+++ b/Tools/Scripts/webkitpy/common/net/buildbot/buildbot.py
@@ -25,15 +25,8 @@
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-# WebKit's Python module for interacting with WebKit's buildbot
-
-try:
- import json
-except ImportError:
- # python 2.5 compatibility
- import webkitpy.thirdparty.simplejson as json
+import json
import operator
import re
import urllib
diff --git a/Tools/Scripts/webkitpy/common/net/credentials_unittest.py b/Tools/Scripts/webkitpy/common/net/credentials_unittest.py
index 59048591f..2ab160c88 100644
--- a/Tools/Scripts/webkitpy/common/net/credentials_unittest.py
+++ b/Tools/Scripts/webkitpy/common/net/credentials_unittest.py
@@ -26,8 +26,6 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-from __future__ import with_statement
-
import os
import tempfile
import unittest
diff --git a/Tools/Scripts/webkitpy/common/net/file_uploader.py b/Tools/Scripts/webkitpy/common/net/file_uploader.py
index aa3488bbf..339045e6a 100644
--- a/Tools/Scripts/webkitpy/common/net/file_uploader.py
+++ b/Tools/Scripts/webkitpy/common/net/file_uploader.py
@@ -27,8 +27,6 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-from __future__ import with_statement
-
import codecs
import mimetypes
import socket
diff --git a/Tools/Scripts/webkitpy/common/net/resultsjsonparser.py b/Tools/Scripts/webkitpy/common/net/resultsjsonparser.py
index 6120713eb..99e8528de 100644
--- a/Tools/Scripts/webkitpy/common/net/resultsjsonparser.py
+++ b/Tools/Scripts/webkitpy/common/net/resultsjsonparser.py
@@ -27,11 +27,7 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-try:
- import json
-except ImportError:
- # python 2.5 compatibility
- import webkitpy.thirdparty.simplejson as json
+import json
from webkitpy.common.memoized import memoized
from webkitpy.common.system.deprecated_logging import log
diff --git a/Tools/Scripts/webkitpy/common/newstringio_unittest.py b/Tools/Scripts/webkitpy/common/newstringio_unittest.py
index 5755c9814..1ee2fb91f 100644
--- a/Tools/Scripts/webkitpy/common/newstringio_unittest.py
+++ b/Tools/Scripts/webkitpy/common/newstringio_unittest.py
@@ -29,8 +29,6 @@
"""Unit tests for newstringio module."""
-from __future__ import with_statement
-
import unittest
import newstringio
diff --git a/Tools/Scripts/webkitpy/common/system/autoinstall.py b/Tools/Scripts/webkitpy/common/system/autoinstall.py
index 4ffcccc64..a928db63a 100755
--- a/Tools/Scripts/webkitpy/common/system/autoinstall.py
+++ b/Tools/Scripts/webkitpy/common/system/autoinstall.py
@@ -31,8 +31,6 @@
"""Support for automatically downloading Python packages from an URL."""
-from __future__ import with_statement
-
import codecs
import logging
import new
@@ -261,43 +259,6 @@ class AutoInstaller(object):
return target_path
- # This is a replacement for ZipFile.extractall(), which is
- # available in Python 2.6 but not in earlier versions.
- def _extract_all(self, zip_file, target_dir):
- self._log_transfer("Extracting zip file...", zip_file, target_dir)
-
- # This is helpful for debugging purposes.
- _log.debug("Listing zip file contents...")
- for name in zip_file.namelist():
- _log.debug(' * "%s"' % name)
-
- for name in zip_file.namelist():
- path = os.path.join(target_dir, name)
- self._log_transfer("Extracting...", name, path)
-
- if not os.path.basename(path):
- # Then the path ends in a slash, so it is a directory.
- self._create_directory(path)
- continue
- # Otherwise, it is a file.
-
- try:
- # We open this file w/o encoding, as we're reading/writing
- # the raw byte-stream from the zip file.
- outfile = open(path, 'wb')
- except IOError, err:
- # Not all zip files seem to list the directories explicitly,
- # so try again after creating the containing directory.
- _log.debug("Got IOError: retrying after creating directory...")
- dir = os.path.dirname(path)
- self._create_directory(dir)
- outfile = open(path, 'wb')
-
- try:
- outfile.write(zip_file.read(name))
- finally:
- outfile.close()
-
def _unzip(self, path, scratch_dir):
# zipfile.extractall() extracts to a path without the
# trailing ".zip".
@@ -315,7 +276,7 @@ class AutoInstaller(object):
raise Exception(message)
try:
- self._extract_all(zip_file, scratch_dir)
+ zip_file.extractall(scratch_dir)
finally:
zip_file.close()
diff --git a/Tools/Scripts/webkitpy/common/system/crashlogs.py b/Tools/Scripts/webkitpy/common/system/crashlogs.py
index 06b0d12d7..a6b6575f6 100644
--- a/Tools/Scripts/webkitpy/common/system/crashlogs.py
+++ b/Tools/Scripts/webkitpy/common/system/crashlogs.py
@@ -26,8 +26,6 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-from __future__ import with_statement
-
import os
import re
import sys
diff --git a/Tools/Scripts/webkitpy/common/system/deprecated_logging.py b/Tools/Scripts/webkitpy/common/system/deprecated_logging.py
index 9e6b5298f..137535438 100644
--- a/Tools/Scripts/webkitpy/common/system/deprecated_logging.py
+++ b/Tools/Scripts/webkitpy/common/system/deprecated_logging.py
@@ -41,7 +41,7 @@ def log(string):
def error(string):
log("ERROR: %s" % string)
- exit(1)
+ sys.exit(1)
# Simple class to split output between multiple destinations
diff --git a/Tools/Scripts/webkitpy/common/system/fileset.py b/Tools/Scripts/webkitpy/common/system/fileset.py
index 598c1c595..57e9a284e 100644
--- a/Tools/Scripts/webkitpy/common/system/fileset.py
+++ b/Tools/Scripts/webkitpy/common/system/fileset.py
@@ -21,8 +21,6 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-from __future__ import with_statement
-
from webkitpy.common.system.filesystem import FileSystem
diff --git a/Tools/Scripts/webkitpy/common/system/filesystem.py b/Tools/Scripts/webkitpy/common/system/filesystem.py
index 7de41a424..60b680c06 100644
--- a/Tools/Scripts/webkitpy/common/system/filesystem.py
+++ b/Tools/Scripts/webkitpy/common/system/filesystem.py
@@ -28,8 +28,6 @@
"""Wrapper object for the file system / source tree."""
-from __future__ import with_statement
-
import codecs
import errno
import exceptions
@@ -41,8 +39,6 @@ import sys
import tempfile
import time
-from webkitpy.common.system import ospath
-
class FileSystem(object):
"""FileSystem interface for webkitpy.
@@ -229,7 +225,7 @@ class FileSystem(object):
return hashlib.sha1(contents).hexdigest()
def relpath(self, path, start='.'):
- return ospath.relpath(path, start)
+ return os.path.relpath(path, start)
class _WindowsError(exceptions.OSError):
"""Fake exception for Linux and Mac."""
diff --git a/Tools/Scripts/webkitpy/common/system/filesystem_mock.py b/Tools/Scripts/webkitpy/common/system/filesystem_mock.py
index e91d6682a..6e106dd83 100644
--- a/Tools/Scripts/webkitpy/common/system/filesystem_mock.py
+++ b/Tools/Scripts/webkitpy/common/system/filesystem_mock.py
@@ -33,7 +33,6 @@ import os
import re
from webkitpy.common.system import path
-from webkitpy.common.system import ospath
class MockFileSystem(object):
@@ -180,7 +179,7 @@ class MockFileSystem(object):
# to a different thread and potentially modifying the dict in
# mid-iteration.
files = self.files.keys()[:]
- result = any(f.startswith(path) for f in files)
+ result = any(f.startswith(path) and len(self.split(f)[0]) >= len(path) for f in files)
if result:
self.dirs.add(path)
return result
@@ -303,7 +302,33 @@ class MockFileSystem(object):
return hashlib.sha1(contents).hexdigest()
def relpath(self, path, start='.'):
- return ospath.relpath(path, start, self.abspath, self.sep)
+ # Since os.path.relpath() calls os.path.normpath()
+ # (see http://docs.python.org/library/os.path.html#os.path.abspath )
+ # it also removes trailing slashes and converts forward and backward
+ # slashes to the preferred slash os.sep.
+ start = self.abspath(start)
+ path = self.abspath(path)
+
+ if not path.lower().startswith(start.lower()):
+ # Then path is outside the directory given by start.
+ return None # FIXME: os.relpath still returns a path here.
+
+ rel_path = path[len(start):]
+
+ if not rel_path:
+ # Then the paths are the same.
+ pass
+ elif rel_path[0] == self.sep:
+ # It is probably sufficient to remove just the first character
+ # since os.path.normpath() collapses separators, but we use
+ # lstrip() just to be sure.
+ rel_path = rel_path.lstrip(self.sep)
+ else:
+ # We are in the case typified by the following example:
+ # path = "/tmp/foobar", start = "/tmp/foo" -> rel_path = "bar"
+ return None
+
+ return rel_path
def remove(self, path):
if self.files[path] is None:
diff --git a/Tools/Scripts/webkitpy/common/system/filesystem_unittest.py b/Tools/Scripts/webkitpy/common/system/filesystem_unittest.py
index c24344c76..4859f7294 100644
--- a/Tools/Scripts/webkitpy/common/system/filesystem_unittest.py
+++ b/Tools/Scripts/webkitpy/common/system/filesystem_unittest.py
@@ -31,8 +31,6 @@
# important; without it, Python will choke while trying to parse the file,
# since it includes non-ASCII characters.
-from __future__ import with_statement
-
import os
import stat
import sys
diff --git a/Tools/Scripts/webkitpy/common/system/ospath.py b/Tools/Scripts/webkitpy/common/system/ospath.py
deleted file mode 100644
index 2504645c0..000000000
--- a/Tools/Scripts/webkitpy/common/system/ospath.py
+++ /dev/null
@@ -1,85 +0,0 @@
-# Copyright (C) 2010 Chris Jerdonek (cjerdonek@webkit.org)
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
-# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-# DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR
-# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-"""Contains a substitute for Python 2.6's os.path.relpath()."""
-
-import os
-
-
-# This function is a replacement for os.path.relpath(), which is only
-# available in Python 2.6:
-#
-# http://docs.python.org/library/os.path.html#os.path.relpath
-#
-# It should behave essentially the same as os.path.relpath(), except for
-# returning None on paths not contained in abs_start_path.
-def relpath(path, start_path, os_path_abspath=None, sep=None):
- """Return a path relative to the given start path, or None.
-
- Returns None if the path is not contained in the directory start_path.
-
- Args:
- path: An absolute or relative path to convert to a relative path.
- start_path: The path relative to which the given path should be
- converted.
- os_path_abspath: A replacement function for unit testing. This
- function should strip trailing slashes just like
- os.path.abspath(). Defaults to os.path.abspath.
- sep: Path separator. Defaults to os.path.sep
-
- """
- if os_path_abspath is None:
- os_path_abspath = os.path.abspath
- sep = sep or os.sep
-
- # Since os_path_abspath() calls os.path.normpath()--
- #
- # (see http://docs.python.org/library/os.path.html#os.path.abspath )
- #
- # it also removes trailing slashes and converts forward and backward
- # slashes to the preferred slash os.sep.
- start_path = os_path_abspath(start_path)
- path = os_path_abspath(path)
-
- if not path.lower().startswith(start_path.lower()):
- # Then path is outside the directory given by start_path.
- return None
-
- rel_path = path[len(start_path):]
-
- if not rel_path:
- # Then the paths are the same.
- pass
- elif rel_path[0] == sep:
- # It is probably sufficient to remove just the first character
- # since os.path.normpath() collapses separators, but we use
- # lstrip() just to be sure.
- rel_path = rel_path.lstrip(sep)
- else:
- # We are in the case typified by the following example:
- #
- # start_path = "/tmp/foo"
- # path = "/tmp/foobar"
- # rel_path = "bar"
- return None
-
- return rel_path
diff --git a/Tools/Scripts/webkitpy/common/system/ospath_unittest.py b/Tools/Scripts/webkitpy/common/system/ospath_unittest.py
deleted file mode 100644
index d84c2c64c..000000000
--- a/Tools/Scripts/webkitpy/common/system/ospath_unittest.py
+++ /dev/null
@@ -1,62 +0,0 @@
-# Copyright (C) 2010 Chris Jerdonek (cjerdonek@webkit.org)
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
-# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-# DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR
-# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-"""Unit tests for ospath.py."""
-
-import os
-import unittest
-
-from webkitpy.common.system.ospath import relpath
-
-
-# Make sure the tests in this class are platform independent.
-class RelPathTest(unittest.TestCase):
-
- """Tests relpath()."""
-
- os_path_abspath = lambda self, path: path
-
- def _rel_path(self, path, abs_start_path):
- return relpath(path, abs_start_path, self.os_path_abspath)
-
- def test_same_path(self):
- rel_path = self._rel_path("WebKit", "WebKit")
- self.assertEquals(rel_path, "")
-
- def test_long_rel_path(self):
- start_path = "WebKit"
- expected_rel_path = os.path.join("test", "Foo.txt")
- path = os.path.join(start_path, expected_rel_path)
-
- rel_path = self._rel_path(path, start_path)
- self.assertEquals(expected_rel_path, rel_path)
-
- def test_none_rel_path(self):
- """Test _rel_path() with None return value."""
- start_path = "WebKit"
- path = os.path.join("other_dir", "foo.txt")
-
- rel_path = self._rel_path(path, start_path)
- self.assertTrue(rel_path is None)
-
- rel_path = self._rel_path("Tools", "WebKit")
- self.assertTrue(rel_path is None)
diff --git a/Tools/Scripts/webkitpy/common/system/outputcapture.py b/Tools/Scripts/webkitpy/common/system/outputcapture.py
index cb6edbec7..66188c0cb 100644
--- a/Tools/Scripts/webkitpy/common/system/outputcapture.py
+++ b/Tools/Scripts/webkitpy/common/system/outputcapture.py
@@ -74,11 +74,14 @@ class OutputCapture(object):
def assert_outputs(self, testcase, function, args=[], kwargs={}, expected_stdout="", expected_stderr="", expected_exception=None, expected_logs=None):
self.capture_output()
- if expected_exception:
- return_value = testcase.assertRaises(expected_exception, function, *args, **kwargs)
- else:
- return_value = function(*args, **kwargs)
- (stdout_string, stderr_string, logs_string) = self.restore_output()
+ try:
+ if expected_exception:
+ return_value = testcase.assertRaises(expected_exception, function, *args, **kwargs)
+ else:
+ return_value = function(*args, **kwargs)
+ finally:
+ (stdout_string, stderr_string, logs_string) = self.restore_output()
+
testcase.assertEqual(stdout_string, expected_stdout)
testcase.assertEqual(stderr_string, expected_stderr)
if expected_logs is not None:
diff --git a/Tools/Scripts/webkitpy/common/system/path.py b/Tools/Scripts/webkitpy/common/system/path.py
index 09787d7e8..b7ad3723a 100644
--- a/Tools/Scripts/webkitpy/common/system/path.py
+++ b/Tools/Scripts/webkitpy/common/system/path.py
@@ -27,7 +27,6 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""generic routines to convert platform-specific paths to URIs."""
-from __future__ import with_statement
import atexit
import subprocess
diff --git a/Tools/Scripts/webkitpy/common/thread/threadedmessagequeue.py b/Tools/Scripts/webkitpy/common/thread/threadedmessagequeue.py
index 17b62773c..e43476764 100644
--- a/Tools/Scripts/webkitpy/common/thread/threadedmessagequeue.py
+++ b/Tools/Scripts/webkitpy/common/thread/threadedmessagequeue.py
@@ -26,8 +26,6 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-from __future__ import with_statement
-
import threading
diff --git a/Tools/Scripts/webkitpy/common/version_check.py b/Tools/Scripts/webkitpy/common/version_check.py
index 290623d32..6acc9b439 100644
--- a/Tools/Scripts/webkitpy/common/version_check.py
+++ b/Tools/Scripts/webkitpy/common/version_check.py
@@ -29,6 +29,6 @@
import sys
-if sys.version < '2.5' or sys.version >= '2.8':
- print >> sys.stderr, "Unsupported Python version: WebKit only supports 2.5.x - 2.7.x, and you're running %s." % sys.version.split()[0]
+if sys.version < '2.6' or sys.version >= '2.8':
+ print >> sys.stderr, "Unsupported Python version: WebKit only supports 2.6.x - 2.7.x, and you're running %s." % sys.version.split()[0]
sys.exit(1)
diff --git a/Tools/Scripts/webkitpy/layout_tests/controllers/manager.py b/Tools/Scripts/webkitpy/layout_tests/controllers/manager.py
index b1df780ac..7113bcb6a 100644
--- a/Tools/Scripts/webkitpy/layout_tests/controllers/manager.py
+++ b/Tools/Scripts/webkitpy/layout_tests/controllers/manager.py
@@ -35,8 +35,6 @@ objects to the Manager. The Manager then aggregates the TestFailures to
create a final report.
"""
-from __future__ import with_statement
-
import errno
import logging
import math
@@ -503,7 +501,10 @@ class Manager(object):
if self._options.iterations:
self._test_files_list = self._test_files_list * self._options.iterations
- result_summary = ResultSummary(self._expectations, self._test_files | skipped)
+ iterations = \
+ (self._options.repeat_each if self._options.repeat_each else 1) * \
+ (self._options.iterations if self._options.iterations else 1)
+ result_summary = ResultSummary(self._expectations, self._test_files | skipped, iterations)
self._print_expected_results_of_type(result_summary, test_expectations.PASS, "passes")
self._print_expected_results_of_type(result_summary, test_expectations.FAIL, "failures")
self._print_expected_results_of_type(result_summary, test_expectations.FLAKY, "flaky")
@@ -518,7 +519,11 @@ class Manager(object):
for test in skipped:
result = test_results.TestResult(test)
result.type = test_expectations.SKIP
- result_summary.add(result, expected=True)
+ iterations = \
+ (self._options.repeat_each if self._options.repeat_each else 1) * \
+ (self._options.iterations if self._options.iterations else 1)
+ for iteration in range(iterations):
+ result_summary.add(result, expected=True)
self._printer.print_expected('')
# Check to make sure we didn't filter out all of the tests.
@@ -1320,9 +1325,8 @@ class Manager(object):
Args:
result_summary: information to log
"""
- failed = len(result_summary.failures)
- skipped = len(
- result_summary.tests_by_expectation[test_expectations.SKIP])
+ failed = result_summary.total_failures
+ skipped = result_summary.total_tests_by_expectation[test_expectations.SKIP]
total = result_summary.total
passed = total - failed - skipped
pct_passed = 0.0
diff --git a/Tools/Scripts/webkitpy/layout_tests/controllers/manager_worker_broker.py b/Tools/Scripts/webkitpy/layout_tests/controllers/manager_worker_broker.py
index 82ba91ff5..34136ff37 100755
--- a/Tools/Scripts/webkitpy/layout_tests/controllers/manager_worker_broker.py
+++ b/Tools/Scripts/webkitpy/layout_tests/controllers/manager_worker_broker.py
@@ -42,17 +42,11 @@ They interact more or less like:
"""
import logging
+import multiprocessing
import optparse
import Queue
import sys
-
-# Handle Python < 2.6 where multiprocessing isn't available.
-try:
- import multiprocessing
-except ImportError:
- multiprocessing = None
-
# These are needed when workers are launched in new child processes.
from webkitpy.common.host import Host
from webkitpy.common.host_mock import MockHost
@@ -99,7 +93,7 @@ def get(port, options, client, worker_class):
if worker_model == 'inline':
queue_class = Queue.Queue
manager_class = _InlineManager
- elif worker_model == 'processes' and multiprocessing:
+ elif worker_model == 'processes':
queue_class = multiprocessing.Queue
manager_class = _MultiProcessManager
else:
@@ -245,40 +239,38 @@ class _InlineWorkerConnection(_WorkerConnection):
raise exc_info[0], exc_info[1], exc_info[2]
-if multiprocessing:
-
- class _Process(multiprocessing.Process):
- def __init__(self, worker_connection, platform_name, options, client):
- multiprocessing.Process.__init__(self)
- self._worker_connection = worker_connection
- self._platform_name = platform_name
- self._options = options
- self._client = client
-
- def run(self):
- # We need to create a new Host object here because this is
- # running in a new process and we can't require the parent's
- # Host to be pickleable and passed to the child.
- if self._platform_name.startswith('test'):
- host = MockHost()
- else:
- host = Host()
- host._initialize_scm()
-
- options = self._options
- port_obj = host.port_factory.get(self._platform_name, options)
-
- # The unix multiprocessing implementation clones the
- # log handler configuration into the child processes,
- # but the win implementation doesn't.
- configure_logging = (sys.platform == 'win32')
-
- # FIXME: this won't work if the calling process is logging
- # somewhere other than sys.stderr and sys.stdout, but I'm not sure
- # if this will be an issue in practice.
- printer = printing.Printer(port_obj, options, sys.stderr, sys.stdout, configure_logging)
- self._client.run(port_obj)
- printer.cleanup()
+class _Process(multiprocessing.Process):
+ def __init__(self, worker_connection, platform_name, options, client):
+ multiprocessing.Process.__init__(self)
+ self._worker_connection = worker_connection
+ self._platform_name = platform_name
+ self._options = options
+ self._client = client
+
+ def run(self):
+ # We need to create a new Host object here because this is
+ # running in a new process and we can't require the parent's
+ # Host to be pickleable and passed to the child.
+ if self._platform_name.startswith('test'):
+ host = MockHost()
+ else:
+ host = Host()
+ host._initialize_scm()
+
+ options = self._options
+ port_obj = host.port_factory.get(self._platform_name, options)
+
+ # The unix multiprocessing implementation clones the
+ # log handler configuration into the child processes,
+ # but the win implementation doesn't.
+ configure_logging = (sys.platform == 'win32')
+
+ # FIXME: this won't work if the calling process is logging
+ # somewhere other than sys.stderr and sys.stdout, but I'm not sure
+ # if this will be an issue in practice.
+ printer = printing.Printer(port_obj, options, sys.stderr, sys.stdout, configure_logging)
+ self._client.run(port_obj)
+ printer.cleanup()
class _MultiProcessWorkerConnection(_WorkerConnection):
diff --git a/Tools/Scripts/webkitpy/layout_tests/controllers/manager_worker_broker_unittest.py b/Tools/Scripts/webkitpy/layout_tests/controllers/manager_worker_broker_unittest.py
index 8e63f93ec..e41e22ca6 100644
--- a/Tools/Scripts/webkitpy/layout_tests/controllers/manager_worker_broker_unittest.py
+++ b/Tools/Scripts/webkitpy/layout_tests/controllers/manager_worker_broker_unittest.py
@@ -31,15 +31,8 @@ import Queue
import sys
import unittest
-try:
- import multiprocessing
-except ImportError:
- multiprocessing = None
-
-
from webkitpy.common.system import outputcapture
from webkitpy.common.host_mock import MockHost
-
from webkitpy.layout_tests import port
from webkitpy.layout_tests.controllers import manager_worker_broker
from webkitpy.layout_tests.controllers import message_broker
@@ -127,11 +120,7 @@ class FunctionTests(unittest.TestCase):
# This test sometimes fails on Windows. See <http://webkit.org/b/55087>.
if sys.platform in ('cygwin', 'win32'):
return
-
- if multiprocessing:
- self.assertTrue(make_broker(self, 'processes') is not None)
- else:
- self.assertRaises(ValueError, make_broker, self, 'processes')
+ self.assertTrue(make_broker(self, 'processes') is not None)
def test_get__unknown(self):
self.assertRaises(ValueError, make_broker, self, 'unknown')
@@ -205,16 +194,13 @@ class _TestsMixin(object):
# FIXME: https://bugs.webkit.org/show_bug.cgi?id=54520.
-if multiprocessing and sys.platform not in ('cygwin', 'win32'):
+if sys.platform not in ('cygwin', 'win32'):
class MultiProcessBrokerTests(_TestsMixin, unittest.TestCase):
def setUp(self):
_TestsMixin.setUp(self)
self._worker_model = 'processes'
- def queue(self):
- return multiprocessing.Queue()
-
class FunctionsTest(unittest.TestCase):
def test_runtime_options(self):
diff --git a/Tools/Scripts/webkitpy/layout_tests/controllers/single_test_runner.py b/Tools/Scripts/webkitpy/layout_tests/controllers/single_test_runner.py
index 791fb6213..987a77978 100644
--- a/Tools/Scripts/webkitpy/layout_tests/controllers/single_test_runner.py
+++ b/Tools/Scripts/webkitpy/layout_tests/controllers/single_test_runner.py
@@ -55,6 +55,7 @@ class SingleTestRunner:
self._timeout = test_input.timeout
self._worker_name = worker_name
self._test_name = test_input.test_name
+ self._should_run_pixel_test = test_input.should_run_pixel_test
self._is_reftest = False
self._reference_files = port.reference_files(self._test_name)
@@ -77,6 +78,8 @@ class SingleTestRunner:
self._port.expected_audio(self._test_name))
def _should_fetch_expected_checksum(self):
+ if not self._should_run_pixel_test:
+ return False
return (self._options.pixel_tests and
not (self._options.new_baseline or self._options.reset_results))
diff --git a/Tools/Scripts/webkitpy/layout_tests/controllers/test_expectations_editor.py b/Tools/Scripts/webkitpy/layout_tests/controllers/test_expectations_editor.py
index 1b2188362..97a2d4ffc 100644
--- a/Tools/Scripts/webkitpy/layout_tests/controllers/test_expectations_editor.py
+++ b/Tools/Scripts/webkitpy/layout_tests/controllers/test_expectations_editor.py
@@ -32,15 +32,10 @@ for layout tests.
"""
import itertools
+import json
import logging
import re
-try:
- import json
-except ImportError:
- # python 2.5 compatibility
- import webkitpy.thirdparty.simplejson as json
-
from webkitpy.layout_tests.models.test_configuration import TestConfiguration, TestConfigurationConverter
from webkitpy.layout_tests.models import test_expectations
diff --git a/Tools/Scripts/webkitpy/layout_tests/controllers/worker.py b/Tools/Scripts/webkitpy/layout_tests/controllers/worker.py
index b66ce9b79..fc7831dfb 100644
--- a/Tools/Scripts/webkitpy/layout_tests/controllers/worker.py
+++ b/Tools/Scripts/webkitpy/layout_tests/controllers/worker.py
@@ -108,6 +108,9 @@ class Worker(manager_worker_broker.AbstractWorker):
start_time = time.time()
num_tests = 0
for test_input in test_list:
+ #FIXME: When the DRT support also this function, that would be useful
+ if self._port.driver_name() == "WebKitTestRunner" and self._port.get_option('skip_pixel_test_if_no_baseline') and self._port.get_option('pixel_tests'):
+ test_input.should_run_pixel_test = (self._port.expected_image(test_input.test_name) != None)
self._run_test(test_input)
num_tests += 1
self._worker_connection.yield_to_broker()
diff --git a/Tools/Scripts/webkitpy/layout_tests/layout_package/json_layout_results_generator.py b/Tools/Scripts/webkitpy/layout_tests/layout_package/json_layout_results_generator.py
index 142d9a5ec..ce7ba45b7 100644
--- a/Tools/Scripts/webkitpy/layout_tests/layout_package/json_layout_results_generator.py
+++ b/Tools/Scripts/webkitpy/layout_tests/layout_package/json_layout_results_generator.py
@@ -64,7 +64,7 @@ class JSONLayoutResultsGenerator(json_results_generator.JSONResultsGeneratorBase
"""
super(JSONLayoutResultsGenerator, self).__init__(
port, builder_name, build_name, build_number, results_file_base_path,
- builder_base_url, {}, port.test_repository_paths(),
+ builder_base_url, {}, port.repository_paths(),
test_results_server, test_type, master_name)
self._expectations = expectations
diff --git a/Tools/Scripts/webkitpy/layout_tests/layout_package/json_results_generator.py b/Tools/Scripts/webkitpy/layout_tests/layout_package/json_results_generator.py
index b073d409e..56ef7abcd 100644
--- a/Tools/Scripts/webkitpy/layout_tests/layout_package/json_results_generator.py
+++ b/Tools/Scripts/webkitpy/layout_tests/layout_package/json_results_generator.py
@@ -26,6 +26,7 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+import json
import logging
import os
import subprocess
@@ -36,12 +37,6 @@ import xml.dom.minidom
from webkitpy.common.net.file_uploader import FileUploader
-try:
- import json
-except ImportError:
- # python 2.5 compatibility
- import webkitpy.thirdparty.simplejson as json
-
# A JSON results generator for generic tests.
# FIXME: move this code out of the layout_package directory.
@@ -528,6 +523,10 @@ class JSONResultsGeneratorBase(object):
# Include SVN revisions for the given repositories.
for (name, path) in self._svn_repositories:
+ # Note: for JSON file's backward-compatibility we use 'chrome' rather
+ # than 'chromium' here.
+ if name == 'chromium':
+ name = 'chrome'
self._insert_item_into_raw_list(results_for_builder,
self._get_svn_revision(path),
name + 'Revision')
diff --git a/Tools/Scripts/webkitpy/layout_tests/layout_package/json_results_generator_unittest.py b/Tools/Scripts/webkitpy/layout_tests/layout_package/json_results_generator_unittest.py
index b00119821..f04300f83 100644
--- a/Tools/Scripts/webkitpy/layout_tests/layout_package/json_results_generator_unittest.py
+++ b/Tools/Scripts/webkitpy/layout_tests/layout_package/json_results_generator_unittest.py
@@ -26,9 +26,8 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-"""Unit tests for json_results_generator.py."""
-
import unittest
+import json
import optparse
import random
@@ -38,10 +37,6 @@ from webkitpy.layout_tests.models import test_expectations
from webkitpy.layout_tests.port import test
from webkitpy.thirdparty.mock import Mock
-try:
- import json
-except ImportError, e:
- from webkitpy.thirdparty import simplejson as json
class JSONGeneratorTest(unittest.TestCase):
def setUp(self):
diff --git a/Tools/Scripts/webkitpy/layout_tests/models/result_summary.py b/Tools/Scripts/webkitpy/layout_tests/models/result_summary.py
index 572ca3037..27c5452c0 100644
--- a/Tools/Scripts/webkitpy/layout_tests/models/result_summary.py
+++ b/Tools/Scripts/webkitpy/layout_tests/models/result_summary.py
@@ -31,8 +31,8 @@ from webkitpy.layout_tests.models.test_expectations import TestExpectations, SKI
class ResultSummary(object):
- def __init__(self, expectations, test_files):
- self.total = len(test_files)
+ def __init__(self, expectations, test_files, iterations=1):
+ self.total = len(test_files) * iterations
self.remaining = self.total
self.expectations = expectations
self.expected = 0
@@ -40,22 +40,28 @@ class ResultSummary(object):
self.unexpected_failures = 0
self.unexpected_crashes = 0
self.unexpected_timeouts = 0
+ self.total_tests_by_expectation = {}
self.tests_by_expectation = {}
self.tests_by_timeline = {}
self.results = {}
self.unexpected_results = {}
self.failures = {}
+ self.total_failures = 0
+ self.total_tests_by_expectation[SKIP] = 0
self.tests_by_expectation[SKIP] = set()
for expectation in TestExpectations.EXPECTATIONS.values():
self.tests_by_expectation[expectation] = set()
+ self.total_tests_by_expectation[expectation] = 0
for timeline in TestExpectations.TIMELINES.values():
self.tests_by_timeline[timeline] = expectations.get_tests_with_timeline(timeline)
def add(self, test_result, expected):
+ self.total_tests_by_expectation[test_result.type] += 1
self.tests_by_expectation[test_result.type].add(test_result.test_name)
self.results[test_result.test_name] = test_result
self.remaining -= 1
if len(test_result.failures):
+ self.total_failures += 1
self.failures[test_result.test_name] = test_result.failures
if expected:
self.expected += 1
diff --git a/Tools/Scripts/webkitpy/layout_tests/models/test_configuration.py b/Tools/Scripts/webkitpy/layout_tests/models/test_configuration.py
index 875ba0415..4375e09dc 100644
--- a/Tools/Scripts/webkitpy/layout_tests/models/test_configuration.py
+++ b/Tools/Scripts/webkitpy/layout_tests/models/test_configuration.py
@@ -25,8 +25,8 @@
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-"""Representation of a layout test configuration."""
+import itertools
class TestConfiguration(object):
def __init__(self, version, architecture, build_type, graphics_type):
@@ -189,26 +189,6 @@ class TestConfigurationConverter(object):
values -= junk_specifier_set
specifiers_list.append(frozenset(values))
- # FIXME: Replace with iteritools.combinations when we obsolete Python 2.5.
- def combinations(iterable, r):
- """This function is borrowed verbatim from http://docs.python.org/library/itertools.html#itertools.combinations."""
- pool = tuple(iterable)
- n = len(pool)
- if r > n:
- return
- indices = range(r)
- yield tuple(pool[i] for i in indices)
- while True:
- for i in reversed(range(r)):
- if indices[i] != i + n - r:
- break
- else:
- return
- indices[i] += 1
- for j in range(i + 1, r):
- indices[j] = indices[j - 1] + 1
- yield tuple(pool[i] for i in indices)
-
def intersect_combination(combination):
return reduce(set.intersection, [set(specifiers) for specifiers in combination])
@@ -218,7 +198,7 @@ class TestConfigurationConverter(object):
def try_collapsing(size, collapsing_sets):
if len(specifiers_list) < size:
return False
- for combination in combinations(specifiers_list, size):
+ for combination in itertools.combinations(specifiers_list, size):
if symmetric_difference(combination) in collapsing_sets:
for item in combination:
specifiers_list.remove(item)
@@ -235,7 +215,7 @@ class TestConfigurationConverter(object):
def try_abbreviating():
if len(specifiers_list) < 2:
return False
- for combination in combinations(specifiers_list, 2):
+ for combination in itertools.combinations(specifiers_list, 2):
for collapsing_set in collapsing_sets:
diff = symmetric_difference(combination)
if diff <= collapsing_set:
diff --git a/Tools/Scripts/webkitpy/layout_tests/models/test_expectations.py b/Tools/Scripts/webkitpy/layout_tests/models/test_expectations.py
index 010ddd848..90842007c 100644
--- a/Tools/Scripts/webkitpy/layout_tests/models/test_expectations.py
+++ b/Tools/Scripts/webkitpy/layout_tests/models/test_expectations.py
@@ -32,15 +32,10 @@ for layout tests.
"""
import itertools
+import json
import logging
import re
-try:
- import json
-except ImportError:
- # python 2.5 compatibility
- import webkitpy.thirdparty.simplejson as json
-
from webkitpy.layout_tests.models.test_configuration import TestConfiguration, TestConfigurationConverter
_log = logging.getLogger(__name__)
@@ -108,15 +103,14 @@ def strip_comments(line):
class ParseError(Exception):
- def __init__(self, fatal, errors):
- self.fatal = fatal
- self.errors = errors
+ def __init__(self, warnings):
+ self.warnings = warnings
def __str__(self):
- return '\n'.join(map(str, self.errors))
+ return '\n'.join(map(str, self.warnings))
def __repr__(self):
- return 'ParseError(fatal=%s, errors=%s)' % (self.fatal, self.errors)
+ return 'ParseError(warnings=%s)' % self.warnings
class TestExpectationSerializer(object):
@@ -126,7 +120,7 @@ class TestExpectationSerializer(object):
self._parsed_expectation_to_string = dict([[parsed_expectation, expectation_string] for expectation_string, parsed_expectation in TestExpectations.EXPECTATIONS.items()])
def to_string(self, expectation_line):
- if expectation_line.is_malformed():
+ if expectation_line.is_invalid():
return expectation_line.original_string or ''
if expectation_line.name is None:
@@ -248,7 +242,7 @@ class TestExpectationParser(object):
elif modifier.startswith(self.BUG_MODIFIER_PREFIX):
has_bugid = True
if re.match(self.BUG_MODIFIER_REGEX, modifier):
- expectation_line.errors.append('BUG\d+ is not allowed, must be one of BUGCR\d+, BUGWK\d+, BUGV8_\d+, or a non-numeric bug identifier.')
+ expectation_line.warnings.append('BUG\d+ is not allowed, must be one of BUGCR\d+, BUGWK\d+, BUGV8_\d+, or a non-numeric bug identifier.')
else:
expectation_line.parsed_bug_modifiers.append(modifier)
else:
@@ -258,23 +252,23 @@ class TestExpectationParser(object):
expectation_line.warnings.append('Test lacks BUG modifier.')
if self._allow_rebaseline_modifier and self.REBASELINE_MODIFIER in expectation_line.modifiers:
- expectation_line.errors.append('REBASELINE should only be used for running rebaseline.py. Cannot be checked in.')
+ expectation_line.warnings.append('REBASELINE should only be used for running rebaseline.py. Cannot be checked in.')
- expectation_line.matching_configurations = self._test_configuration_converter.to_config_set(parsed_specifiers, expectation_line.errors)
+ expectation_line.matching_configurations = self._test_configuration_converter.to_config_set(parsed_specifiers, expectation_line.warnings)
def _parse_expectations(self, expectation_line):
result = set()
for part in expectation_line.expectations:
expectation = TestExpectations.expectation_from_string(part)
if expectation is None: # Careful, PASS is currently 0.
- expectation_line.errors.append('Unsupported expectation: %s' % part)
+ expectation_line.warnings.append('Unsupported expectation: %s' % part)
continue
result.add(expectation)
expectation_line.parsed_expectations = result
def _check_modifiers_against_expectations(self, expectation_line):
if self.SLOW_MODIFIER in expectation_line.modifiers and self.TIMEOUT_EXPECTATION in expectation_line.expectations:
- expectation_line.errors.append('A test can not be both SLOW and TIMEOUT. If it times out indefinitely, then it should be just TIMEOUT.')
+ expectation_line.warnings.append('A test can not be both SLOW and TIMEOUT. If it times out indefinitely, then it should be just TIMEOUT.')
def _check_path_does_not_exist(self, expectation_line):
# WebKit's way of skipping tests is to add a -disabled suffix.
@@ -338,13 +332,13 @@ class TestExpectationParser(object):
parts = remaining_string.split(':')
if len(parts) != 2:
- expectation_line.errors.append("Missing a ':'" if len(parts) < 2 else "Extraneous ':'")
+ expectation_line.warnings.append("Missing a ':'" if len(parts) < 2 else "Extraneous ':'")
else:
test_and_expectation = parts[1].split('=')
if len(test_and_expectation) != 2:
- expectation_line.errors.append("Missing expectations" if len(test_and_expectation) < 2 else "Extraneous '='")
+ expectation_line.warnings.append("Missing expectations" if len(test_and_expectation) < 2 else "Extraneous '='")
- if not expectation_line.is_malformed():
+ if not expectation_line.is_invalid():
expectation_line.modifiers = cls._split_space_separated(parts[0])
expectation_line.name = test_and_expectation[0].strip()
expectation_line.expectations = cls._split_space_separated(test_and_expectation[1])
@@ -385,14 +379,10 @@ class TestExpectationLine:
self.parsed_expectations = set()
self.comment = None
self.matching_tests = []
- self.errors = []
self.warnings = []
- def is_malformed(self):
- return len(self.errors) > 0
-
def is_invalid(self):
- return self.is_malformed() or len(self.warnings) > 0
+ return len(self.warnings) > 0
def is_flaky(self):
return len(self.parsed_expectations) > 1
@@ -476,7 +466,7 @@ class TestExpectationsModel(object):
return self._test_to_expectations[test]
def add_expectation_line(self, expectation_line, overrides_allowed):
- """Returns a list of errors, encountered while matching modifiers."""
+ """Returns a list of warnings encountered while matching modifiers."""
if expectation_line.is_invalid():
return
@@ -592,20 +582,20 @@ class TestExpectationsModel(object):
# to be warnings and return False".
if prev_expectation_line.matching_configurations == expectation_line.matching_configurations:
- expectation_line.errors.append('Duplicate or ambiguous %s.' % expectation_source)
+ expectation_line.warnings.append('Duplicate or ambiguous %s.' % expectation_source)
return True
if prev_expectation_line.matching_configurations >= expectation_line.matching_configurations:
- expectation_line.errors.append('More specific entry on line %d overrides line %d' % (expectation_line.line_number, prev_expectation_line.line_number))
+ expectation_line.warnings.append('More specific entry on line %d overrides line %d' % (expectation_line.line_number, prev_expectation_line.line_number))
# FIXME: return False if we want more specific to win.
return True
if prev_expectation_line.matching_configurations <= expectation_line.matching_configurations:
- expectation_line.errors.append('More specific entry on line %d overrides line %d' % (prev_expectation_line.line_number, expectation_line.line_number))
+ expectation_line.warnings.append('More specific entry on line %d overrides line %d' % (prev_expectation_line.line_number, expectation_line.line_number))
return True
if prev_expectation_line.matching_configurations & expectation_line.matching_configurations:
- expectation_line.errors.append('Entries on line %d and line %d match overlapping sets of configurations' % (prev_expectation_line.line_number, expectation_line.line_number))
+ expectation_line.warnings.append('Entries on line %d and line %d match overlapping sets of configurations' % (prev_expectation_line.line_number, expectation_line.line_number))
return True
# Configuration sets are disjoint, then.
@@ -706,8 +696,8 @@ class TestExpectations(object):
test_config: specific values to check against when
parsing the file (usually port.test_config(),
but may be different when linting or doing other things).
- is_lint_mode: If True, just parse the expectations string
- looking for errors.
+ is_lint_mode: If True, parse the expectations string and raise
+ an exception if warnings are encountered.
overrides: test expectations that are allowed to override any
entries in |expectations|. This is used by callers
that need to manage two sets of expectations (e.g., upstream
@@ -731,7 +721,7 @@ class TestExpectations(object):
self._expectations += overrides_expectations
self._has_warnings = False
- self._report_errors()
+ self._report_warnings()
self._process_tests_without_expectations()
# TODO(ojan): Allow for removing skipped tests when getting the list of
@@ -798,28 +788,22 @@ class TestExpectations(object):
def is_rebaselining(self, test):
return self._model.has_modifier(test, REBASELINE)
- def _report_errors(self):
- errors = []
+ def _report_warnings(self):
warnings = []
test_expectation_path = self._port.path_to_test_expectations_file()
if test_expectation_path.startswith(self._port.path_from_webkit_base()):
test_expectation_path = self._port.host.filesystem.relpath(test_expectation_path, self._port.path_from_webkit_base())
for expectation in self._expectations:
- for error in expectation.errors:
- errors.append('%s:%d %s %s' % (test_expectation_path, expectation.line_number, error, expectation.name if expectation.expectations else expectation.original_string))
for warning in expectation.warnings:
warnings.append('%s:%d %s %s' % (test_expectation_path, expectation.line_number, warning, expectation.name if expectation.expectations else expectation.original_string))
for warning in self._skipped_tests_warnings:
warnings.append('%s%s' % (test_expectation_path, warning))
- if errors or warnings:
- if errors:
- raise ParseError(fatal=True, errors=sorted(errors + warnings))
- if warnings:
- self._has_warnings = True
- if self._is_lint_mode:
- raise ParseError(fatal=False, errors=warnings)
+ if warnings:
+ self._has_warnings = True
+ if self._is_lint_mode:
+ raise ParseError(warnings)
def _process_tests_without_expectations(self):
if self._full_test_list:
@@ -833,7 +817,7 @@ class TestExpectations(object):
def remove_rebaselined_tests(self, except_these_tests):
"""Returns a copy of the expectations with the tests removed."""
def without_rebaseline_modifier(expectation):
- return not (not expectation.is_malformed() and expectation.name in except_these_tests and "rebaseline" in expectation.modifiers)
+ return not (not expectation.is_invalid() and expectation.name in except_these_tests and "rebaseline" in expectation.modifiers)
return TestExpectationSerializer.list_to_string(filter(without_rebaseline_modifier, self._expectations))
diff --git a/Tools/Scripts/webkitpy/layout_tests/models/test_expectations_unittest.py b/Tools/Scripts/webkitpy/layout_tests/models/test_expectations_unittest.py
index 98b91aeed..a2c94cbcd 100644
--- a/Tools/Scripts/webkitpy/layout_tests/models/test_expectations_unittest.py
+++ b/Tools/Scripts/webkitpy/layout_tests/models/test_expectations_unittest.py
@@ -131,6 +131,9 @@ BUG_TEST WONTFIX MAC : failures/expected/image.html = IMAGE
self.assertEquals(self._exp.get_expectations(self.get_test(test)),
set([result]))
+ def assert_bad_expectations(self, expectations, overrides=None):
+ self.assertRaises(ParseError, self.parse_exp, expectations, is_lint_mode=True, overrides=overrides)
+
class BasicTests(Base):
def test_basic(self):
@@ -192,26 +195,23 @@ BUGX WONTFIX : failures/expected = IMAGE
s = self._exp.get_test_set(WONTFIX, CRASH, include_skips=False)
self.assertEqual(s, set([]))
- def test_parse_error_fatal(self):
+ def test_parse_warning(self):
try:
self.parse_exp("""FOO : failures/expected/text.html = TEXT
-SKIP : failures/expected/image.html""")
+SKIP : failures/expected/image.html""", is_lint_mode=True)
self.assertFalse(True, "ParseError wasn't raised")
except ParseError, e:
- self.assertTrue(e.fatal)
- exp_errors = [u":1 Test lacks BUG modifier. failures/expected/text.html",
- u":1 Unrecognized modifier 'foo' failures/expected/text.html",
- u":2 Missing expectations SKIP : failures/expected/image.html"]
- self.assertEqual(str(e), '\n'.join(self._port.path_to_test_expectations_file() + str(error) for error in exp_errors))
+ warnings = [u":1 Test lacks BUG modifier. failures/expected/text.html",
+ u":1 Unrecognized modifier 'foo' failures/expected/text.html",
+ u":2 Missing expectations SKIP : failures/expected/image.html"]
+ self.assertEqual(str(e), '\n'.join(self._port.path_to_test_expectations_file() + str(warning) for warning in warnings))
- def test_parse_error_nonfatal(self):
try:
self.parse_exp('SKIP : failures/expected/text.html = TEXT', is_lint_mode=True)
self.assertFalse(True, "ParseError wasn't raised")
except ParseError, e:
- self.assertFalse(e.fatal)
- exp_errors = [u':1 Test lacks BUG modifier. failures/expected/text.html']
- self.assertEqual(str(e), '\n'.join(self._port.path_to_test_expectations_file() + str(error) for error in exp_errors))
+ warnings = [u':1 Test lacks BUG modifier. failures/expected/text.html']
+ self.assertEqual(str(e), '\n'.join(self._port.path_to_test_expectations_file() + str(warning) for warning in warnings))
def test_error_on_different_platform(self):
# parse_exp uses a Windows port. Assert errors on Mac show up in lint mode.
@@ -237,12 +237,9 @@ SKIP : failures/expected/image.html""")
self.assert_exp('failures/expected/text.html', IMAGE)
def test_overrides__duplicate(self):
- self.assertRaises(ParseError, self.parse_exp,
- "BUG_EXP: failures/expected/text.html = TEXT",
- """
-BUG_OVERRIDE : failures/expected/text.html = IMAGE
-BUG_OVERRIDE : failures/expected/text.html = CRASH
-""")
+ self.assert_bad_expectations("BUG_EXP: failures/expected/text.html = TEXT",
+ "BUG_OVERRIDE : failures/expected/text.html = IMAGE\n"
+ "BUG_OVERRIDE : failures/expected/text.html = CRASH\n")
def test_pixel_tests_flag(self):
def match(test, result, pixel_tests_enabled):
@@ -287,26 +284,20 @@ BUG_OVERRIDE : failures/expected/text.html = CRASH
class ExpectationSyntaxTests(Base):
def test_missing_expectation(self):
# This is missing the expectation.
- self.assertRaises(ParseError, self.parse_exp,
- 'BUG_TEST: failures/expected/text.html')
+ self.assert_bad_expectations('BUG_TEST: failures/expected/text.html')
def test_missing_colon(self):
# This is missing the modifiers and the ':'
- self.assertRaises(ParseError, self.parse_exp,
- 'failures/expected/text.html = TEXT')
+ self.assert_bad_expectations('failures/expected/text.html = TEXT')
- def disabled_test_too_many_colons(self):
- # FIXME: Enable this test and fix the underlying bug.
- self.assertRaises(ParseError, self.parse_exp,
- 'BUG_TEST: failures/expected/text.html = PASS :')
+ def test_too_many_colons(self):
+ self.assert_bad_expectations('BUG_TEST: failures/expected/text.html = PASS :')
def test_too_many_equals_signs(self):
- self.assertRaises(ParseError, self.parse_exp,
- 'BUG_TEST: failures/expected/text.html = TEXT = IMAGE')
+ self.assert_bad_expectations('BUG_TEST: failures/expected/text.html = TEXT = IMAGE')
def test_unrecognized_expectation(self):
- self.assertRaises(ParseError, self.parse_exp,
- 'BUG_TEST: failures/expected/text.html = UNKNOWN')
+ self.assert_bad_expectations('BUG_TEST: failures/expected/text.html = UNKNOWN')
def test_macro(self):
exp_str = """
@@ -318,25 +309,23 @@ BUG_TEST WIN : failures/expected/text.html = TEXT
class SemanticTests(Base):
def test_bug_format(self):
- self.assertRaises(ParseError, self.parse_exp, 'BUG1234 : failures/expected/text.html = TEXT')
+ self.assertRaises(ParseError, self.parse_exp, 'BUG1234 : failures/expected/text.html = TEXT', is_lint_mode=True)
def test_bad_bugid(self):
try:
- self.parse_exp('BUG1234 SLOW : failures/expected/text.html = TEXT')
+ self.parse_exp('BUG1234 SLOW : failures/expected/text.html = TEXT', is_lint_mode=True)
self.fail('should have raised an error about a bad bug identifier')
except ParseError, exp:
- self.assertEquals(exp.fatal, True)
- self.assertEquals(len(exp.errors), 1)
+ self.assertEquals(len(exp.warnings), 1)
def test_missing_bugid(self):
- # This should log a non-fatal error.
self.parse_exp('SLOW : failures/expected/text.html = TEXT')
self.assertTrue(self._exp.has_warnings())
def test_slow_and_timeout(self):
# A test cannot be SLOW and expected to TIMEOUT.
self.assertRaises(ParseError, self.parse_exp,
- 'BUG_TEST SLOW : failures/expected/timeout.html = TIMEOUT')
+ 'BUG_TEST SLOW : failures/expected/timeout.html = TIMEOUT', is_lint_mode=True)
def test_rebaseline(self):
# Can't lint a file w/ 'REBASELINE' in it.
@@ -347,12 +336,12 @@ class SemanticTests(Base):
def test_duplicates(self):
self.assertRaises(ParseError, self.parse_exp, """
BUG_EXP : failures/expected/text.html = TEXT
-BUG_EXP : failures/expected/text.html = IMAGE""")
+BUG_EXP : failures/expected/text.html = IMAGE""", is_lint_mode=True)
self.assertRaises(ParseError, self.parse_exp,
self.get_basic_expectations(), overrides="""
BUG_OVERRIDE : failures/expected/text.html = TEXT
-BUG_OVERRIDE : failures/expected/text.html = IMAGE""", )
+BUG_OVERRIDE : failures/expected/text.html = IMAGE""", is_lint_mode=True)
def test_missing_file(self):
# This should log a non-fatal error.
@@ -381,37 +370,26 @@ BUGX : failures/expected/text.html = TEXT
self.assert_exp('failures/expected/crash.html', IMAGE)
def test_ambiguous(self):
- self.assertRaises(ParseError, self.parse_exp, """
-BUG_TEST RELEASE : passes/text.html = PASS
-BUG_TEST WIN : passes/text.html = FAIL
-""")
+ self.assert_bad_expectations("BUG_TEST RELEASE : passes/text.html = PASS\n"
+ "BUG_TEST WIN : passes/text.html = FAIL\n")
def test_more_modifiers(self):
- exp_str = """
-BUG_TEST RELEASE : passes/text.html = PASS
-BUG_TEST WIN RELEASE : passes/text.html = TEXT
-"""
- self.assertRaises(ParseError, self.parse_exp, exp_str)
+ self.assert_bad_expectations("BUG_TEST RELEASE : passes/text.html = PASS\n"
+ "BUG_TEST WIN RELEASE : passes/text.html = TEXT\n")
def test_order_in_file(self):
- exp_str = """
-BUG_TEST WIN RELEASE : passes/text.html = TEXT
-BUG_TEST RELEASE : passes/text.html = PASS
-"""
- self.assertRaises(ParseError, self.parse_exp, exp_str)
+ self.assert_bad_expectations("BUG_TEST WIN RELEASE : passes/text.html = TEXT\n"
+ "BUG_TEST RELEASE : passes/text.html = PASS\n")
def test_macro_overrides(self):
- exp_str = """
-BUG_TEST WIN : passes/text.html = PASS
-BUG_TEST XP : passes/text.html = TEXT
-"""
- self.assertRaises(ParseError, self.parse_exp, exp_str)
+ self.assert_bad_expectations("BUG_TEST WIN : passes/text.html = PASS\n"
+ "BUG_TEST XP : passes/text.html = TEXT\n")
class RebaseliningTest(Base):
"""Test rebaselining-specific functionality."""
def assertRemove(self, input_expectations, tests, expected_expectations):
- self.parse_exp(input_expectations)
+ self.parse_exp(input_expectations, is_lint_mode=False)
actual_expectations = self._exp.remove_rebaselined_tests(tests)
self.assertEqual(expected_expectations, actual_expectations)
@@ -431,63 +409,53 @@ class RebaseliningTest(Base):
class TestExpectationParserTests(unittest.TestCase):
def test_tokenize_blank(self):
expectation = TestExpectationParser._tokenize('')
- self.assertEqual(expectation.is_malformed(), False)
self.assertEqual(expectation.comment, None)
- self.assertEqual(len(expectation.errors), 0)
+ self.assertEqual(len(expectation.warnings), 0)
def test_tokenize_missing_colon(self):
expectation = TestExpectationParser._tokenize('Qux.')
- self.assertEqual(expectation.is_malformed(), True)
- self.assertEqual(str(expectation.errors), '["Missing a \':\'"]')
+ self.assertEqual(str(expectation.warnings), '["Missing a \':\'"]')
def test_tokenize_extra_colon(self):
expectation = TestExpectationParser._tokenize('FOO : : bar')
- self.assertEqual(expectation.is_malformed(), True)
- self.assertEqual(str(expectation.errors), '["Extraneous \':\'"]')
+ self.assertEqual(str(expectation.warnings), '["Extraneous \':\'"]')
def test_tokenize_empty_comment(self):
expectation = TestExpectationParser._tokenize('//')
- self.assertEqual(expectation.is_malformed(), False)
self.assertEqual(expectation.comment, '')
- self.assertEqual(len(expectation.errors), 0)
+ self.assertEqual(len(expectation.warnings), 0)
def test_tokenize_comment(self):
expectation = TestExpectationParser._tokenize('//Qux.')
- self.assertEqual(expectation.is_malformed(), False)
self.assertEqual(expectation.comment, 'Qux.')
- self.assertEqual(len(expectation.errors), 0)
+ self.assertEqual(len(expectation.warnings), 0)
def test_tokenize_missing_equal(self):
expectation = TestExpectationParser._tokenize('FOO : bar')
- self.assertEqual(expectation.is_malformed(), True)
- self.assertEqual(str(expectation.errors), "['Missing expectations\']")
+ self.assertEqual(str(expectation.warnings), "['Missing expectations\']")
def test_tokenize_extra_equal(self):
expectation = TestExpectationParser._tokenize('FOO : bar = BAZ = Qux.')
- self.assertEqual(expectation.is_malformed(), True)
- self.assertEqual(str(expectation.errors), '["Extraneous \'=\'"]')
+ self.assertEqual(str(expectation.warnings), '["Extraneous \'=\'"]')
def test_tokenize_valid(self):
expectation = TestExpectationParser._tokenize('FOO : bar = BAZ')
- self.assertEqual(expectation.is_malformed(), False)
self.assertEqual(expectation.comment, None)
- self.assertEqual(len(expectation.errors), 0)
+ self.assertEqual(len(expectation.warnings), 0)
def test_tokenize_valid_with_comment(self):
expectation = TestExpectationParser._tokenize('FOO : bar = BAZ //Qux.')
- self.assertEqual(expectation.is_malformed(), False)
self.assertEqual(expectation.comment, 'Qux.')
self.assertEqual(str(expectation.modifiers), '[\'foo\']')
self.assertEqual(str(expectation.expectations), '[\'baz\']')
- self.assertEqual(len(expectation.errors), 0)
+ self.assertEqual(len(expectation.warnings), 0)
def test_tokenize_valid_with_multiple_modifiers(self):
expectation = TestExpectationParser._tokenize('FOO1 FOO2 : bar = BAZ //Qux.')
- self.assertEqual(expectation.is_malformed(), False)
self.assertEqual(expectation.comment, 'Qux.')
self.assertEqual(str(expectation.modifiers), '[\'foo1\', \'foo2\']')
self.assertEqual(str(expectation.expectations), '[\'baz\']')
- self.assertEqual(len(expectation.errors), 0)
+ self.assertEqual(len(expectation.warnings), 0)
def test_parse_empty_string(self):
host = MockHost()
@@ -538,7 +506,7 @@ class TestExpectationSerializerTests(unittest.TestCase):
self.assertEqual(serializer.to_string(expectation), 'FOO : bar = BAZ1 BAZ2 //Qux.')
expectation.modifiers = ['foo1', 'foO2']
self.assertEqual(serializer.to_string(expectation), 'FOO1 FOO2 : bar = BAZ1 BAZ2 //Qux.')
- expectation.errors.append('Oh the horror.')
+ expectation.warnings.append('Oh the horror.')
self.assertEqual(serializer.to_string(expectation), '')
expectation.original_string = 'Yes it is!'
self.assertEqual(serializer.to_string(expectation), 'Yes it is!')
diff --git a/Tools/Scripts/webkitpy/layout_tests/models/test_input.py b/Tools/Scripts/webkitpy/layout_tests/models/test_input.py
index 6b5d1480c..5c8b30d2e 100644
--- a/Tools/Scripts/webkitpy/layout_tests/models/test_input.py
+++ b/Tools/Scripts/webkitpy/layout_tests/models/test_input.py
@@ -36,7 +36,7 @@ class TestInput:
ref_file = None
is_mismatch_reftest = None
- def __init__(self, test_name, timeout):
+ def __init__(self, test_name, timeout, should_run_pixel_test=True):
"""Holds the input parameters for a test.
Args:
test: name of test (not an absolute path!)
@@ -46,6 +46,7 @@ class TestInput:
"""
self.test_name = test_name
self.timeout = timeout
+ self.should_run_pixel_test = should_run_pixel_test
def __repr__(self):
return "TestInput('%s', %d)" % (self.test_name, self.timeout)
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/base.py b/Tools/Scripts/webkitpy/layout_tests/port/base.py
index a8b98fda2..10e2a822c 100755
--- a/Tools/Scripts/webkitpy/layout_tests/port/base.py
+++ b/Tools/Scripts/webkitpy/layout_tests/port/base.py
@@ -27,11 +27,9 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-"""Abstract base class of Port-specific entrypoints for the layout tests
+"""Abstract base class of Port-specific entry points for the layout tests
test infrastructure (the Port and Driver classes)."""
-from __future__ import with_statement
-
import cgi
import difflib
import errno
@@ -40,14 +38,6 @@ import re
from webkitpy.common.memoized import memoized
from webkitpy.common.system import path
-
-
-# Handle Python < 2.6 where multiprocessing isn't available.
-try:
- import multiprocessing
-except ImportError:
- multiprocessing = None
-
from webkitpy.common import find_files
from webkitpy.common.system import logutils
from webkitpy.common.system.executive import ScriptError
@@ -150,7 +140,6 @@ class Port(object):
self.set_option_default('configuration', self.default_configuration())
self._test_configuration = None
self._reftest_list = {}
- self._multiprocessing_is_available = (multiprocessing is not None)
self._results_directory = None
def wdiff_available(self):
@@ -178,9 +167,7 @@ class Port(object):
return cpu_count
def default_worker_model(self):
- if self._multiprocessing_is_available:
- return 'processes'
- return 'inline'
+ return 'processes'
def baseline_path(self):
"""Return the absolute path to the directory to store new baselines in for this port."""
@@ -468,19 +455,16 @@ class Port(object):
reftest_list = self._get_reftest_list(test_name)
if not reftest_list:
- expected_filenames = [('==', self.expected_filename(test_name, '.html')), ('!=', self.expected_filename(test_name, '-mismatch.html'))]
- return [(expectation, filename) for expectation, filename in expected_filenames if self._filesystem.exists(filename)]
+ reftest_list = []
+ for expectation, prefix in (('==', ''), ('!=', '-mismatch')):
+ for extention in Port._supported_file_extensions:
+ path = self.expected_filename(test_name, prefix + extention)
+ if self._filesystem.exists(path):
+ reftest_list.append((expectation, path))
+ return reftest_list
return reftest_list.get(self._filesystem.join(self.layout_tests_dir(), test_name), [])
- def is_reftest(self, test_name):
- reftest_list = self._get_reftest_list(test_name)
- if not reftest_list:
- has_expected = self._filesystem.exists(self.expected_filename(test_name, '.html'))
- return has_expected or self._filesystem.exists(self.expected_filename(test_name, '-mismatch.html'))
- filename = self._filesystem.join(self.layout_tests_dir(), test_name)
- return filename in reftest_list
-
def tests(self, paths):
"""Return the list of tests found."""
# When collecting test cases, skip these directories
@@ -900,11 +884,12 @@ class Port(object):
sync up the two repos."""
return None
- def test_repository_paths(self):
- """Returns a list of (repository_name, repository_path) tuples
- of its depending code base. By default it returns a list that only
- contains a ('webkit', <webkitRepossitoryPath>) tuple.
- """
+ def repository_paths(self):
+ """Returns a list of (repository_name, repository_path) tuples of its depending code base.
+ By default it returns a list that only contains a ('webkit', <webkitRepossitoryPath>) tuple."""
+
+ # We use LayoutTest directory here because webkit_base isn't a part webkit repository in Chromium port
+ # where turnk isn't checked out as a whole.
return [('webkit', self.layout_tests_dir())]
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/base_unittest.py b/Tools/Scripts/webkitpy/layout_tests/port/base_unittest.py
index f981ac2cb..8465f6019 100644
--- a/Tools/Scripts/webkitpy/layout_tests/port/base_unittest.py
+++ b/Tools/Scripts/webkitpy/layout_tests/port/base_unittest.py
@@ -324,10 +324,15 @@ class PortTest(unittest.TestCase):
filesystem = MockFileSystem()
self.assertTrue(Port._is_test_file(filesystem, '', 'foo.html'))
self.assertTrue(Port._is_test_file(filesystem, '', 'foo.shtml'))
+ self.assertTrue(Port._is_test_file(filesystem, '', 'foo.svg'))
self.assertTrue(Port._is_test_file(filesystem, '', 'test-ref-test.html'))
self.assertFalse(Port._is_test_file(filesystem, '', 'foo.png'))
self.assertFalse(Port._is_test_file(filesystem, '', 'foo-expected.html'))
+ self.assertFalse(Port._is_test_file(filesystem, '', 'foo-expected.svg'))
+ self.assertFalse(Port._is_test_file(filesystem, '', 'foo-expected.xht'))
self.assertFalse(Port._is_test_file(filesystem, '', 'foo-expected-mismatch.html'))
+ self.assertFalse(Port._is_test_file(filesystem, '', 'foo-expected-mismatch.svg'))
+ self.assertFalse(Port._is_test_file(filesystem, '', 'foo-expected-mismatch.xhtml'))
self.assertFalse(Port._is_test_file(filesystem, '', 'foo-ref.html'))
self.assertFalse(Port._is_test_file(filesystem, '', 'foo-notref.html'))
self.assertFalse(Port._is_test_file(filesystem, '', 'foo-notref.xht'))
@@ -350,6 +355,12 @@ class PortTest(unittest.TestCase):
'bar/test-2.html': [('!=', 'bar/test-notref.html')],
'bar/test-3.html': [('==', 'bar/test-ref.html'), ('==', 'bar/test-ref2.html'), ('!=', 'bar/test-notref.html')]})
+ def test_reference_files(self):
+ port = self.make_port(with_tests=True)
+ self.assertEqual(port.reference_files('passes/svgreftest.svg'), [('==', port.layout_tests_dir() + '/passes/svgreftest-expected.svg')])
+ self.assertEqual(port.reference_files('passes/xhtreftest.svg'), [('==', port.layout_tests_dir() + '/passes/xhtreftest-expected.html')])
+ self.assertEqual(port.reference_files('passes/phpreftest.php'), [('!=', port.layout_tests_dir() + '/passes/phpreftest-expected-mismatch.svg')])
+
def test_operating_system(self):
self.assertEqual('mac', self.make_port().operating_system())
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/chromium.py b/Tools/Scripts/webkitpy/layout_tests/port/chromium.py
index c530d7c17..199a2ecb9 100755
--- a/Tools/Scripts/webkitpy/layout_tests/port/chromium.py
+++ b/Tools/Scripts/webkitpy/layout_tests/port/chromium.py
@@ -335,11 +335,9 @@ class ChromiumPort(Port):
is_lint_mode=False, overrides=overrides_str)
return expectations.get_tests_with_result_type(test_expectations.SKIP)
- def test_repository_paths(self):
- # Note: for JSON file's backward-compatibility we use 'chrome' rather
- # than 'chromium' here.
- repos = super(ChromiumPort, self).test_repository_paths()
- repos.append(('chrome', self.path_from_chromium_base()))
+ def repository_paths(self):
+ repos = super(ChromiumPort, self).repository_paths()
+ repos.append(('chromium', self.path_from_chromium_base('build')))
return repos
#
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/chromium_mac.py b/Tools/Scripts/webkitpy/layout_tests/port/chromium_mac.py
index e6d557f55..30f4aa991 100644
--- a/Tools/Scripts/webkitpy/layout_tests/port/chromium_mac.py
+++ b/Tools/Scripts/webkitpy/layout_tests/port/chromium_mac.py
@@ -102,13 +102,6 @@ class ChromiumMacPort(chromium.ChromiumPort):
return result
- def default_child_processes(self):
- if not self._multiprocessing_is_available:
- # Running multiple threads in Mac Python is unstable (See
- # https://bugs.webkit.org/show_bug.cgi?id=38553 for more info).
- return 1
- return chromium.ChromiumPort.default_child_processes(self)
-
def operating_system(self):
return 'mac'
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/efl.py b/Tools/Scripts/webkitpy/layout_tests/port/efl.py
index a4b70a378..39b084951 100644
--- a/Tools/Scripts/webkitpy/layout_tests/port/efl.py
+++ b/Tools/Scripts/webkitpy/layout_tests/port/efl.py
@@ -47,10 +47,10 @@ class EflPort(WebKitPort):
return [TestConfiguration(version=self._version, architecture='x86', build_type=build_type, graphics_type='cpu') for build_type in self.ALL_BUILD_TYPES]
def _path_to_driver(self):
- return self._build_path('Programs', self.driver_name())
+ return self._build_path('bin', self.driver_name())
def _path_to_image_diff(self):
- return self._build_path('Programs', 'ImageDiff')
+ return self._build_path('bin', 'ImageDiff')
# FIXME: I doubt EFL wants to override this method.
def check_build(self, needs_http):
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/gtk.py b/Tools/Scripts/webkitpy/layout_tests/port/gtk.py
index 745ff1565..c9ee1cbfe 100644
--- a/Tools/Scripts/webkitpy/layout_tests/port/gtk.py
+++ b/Tools/Scripts/webkitpy/layout_tests/port/gtk.py
@@ -26,10 +26,6 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-from __future__ import with_statement
-
-"""WebKit Gtk implementation of the Port interface."""
-
import logging
import os
import signal
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/mac.py b/Tools/Scripts/webkitpy/layout_tests/port/mac.py
index e23fb82cc..202f2de2a 100644
--- a/Tools/Scripts/webkitpy/layout_tests/port/mac.py
+++ b/Tools/Scripts/webkitpy/layout_tests/port/mac.py
@@ -87,6 +87,12 @@ class MacPort(ApplePort):
def is_crash_reporter(self, process_name):
return re.search(r'ReportCrash', process_name)
+ def default_child_processes(self):
+ if self.is_snowleopard():
+ _log.warn("Cannot run tests in parallel on Snow Leopard due to rdar://problem/10621525.")
+ return 1
+ return super(MacPort, self).default_child_processes()
+
def _build_java_test_support(self):
java_tests_path = self._filesystem.join(self.layout_tests_dir(), "java")
build_java = ["/usr/bin/make", "-C", java_tests_path]
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/mac_unittest.py b/Tools/Scripts/webkitpy/layout_tests/port/mac_unittest.py
index 43a800839..bdef980bd 100644
--- a/Tools/Scripts/webkitpy/layout_tests/port/mac_unittest.py
+++ b/Tools/Scripts/webkitpy/layout_tests/port/mac_unittest.py
@@ -166,3 +166,14 @@ java/
def test_operating_system(self):
self.assertEqual('mac', self.make_port().operating_system())
+
+ def test_default_child_processes(self):
+ port = self.make_port(port_name='mac-lion')
+ # MockPlatformInfo only has 2 mock cores. The important part is that 2 > 1.
+ self.assertEqual(port.default_child_processes(), 2)
+
+ # SnowLeopard has a CFNetwork bug which causes crashes if we execute more than one copy of DRT at once.
+ port = self.make_port(port_name='mac-snowleopard')
+ expected_logs = "Cannot run tests in parallel on Snow Leopard due to rdar://problem/10621525.\n"
+ child_processes = OutputCapture().assert_outputs(self, port.default_child_processes, (), expected_logs=expected_logs)
+ self.assertEqual(child_processes, 1)
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/mock_drt.py b/Tools/Scripts/webkitpy/layout_tests/port/mock_drt.py
index f4696698f..e56e27b1a 100644
--- a/Tools/Scripts/webkitpy/layout_tests/port/mock_drt.py
+++ b/Tools/Scripts/webkitpy/layout_tests/port/mock_drt.py
@@ -203,7 +203,7 @@ class MockDRT(object):
else:
test_name = self._port.relative_test_filename(uri)
- is_reftest = (self._port.is_reftest(test_name) or
+ is_reftest = (self._port.reference_files(test_name) or
test_name.endswith('-expected.html') or
test_name.endswith('-mismatch.html'))
return DriverInput(test_name, 0, checksum, is_reftest)
@@ -267,7 +267,7 @@ class MockChromiumDRT(MockDRT):
checksum = None
test_name = self._driver.uri_to_test(uri)
- is_reftest = (self._port.is_reftest(test_name) or
+ is_reftest = (self._port.reference_files(test_name) or
test_name.endswith('-expected.html') or
test_name.endswith('-mismatch.html'))
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/port_testcase.py b/Tools/Scripts/webkitpy/layout_tests/port/port_testcase.py
index 38b54fe64..8df039ca2 100755
--- a/Tools/Scripts/webkitpy/layout_tests/port/port_testcase.py
+++ b/Tools/Scripts/webkitpy/layout_tests/port/port_testcase.py
@@ -30,19 +30,11 @@
import errno
import socket
-
import sys
import time
import unittest
-# Handle Python < 2.6 where multiprocessing isn't available.
-try:
- import multiprocessing
-except ImportError:
- multiprocessing = None
-
from webkitpy.layout_tests.servers import http_server_base
-
from webkitpy.common.system.filesystem_mock import MockFileSystem
from webkitpy.tool.mocktool import MockOptions
from webkitpy.common.system.executive_mock import MockExecutive
@@ -68,10 +60,7 @@ class PortTestCase(unittest.TestCase):
def test_default_worker_model(self):
port = self.make_port()
- if multiprocessing:
- self.assertEqual(port.default_worker_model(), 'processes')
- else:
- self.assertEqual(port.default_worker_model(), 'inline')
+ self.assertEqual(port.default_worker_model(), 'processes')
def test_driver_cmd_line(self):
port = self.make_port()
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/test.py b/Tools/Scripts/webkitpy/layout_tests/port/test.py
index de002c14b..99c7ce921 100644
--- a/Tools/Scripts/webkitpy/layout_tests/port/test.py
+++ b/Tools/Scripts/webkitpy/layout_tests/port/test.py
@@ -27,9 +27,6 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-"""Dummy Port implementation used for testing."""
-from __future__ import with_statement
-
import base64
import sys
import time
@@ -44,7 +41,7 @@ from webkitpy.common.system.filesystem_mock import MockFileSystem
class TestInstance(object):
def __init__(self, name):
self.name = name
- self.base = name[(name.rfind("/") + 1):name.rfind(".html")]
+ self.base = name[(name.rfind("/") + 1):name.rfind(".")]
self.crash = False
self.web_process_crash = False
self.exception = False
@@ -182,6 +179,9 @@ layer at (0,0) size 800x34
# For reftests.
tests.add_reftest('passes/reftest.html', 'passes/reftest-expected.html', same_image=True)
tests.add_reftest('passes/mismatch.html', 'passes/mismatch-expected-mismatch.html', same_image=False)
+ tests.add_reftest('passes/svgreftest.svg', 'passes/svgreftest-expected.svg', same_image=True)
+ tests.add_reftest('passes/xhtreftest.xht', 'passes/xhtreftest-expected.html', same_image=True)
+ tests.add_reftest('passes/phpreftest.php', 'passes/phpreftest-expected-mismatch.svg', same_image=False)
tests.add_reftest('failures/expected/reftest.html', 'failures/expected/reftest-expected.html', same_image=False)
tests.add_reftest('failures/expected/mismatch.html', 'failures/expected/mismatch-expected-mismatch.html', same_image=True)
tests.add_reftest('failures/unexpected/reftest.html', 'failures/unexpected/reftest-expected.html', same_image=False)
@@ -292,7 +292,7 @@ WONTFIX SKIP : failures/expected/exception.html = CRASH
# Add each test and the expected output, if any.
test_list = unit_test_list()
for test in test_list.tests.values():
- add_file(test, '.html', '')
+ add_file(test, test.name[test.name.rfind('.'):], '')
if test.is_reftest:
continue
if test.actual_audio:
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/webkit.py b/Tools/Scripts/webkitpy/layout_tests/port/webkit.py
index 6f7967efe..967e1f1ba 100644
--- a/Tools/Scripts/webkitpy/layout_tests/port/webkit.py
+++ b/Tools/Scripts/webkitpy/layout_tests/port/webkit.py
@@ -307,6 +307,9 @@ class WebKitPort(Port):
}
def _has_test_in_directories(self, directory_lists, test_list):
+ if not test_list:
+ return False
+
directories = itertools.chain.from_iterable(directory_lists)
for directory, test in itertools.product(directories, test_list):
if test.startswith(directory):
@@ -464,6 +467,8 @@ class WebKitDriver(Driver):
def cmd_line(self):
cmd = self._command_wrapper(self._port.get_option('wrapper'))
cmd.append(self._port._path_to_driver())
+ if self._port.get_option('skip_pixel_test_if_no_baseline'):
+ cmd.append('--skip-pixel-test-if-no-baseline')
if self._pixel_tests:
cmd.append('--pixel-tests')
if self._port.get_option('gc_between_tests'):
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/webkit_unittest.py b/Tools/Scripts/webkitpy/layout_tests/port/webkit_unittest.py
index a8cc8e5b8..ffaae6eb7 100755
--- a/Tools/Scripts/webkitpy/layout_tests/port/webkit_unittest.py
+++ b/Tools/Scripts/webkitpy/layout_tests/port/webkit_unittest.py
@@ -145,6 +145,12 @@ class WebKitPortTest(port_testcase.PortTestCase):
result_directories = set(TestWebKitPort(None, supported_features)._skipped_tests_for_unsupported_features(test_list=['foo.html']))
self.assertEqual(result_directories, expected_directories)
+ def test_skipped_tests_for_unsupported_features_empty_test_list(self):
+ supported_features = ["Accelerated Compositing", "Foo Feature"]
+ expected_directories = set([])
+ result_directories = set(TestWebKitPort(None, supported_features)._skipped_tests_for_unsupported_features(test_list=None))
+ self.assertEqual(result_directories, expected_directories)
+
def test_skipped_layout_tests(self):
self.assertEqual(TestWebKitPort(None, None).skipped_layout_tests(test_list=[]), set(['media']))
diff --git a/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests.py b/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests.py
index 366e335d5..96508caf7 100755
--- a/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests.py
+++ b/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests.py
@@ -70,8 +70,8 @@ def lint(port, options, expectations_class):
except test_expectations.ParseError, e:
lint_failed = True
_log.error('')
- for error in e.errors:
- _log.error(error)
+ for warning in e.warnings:
+ _log.error(warning)
_log.error('')
files_linted.add(expectations_file)
@@ -175,6 +175,9 @@ def _set_up_derived_options(port, options):
warnings.append("--no-http is ignored since --force is also provided")
options.http = True
+ if options.skip_pixel_test_if_no_baseline and not options.pixel_tests:
+ warnings.append("--skip-pixel-test-if-no-baseline is only supported with -p (--pixel-tests)")
+
if options.ignore_metrics and (options.new_baseline or options.reset_results):
warnings.append("--ignore-metrics has no effect with --new-baselines or with --reset-results")
@@ -314,6 +317,9 @@ def parse_args(args=None):
optparse.make_option("--no-new-test-results", action="store_false",
dest="new_test_results", default=True,
help="Don't create new baselines when no expected results exist"),
+ optparse.make_option("--skip-pixel-test-if-no-baseline", action="store_true",
+ dest="skip_pixel_test_if_no_baseline", help="Do not generate and check pixel result in the case when "
+ "no image baseline is available for the test."),
optparse.make_option("--skip-failing-tests", action="store_true",
default=False, help="Skip tests that are expected to fail. "
"Note: When using this option, you might miss new crashes "
diff --git a/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests_integrationtest.py b/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests_integrationtest.py
index bec720805..ac9f8bbad 100755
--- a/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests_integrationtest.py
+++ b/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests_integrationtest.py
@@ -29,12 +29,9 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-"""Unit tests for run_webkit_tests."""
-
-from __future__ import with_statement
-
import codecs
import itertools
+import json
import logging
import Queue
import re
@@ -46,20 +43,9 @@ import unittest
from webkitpy.common.system import path
-try:
- import multiprocessing
-except ImportError:
- multiprocessing = None
-
-try:
- import json
-except ImportError:
- # python 2.5 compatibility
- import webkitpy.thirdparty.simplejson as json
-
# FIXME: remove this when we fix test-webkitpy to work properly on cygwin
# (bug 63846).
-SHOULD_TEST_PROCESSES = multiprocessing and sys.platform not in ('cygwin', 'win32')
+SHOULD_TEST_PROCESSES = sys.platform not in ('cygwin', 'win32')
from webkitpy.common import array_stream
from webkitpy.common.system import outputcapture
@@ -385,11 +371,28 @@ class MainTest(unittest.TestCase):
tests_run = get_tests_run(['--repeat-each', '2'] + tests_to_run, tests_included=True, flatten_batches=True)
self.assertEquals(tests_run, ['passes/image.html', 'passes/image.html', 'passes/text.html', 'passes/text.html'])
+ def test_skip_pixel_test_if_no_baseline_option(self):
+ tests_to_run = ['passes/image.html', 'passes/text.html']
+ tests_run = get_tests_run(['--skip-pixel-test-if-no-baseline'] + tests_to_run, tests_included=True, flatten_batches=True)
+ self.assertEquals(tests_run, ['passes/image.html', 'passes/text.html'])
+
def test_iterations(self):
tests_to_run = ['passes/image.html', 'passes/text.html']
tests_run = get_tests_run(['--iterations', '2'] + tests_to_run, tests_included=True, flatten_batches=True)
self.assertEquals(tests_run, ['passes/image.html', 'passes/text.html', 'passes/image.html', 'passes/text.html'])
+ def test_repeat_each_iterations_num_tests(self):
+ # The total number of tests should be: number_of_tests *
+ # repeat_each * iterations
+ host = MockHost()
+ res, out, err, _ = logging_run(['--iterations', '2',
+ '--repeat-each', '4',
+ '--print', 'everything',
+ 'passes/text.html', 'failures/expected/text.html'],
+ tests_included=True, host=host, record_results=True)
+ self.assertTrue("=> Results: 8/16 tests passed (50.0%)\n" in out.get())
+ self.assertTrue(err.get()[-2] == "All 16 tests ran as expected.\n")
+
def test_run_chunk(self):
# Test that we actually select the right chunk
all_tests_run = get_tests_run(flatten_batches=True)
diff --git a/Tools/Scripts/webkitpy/performance_tests/perftestsrunner.py b/Tools/Scripts/webkitpy/performance_tests/perftestsrunner.py
index 097a53726..d605829a0 100644
--- a/Tools/Scripts/webkitpy/performance_tests/perftestsrunner.py
+++ b/Tools/Scripts/webkitpy/performance_tests/perftestsrunner.py
@@ -46,8 +46,6 @@ _log = logging.getLogger(__name__)
class PerfTestsRunner(object):
- _perf_tests_base_dir = 'PerformanceTests'
- _initial_page_relative_path = 'resources/init.html'
_test_directories_for_chromium_style_tests = ['inspector']
_default_branch = 'webkit-trunk'
_EXIT_CODE_BAD_BUILD = -1
@@ -67,7 +65,6 @@ class PerfTestsRunner(object):
self._printer = printing.Printer(self._port, self._options, regular_output, buildbot_output, configure_logging=False)
self._webkit_base_dir_len = len(self._port.webkit_base())
self._base_path = self._port.perf_tests_dir()
- self._initial_page_path = self._host.filesystem.join(self._base_path, self._initial_page_relative_path)
self._results = {}
self._timestamp = time.time()
@@ -109,8 +106,15 @@ class PerfTestsRunner(object):
def _is_test_file(filesystem, dirname, filename):
return filename.endswith('.html')
+ paths = []
+ for arg in self._args:
+ paths.append(arg)
+ relpath = self._host.filesystem.relpath(arg, self._base_path)
+ if relpath:
+ paths.append(relpath)
+
skipped_directories = set(['.svn', 'resources'])
- tests = find_files.find(self._host.filesystem, self._base_path, self._args, skipped_directories, _is_test_file)
+ tests = find_files.find(self._host.filesystem, self._base_path, paths, skipped_directories, _is_test_file)
return [test for test in tests if not self._port.skips_perf_test(self._port.relative_perf_test_filename(test))]
def run(self):
@@ -147,14 +151,16 @@ class PerfTestsRunner(object):
return unexpected
def _generate_json(self, timestamp, output_json_path, source_json_path, branch, platform, builder_name, build_number):
- revision = self._host.scm().head_svn_revision()
- contents = {'timestamp': int(timestamp), 'revision': revision, 'results': self._results}
+ contents = {'timestamp': int(timestamp), 'results': self._results}
+ for (name, path) in self._port.repository_paths():
+ contents[name + '-revision'] = self._host.scm().svn_revision(path)
for key, value in {'branch': branch, 'platform': platform, 'builder-name': builder_name, 'build-number': build_number}.items():
if value:
contents[key] = value
filesystem = self._host.filesystem
+ succeeded = False
if source_json_path:
try:
source_json_file = filesystem.open_text_file_for_reading(source_json_path)
@@ -204,6 +210,7 @@ class PerfTestsRunner(object):
result_count = len(tests)
expected = 0
unexpected = 0
+ driver = None
for test in tests:
driver = port.create_driver(worker_number=1, no_timeout=True)
@@ -245,7 +252,8 @@ class PerfTestsRunner(object):
re.compile(r'^\d+(.\d+)?$'),
# Following are for handle existing test like Dromaeo
re.compile(re.escape("""main frame - has 1 onunload handler(s)""")),
- re.compile(re.escape("""frame "<!--framePath //<!--frame0-->-->" - has 1 onunload handler(s)"""))]
+ re.compile(re.escape("""frame "<!--framePath //<!--frame0-->-->" - has 1 onunload handler(s)""")),
+ re.compile(re.escape("""frame "<!--framePath //<!--frame0-->/<!--frame0-->-->" - has 1 onunload handler(s)"""))]
def _should_ignore_line_in_parser_test_result(self, line):
if not line:
@@ -283,9 +291,6 @@ class PerfTestsRunner(object):
def _run_single_test(self, test, driver, is_chromium_style):
test_failed = False
- output = driver.run_test(DriverInput(self._initial_page_path, 10000, None, False))
- if output.text != 'PASS\n':
- self._printer.write('Initialization page failed to load.')
output = driver.run_test(DriverInput(test, self._options.time_out_ms, None, False))
if output.text == None:
diff --git a/Tools/Scripts/webkitpy/performance_tests/perftestsrunner_unittest.py b/Tools/Scripts/webkitpy/performance_tests/perftestsrunner_unittest.py
index 56f052e04..5c4aafdab 100755
--- a/Tools/Scripts/webkitpy/performance_tests/perftestsrunner_unittest.py
+++ b/Tools/Scripts/webkitpy/performance_tests/perftestsrunner_unittest.py
@@ -49,9 +49,7 @@ class MainTest(unittest.TestCase):
text = ''
timeout = False
crash = False
- if driver_input.test_name.endswith('init.html'):
- text = 'PASS\n'
- elif driver_input.test_name.endswith('pass.html'):
+ if driver_input.test_name.endswith('pass.html'):
text = 'RESULT group_name: test_name= 42 ms'
elif driver_input.test_name.endswith('timeout.html'):
timeout = True
@@ -125,24 +123,6 @@ max 1120
driver = MainTest.TestDriver()
return runner._run_single_test(test_name, driver, is_chromium_style=True)
- def test_initial_page_loaded(self):
- runner = self.create_runner()
- driver = MainTest.TestDriver()
- inputs = []
-
- def run_test(input):
- inputs.append(input)
- if input.test_name.endswith('init.html'):
- return DriverOutput('PASS\n', 'image output', 'some hash', None)
- else:
- return DriverOutput('RESULT group_name: test_name= 42 ms\n', 'image output', 'some hash', None)
-
- driver.run_test = run_test
- self.assertTrue(runner._run_single_test('pass.html', driver, is_chromium_style=True))
- self.assertEqual(len(inputs), 2)
- self.assertEqual(inputs[0].test_name, runner._base_path + '/resources/init.html')
- self.assertEqual(inputs[1].test_name, 'pass.html')
-
def test_run_passing_test(self):
self.assertTrue(self.run_test('pass.html'))
@@ -220,7 +200,7 @@ max 1120
"timestamp": 123456789, "results":
{"Bindings/event-target-wrapper": {"max": 1510, "avg": 1489.05, "median": 1487, "min": 1471, "stdev": 14.46},
"group_name:test_name": 42},
- "revision": 1234})
+ "webkit-revision": 5678})
def test_run_test_set_with_json_source(self):
buildbot_output = array_stream.ArrayStream()
@@ -240,9 +220,20 @@ max 1120
"timestamp": 123456789, "results":
{"Bindings/event-target-wrapper": {"max": 1510, "avg": 1489.05, "median": 1487, "min": 1471, "stdev": 14.46},
"group_name:test_name": 42},
- "revision": 1234,
+ "webkit-revision": 5678,
"key": "value"})
+ def test_run_test_set_with_multiple_repositories(self):
+ buildbot_output = array_stream.ArrayStream()
+ runner = self.create_runner(buildbot_output, args=['--output-json-path=/mock-checkout/output.json'])
+ runner._host.filesystem.files[runner._base_path + '/inspector/pass.html'] = True
+ runner._timestamp = 123456789
+ runner._port.repository_paths = lambda: [('webkit', '/mock-checkout'), ('some', '/mock-checkout/some')]
+ self.assertEqual(runner.run(), 0)
+
+ self.assertEqual(json.loads(runner._host.filesystem.files['/mock-checkout/output.json']), {
+ "timestamp": 123456789, "results": {"group_name:test_name": 42.0}, "webkit-revision": 5678, "some-revision": 5678})
+
def test_run_with_upload_json(self):
runner = self.create_runner(args=['--output-json-path=/mock-checkout/output.json',
'--test-results-server', 'some.host', '--platform', 'platform1', '--builder-name', 'builder1', '--build-number', '123'])
@@ -316,6 +307,19 @@ max 1120
tests = runner._collect_tests()
self.assertEqual(len(tests), 1)
+ def test_collect_tests(self):
+ runner = self.create_runner(args=['PerformanceTests/test1.html', 'test2.html'])
+
+ def add_file(filename):
+ runner._host.filesystem.files[runner._host.filesystem.join(runner._base_path, filename)] = 'some content'
+
+ add_file('test1.html')
+ add_file('test2.html')
+ add_file('test3.html')
+ runner._host.filesystem.chdir(runner._port.perf_tests_dir()[:runner._port.perf_tests_dir().rfind(runner._host.filesystem.sep)])
+ tests = [runner._port.relative_perf_test_filename(test) for test in runner._collect_tests()]
+ self.assertEqual(sorted(tests), ['test1.html', 'test2.html'])
+
def test_collect_tests_with_skipped_list(self):
runner = self.create_runner()
diff --git a/Tools/Scripts/webkitpy/style/checker.py b/Tools/Scripts/webkitpy/style/checker.py
index 3440609eb..78235b3fa 100644
--- a/Tools/Scripts/webkitpy/style/checker.py
+++ b/Tools/Scripts/webkitpy/style/checker.py
@@ -206,6 +206,13 @@ _PATH_RULES_SPECIFIER = [
["-readability/naming",
"-readability/parameter_name",
"-whitespace/declaration"]),
+ ([# These files define GObjects, which implies some definitions of
+ # variables and functions containing underscores.
+ "Source/WebCore/platform/graphics/gstreamer/VideoSinkGStreamer1.cpp",
+ "Source/WebCore/platform/graphics/gstreamer/VideoSinkGStreamer.cpp",
+ "Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp",
+ "Source/WebCore/platform/audio/gstreamer/WebKitWebAudioSourceGStreamer.cpp"],
+ ["-readability/naming"]),
# For third-party Python code, keep only the following checks--
#
diff --git a/Tools/Scripts/webkitpy/style/checker_unittest.py b/Tools/Scripts/webkitpy/style/checker_unittest.py
index 48bb19501..bc1441577 100755
--- a/Tools/Scripts/webkitpy/style/checker_unittest.py
+++ b/Tools/Scripts/webkitpy/style/checker_unittest.py
@@ -253,6 +253,9 @@ class GlobalVariablesTest(unittest.TestCase):
assertNoCheck("Source/WebCore/ForwardingHeaders/debugger/Debugger.h",
"build/header_guard")
+ assertNoCheck("Source/WebCore/platform/graphics/gstreamer/VideoSinkGStreamer.cpp",
+ "readability/naming")
+
# Third-party Python code: webkitpy/thirdparty
path = "Tools/Scripts/webkitpy/thirdparty/mock.py"
assertNoCheck(path, "build/include")
@@ -315,6 +318,8 @@ class CheckerDispatcherSkipTest(unittest.TestCase):
"Source/WebKit2/UIProcess/API/gtk/HelperClass.h",
"Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp",
"Source/WebKit2/UIProcess/API/gtk/WebKitWebViewPrivate.h",
+ "Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.cpp",
+ "Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.h",
]
for path in paths_not_to_skip:
diff --git a/Tools/Scripts/webkitpy/style/checkers/cpp.py b/Tools/Scripts/webkitpy/style/checkers/cpp.py
index 6241de9df..27ffecaa8 100644
--- a/Tools/Scripts/webkitpy/style/checkers/cpp.py
+++ b/Tools/Scripts/webkitpy/style/checkers/cpp.py
@@ -2414,6 +2414,10 @@ def check_for_null(clean_lines, line_number, file_state, error):
if search(r'\bgtk_widget_style_get\(\w+\b', line):
return
+ # Don't warn about NULL usage in soup_server_new(). See Bug 77890.
+ if search(r'\bsoup_server_new\(\w+\b', line):
+ return
+
if search(r'\bNULL\b', line):
error(line_number, 'readability/null', 5, 'Use 0 instead of NULL.')
return
diff --git a/Tools/Scripts/webkitpy/style/checkers/jsonchecker.py b/Tools/Scripts/webkitpy/style/checkers/jsonchecker.py
index 520b8758d..264cbeec3 100644
--- a/Tools/Scripts/webkitpy/style/checkers/jsonchecker.py
+++ b/Tools/Scripts/webkitpy/style/checkers/jsonchecker.py
@@ -22,14 +22,9 @@
"""Checks WebKit style for JSON files."""
+import json
import re
-try:
- import json
-except ImportError:
- # python 2.5 compatibility
- import webkitpy.thirdparty.simplejson as json
-
class JSONChecker(object):
"""Processes JSON lines for checking style."""
diff --git a/Tools/Scripts/webkitpy/style/checkers/test_expectations.py b/Tools/Scripts/webkitpy/style/checkers/test_expectations.py
index 7ddd6882a..ff1be9c29 100644
--- a/Tools/Scripts/webkitpy/style/checkers/test_expectations.py
+++ b/Tools/Scripts/webkitpy/style/checkers/test_expectations.py
@@ -47,17 +47,14 @@ class TestExpectationsChecker(object):
categories = set(['test/expectations'])
- def _determine_port_from_exepectations_path(self, host, expectations_path):
- try:
- port_name = expectations_path.split(host.filesystem.sep)[-2]
- if not port_name:
- return None
-
- # Pass a configuration to avoid calling default_configuration() when initializing the port (takes 0.5 seconds on a Mac Pro!).
- return host.port_factory.get(port_name, options=DummyOptions(configuration="Release"))
- except Exception, e:
- _log.warn("Exception while getting port for path %s" % expectations_path)
- return None
+ def _determine_port_from_expectations_path(self, host, expectations_path):
+ # Pass a configuration to avoid calling default_configuration() when initializing the port (takes 0.5 seconds on a Mac Pro!).
+ options = DummyOptions(configuration='Release')
+ for port_name in host.port_factory.all_port_names():
+ port = host.port_factory.get(port_name, options=options)
+ if port.path_to_test_expectations_file().replace(port.path_from_webkit_base() + host.filesystem.sep, '') == expectations_path:
+ return port
+ return None
def __init__(self, file_path, handle_style_error, host=None):
self._file_path = file_path
@@ -70,15 +67,8 @@ class TestExpectationsChecker(object):
host = host or Host()
host._initialize_scm()
- # Determining the port of this expectations.
- self._port_obj = self._determine_port_from_exepectations_path(host, file_path)
- # Using 'test' port when we couldn't determine the port for this
- # expectations.
- if not self._port_obj:
- _log.warn("Could not determine the port for %s. "
- "Using 'test' port, but platform-specific expectations "
- "will fail the check." % self._file_path)
- self._port_obj = host.port_factory.get('test')
+ self._port_obj = self._determine_port_from_expectations_path(host, file_path)
+
# Suppress error messages of test_expectations module since they will be reported later.
log = logging.getLogger("webkitpy.layout_tests.layout_package.test_expectations")
log.setLevel(logging.CRITICAL)
@@ -98,11 +88,9 @@ class TestExpectationsChecker(object):
err = error
if err:
- level = 2
- if err.fatal:
- level = 5
- for error in err.errors:
- matched = self._output_regex.match(error)
+ level = 5
+ for warning in err.warnings:
+ matched = self._output_regex.match(warning)
if matched:
lineno, message = matched.group('line', 'message')
self._handle_style_error(int(lineno), 'test/expectations', level, message)
@@ -114,8 +102,12 @@ class TestExpectationsChecker(object):
def check(self, lines):
overrides = self._port_obj.test_expectations_overrides()
expectations = '\n'.join(lines)
- self.check_test_expectations(expectations_str=expectations,
- tests=None,
- overrides=overrides)
+ if self._port_obj:
+ self.check_test_expectations(expectations_str=expectations,
+ tests=None,
+ overrides=overrides)
+ else:
+ self._handle_style_error(1, 'test/expectations', 5,
+ 'No port uses path %s for test_expectations' % self._file_path)
# Warn tabs in lines as well
self.check_tabs(lines)
diff --git a/Tools/Scripts/webkitpy/style/checkers/test_expectations_unittest.py b/Tools/Scripts/webkitpy/style/checkers/test_expectations_unittest.py
index 10cc7dee5..77bdf8289 100644
--- a/Tools/Scripts/webkitpy/style/checkers/test_expectations_unittest.py
+++ b/Tools/Scripts/webkitpy/style/checkers/test_expectations_unittest.py
@@ -63,23 +63,34 @@ class TestExpectationsTestCase(unittest.TestCase):
self._error_collector = ErrorCollector()
self._test_file = 'passes/text.html'
- def _expect_port_for_expectations_path(self, expected_port_or_port_class, expectations_path):
+ def _expect_port_for_expectations_path(self, expected_port_implementation, expectations_path):
host = MockHost()
checker = TestExpectationsChecker(expectations_path, ErrorCollector(), host=host)
- port = checker._determine_port_from_exepectations_path(host, expectations_path)
+ port = checker._determine_port_from_expectations_path(host, expectations_path)
if port:
- self.assertEquals(port.__class__.__name__, expected_port_or_port_class)
+ self.assertTrue(port.name().startswith(expected_port_implementation))
else:
- self.assertEquals(port, expected_port_or_port_class)
+ self.assertEquals(None, expected_port_implementation)
- def test_determine_port_from_exepectations_path(self):
- self._expect_port_for_expectations_path(None, "/")
- self._expect_port_for_expectations_path("ChromiumMacPort", "/mock-checkout/LayoutTests/chromium-mac/test_expectations.txt")
+ def test_determine_port_from_expectations_path(self):
+ self._expect_port_for_expectations_path(None, '/')
+ self._expect_port_for_expectations_path(None, 'LayoutTests/chromium-mac/test_expectations.txt')
+ self._expect_port_for_expectations_path('chromium', 'LayoutTests/platform/chromium/test_expectations.txt')
+ self._expect_port_for_expectations_path(None, '/mock-checkout/LayoutTests/platform/win/test_expectations.txt')
+ self._expect_port_for_expectations_path('win', 'LayoutTests/platform/win/test_expectations.txt')
def assert_lines_lint(self, lines, should_pass, expected_output=None):
self._error_collector.reset_errors()
+
+ host = MockHost()
checker = TestExpectationsChecker('test/test_expectations.txt',
- self._error_collector, host=MockHost())
+ self._error_collector, host=host)
+
+ # We should have failed to find a valid port object for that path.
+ self.assertEquals(checker._port_obj, None)
+
+ # Now use a test port so we can check the lines.
+ checker._port_obj = host.port_factory.get('test-mac-leopard')
checker.check_test_expectations(expectations_str='\n'.join(lines),
tests=[self._test_file],
overrides=None)
diff --git a/Tools/Scripts/webkitpy/style/filereader_unittest.py b/Tools/Scripts/webkitpy/style/filereader_unittest.py
index a7b2edb3d..bcf94f33e 100644
--- a/Tools/Scripts/webkitpy/style/filereader_unittest.py
+++ b/Tools/Scripts/webkitpy/style/filereader_unittest.py
@@ -20,10 +20,6 @@
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-"""Contains unit tests for filereader.py."""
-
-from __future__ import with_statement
-
import unittest
from webkitpy.common.system.filesystem import FileSystem
diff --git a/Tools/Scripts/webkitpy/thirdparty/simplejson/LICENSE.txt b/Tools/Scripts/webkitpy/thirdparty/simplejson/LICENSE.txt
deleted file mode 100644
index ad95f29c1..000000000
--- a/Tools/Scripts/webkitpy/thirdparty/simplejson/LICENSE.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-Copyright (c) 2006 Bob Ippolito
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
-of the Software, and to permit persons to whom the Software is furnished to do
-so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/Tools/Scripts/webkitpy/thirdparty/simplejson/README.txt b/Tools/Scripts/webkitpy/thirdparty/simplejson/README.txt
deleted file mode 100644
index a8837144d..000000000
--- a/Tools/Scripts/webkitpy/thirdparty/simplejson/README.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-URL: http://undefined.org/python/#simplejson
-Version: 2.1.6
-License: MIT
-License File: LICENSE.txt
-
-Description:
-simplejson is a JSON encoder and decoder for Python.
-
-
-Local Modifications:
-Removed unit tests from current distribution.
diff --git a/Tools/Scripts/webkitpy/thirdparty/simplejson/__init__.py b/Tools/Scripts/webkitpy/thirdparty/simplejson/__init__.py
deleted file mode 100644
index 210b957a9..000000000
--- a/Tools/Scripts/webkitpy/thirdparty/simplejson/__init__.py
+++ /dev/null
@@ -1,438 +0,0 @@
-r"""JSON (JavaScript Object Notation) <http://json.org> is a subset of
-JavaScript syntax (ECMA-262 3rd edition) used as a lightweight data
-interchange format.
-
-:mod:`simplejson` exposes an API familiar to users of the standard library
-:mod:`marshal` and :mod:`pickle` modules. It is the externally maintained
-version of the :mod:`json` library contained in Python 2.6, but maintains
-compatibility with Python 2.4 and Python 2.5 and (currently) has
-significant performance advantages, even without using the optional C
-extension for speedups.
-
-Encoding basic Python object hierarchies::
-
- >>> import simplejson as json
- >>> json.dumps(['foo', {'bar': ('baz', None, 1.0, 2)}])
- '["foo", {"bar": ["baz", null, 1.0, 2]}]'
- >>> print json.dumps("\"foo\bar")
- "\"foo\bar"
- >>> print json.dumps(u'\u1234')
- "\u1234"
- >>> print json.dumps('\\')
- "\\"
- >>> print json.dumps({"c": 0, "b": 0, "a": 0}, sort_keys=True)
- {"a": 0, "b": 0, "c": 0}
- >>> from StringIO import StringIO
- >>> io = StringIO()
- >>> json.dump(['streaming API'], io)
- >>> io.getvalue()
- '["streaming API"]'
-
-Compact encoding::
-
- >>> import simplejson as json
- >>> json.dumps([1,2,3,{'4': 5, '6': 7}], separators=(',',':'))
- '[1,2,3,{"4":5,"6":7}]'
-
-Pretty printing::
-
- >>> import simplejson as json
- >>> s = json.dumps({'4': 5, '6': 7}, sort_keys=True, indent=' ')
- >>> print '\n'.join([l.rstrip() for l in s.splitlines()])
- {
- "4": 5,
- "6": 7
- }
-
-Decoding JSON::
-
- >>> import simplejson as json
- >>> obj = [u'foo', {u'bar': [u'baz', None, 1.0, 2]}]
- >>> json.loads('["foo", {"bar":["baz", null, 1.0, 2]}]') == obj
- True
- >>> json.loads('"\\"foo\\bar"') == u'"foo\x08ar'
- True
- >>> from StringIO import StringIO
- >>> io = StringIO('["streaming API"]')
- >>> json.load(io)[0] == 'streaming API'
- True
-
-Specializing JSON object decoding::
-
- >>> import simplejson as json
- >>> def as_complex(dct):
- ... if '__complex__' in dct:
- ... return complex(dct['real'], dct['imag'])
- ... return dct
- ...
- >>> json.loads('{"__complex__": true, "real": 1, "imag": 2}',
- ... object_hook=as_complex)
- (1+2j)
- >>> from decimal import Decimal
- >>> json.loads('1.1', parse_float=Decimal) == Decimal('1.1')
- True
-
-Specializing JSON object encoding::
-
- >>> import simplejson as json
- >>> def encode_complex(obj):
- ... if isinstance(obj, complex):
- ... return [obj.real, obj.imag]
- ... raise TypeError(repr(o) + " is not JSON serializable")
- ...
- >>> json.dumps(2 + 1j, default=encode_complex)
- '[2.0, 1.0]'
- >>> json.JSONEncoder(default=encode_complex).encode(2 + 1j)
- '[2.0, 1.0]'
- >>> ''.join(json.JSONEncoder(default=encode_complex).iterencode(2 + 1j))
- '[2.0, 1.0]'
-
-
-Using simplejson.tool from the shell to validate and pretty-print::
-
- $ echo '{"json":"obj"}' | python -m simplejson.tool
- {
- "json": "obj"
- }
- $ echo '{ 1.2:3.4}' | python -m simplejson.tool
- Expecting property name: line 1 column 2 (char 2)
-"""
-__version__ = '2.1.6'
-__all__ = [
- 'dump', 'dumps', 'load', 'loads',
- 'JSONDecoder', 'JSONDecodeError', 'JSONEncoder',
- 'OrderedDict',
-]
-
-__author__ = 'Bob Ippolito <bob@redivi.com>'
-
-from decimal import Decimal
-
-from decoder import JSONDecoder, JSONDecodeError
-from encoder import JSONEncoder
-def _import_OrderedDict():
- import collections
- try:
- return collections.OrderedDict
- except AttributeError:
- import ordered_dict
- return ordered_dict.OrderedDict
-OrderedDict = _import_OrderedDict()
-
-def _import_c_make_encoder():
- try:
- from simplejson._speedups import make_encoder
- return make_encoder
- except ImportError:
- return None
-
-_default_encoder = JSONEncoder(
- skipkeys=False,
- ensure_ascii=True,
- check_circular=True,
- allow_nan=True,
- indent=None,
- separators=None,
- encoding='utf-8',
- default=None,
- use_decimal=False,
-)
-
-def dump(obj, fp, skipkeys=False, ensure_ascii=True, check_circular=True,
- allow_nan=True, cls=None, indent=None, separators=None,
- encoding='utf-8', default=None, use_decimal=False, **kw):
- """Serialize ``obj`` as a JSON formatted stream to ``fp`` (a
- ``.write()``-supporting file-like object).
-
- If ``skipkeys`` is true then ``dict`` keys that are not basic types
- (``str``, ``unicode``, ``int``, ``long``, ``float``, ``bool``, ``None``)
- will be skipped instead of raising a ``TypeError``.
-
- If ``ensure_ascii`` is false, then the some chunks written to ``fp``
- may be ``unicode`` instances, subject to normal Python ``str`` to
- ``unicode`` coercion rules. Unless ``fp.write()`` explicitly
- understands ``unicode`` (as in ``codecs.getwriter()``) this is likely
- to cause an error.
-
- If ``check_circular`` is false, then the circular reference check
- for container types will be skipped and a circular reference will
- result in an ``OverflowError`` (or worse).
-
- If ``allow_nan`` is false, then it will be a ``ValueError`` to
- serialize out of range ``float`` values (``nan``, ``inf``, ``-inf``)
- in strict compliance of the JSON specification, instead of using the
- JavaScript equivalents (``NaN``, ``Infinity``, ``-Infinity``).
-
- If *indent* is a string, then JSON array elements and object members
- will be pretty-printed with a newline followed by that string repeated
- for each level of nesting. ``None`` (the default) selects the most compact
- representation without any newlines. For backwards compatibility with
- versions of simplejson earlier than 2.1.0, an integer is also accepted
- and is converted to a string with that many spaces.
-
- If ``separators`` is an ``(item_separator, dict_separator)`` tuple
- then it will be used instead of the default ``(', ', ': ')`` separators.
- ``(',', ':')`` is the most compact JSON representation.
-
- ``encoding`` is the character encoding for str instances, default is UTF-8.
-
- ``default(obj)`` is a function that should return a serializable version
- of obj or raise TypeError. The default simply raises TypeError.
-
- If *use_decimal* is true (default: ``False``) then decimal.Decimal
- will be natively serialized to JSON with full precision.
-
- To use a custom ``JSONEncoder`` subclass (e.g. one that overrides the
- ``.default()`` method to serialize additional types), specify it with
- the ``cls`` kwarg.
-
- """
- # cached encoder
- if (not skipkeys and ensure_ascii and
- check_circular and allow_nan and
- cls is None and indent is None and separators is None and
- encoding == 'utf-8' and default is None and not use_decimal
- and not kw):
- iterable = _default_encoder.iterencode(obj)
- else:
- if cls is None:
- cls = JSONEncoder
- iterable = cls(skipkeys=skipkeys, ensure_ascii=ensure_ascii,
- check_circular=check_circular, allow_nan=allow_nan, indent=indent,
- separators=separators, encoding=encoding,
- default=default, use_decimal=use_decimal, **kw).iterencode(obj)
- # could accelerate with writelines in some versions of Python, at
- # a debuggability cost
- for chunk in iterable:
- fp.write(chunk)
-
-
-def dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True,
- allow_nan=True, cls=None, indent=None, separators=None,
- encoding='utf-8', default=None, use_decimal=False, **kw):
- """Serialize ``obj`` to a JSON formatted ``str``.
-
- If ``skipkeys`` is false then ``dict`` keys that are not basic types
- (``str``, ``unicode``, ``int``, ``long``, ``float``, ``bool``, ``None``)
- will be skipped instead of raising a ``TypeError``.
-
- If ``ensure_ascii`` is false, then the return value will be a
- ``unicode`` instance subject to normal Python ``str`` to ``unicode``
- coercion rules instead of being escaped to an ASCII ``str``.
-
- If ``check_circular`` is false, then the circular reference check
- for container types will be skipped and a circular reference will
- result in an ``OverflowError`` (or worse).
-
- If ``allow_nan`` is false, then it will be a ``ValueError`` to
- serialize out of range ``float`` values (``nan``, ``inf``, ``-inf``) in
- strict compliance of the JSON specification, instead of using the
- JavaScript equivalents (``NaN``, ``Infinity``, ``-Infinity``).
-
- If ``indent`` is a string, then JSON array elements and object members
- will be pretty-printed with a newline followed by that string repeated
- for each level of nesting. ``None`` (the default) selects the most compact
- representation without any newlines. For backwards compatibility with
- versions of simplejson earlier than 2.1.0, an integer is also accepted
- and is converted to a string with that many spaces.
-
- If ``separators`` is an ``(item_separator, dict_separator)`` tuple
- then it will be used instead of the default ``(', ', ': ')`` separators.
- ``(',', ':')`` is the most compact JSON representation.
-
- ``encoding`` is the character encoding for str instances, default is UTF-8.
-
- ``default(obj)`` is a function that should return a serializable version
- of obj or raise TypeError. The default simply raises TypeError.
-
- If *use_decimal* is true (default: ``False``) then decimal.Decimal
- will be natively serialized to JSON with full precision.
-
- To use a custom ``JSONEncoder`` subclass (e.g. one that overrides the
- ``.default()`` method to serialize additional types), specify it with
- the ``cls`` kwarg.
-
- """
- # cached encoder
- if (not skipkeys and ensure_ascii and
- check_circular and allow_nan and
- cls is None and indent is None and separators is None and
- encoding == 'utf-8' and default is None and not use_decimal
- and not kw):
- return _default_encoder.encode(obj)
- if cls is None:
- cls = JSONEncoder
- return cls(
- skipkeys=skipkeys, ensure_ascii=ensure_ascii,
- check_circular=check_circular, allow_nan=allow_nan, indent=indent,
- separators=separators, encoding=encoding, default=default,
- use_decimal=use_decimal, **kw).encode(obj)
-
-
-_default_decoder = JSONDecoder(encoding=None, object_hook=None,
- object_pairs_hook=None)
-
-
-def load(fp, encoding=None, cls=None, object_hook=None, parse_float=None,
- parse_int=None, parse_constant=None, object_pairs_hook=None,
- use_decimal=False, **kw):
- """Deserialize ``fp`` (a ``.read()``-supporting file-like object containing
- a JSON document) to a Python object.
-
- *encoding* determines the encoding used to interpret any
- :class:`str` objects decoded by this instance (``'utf-8'`` by
- default). It has no effect when decoding :class:`unicode` objects.
-
- Note that currently only encodings that are a superset of ASCII work,
- strings of other encodings should be passed in as :class:`unicode`.
-
- *object_hook*, if specified, will be called with the result of every
- JSON object decoded and its return value will be used in place of the
- given :class:`dict`. This can be used to provide custom
- deserializations (e.g. to support JSON-RPC class hinting).
-
- *object_pairs_hook* is an optional function that will be called with
- the result of any object literal decode with an ordered list of pairs.
- The return value of *object_pairs_hook* will be used instead of the
- :class:`dict`. This feature can be used to implement custom decoders
- that rely on the order that the key and value pairs are decoded (for
- example, :func:`collections.OrderedDict` will remember the order of
- insertion). If *object_hook* is also defined, the *object_pairs_hook*
- takes priority.
-
- *parse_float*, if specified, will be called with the string of every
- JSON float to be decoded. By default, this is equivalent to
- ``float(num_str)``. This can be used to use another datatype or parser
- for JSON floats (e.g. :class:`decimal.Decimal`).
-
- *parse_int*, if specified, will be called with the string of every
- JSON int to be decoded. By default, this is equivalent to
- ``int(num_str)``. This can be used to use another datatype or parser
- for JSON integers (e.g. :class:`float`).
-
- *parse_constant*, if specified, will be called with one of the
- following strings: ``'-Infinity'``, ``'Infinity'``, ``'NaN'``. This
- can be used to raise an exception if invalid JSON numbers are
- encountered.
-
- If *use_decimal* is true (default: ``False``) then it implies
- parse_float=decimal.Decimal for parity with ``dump``.
-
- To use a custom ``JSONDecoder`` subclass, specify it with the ``cls``
- kwarg.
-
- """
- return loads(fp.read(),
- encoding=encoding, cls=cls, object_hook=object_hook,
- parse_float=parse_float, parse_int=parse_int,
- parse_constant=parse_constant, object_pairs_hook=object_pairs_hook,
- use_decimal=use_decimal, **kw)
-
-
-def loads(s, encoding=None, cls=None, object_hook=None, parse_float=None,
- parse_int=None, parse_constant=None, object_pairs_hook=None,
- use_decimal=False, **kw):
- """Deserialize ``s`` (a ``str`` or ``unicode`` instance containing a JSON
- document) to a Python object.
-
- *encoding* determines the encoding used to interpret any
- :class:`str` objects decoded by this instance (``'utf-8'`` by
- default). It has no effect when decoding :class:`unicode` objects.
-
- Note that currently only encodings that are a superset of ASCII work,
- strings of other encodings should be passed in as :class:`unicode`.
-
- *object_hook*, if specified, will be called with the result of every
- JSON object decoded and its return value will be used in place of the
- given :class:`dict`. This can be used to provide custom
- deserializations (e.g. to support JSON-RPC class hinting).
-
- *object_pairs_hook* is an optional function that will be called with
- the result of any object literal decode with an ordered list of pairs.
- The return value of *object_pairs_hook* will be used instead of the
- :class:`dict`. This feature can be used to implement custom decoders
- that rely on the order that the key and value pairs are decoded (for
- example, :func:`collections.OrderedDict` will remember the order of
- insertion). If *object_hook* is also defined, the *object_pairs_hook*
- takes priority.
-
- *parse_float*, if specified, will be called with the string of every
- JSON float to be decoded. By default, this is equivalent to
- ``float(num_str)``. This can be used to use another datatype or parser
- for JSON floats (e.g. :class:`decimal.Decimal`).
-
- *parse_int*, if specified, will be called with the string of every
- JSON int to be decoded. By default, this is equivalent to
- ``int(num_str)``. This can be used to use another datatype or parser
- for JSON integers (e.g. :class:`float`).
-
- *parse_constant*, if specified, will be called with one of the
- following strings: ``'-Infinity'``, ``'Infinity'``, ``'NaN'``. This
- can be used to raise an exception if invalid JSON numbers are
- encountered.
-
- If *use_decimal* is true (default: ``False``) then it implies
- parse_float=decimal.Decimal for parity with ``dump``.
-
- To use a custom ``JSONDecoder`` subclass, specify it with the ``cls``
- kwarg.
-
- """
- if (cls is None and encoding is None and object_hook is None and
- parse_int is None and parse_float is None and
- parse_constant is None and object_pairs_hook is None
- and not use_decimal and not kw):
- return _default_decoder.decode(s)
- if cls is None:
- cls = JSONDecoder
- if object_hook is not None:
- kw['object_hook'] = object_hook
- if object_pairs_hook is not None:
- kw['object_pairs_hook'] = object_pairs_hook
- if parse_float is not None:
- kw['parse_float'] = parse_float
- if parse_int is not None:
- kw['parse_int'] = parse_int
- if parse_constant is not None:
- kw['parse_constant'] = parse_constant
- if use_decimal:
- if parse_float is not None:
- raise TypeError("use_decimal=True implies parse_float=Decimal")
- kw['parse_float'] = Decimal
- return cls(encoding=encoding, **kw).decode(s)
-
-
-def _toggle_speedups(enabled):
- import simplejson.decoder as dec
- import simplejson.encoder as enc
- import simplejson.scanner as scan
- c_make_encoder = _import_c_make_encoder()
- if enabled:
- dec.scanstring = dec.c_scanstring or dec.py_scanstring
- enc.c_make_encoder = c_make_encoder
- enc.encode_basestring_ascii = (enc.c_encode_basestring_ascii or
- enc.py_encode_basestring_ascii)
- scan.make_scanner = scan.c_make_scanner or scan.py_make_scanner
- else:
- dec.scanstring = dec.py_scanstring
- enc.c_make_encoder = None
- enc.encode_basestring_ascii = enc.py_encode_basestring_ascii
- scan.make_scanner = scan.py_make_scanner
- dec.make_scanner = scan.make_scanner
- global _default_decoder
- _default_decoder = JSONDecoder(
- encoding=None,
- object_hook=None,
- object_pairs_hook=None,
- )
- global _default_encoder
- _default_encoder = JSONEncoder(
- skipkeys=False,
- ensure_ascii=True,
- check_circular=True,
- allow_nan=True,
- indent=None,
- separators=None,
- encoding='utf-8',
- default=None,
- )
diff --git a/Tools/Scripts/webkitpy/thirdparty/simplejson/_speedups.c b/Tools/Scripts/webkitpy/thirdparty/simplejson/_speedups.c
deleted file mode 100644
index 8b3474702..000000000
--- a/Tools/Scripts/webkitpy/thirdparty/simplejson/_speedups.c
+++ /dev/null
@@ -1,2652 +0,0 @@
-#include "Python.h"
-#include "structmember.h"
-#if PY_VERSION_HEX < 0x02070000 && !defined(PyOS_string_to_double)
-#define PyOS_string_to_double json_PyOS_string_to_double
-static double
-json_PyOS_string_to_double(const char *s, char **endptr, PyObject *overflow_exception);
-static double
-json_PyOS_string_to_double(const char *s, char **endptr, PyObject *overflow_exception) {
- double x;
- assert(endptr == NULL);
- assert(overflow_exception == NULL);
- PyFPE_START_PROTECT("json_PyOS_string_to_double", return -1.0;)
- x = PyOS_ascii_atof(s);
- PyFPE_END_PROTECT(x)
- return x;
-}
-#endif
-#if PY_VERSION_HEX < 0x02060000 && !defined(Py_TYPE)
-#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
-#endif
-#if PY_VERSION_HEX < 0x02060000 && !defined(Py_SIZE)
-#define Py_SIZE(ob) (((PyVarObject*)(ob))->ob_size)
-#endif
-#if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN)
-typedef int Py_ssize_t;
-#define PY_SSIZE_T_MAX INT_MAX
-#define PY_SSIZE_T_MIN INT_MIN
-#define PyInt_FromSsize_t PyInt_FromLong
-#define PyInt_AsSsize_t PyInt_AsLong
-#endif
-#ifndef Py_IS_FINITE
-#define Py_IS_FINITE(X) (!Py_IS_INFINITY(X) && !Py_IS_NAN(X))
-#endif
-
-#ifdef __GNUC__
-#define UNUSED __attribute__((__unused__))
-#else
-#define UNUSED
-#endif
-
-#define DEFAULT_ENCODING "utf-8"
-
-#define PyScanner_Check(op) PyObject_TypeCheck(op, &PyScannerType)
-#define PyScanner_CheckExact(op) (Py_TYPE(op) == &PyScannerType)
-#define PyEncoder_Check(op) PyObject_TypeCheck(op, &PyEncoderType)
-#define PyEncoder_CheckExact(op) (Py_TYPE(op) == &PyEncoderType)
-#define Decimal_Check(op) (PyObject_TypeCheck(op, DecimalTypePtr))
-
-static PyTypeObject PyScannerType;
-static PyTypeObject PyEncoderType;
-static PyTypeObject *DecimalTypePtr;
-
-typedef struct _PyScannerObject {
- PyObject_HEAD
- PyObject *encoding;
- PyObject *strict;
- PyObject *object_hook;
- PyObject *pairs_hook;
- PyObject *parse_float;
- PyObject *parse_int;
- PyObject *parse_constant;
- PyObject *memo;
-} PyScannerObject;
-
-static PyMemberDef scanner_members[] = {
- {"encoding", T_OBJECT, offsetof(PyScannerObject, encoding), READONLY, "encoding"},
- {"strict", T_OBJECT, offsetof(PyScannerObject, strict), READONLY, "strict"},
- {"object_hook", T_OBJECT, offsetof(PyScannerObject, object_hook), READONLY, "object_hook"},
- {"object_pairs_hook", T_OBJECT, offsetof(PyScannerObject, pairs_hook), READONLY, "object_pairs_hook"},
- {"parse_float", T_OBJECT, offsetof(PyScannerObject, parse_float), READONLY, "parse_float"},
- {"parse_int", T_OBJECT, offsetof(PyScannerObject, parse_int), READONLY, "parse_int"},
- {"parse_constant", T_OBJECT, offsetof(PyScannerObject, parse_constant), READONLY, "parse_constant"},
- {NULL}
-};
-
-typedef struct _PyEncoderObject {
- PyObject_HEAD
- PyObject *markers;
- PyObject *defaultfn;
- PyObject *encoder;
- PyObject *indent;
- PyObject *key_separator;
- PyObject *item_separator;
- PyObject *sort_keys;
- PyObject *skipkeys;
- PyObject *key_memo;
- int fast_encode;
- int allow_nan;
- int use_decimal;
-} PyEncoderObject;
-
-static PyMemberDef encoder_members[] = {
- {"markers", T_OBJECT, offsetof(PyEncoderObject, markers), READONLY, "markers"},
- {"default", T_OBJECT, offsetof(PyEncoderObject, defaultfn), READONLY, "default"},
- {"encoder", T_OBJECT, offsetof(PyEncoderObject, encoder), READONLY, "encoder"},
- {"indent", T_OBJECT, offsetof(PyEncoderObject, indent), READONLY, "indent"},
- {"key_separator", T_OBJECT, offsetof(PyEncoderObject, key_separator), READONLY, "key_separator"},
- {"item_separator", T_OBJECT, offsetof(PyEncoderObject, item_separator), READONLY, "item_separator"},
- {"sort_keys", T_OBJECT, offsetof(PyEncoderObject, sort_keys), READONLY, "sort_keys"},
- {"skipkeys", T_OBJECT, offsetof(PyEncoderObject, skipkeys), READONLY, "skipkeys"},
- {"key_memo", T_OBJECT, offsetof(PyEncoderObject, key_memo), READONLY, "key_memo"},
- {NULL}
-};
-
-static Py_ssize_t
-ascii_escape_char(Py_UNICODE c, char *output, Py_ssize_t chars);
-static PyObject *
-ascii_escape_unicode(PyObject *pystr);
-static PyObject *
-ascii_escape_str(PyObject *pystr);
-static PyObject *
-py_encode_basestring_ascii(PyObject* self UNUSED, PyObject *pystr);
-void init_speedups(void);
-static PyObject *
-scan_once_str(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr);
-static PyObject *
-scan_once_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr);
-static PyObject *
-_build_rval_index_tuple(PyObject *rval, Py_ssize_t idx);
-static PyObject *
-scanner_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
-static int
-scanner_init(PyObject *self, PyObject *args, PyObject *kwds);
-static void
-scanner_dealloc(PyObject *self);
-static int
-scanner_clear(PyObject *self);
-static PyObject *
-encoder_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
-static int
-encoder_init(PyObject *self, PyObject *args, PyObject *kwds);
-static void
-encoder_dealloc(PyObject *self);
-static int
-encoder_clear(PyObject *self);
-static int
-encoder_listencode_list(PyEncoderObject *s, PyObject *rval, PyObject *seq, Py_ssize_t indent_level);
-static int
-encoder_listencode_obj(PyEncoderObject *s, PyObject *rval, PyObject *obj, Py_ssize_t indent_level);
-static int
-encoder_listencode_dict(PyEncoderObject *s, PyObject *rval, PyObject *dct, Py_ssize_t indent_level);
-static PyObject *
-_encoded_const(PyObject *obj);
-static void
-raise_errmsg(char *msg, PyObject *s, Py_ssize_t end);
-static PyObject *
-encoder_encode_string(PyEncoderObject *s, PyObject *obj);
-static int
-_convertPyInt_AsSsize_t(PyObject *o, Py_ssize_t *size_ptr);
-static PyObject *
-_convertPyInt_FromSsize_t(Py_ssize_t *size_ptr);
-static PyObject *
-encoder_encode_float(PyEncoderObject *s, PyObject *obj);
-
-#define S_CHAR(c) (c >= ' ' && c <= '~' && c != '\\' && c != '"')
-#define IS_WHITESPACE(c) (((c) == ' ') || ((c) == '\t') || ((c) == '\n') || ((c) == '\r'))
-
-#define MIN_EXPANSION 6
-#ifdef Py_UNICODE_WIDE
-#define MAX_EXPANSION (2 * MIN_EXPANSION)
-#else
-#define MAX_EXPANSION MIN_EXPANSION
-#endif
-
-static int
-_convertPyInt_AsSsize_t(PyObject *o, Py_ssize_t *size_ptr)
-{
- /* PyObject to Py_ssize_t converter */
- *size_ptr = PyInt_AsSsize_t(o);
- if (*size_ptr == -1 && PyErr_Occurred())
- return 0;
- return 1;
-}
-
-static PyObject *
-_convertPyInt_FromSsize_t(Py_ssize_t *size_ptr)
-{
- /* Py_ssize_t to PyObject converter */
- return PyInt_FromSsize_t(*size_ptr);
-}
-
-static Py_ssize_t
-ascii_escape_char(Py_UNICODE c, char *output, Py_ssize_t chars)
-{
- /* Escape unicode code point c to ASCII escape sequences
- in char *output. output must have at least 12 bytes unused to
- accommodate an escaped surrogate pair "\uXXXX\uXXXX" */
- output[chars++] = '\\';
- switch (c) {
- case '\\': output[chars++] = (char)c; break;
- case '"': output[chars++] = (char)c; break;
- case '\b': output[chars++] = 'b'; break;
- case '\f': output[chars++] = 'f'; break;
- case '\n': output[chars++] = 'n'; break;
- case '\r': output[chars++] = 'r'; break;
- case '\t': output[chars++] = 't'; break;
- default:
-#ifdef Py_UNICODE_WIDE
- if (c >= 0x10000) {
- /* UTF-16 surrogate pair */
- Py_UNICODE v = c - 0x10000;
- c = 0xd800 | ((v >> 10) & 0x3ff);
- output[chars++] = 'u';
- output[chars++] = "0123456789abcdef"[(c >> 12) & 0xf];
- output[chars++] = "0123456789abcdef"[(c >> 8) & 0xf];
- output[chars++] = "0123456789abcdef"[(c >> 4) & 0xf];
- output[chars++] = "0123456789abcdef"[(c ) & 0xf];
- c = 0xdc00 | (v & 0x3ff);
- output[chars++] = '\\';
- }
-#endif
- output[chars++] = 'u';
- output[chars++] = "0123456789abcdef"[(c >> 12) & 0xf];
- output[chars++] = "0123456789abcdef"[(c >> 8) & 0xf];
- output[chars++] = "0123456789abcdef"[(c >> 4) & 0xf];
- output[chars++] = "0123456789abcdef"[(c ) & 0xf];
- }
- return chars;
-}
-
-static PyObject *
-ascii_escape_unicode(PyObject *pystr)
-{
- /* Take a PyUnicode pystr and return a new ASCII-only escaped PyString */
- Py_ssize_t i;
- Py_ssize_t input_chars;
- Py_ssize_t output_size;
- Py_ssize_t max_output_size;
- Py_ssize_t chars;
- PyObject *rval;
- char *output;
- Py_UNICODE *input_unicode;
-
- input_chars = PyUnicode_GET_SIZE(pystr);
- input_unicode = PyUnicode_AS_UNICODE(pystr);
-
- /* One char input can be up to 6 chars output, estimate 4 of these */
- output_size = 2 + (MIN_EXPANSION * 4) + input_chars;
- max_output_size = 2 + (input_chars * MAX_EXPANSION);
- rval = PyString_FromStringAndSize(NULL, output_size);
- if (rval == NULL) {
- return NULL;
- }
- output = PyString_AS_STRING(rval);
- chars = 0;
- output[chars++] = '"';
- for (i = 0; i < input_chars; i++) {
- Py_UNICODE c = input_unicode[i];
- if (S_CHAR(c)) {
- output[chars++] = (char)c;
- }
- else {
- chars = ascii_escape_char(c, output, chars);
- }
- if (output_size - chars < (1 + MAX_EXPANSION)) {
- /* There's more than four, so let's resize by a lot */
- Py_ssize_t new_output_size = output_size * 2;
- /* This is an upper bound */
- if (new_output_size > max_output_size) {
- new_output_size = max_output_size;
- }
- /* Make sure that the output size changed before resizing */
- if (new_output_size != output_size) {
- output_size = new_output_size;
- if (_PyString_Resize(&rval, output_size) == -1) {
- return NULL;
- }
- output = PyString_AS_STRING(rval);
- }
- }
- }
- output[chars++] = '"';
- if (_PyString_Resize(&rval, chars) == -1) {
- return NULL;
- }
- return rval;
-}
-
-static PyObject *
-ascii_escape_str(PyObject *pystr)
-{
- /* Take a PyString pystr and return a new ASCII-only escaped PyString */
- Py_ssize_t i;
- Py_ssize_t input_chars;
- Py_ssize_t output_size;
- Py_ssize_t chars;
- PyObject *rval;
- char *output;
- char *input_str;
-
- input_chars = PyString_GET_SIZE(pystr);
- input_str = PyString_AS_STRING(pystr);
-
- /* Fast path for a string that's already ASCII */
- for (i = 0; i < input_chars; i++) {
- Py_UNICODE c = (Py_UNICODE)(unsigned char)input_str[i];
- if (!S_CHAR(c)) {
- /* If we have to escape something, scan the string for unicode */
- Py_ssize_t j;
- for (j = i; j < input_chars; j++) {
- c = (Py_UNICODE)(unsigned char)input_str[j];
- if (c > 0x7f) {
- /* We hit a non-ASCII character, bail to unicode mode */
- PyObject *uni;
- uni = PyUnicode_DecodeUTF8(input_str, input_chars, "strict");
- if (uni == NULL) {
- return NULL;
- }
- rval = ascii_escape_unicode(uni);
- Py_DECREF(uni);
- return rval;
- }
- }
- break;
- }
- }
-
- if (i == input_chars) {
- /* Input is already ASCII */
- output_size = 2 + input_chars;
- }
- else {
- /* One char input can be up to 6 chars output, estimate 4 of these */
- output_size = 2 + (MIN_EXPANSION * 4) + input_chars;
- }
- rval = PyString_FromStringAndSize(NULL, output_size);
- if (rval == NULL) {
- return NULL;
- }
- output = PyString_AS_STRING(rval);
- output[0] = '"';
-
- /* We know that everything up to i is ASCII already */
- chars = i + 1;
- memcpy(&output[1], input_str, i);
-
- for (; i < input_chars; i++) {
- Py_UNICODE c = (Py_UNICODE)(unsigned char)input_str[i];
- if (S_CHAR(c)) {
- output[chars++] = (char)c;
- }
- else {
- chars = ascii_escape_char(c, output, chars);
- }
- /* An ASCII char can't possibly expand to a surrogate! */
- if (output_size - chars < (1 + MIN_EXPANSION)) {
- /* There's more than four, so let's resize by a lot */
- output_size *= 2;
- if (output_size > 2 + (input_chars * MIN_EXPANSION)) {
- output_size = 2 + (input_chars * MIN_EXPANSION);
- }
- if (_PyString_Resize(&rval, output_size) == -1) {
- return NULL;
- }
- output = PyString_AS_STRING(rval);
- }
- }
- output[chars++] = '"';
- if (_PyString_Resize(&rval, chars) == -1) {
- return NULL;
- }
- return rval;
-}
-
-static void
-raise_errmsg(char *msg, PyObject *s, Py_ssize_t end)
-{
- /* Use the Python function simplejson.decoder.errmsg to raise a nice
- looking ValueError exception */
- static PyObject *JSONDecodeError = NULL;
- PyObject *exc;
- if (JSONDecodeError == NULL) {
- PyObject *decoder = PyImport_ImportModule("simplejson.decoder");
- if (decoder == NULL)
- return;
- JSONDecodeError = PyObject_GetAttrString(decoder, "JSONDecodeError");
- Py_DECREF(decoder);
- if (JSONDecodeError == NULL)
- return;
- }
- exc = PyObject_CallFunction(JSONDecodeError, "(zOO&)", msg, s, _convertPyInt_FromSsize_t, &end);
- if (exc) {
- PyErr_SetObject(JSONDecodeError, exc);
- Py_DECREF(exc);
- }
-}
-
-static PyObject *
-join_list_unicode(PyObject *lst)
-{
- /* return u''.join(lst) */
- static PyObject *joinfn = NULL;
- if (joinfn == NULL) {
- PyObject *ustr = PyUnicode_FromUnicode(NULL, 0);
- if (ustr == NULL)
- return NULL;
-
- joinfn = PyObject_GetAttrString(ustr, "join");
- Py_DECREF(ustr);
- if (joinfn == NULL)
- return NULL;
- }
- return PyObject_CallFunctionObjArgs(joinfn, lst, NULL);
-}
-
-static PyObject *
-join_list_string(PyObject *lst)
-{
- /* return ''.join(lst) */
- static PyObject *joinfn = NULL;
- if (joinfn == NULL) {
- PyObject *ustr = PyString_FromStringAndSize(NULL, 0);
- if (ustr == NULL)
- return NULL;
-
- joinfn = PyObject_GetAttrString(ustr, "join");
- Py_DECREF(ustr);
- if (joinfn == NULL)
- return NULL;
- }
- return PyObject_CallFunctionObjArgs(joinfn, lst, NULL);
-}
-
-static PyObject *
-_build_rval_index_tuple(PyObject *rval, Py_ssize_t idx) {
- /* return (rval, idx) tuple, stealing reference to rval */
- PyObject *tpl;
- PyObject *pyidx;
- /*
- steal a reference to rval, returns (rval, idx)
- */
- if (rval == NULL) {
- return NULL;
- }
- pyidx = PyInt_FromSsize_t(idx);
- if (pyidx == NULL) {
- Py_DECREF(rval);
- return NULL;
- }
- tpl = PyTuple_New(2);
- if (tpl == NULL) {
- Py_DECREF(pyidx);
- Py_DECREF(rval);
- return NULL;
- }
- PyTuple_SET_ITEM(tpl, 0, rval);
- PyTuple_SET_ITEM(tpl, 1, pyidx);
- return tpl;
-}
-
-#define APPEND_OLD_CHUNK \
- if (chunk != NULL) { \
- if (chunks == NULL) { \
- chunks = PyList_New(0); \
- if (chunks == NULL) { \
- goto bail; \
- } \
- } \
- if (PyList_Append(chunks, chunk)) { \
- goto bail; \
- } \
- Py_CLEAR(chunk); \
- }
-
-static PyObject *
-scanstring_str(PyObject *pystr, Py_ssize_t end, char *encoding, int strict, Py_ssize_t *next_end_ptr)
-{
- /* Read the JSON string from PyString pystr.
- end is the index of the first character after the quote.
- encoding is the encoding of pystr (must be an ASCII superset)
- if strict is zero then literal control characters are allowed
- *next_end_ptr is a return-by-reference index of the character
- after the end quote
-
- Return value is a new PyString (if ASCII-only) or PyUnicode
- */
- PyObject *rval;
- Py_ssize_t len = PyString_GET_SIZE(pystr);
- Py_ssize_t begin = end - 1;
- Py_ssize_t next = begin;
- int has_unicode = 0;
- char *buf = PyString_AS_STRING(pystr);
- PyObject *chunks = NULL;
- PyObject *chunk = NULL;
-
- if (end < 0 || len <= end) {
- PyErr_SetString(PyExc_ValueError, "end is out of bounds");
- goto bail;
- }
- while (1) {
- /* Find the end of the string or the next escape */
- Py_UNICODE c = 0;
- for (next = end; next < len; next++) {
- c = (unsigned char)buf[next];
- if (c == '"' || c == '\\') {
- break;
- }
- else if (strict && c <= 0x1f) {
- raise_errmsg("Invalid control character at", pystr, next);
- goto bail;
- }
- else if (c > 0x7f) {
- has_unicode = 1;
- }
- }
- if (!(c == '"' || c == '\\')) {
- raise_errmsg("Unterminated string starting at", pystr, begin);
- goto bail;
- }
- /* Pick up this chunk if it's not zero length */
- if (next != end) {
- PyObject *strchunk;
- APPEND_OLD_CHUNK
- strchunk = PyString_FromStringAndSize(&buf[end], next - end);
- if (strchunk == NULL) {
- goto bail;
- }
- if (has_unicode) {
- chunk = PyUnicode_FromEncodedObject(strchunk, encoding, NULL);
- Py_DECREF(strchunk);
- if (chunk == NULL) {
- goto bail;
- }
- }
- else {
- chunk = strchunk;
- }
- }
- next++;
- if (c == '"') {
- end = next;
- break;
- }
- if (next == len) {
- raise_errmsg("Unterminated string starting at", pystr, begin);
- goto bail;
- }
- c = buf[next];
- if (c != 'u') {
- /* Non-unicode backslash escapes */
- end = next + 1;
- switch (c) {
- case '"': break;
- case '\\': break;
- case '/': break;
- case 'b': c = '\b'; break;
- case 'f': c = '\f'; break;
- case 'n': c = '\n'; break;
- case 'r': c = '\r'; break;
- case 't': c = '\t'; break;
- default: c = 0;
- }
- if (c == 0) {
- raise_errmsg("Invalid \\escape", pystr, end - 2);
- goto bail;
- }
- }
- else {
- c = 0;
- next++;
- end = next + 4;
- if (end >= len) {
- raise_errmsg("Invalid \\uXXXX escape", pystr, next - 1);
- goto bail;
- }
- /* Decode 4 hex digits */
- for (; next < end; next++) {
- Py_UNICODE digit = buf[next];
- c <<= 4;
- switch (digit) {
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- c |= (digit - '0'); break;
- case 'a': case 'b': case 'c': case 'd': case 'e':
- case 'f':
- c |= (digit - 'a' + 10); break;
- case 'A': case 'B': case 'C': case 'D': case 'E':
- case 'F':
- c |= (digit - 'A' + 10); break;
- default:
- raise_errmsg("Invalid \\uXXXX escape", pystr, end - 5);
- goto bail;
- }
- }
-#ifdef Py_UNICODE_WIDE
- /* Surrogate pair */
- if ((c & 0xfc00) == 0xd800) {
- Py_UNICODE c2 = 0;
- if (end + 6 >= len) {
- raise_errmsg("Unpaired high surrogate", pystr, end - 5);
- goto bail;
- }
- if (buf[next++] != '\\' || buf[next++] != 'u') {
- raise_errmsg("Unpaired high surrogate", pystr, end - 5);
- goto bail;
- }
- end += 6;
- /* Decode 4 hex digits */
- for (; next < end; next++) {
- c2 <<= 4;
- Py_UNICODE digit = buf[next];
- switch (digit) {
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- c2 |= (digit - '0'); break;
- case 'a': case 'b': case 'c': case 'd': case 'e':
- case 'f':
- c2 |= (digit - 'a' + 10); break;
- case 'A': case 'B': case 'C': case 'D': case 'E':
- case 'F':
- c2 |= (digit - 'A' + 10); break;
- default:
- raise_errmsg("Invalid \\uXXXX escape", pystr, end - 5);
- goto bail;
- }
- }
- if ((c2 & 0xfc00) != 0xdc00) {
- raise_errmsg("Unpaired high surrogate", pystr, end - 5);
- goto bail;
- }
- c = 0x10000 + (((c - 0xd800) << 10) | (c2 - 0xdc00));
- }
- else if ((c & 0xfc00) == 0xdc00) {
- raise_errmsg("Unpaired low surrogate", pystr, end - 5);
- goto bail;
- }
-#endif
- }
- if (c > 0x7f) {
- has_unicode = 1;
- }
- APPEND_OLD_CHUNK
- if (has_unicode) {
- chunk = PyUnicode_FromUnicode(&c, 1);
- if (chunk == NULL) {
- goto bail;
- }
- }
- else {
- char c_char = Py_CHARMASK(c);
- chunk = PyString_FromStringAndSize(&c_char, 1);
- if (chunk == NULL) {
- goto bail;
- }
- }
- }
-
- if (chunks == NULL) {
- if (chunk != NULL)
- rval = chunk;
- else
- rval = PyString_FromStringAndSize("", 0);
- }
- else {
- APPEND_OLD_CHUNK
- rval = join_list_string(chunks);
- if (rval == NULL) {
- goto bail;
- }
- Py_CLEAR(chunks);
- }
-
- *next_end_ptr = end;
- return rval;
-bail:
- *next_end_ptr = -1;
- Py_XDECREF(chunk);
- Py_XDECREF(chunks);
- return NULL;
-}
-
-
-static PyObject *
-scanstring_unicode(PyObject *pystr, Py_ssize_t end, int strict, Py_ssize_t *next_end_ptr)
-{
- /* Read the JSON string from PyUnicode pystr.
- end is the index of the first character after the quote.
- if strict is zero then literal control characters are allowed
- *next_end_ptr is a return-by-reference index of the character
- after the end quote
-
- Return value is a new PyUnicode
- */
- PyObject *rval;
- Py_ssize_t len = PyUnicode_GET_SIZE(pystr);
- Py_ssize_t begin = end - 1;
- Py_ssize_t next = begin;
- const Py_UNICODE *buf = PyUnicode_AS_UNICODE(pystr);
- PyObject *chunks = NULL;
- PyObject *chunk = NULL;
-
- if (end < 0 || len <= end) {
- PyErr_SetString(PyExc_ValueError, "end is out of bounds");
- goto bail;
- }
- while (1) {
- /* Find the end of the string or the next escape */
- Py_UNICODE c = 0;
- for (next = end; next < len; next++) {
- c = buf[next];
- if (c == '"' || c == '\\') {
- break;
- }
- else if (strict && c <= 0x1f) {
- raise_errmsg("Invalid control character at", pystr, next);
- goto bail;
- }
- }
- if (!(c == '"' || c == '\\')) {
- raise_errmsg("Unterminated string starting at", pystr, begin);
- goto bail;
- }
- /* Pick up this chunk if it's not zero length */
- if (next != end) {
- APPEND_OLD_CHUNK
- chunk = PyUnicode_FromUnicode(&buf[end], next - end);
- if (chunk == NULL) {
- goto bail;
- }
- }
- next++;
- if (c == '"') {
- end = next;
- break;
- }
- if (next == len) {
- raise_errmsg("Unterminated string starting at", pystr, begin);
- goto bail;
- }
- c = buf[next];
- if (c != 'u') {
- /* Non-unicode backslash escapes */
- end = next + 1;
- switch (c) {
- case '"': break;
- case '\\': break;
- case '/': break;
- case 'b': c = '\b'; break;
- case 'f': c = '\f'; break;
- case 'n': c = '\n'; break;
- case 'r': c = '\r'; break;
- case 't': c = '\t'; break;
- default: c = 0;
- }
- if (c == 0) {
- raise_errmsg("Invalid \\escape", pystr, end - 2);
- goto bail;
- }
- }
- else {
- c = 0;
- next++;
- end = next + 4;
- if (end >= len) {
- raise_errmsg("Invalid \\uXXXX escape", pystr, next - 1);
- goto bail;
- }
- /* Decode 4 hex digits */
- for (; next < end; next++) {
- Py_UNICODE digit = buf[next];
- c <<= 4;
- switch (digit) {
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- c |= (digit - '0'); break;
- case 'a': case 'b': case 'c': case 'd': case 'e':
- case 'f':
- c |= (digit - 'a' + 10); break;
- case 'A': case 'B': case 'C': case 'D': case 'E':
- case 'F':
- c |= (digit - 'A' + 10); break;
- default:
- raise_errmsg("Invalid \\uXXXX escape", pystr, end - 5);
- goto bail;
- }
- }
-#ifdef Py_UNICODE_WIDE
- /* Surrogate pair */
- if ((c & 0xfc00) == 0xd800) {
- Py_UNICODE c2 = 0;
- if (end + 6 >= len) {
- raise_errmsg("Unpaired high surrogate", pystr, end - 5);
- goto bail;
- }
- if (buf[next++] != '\\' || buf[next++] != 'u') {
- raise_errmsg("Unpaired high surrogate", pystr, end - 5);
- goto bail;
- }
- end += 6;
- /* Decode 4 hex digits */
- for (; next < end; next++) {
- c2 <<= 4;
- Py_UNICODE digit = buf[next];
- switch (digit) {
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- c2 |= (digit - '0'); break;
- case 'a': case 'b': case 'c': case 'd': case 'e':
- case 'f':
- c2 |= (digit - 'a' + 10); break;
- case 'A': case 'B': case 'C': case 'D': case 'E':
- case 'F':
- c2 |= (digit - 'A' + 10); break;
- default:
- raise_errmsg("Invalid \\uXXXX escape", pystr, end - 5);
- goto bail;
- }
- }
- if ((c2 & 0xfc00) != 0xdc00) {
- raise_errmsg("Unpaired high surrogate", pystr, end - 5);
- goto bail;
- }
- c = 0x10000 + (((c - 0xd800) << 10) | (c2 - 0xdc00));
- }
- else if ((c & 0xfc00) == 0xdc00) {
- raise_errmsg("Unpaired low surrogate", pystr, end - 5);
- goto bail;
- }
-#endif
- }
- APPEND_OLD_CHUNK
- chunk = PyUnicode_FromUnicode(&c, 1);
- if (chunk == NULL) {
- goto bail;
- }
- }
-
- if (chunks == NULL) {
- if (chunk != NULL)
- rval = chunk;
- else
- rval = PyUnicode_FromUnicode(NULL, 0);
- }
- else {
- APPEND_OLD_CHUNK
- rval = join_list_unicode(chunks);
- if (rval == NULL) {
- goto bail;
- }
- Py_CLEAR(chunks);
- }
- *next_end_ptr = end;
- return rval;
-bail:
- *next_end_ptr = -1;
- Py_XDECREF(chunk);
- Py_XDECREF(chunks);
- return NULL;
-}
-
-PyDoc_STRVAR(pydoc_scanstring,
- "scanstring(basestring, end, encoding, strict=True) -> (str, end)\n"
- "\n"
- "Scan the string s for a JSON string. End is the index of the\n"
- "character in s after the quote that started the JSON string.\n"
- "Unescapes all valid JSON string escape sequences and raises ValueError\n"
- "on attempt to decode an invalid string. If strict is False then literal\n"
- "control characters are allowed in the string.\n"
- "\n"
- "Returns a tuple of the decoded string and the index of the character in s\n"
- "after the end quote."
-);
-
-static PyObject *
-py_scanstring(PyObject* self UNUSED, PyObject *args)
-{
- PyObject *pystr;
- PyObject *rval;
- Py_ssize_t end;
- Py_ssize_t next_end = -1;
- char *encoding = NULL;
- int strict = 1;
- if (!PyArg_ParseTuple(args, "OO&|zi:scanstring", &pystr, _convertPyInt_AsSsize_t, &end, &encoding, &strict)) {
- return NULL;
- }
- if (encoding == NULL) {
- encoding = DEFAULT_ENCODING;
- }
- if (PyString_Check(pystr)) {
- rval = scanstring_str(pystr, end, encoding, strict, &next_end);
- }
- else if (PyUnicode_Check(pystr)) {
- rval = scanstring_unicode(pystr, end, strict, &next_end);
- }
- else {
- PyErr_Format(PyExc_TypeError,
- "first argument must be a string, not %.80s",
- Py_TYPE(pystr)->tp_name);
- return NULL;
- }
- return _build_rval_index_tuple(rval, next_end);
-}
-
-PyDoc_STRVAR(pydoc_encode_basestring_ascii,
- "encode_basestring_ascii(basestring) -> str\n"
- "\n"
- "Return an ASCII-only JSON representation of a Python string"
-);
-
-static PyObject *
-py_encode_basestring_ascii(PyObject* self UNUSED, PyObject *pystr)
-{
- /* Return an ASCII-only JSON representation of a Python string */
- /* METH_O */
- if (PyString_Check(pystr)) {
- return ascii_escape_str(pystr);
- }
- else if (PyUnicode_Check(pystr)) {
- return ascii_escape_unicode(pystr);
- }
- else {
- PyErr_Format(PyExc_TypeError,
- "first argument must be a string, not %.80s",
- Py_TYPE(pystr)->tp_name);
- return NULL;
- }
-}
-
-static void
-scanner_dealloc(PyObject *self)
-{
- /* Deallocate scanner object */
- scanner_clear(self);
- Py_TYPE(self)->tp_free(self);
-}
-
-static int
-scanner_traverse(PyObject *self, visitproc visit, void *arg)
-{
- PyScannerObject *s;
- assert(PyScanner_Check(self));
- s = (PyScannerObject *)self;
- Py_VISIT(s->encoding);
- Py_VISIT(s->strict);
- Py_VISIT(s->object_hook);
- Py_VISIT(s->pairs_hook);
- Py_VISIT(s->parse_float);
- Py_VISIT(s->parse_int);
- Py_VISIT(s->parse_constant);
- Py_VISIT(s->memo);
- return 0;
-}
-
-static int
-scanner_clear(PyObject *self)
-{
- PyScannerObject *s;
- assert(PyScanner_Check(self));
- s = (PyScannerObject *)self;
- Py_CLEAR(s->encoding);
- Py_CLEAR(s->strict);
- Py_CLEAR(s->object_hook);
- Py_CLEAR(s->pairs_hook);
- Py_CLEAR(s->parse_float);
- Py_CLEAR(s->parse_int);
- Py_CLEAR(s->parse_constant);
- Py_CLEAR(s->memo);
- return 0;
-}
-
-static PyObject *
-_parse_object_str(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr) {
- /* Read a JSON object from PyString pystr.
- idx is the index of the first character after the opening curly brace.
- *next_idx_ptr is a return-by-reference index to the first character after
- the closing curly brace.
-
- Returns a new PyObject (usually a dict, but object_hook or
- object_pairs_hook can change that)
- */
- char *str = PyString_AS_STRING(pystr);
- Py_ssize_t end_idx = PyString_GET_SIZE(pystr) - 1;
- PyObject *rval = NULL;
- PyObject *pairs = NULL;
- PyObject *item;
- PyObject *key = NULL;
- PyObject *val = NULL;
- char *encoding = PyString_AS_STRING(s->encoding);
- int strict = PyObject_IsTrue(s->strict);
- int has_pairs_hook = (s->pairs_hook != Py_None);
- Py_ssize_t next_idx;
- if (has_pairs_hook) {
- pairs = PyList_New(0);
- if (pairs == NULL)
- return NULL;
- }
- else {
- rval = PyDict_New();
- if (rval == NULL)
- return NULL;
- }
-
- /* skip whitespace after { */
- while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++;
-
- /* only loop if the object is non-empty */
- if (idx <= end_idx && str[idx] != '}') {
- while (idx <= end_idx) {
- PyObject *memokey;
-
- /* read key */
- if (str[idx] != '"') {
- raise_errmsg("Expecting property name", pystr, idx);
- goto bail;
- }
- key = scanstring_str(pystr, idx + 1, encoding, strict, &next_idx);
- if (key == NULL)
- goto bail;
- memokey = PyDict_GetItem(s->memo, key);
- if (memokey != NULL) {
- Py_INCREF(memokey);
- Py_DECREF(key);
- key = memokey;
- }
- else {
- if (PyDict_SetItem(s->memo, key, key) < 0)
- goto bail;
- }
- idx = next_idx;
-
- /* skip whitespace between key and : delimiter, read :, skip whitespace */
- while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++;
- if (idx > end_idx || str[idx] != ':') {
- raise_errmsg("Expecting : delimiter", pystr, idx);
- goto bail;
- }
- idx++;
- while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++;
-
- /* read any JSON data type */
- val = scan_once_str(s, pystr, idx, &next_idx);
- if (val == NULL)
- goto bail;
-
- if (has_pairs_hook) {
- item = PyTuple_Pack(2, key, val);
- if (item == NULL)
- goto bail;
- Py_CLEAR(key);
- Py_CLEAR(val);
- if (PyList_Append(pairs, item) == -1) {
- Py_DECREF(item);
- goto bail;
- }
- Py_DECREF(item);
- }
- else {
- if (PyDict_SetItem(rval, key, val) < 0)
- goto bail;
- Py_CLEAR(key);
- Py_CLEAR(val);
- }
- idx = next_idx;
-
- /* skip whitespace before } or , */
- while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++;
-
- /* bail if the object is closed or we didn't get the , delimiter */
- if (idx > end_idx) break;
- if (str[idx] == '}') {
- break;
- }
- else if (str[idx] != ',') {
- raise_errmsg("Expecting , delimiter", pystr, idx);
- goto bail;
- }
- idx++;
-
- /* skip whitespace after , delimiter */
- while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++;
- }
- }
- /* verify that idx < end_idx, str[idx] should be '}' */
- if (idx > end_idx || str[idx] != '}') {
- raise_errmsg("Expecting object", pystr, end_idx);
- goto bail;
- }
-
- /* if pairs_hook is not None: rval = object_pairs_hook(pairs) */
- if (s->pairs_hook != Py_None) {
- val = PyObject_CallFunctionObjArgs(s->pairs_hook, pairs, NULL);
- if (val == NULL)
- goto bail;
- Py_DECREF(pairs);
- *next_idx_ptr = idx + 1;
- return val;
- }
-
- /* if object_hook is not None: rval = object_hook(rval) */
- if (s->object_hook != Py_None) {
- val = PyObject_CallFunctionObjArgs(s->object_hook, rval, NULL);
- if (val == NULL)
- goto bail;
- Py_DECREF(rval);
- rval = val;
- val = NULL;
- }
- *next_idx_ptr = idx + 1;
- return rval;
-bail:
- Py_XDECREF(rval);
- Py_XDECREF(key);
- Py_XDECREF(val);
- Py_XDECREF(pairs);
- return NULL;
-}
-
-static PyObject *
-_parse_object_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr) {
- /* Read a JSON object from PyUnicode pystr.
- idx is the index of the first character after the opening curly brace.
- *next_idx_ptr is a return-by-reference index to the first character after
- the closing curly brace.
-
- Returns a new PyObject (usually a dict, but object_hook can change that)
- */
- Py_UNICODE *str = PyUnicode_AS_UNICODE(pystr);
- Py_ssize_t end_idx = PyUnicode_GET_SIZE(pystr) - 1;
- PyObject *rval = NULL;
- PyObject *pairs = NULL;
- PyObject *item;
- PyObject *key = NULL;
- PyObject *val = NULL;
- int strict = PyObject_IsTrue(s->strict);
- int has_pairs_hook = (s->pairs_hook != Py_None);
- Py_ssize_t next_idx;
-
- if (has_pairs_hook) {
- pairs = PyList_New(0);
- if (pairs == NULL)
- return NULL;
- }
- else {
- rval = PyDict_New();
- if (rval == NULL)
- return NULL;
- }
-
- /* skip whitespace after { */
- while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++;
-
- /* only loop if the object is non-empty */
- if (idx <= end_idx && str[idx] != '}') {
- while (idx <= end_idx) {
- PyObject *memokey;
-
- /* read key */
- if (str[idx] != '"') {
- raise_errmsg("Expecting property name", pystr, idx);
- goto bail;
- }
- key = scanstring_unicode(pystr, idx + 1, strict, &next_idx);
- if (key == NULL)
- goto bail;
- memokey = PyDict_GetItem(s->memo, key);
- if (memokey != NULL) {
- Py_INCREF(memokey);
- Py_DECREF(key);
- key = memokey;
- }
- else {
- if (PyDict_SetItem(s->memo, key, key) < 0)
- goto bail;
- }
- idx = next_idx;
-
- /* skip whitespace between key and : delimiter, read :, skip whitespace */
- while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++;
- if (idx > end_idx || str[idx] != ':') {
- raise_errmsg("Expecting : delimiter", pystr, idx);
- goto bail;
- }
- idx++;
- while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++;
-
- /* read any JSON term */
- val = scan_once_unicode(s, pystr, idx, &next_idx);
- if (val == NULL)
- goto bail;
-
- if (has_pairs_hook) {
- item = PyTuple_Pack(2, key, val);
- if (item == NULL)
- goto bail;
- Py_CLEAR(key);
- Py_CLEAR(val);
- if (PyList_Append(pairs, item) == -1) {
- Py_DECREF(item);
- goto bail;
- }
- Py_DECREF(item);
- }
- else {
- if (PyDict_SetItem(rval, key, val) < 0)
- goto bail;
- Py_CLEAR(key);
- Py_CLEAR(val);
- }
- idx = next_idx;
-
- /* skip whitespace before } or , */
- while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++;
-
- /* bail if the object is closed or we didn't get the , delimiter */
- if (idx > end_idx) break;
- if (str[idx] == '}') {
- break;
- }
- else if (str[idx] != ',') {
- raise_errmsg("Expecting , delimiter", pystr, idx);
- goto bail;
- }
- idx++;
-
- /* skip whitespace after , delimiter */
- while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++;
- }
- }
-
- /* verify that idx < end_idx, str[idx] should be '}' */
- if (idx > end_idx || str[idx] != '}') {
- raise_errmsg("Expecting object", pystr, end_idx);
- goto bail;
- }
-
- /* if pairs_hook is not None: rval = object_pairs_hook(pairs) */
- if (s->pairs_hook != Py_None) {
- val = PyObject_CallFunctionObjArgs(s->pairs_hook, pairs, NULL);
- if (val == NULL)
- goto bail;
- Py_DECREF(pairs);
- *next_idx_ptr = idx + 1;
- return val;
- }
-
- /* if object_hook is not None: rval = object_hook(rval) */
- if (s->object_hook != Py_None) {
- val = PyObject_CallFunctionObjArgs(s->object_hook, rval, NULL);
- if (val == NULL)
- goto bail;
- Py_DECREF(rval);
- rval = val;
- val = NULL;
- }
- *next_idx_ptr = idx + 1;
- return rval;
-bail:
- Py_XDECREF(rval);
- Py_XDECREF(key);
- Py_XDECREF(val);
- Py_XDECREF(pairs);
- return NULL;
-}
-
-static PyObject *
-_parse_array_str(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr) {
- /* Read a JSON array from PyString pystr.
- idx is the index of the first character after the opening brace.
- *next_idx_ptr is a return-by-reference index to the first character after
- the closing brace.
-
- Returns a new PyList
- */
- char *str = PyString_AS_STRING(pystr);
- Py_ssize_t end_idx = PyString_GET_SIZE(pystr) - 1;
- PyObject *val = NULL;
- PyObject *rval = PyList_New(0);
- Py_ssize_t next_idx;
- if (rval == NULL)
- return NULL;
-
- /* skip whitespace after [ */
- while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++;
-
- /* only loop if the array is non-empty */
- if (idx <= end_idx && str[idx] != ']') {
- while (idx <= end_idx) {
-
- /* read any JSON term and de-tuplefy the (rval, idx) */
- val = scan_once_str(s, pystr, idx, &next_idx);
- if (val == NULL) {
- if (PyErr_ExceptionMatches(PyExc_StopIteration)) {
- PyErr_Clear();
- raise_errmsg("Expecting object", pystr, idx);
- }
- goto bail;
- }
-
- if (PyList_Append(rval, val) == -1)
- goto bail;
-
- Py_CLEAR(val);
- idx = next_idx;
-
- /* skip whitespace between term and , */
- while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++;
-
- /* bail if the array is closed or we didn't get the , delimiter */
- if (idx > end_idx) break;
- if (str[idx] == ']') {
- break;
- }
- else if (str[idx] != ',') {
- raise_errmsg("Expecting , delimiter", pystr, idx);
- goto bail;
- }
- idx++;
-
- /* skip whitespace after , */
- while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++;
- }
- }
-
- /* verify that idx < end_idx, str[idx] should be ']' */
- if (idx > end_idx || str[idx] != ']') {
- raise_errmsg("Expecting object", pystr, end_idx);
- goto bail;
- }
- *next_idx_ptr = idx + 1;
- return rval;
-bail:
- Py_XDECREF(val);
- Py_DECREF(rval);
- return NULL;
-}
-
-static PyObject *
-_parse_array_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr) {
- /* Read a JSON array from PyString pystr.
- idx is the index of the first character after the opening brace.
- *next_idx_ptr is a return-by-reference index to the first character after
- the closing brace.
-
- Returns a new PyList
- */
- Py_UNICODE *str = PyUnicode_AS_UNICODE(pystr);
- Py_ssize_t end_idx = PyUnicode_GET_SIZE(pystr) - 1;
- PyObject *val = NULL;
- PyObject *rval = PyList_New(0);
- Py_ssize_t next_idx;
- if (rval == NULL)
- return NULL;
-
- /* skip whitespace after [ */
- while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++;
-
- /* only loop if the array is non-empty */
- if (idx <= end_idx && str[idx] != ']') {
- while (idx <= end_idx) {
-
- /* read any JSON term */
- val = scan_once_unicode(s, pystr, idx, &next_idx);
- if (val == NULL) {
- if (PyErr_ExceptionMatches(PyExc_StopIteration)) {
- PyErr_Clear();
- raise_errmsg("Expecting object", pystr, idx);
- }
- goto bail;
- }
-
- if (PyList_Append(rval, val) == -1)
- goto bail;
-
- Py_CLEAR(val);
- idx = next_idx;
-
- /* skip whitespace between term and , */
- while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++;
-
- /* bail if the array is closed or we didn't get the , delimiter */
- if (idx > end_idx) break;
- if (str[idx] == ']') {
- break;
- }
- else if (str[idx] != ',') {
- raise_errmsg("Expecting , delimiter", pystr, idx);
- goto bail;
- }
- idx++;
-
- /* skip whitespace after , */
- while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++;
- }
- }
-
- /* verify that idx < end_idx, str[idx] should be ']' */
- if (idx > end_idx || str[idx] != ']') {
- raise_errmsg("Expecting object", pystr, end_idx);
- goto bail;
- }
- *next_idx_ptr = idx + 1;
- return rval;
-bail:
- Py_XDECREF(val);
- Py_DECREF(rval);
- return NULL;
-}
-
-static PyObject *
-_parse_constant(PyScannerObject *s, char *constant, Py_ssize_t idx, Py_ssize_t *next_idx_ptr) {
- /* Read a JSON constant from PyString pystr.
- constant is the constant string that was found
- ("NaN", "Infinity", "-Infinity").
- idx is the index of the first character of the constant
- *next_idx_ptr is a return-by-reference index to the first character after
- the constant.
-
- Returns the result of parse_constant
- */
- PyObject *cstr;
- PyObject *rval;
- /* constant is "NaN", "Infinity", or "-Infinity" */
- cstr = PyString_InternFromString(constant);
- if (cstr == NULL)
- return NULL;
-
- /* rval = parse_constant(constant) */
- rval = PyObject_CallFunctionObjArgs(s->parse_constant, cstr, NULL);
- idx += PyString_GET_SIZE(cstr);
- Py_DECREF(cstr);
- *next_idx_ptr = idx;
- return rval;
-}
-
-static PyObject *
-_match_number_str(PyScannerObject *s, PyObject *pystr, Py_ssize_t start, Py_ssize_t *next_idx_ptr) {
- /* Read a JSON number from PyString pystr.
- idx is the index of the first character of the number
- *next_idx_ptr is a return-by-reference index to the first character after
- the number.
-
- Returns a new PyObject representation of that number:
- PyInt, PyLong, or PyFloat.
- May return other types if parse_int or parse_float are set
- */
- char *str = PyString_AS_STRING(pystr);
- Py_ssize_t end_idx = PyString_GET_SIZE(pystr) - 1;
- Py_ssize_t idx = start;
- int is_float = 0;
- PyObject *rval;
- PyObject *numstr;
-
- /* read a sign if it's there, make sure it's not the end of the string */
- if (str[idx] == '-') {
- idx++;
- if (idx > end_idx) {
- PyErr_SetNone(PyExc_StopIteration);
- return NULL;
- }
- }
-
- /* read as many integer digits as we find as long as it doesn't start with 0 */
- if (str[idx] >= '1' && str[idx] <= '9') {
- idx++;
- while (idx <= end_idx && str[idx] >= '0' && str[idx] <= '9') idx++;
- }
- /* if it starts with 0 we only expect one integer digit */
- else if (str[idx] == '0') {
- idx++;
- }
- /* no integer digits, error */
- else {
- PyErr_SetNone(PyExc_StopIteration);
- return NULL;
- }
-
- /* if the next char is '.' followed by a digit then read all float digits */
- if (idx < end_idx && str[idx] == '.' && str[idx + 1] >= '0' && str[idx + 1] <= '9') {
- is_float = 1;
- idx += 2;
- while (idx <= end_idx && str[idx] >= '0' && str[idx] <= '9') idx++;
- }
-
- /* if the next char is 'e' or 'E' then maybe read the exponent (or backtrack) */
- if (idx < end_idx && (str[idx] == 'e' || str[idx] == 'E')) {
-
- /* save the index of the 'e' or 'E' just in case we need to backtrack */
- Py_ssize_t e_start = idx;
- idx++;
-
- /* read an exponent sign if present */
- if (idx < end_idx && (str[idx] == '-' || str[idx] == '+')) idx++;
-
- /* read all digits */
- while (idx <= end_idx && str[idx] >= '0' && str[idx] <= '9') idx++;
-
- /* if we got a digit, then parse as float. if not, backtrack */
- if (str[idx - 1] >= '0' && str[idx - 1] <= '9') {
- is_float = 1;
- }
- else {
- idx = e_start;
- }
- }
-
- /* copy the section we determined to be a number */
- numstr = PyString_FromStringAndSize(&str[start], idx - start);
- if (numstr == NULL)
- return NULL;
- if (is_float) {
- /* parse as a float using a fast path if available, otherwise call user defined method */
- if (s->parse_float != (PyObject *)&PyFloat_Type) {
- rval = PyObject_CallFunctionObjArgs(s->parse_float, numstr, NULL);
- }
- else {
- /* rval = PyFloat_FromDouble(PyOS_ascii_atof(PyString_AS_STRING(numstr))); */
- double d = PyOS_string_to_double(PyString_AS_STRING(numstr),
- NULL, NULL);
- if (d == -1.0 && PyErr_Occurred())
- return NULL;
- rval = PyFloat_FromDouble(d);
- }
- }
- else {
- /* parse as an int using a fast path if available, otherwise call user defined method */
- if (s->parse_int != (PyObject *)&PyInt_Type) {
- rval = PyObject_CallFunctionObjArgs(s->parse_int, numstr, NULL);
- }
- else {
- rval = PyInt_FromString(PyString_AS_STRING(numstr), NULL, 10);
- }
- }
- Py_DECREF(numstr);
- *next_idx_ptr = idx;
- return rval;
-}
-
-static PyObject *
-_match_number_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t start, Py_ssize_t *next_idx_ptr) {
- /* Read a JSON number from PyUnicode pystr.
- idx is the index of the first character of the number
- *next_idx_ptr is a return-by-reference index to the first character after
- the number.
-
- Returns a new PyObject representation of that number:
- PyInt, PyLong, or PyFloat.
- May return other types if parse_int or parse_float are set
- */
- Py_UNICODE *str = PyUnicode_AS_UNICODE(pystr);
- Py_ssize_t end_idx = PyUnicode_GET_SIZE(pystr) - 1;
- Py_ssize_t idx = start;
- int is_float = 0;
- PyObject *rval;
- PyObject *numstr;
-
- /* read a sign if it's there, make sure it's not the end of the string */
- if (str[idx] == '-') {
- idx++;
- if (idx > end_idx) {
- PyErr_SetNone(PyExc_StopIteration);
- return NULL;
- }
- }
-
- /* read as many integer digits as we find as long as it doesn't start with 0 */
- if (str[idx] >= '1' && str[idx] <= '9') {
- idx++;
- while (idx <= end_idx && str[idx] >= '0' && str[idx] <= '9') idx++;
- }
- /* if it starts with 0 we only expect one integer digit */
- else if (str[idx] == '0') {
- idx++;
- }
- /* no integer digits, error */
- else {
- PyErr_SetNone(PyExc_StopIteration);
- return NULL;
- }
-
- /* if the next char is '.' followed by a digit then read all float digits */
- if (idx < end_idx && str[idx] == '.' && str[idx + 1] >= '0' && str[idx + 1] <= '9') {
- is_float = 1;
- idx += 2;
- while (idx <= end_idx && str[idx] >= '0' && str[idx] <= '9') idx++;
- }
-
- /* if the next char is 'e' or 'E' then maybe read the exponent (or backtrack) */
- if (idx < end_idx && (str[idx] == 'e' || str[idx] == 'E')) {
- Py_ssize_t e_start = idx;
- idx++;
-
- /* read an exponent sign if present */
- if (idx < end_idx && (str[idx] == '-' || str[idx] == '+')) idx++;
-
- /* read all digits */
- while (idx <= end_idx && str[idx] >= '0' && str[idx] <= '9') idx++;
-
- /* if we got a digit, then parse as float. if not, backtrack */
- if (str[idx - 1] >= '0' && str[idx - 1] <= '9') {
- is_float = 1;
- }
- else {
- idx = e_start;
- }
- }
-
- /* copy the section we determined to be a number */
- numstr = PyUnicode_FromUnicode(&str[start], idx - start);
- if (numstr == NULL)
- return NULL;
- if (is_float) {
- /* parse as a float using a fast path if available, otherwise call user defined method */
- if (s->parse_float != (PyObject *)&PyFloat_Type) {
- rval = PyObject_CallFunctionObjArgs(s->parse_float, numstr, NULL);
- }
- else {
- rval = PyFloat_FromString(numstr, NULL);
- }
- }
- else {
- /* no fast path for unicode -> int, just call */
- rval = PyObject_CallFunctionObjArgs(s->parse_int, numstr, NULL);
- }
- Py_DECREF(numstr);
- *next_idx_ptr = idx;
- return rval;
-}
-
-static PyObject *
-scan_once_str(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr)
-{
- /* Read one JSON term (of any kind) from PyString pystr.
- idx is the index of the first character of the term
- *next_idx_ptr is a return-by-reference index to the first character after
- the number.
-
- Returns a new PyObject representation of the term.
- */
- char *str = PyString_AS_STRING(pystr);
- Py_ssize_t length = PyString_GET_SIZE(pystr);
- PyObject *rval = NULL;
- int fallthrough = 0;
- if (idx >= length) {
- PyErr_SetNone(PyExc_StopIteration);
- return NULL;
- }
- if (Py_EnterRecursiveCall(" while decoding a JSON document"))
- return NULL;
- switch (str[idx]) {
- case '"':
- /* string */
- rval = scanstring_str(pystr, idx + 1,
- PyString_AS_STRING(s->encoding),
- PyObject_IsTrue(s->strict),
- next_idx_ptr);
- break;
- case '{':
- /* object */
- rval = _parse_object_str(s, pystr, idx + 1, next_idx_ptr);
- break;
- case '[':
- /* array */
- rval = _parse_array_str(s, pystr, idx + 1, next_idx_ptr);
- break;
- case 'n':
- /* null */
- if ((idx + 3 < length) && str[idx + 1] == 'u' && str[idx + 2] == 'l' && str[idx + 3] == 'l') {
- Py_INCREF(Py_None);
- *next_idx_ptr = idx + 4;
- rval = Py_None;
- }
- else
- fallthrough = 1;
- break;
- case 't':
- /* true */
- if ((idx + 3 < length) && str[idx + 1] == 'r' && str[idx + 2] == 'u' && str[idx + 3] == 'e') {
- Py_INCREF(Py_True);
- *next_idx_ptr = idx + 4;
- rval = Py_True;
- }
- else
- fallthrough = 1;
- break;
- case 'f':
- /* false */
- if ((idx + 4 < length) && str[idx + 1] == 'a' && str[idx + 2] == 'l' && str[idx + 3] == 's' && str[idx + 4] == 'e') {
- Py_INCREF(Py_False);
- *next_idx_ptr = idx + 5;
- rval = Py_False;
- }
- else
- fallthrough = 1;
- break;
- case 'N':
- /* NaN */
- if ((idx + 2 < length) && str[idx + 1] == 'a' && str[idx + 2] == 'N') {
- rval = _parse_constant(s, "NaN", idx, next_idx_ptr);
- }
- else
- fallthrough = 1;
- break;
- case 'I':
- /* Infinity */
- if ((idx + 7 < length) && str[idx + 1] == 'n' && str[idx + 2] == 'f' && str[idx + 3] == 'i' && str[idx + 4] == 'n' && str[idx + 5] == 'i' && str[idx + 6] == 't' && str[idx + 7] == 'y') {
- rval = _parse_constant(s, "Infinity", idx, next_idx_ptr);
- }
- else
- fallthrough = 1;
- break;
- case '-':
- /* -Infinity */
- if ((idx + 8 < length) && str[idx + 1] == 'I' && str[idx + 2] == 'n' && str[idx + 3] == 'f' && str[idx + 4] == 'i' && str[idx + 5] == 'n' && str[idx + 6] == 'i' && str[idx + 7] == 't' && str[idx + 8] == 'y') {
- rval = _parse_constant(s, "-Infinity", idx, next_idx_ptr);
- }
- else
- fallthrough = 1;
- break;
- default:
- fallthrough = 1;
- }
- /* Didn't find a string, object, array, or named constant. Look for a number. */
- if (fallthrough)
- rval = _match_number_str(s, pystr, idx, next_idx_ptr);
- Py_LeaveRecursiveCall();
- return rval;
-}
-
-static PyObject *
-scan_once_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr)
-{
- /* Read one JSON term (of any kind) from PyUnicode pystr.
- idx is the index of the first character of the term
- *next_idx_ptr is a return-by-reference index to the first character after
- the number.
-
- Returns a new PyObject representation of the term.
- */
- Py_UNICODE *str = PyUnicode_AS_UNICODE(pystr);
- Py_ssize_t length = PyUnicode_GET_SIZE(pystr);
- PyObject *rval = NULL;
- int fallthrough = 0;
- if (idx >= length) {
- PyErr_SetNone(PyExc_StopIteration);
- return NULL;
- }
- if (Py_EnterRecursiveCall(" while decoding a JSON document"))
- return NULL;
- switch (str[idx]) {
- case '"':
- /* string */
- rval = scanstring_unicode(pystr, idx + 1,
- PyObject_IsTrue(s->strict),
- next_idx_ptr);
- break;
- case '{':
- /* object */
- rval = _parse_object_unicode(s, pystr, idx + 1, next_idx_ptr);
- break;
- case '[':
- /* array */
- rval = _parse_array_unicode(s, pystr, idx + 1, next_idx_ptr);
- break;
- case 'n':
- /* null */
- if ((idx + 3 < length) && str[idx + 1] == 'u' && str[idx + 2] == 'l' && str[idx + 3] == 'l') {
- Py_INCREF(Py_None);
- *next_idx_ptr = idx + 4;
- rval = Py_None;
- }
- else
- fallthrough = 1;
- break;
- case 't':
- /* true */
- if ((idx + 3 < length) && str[idx + 1] == 'r' && str[idx + 2] == 'u' && str[idx + 3] == 'e') {
- Py_INCREF(Py_True);
- *next_idx_ptr = idx + 4;
- rval = Py_True;
- }
- else
- fallthrough = 1;
- break;
- case 'f':
- /* false */
- if ((idx + 4 < length) && str[idx + 1] == 'a' && str[idx + 2] == 'l' && str[idx + 3] == 's' && str[idx + 4] == 'e') {
- Py_INCREF(Py_False);
- *next_idx_ptr = idx + 5;
- rval = Py_False;
- }
- else
- fallthrough = 1;
- break;
- case 'N':
- /* NaN */
- if ((idx + 2 < length) && str[idx + 1] == 'a' && str[idx + 2] == 'N') {
- rval = _parse_constant(s, "NaN", idx, next_idx_ptr);
- }
- else
- fallthrough = 1;
- break;
- case 'I':
- /* Infinity */
- if ((idx + 7 < length) && str[idx + 1] == 'n' && str[idx + 2] == 'f' && str[idx + 3] == 'i' && str[idx + 4] == 'n' && str[idx + 5] == 'i' && str[idx + 6] == 't' && str[idx + 7] == 'y') {
- rval = _parse_constant(s, "Infinity", idx, next_idx_ptr);
- }
- else
- fallthrough = 1;
- break;
- case '-':
- /* -Infinity */
- if ((idx + 8 < length) && str[idx + 1] == 'I' && str[idx + 2] == 'n' && str[idx + 3] == 'f' && str[idx + 4] == 'i' && str[idx + 5] == 'n' && str[idx + 6] == 'i' && str[idx + 7] == 't' && str[idx + 8] == 'y') {
- rval = _parse_constant(s, "-Infinity", idx, next_idx_ptr);
- }
- else
- fallthrough = 1;
- break;
- default:
- fallthrough = 1;
- }
- /* Didn't find a string, object, array, or named constant. Look for a number. */
- if (fallthrough)
- rval = _match_number_unicode(s, pystr, idx, next_idx_ptr);
- Py_LeaveRecursiveCall();
- return rval;
-}
-
-static PyObject *
-scanner_call(PyObject *self, PyObject *args, PyObject *kwds)
-{
- /* Python callable interface to scan_once_{str,unicode} */
- PyObject *pystr;
- PyObject *rval;
- Py_ssize_t idx;
- Py_ssize_t next_idx = -1;
- static char *kwlist[] = {"string", "idx", NULL};
- PyScannerObject *s;
- assert(PyScanner_Check(self));
- s = (PyScannerObject *)self;
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO&:scan_once", kwlist, &pystr, _convertPyInt_AsSsize_t, &idx))
- return NULL;
-
- if (PyString_Check(pystr)) {
- rval = scan_once_str(s, pystr, idx, &next_idx);
- }
- else if (PyUnicode_Check(pystr)) {
- rval = scan_once_unicode(s, pystr, idx, &next_idx);
- }
- else {
- PyErr_Format(PyExc_TypeError,
- "first argument must be a string, not %.80s",
- Py_TYPE(pystr)->tp_name);
- return NULL;
- }
- PyDict_Clear(s->memo);
- return _build_rval_index_tuple(rval, next_idx);
-}
-
-static PyObject *
-scanner_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
- PyScannerObject *s;
- s = (PyScannerObject *)type->tp_alloc(type, 0);
- if (s != NULL) {
- s->encoding = NULL;
- s->strict = NULL;
- s->object_hook = NULL;
- s->pairs_hook = NULL;
- s->parse_float = NULL;
- s->parse_int = NULL;
- s->parse_constant = NULL;
- }
- return (PyObject *)s;
-}
-
-static int
-scanner_init(PyObject *self, PyObject *args, PyObject *kwds)
-{
- /* Initialize Scanner object */
- PyObject *ctx;
- static char *kwlist[] = {"context", NULL};
- PyScannerObject *s;
-
- assert(PyScanner_Check(self));
- s = (PyScannerObject *)self;
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:make_scanner", kwlist, &ctx))
- return -1;
-
- if (s->memo == NULL) {
- s->memo = PyDict_New();
- if (s->memo == NULL)
- goto bail;
- }
-
- /* PyString_AS_STRING is used on encoding */
- s->encoding = PyObject_GetAttrString(ctx, "encoding");
- if (s->encoding == NULL)
- goto bail;
- if (s->encoding == Py_None) {
- Py_DECREF(Py_None);
- s->encoding = PyString_InternFromString(DEFAULT_ENCODING);
- }
- else if (PyUnicode_Check(s->encoding)) {
- PyObject *tmp = PyUnicode_AsEncodedString(s->encoding, NULL, NULL);
- Py_DECREF(s->encoding);
- s->encoding = tmp;
- }
- if (s->encoding == NULL || !PyString_Check(s->encoding))
- goto bail;
-
- /* All of these will fail "gracefully" so we don't need to verify them */
- s->strict = PyObject_GetAttrString(ctx, "strict");
- if (s->strict == NULL)
- goto bail;
- s->object_hook = PyObject_GetAttrString(ctx, "object_hook");
- if (s->object_hook == NULL)
- goto bail;
- s->pairs_hook = PyObject_GetAttrString(ctx, "object_pairs_hook");
- if (s->pairs_hook == NULL)
- goto bail;
- s->parse_float = PyObject_GetAttrString(ctx, "parse_float");
- if (s->parse_float == NULL)
- goto bail;
- s->parse_int = PyObject_GetAttrString(ctx, "parse_int");
- if (s->parse_int == NULL)
- goto bail;
- s->parse_constant = PyObject_GetAttrString(ctx, "parse_constant");
- if (s->parse_constant == NULL)
- goto bail;
-
- return 0;
-
-bail:
- Py_CLEAR(s->encoding);
- Py_CLEAR(s->strict);
- Py_CLEAR(s->object_hook);
- Py_CLEAR(s->pairs_hook);
- Py_CLEAR(s->parse_float);
- Py_CLEAR(s->parse_int);
- Py_CLEAR(s->parse_constant);
- return -1;
-}
-
-PyDoc_STRVAR(scanner_doc, "JSON scanner object");
-
-static
-PyTypeObject PyScannerType = {
- PyObject_HEAD_INIT(NULL)
- 0, /* tp_internal */
- "simplejson._speedups.Scanner", /* tp_name */
- sizeof(PyScannerObject), /* tp_basicsize */
- 0, /* tp_itemsize */
- scanner_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- 0, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- scanner_call, /* tp_call */
- 0, /* tp_str */
- 0,/* PyObject_GenericGetAttr, */ /* tp_getattro */
- 0,/* PyObject_GenericSetAttr, */ /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
- scanner_doc, /* tp_doc */
- scanner_traverse, /* tp_traverse */
- scanner_clear, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- 0, /* tp_methods */
- scanner_members, /* tp_members */
- 0, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- scanner_init, /* tp_init */
- 0,/* PyType_GenericAlloc, */ /* tp_alloc */
- scanner_new, /* tp_new */
- 0,/* PyObject_GC_Del, */ /* tp_free */
-};
-
-static PyObject *
-encoder_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
- PyEncoderObject *s;
- s = (PyEncoderObject *)type->tp_alloc(type, 0);
- if (s != NULL) {
- s->markers = NULL;
- s->defaultfn = NULL;
- s->encoder = NULL;
- s->indent = NULL;
- s->key_separator = NULL;
- s->item_separator = NULL;
- s->sort_keys = NULL;
- s->skipkeys = NULL;
- s->key_memo = NULL;
- }
- return (PyObject *)s;
-}
-
-static int
-encoder_init(PyObject *self, PyObject *args, PyObject *kwds)
-{
- /* initialize Encoder object */
- static char *kwlist[] = {"markers", "default", "encoder", "indent", "key_separator", "item_separator", "sort_keys", "skipkeys", "allow_nan", "key_memo", "use_decimal", NULL};
-
- PyEncoderObject *s;
- PyObject *markers, *defaultfn, *encoder, *indent, *key_separator;
- PyObject *item_separator, *sort_keys, *skipkeys, *allow_nan, *key_memo, *use_decimal;
-
- assert(PyEncoder_Check(self));
- s = (PyEncoderObject *)self;
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOOOOOOOOOO:make_encoder", kwlist,
- &markers, &defaultfn, &encoder, &indent, &key_separator, &item_separator,
- &sort_keys, &skipkeys, &allow_nan, &key_memo, &use_decimal))
- return -1;
-
- s->markers = markers;
- s->defaultfn = defaultfn;
- s->encoder = encoder;
- s->indent = indent;
- s->key_separator = key_separator;
- s->item_separator = item_separator;
- s->sort_keys = sort_keys;
- s->skipkeys = skipkeys;
- s->key_memo = key_memo;
- s->fast_encode = (PyCFunction_Check(s->encoder) && PyCFunction_GetFunction(s->encoder) == (PyCFunction)py_encode_basestring_ascii);
- s->allow_nan = PyObject_IsTrue(allow_nan);
- s->use_decimal = PyObject_IsTrue(use_decimal);
-
- Py_INCREF(s->markers);
- Py_INCREF(s->defaultfn);
- Py_INCREF(s->encoder);
- Py_INCREF(s->indent);
- Py_INCREF(s->key_separator);
- Py_INCREF(s->item_separator);
- Py_INCREF(s->sort_keys);
- Py_INCREF(s->skipkeys);
- Py_INCREF(s->key_memo);
- return 0;
-}
-
-static PyObject *
-encoder_call(PyObject *self, PyObject *args, PyObject *kwds)
-{
- /* Python callable interface to encode_listencode_obj */
- static char *kwlist[] = {"obj", "_current_indent_level", NULL};
- PyObject *obj;
- PyObject *rval;
- Py_ssize_t indent_level;
- PyEncoderObject *s;
- assert(PyEncoder_Check(self));
- s = (PyEncoderObject *)self;
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO&:_iterencode", kwlist,
- &obj, _convertPyInt_AsSsize_t, &indent_level))
- return NULL;
- rval = PyList_New(0);
- if (rval == NULL)
- return NULL;
- if (encoder_listencode_obj(s, rval, obj, indent_level)) {
- Py_DECREF(rval);
- return NULL;
- }
- return rval;
-}
-
-static PyObject *
-_encoded_const(PyObject *obj)
-{
- /* Return the JSON string representation of None, True, False */
- if (obj == Py_None) {
- static PyObject *s_null = NULL;
- if (s_null == NULL) {
- s_null = PyString_InternFromString("null");
- }
- Py_INCREF(s_null);
- return s_null;
- }
- else if (obj == Py_True) {
- static PyObject *s_true = NULL;
- if (s_true == NULL) {
- s_true = PyString_InternFromString("true");
- }
- Py_INCREF(s_true);
- return s_true;
- }
- else if (obj == Py_False) {
- static PyObject *s_false = NULL;
- if (s_false == NULL) {
- s_false = PyString_InternFromString("false");
- }
- Py_INCREF(s_false);
- return s_false;
- }
- else {
- PyErr_SetString(PyExc_ValueError, "not a const");
- return NULL;
- }
-}
-
-static PyObject *
-encoder_encode_float(PyEncoderObject *s, PyObject *obj)
-{
- /* Return the JSON representation of a PyFloat */
- double i = PyFloat_AS_DOUBLE(obj);
- if (!Py_IS_FINITE(i)) {
- if (!s->allow_nan) {
- PyErr_SetString(PyExc_ValueError, "Out of range float values are not JSON compliant");
- return NULL;
- }
- if (i > 0) {
- return PyString_FromString("Infinity");
- }
- else if (i < 0) {
- return PyString_FromString("-Infinity");
- }
- else {
- return PyString_FromString("NaN");
- }
- }
- /* Use a better float format here? */
- return PyObject_Repr(obj);
-}
-
-static PyObject *
-encoder_encode_string(PyEncoderObject *s, PyObject *obj)
-{
- /* Return the JSON representation of a string */
- if (s->fast_encode)
- return py_encode_basestring_ascii(NULL, obj);
- else
- return PyObject_CallFunctionObjArgs(s->encoder, obj, NULL);
-}
-
-static int
-_steal_list_append(PyObject *lst, PyObject *stolen)
-{
- /* Append stolen and then decrement its reference count */
- int rval = PyList_Append(lst, stolen);
- Py_DECREF(stolen);
- return rval;
-}
-
-static int
-encoder_listencode_obj(PyEncoderObject *s, PyObject *rval, PyObject *obj, Py_ssize_t indent_level)
-{
- /* Encode Python object obj to a JSON term, rval is a PyList */
- int rv = -1;
- if (Py_EnterRecursiveCall(" while encoding a JSON document"))
- return rv;
- do {
- if (obj == Py_None || obj == Py_True || obj == Py_False) {
- PyObject *cstr = _encoded_const(obj);
- if (cstr != NULL)
- rv = _steal_list_append(rval, cstr);
- }
- else if (PyString_Check(obj) || PyUnicode_Check(obj))
- {
- PyObject *encoded = encoder_encode_string(s, obj);
- if (encoded != NULL)
- rv = _steal_list_append(rval, encoded);
- }
- else if (PyInt_Check(obj) || PyLong_Check(obj)) {
- PyObject *encoded = PyObject_Str(obj);
- if (encoded != NULL)
- rv = _steal_list_append(rval, encoded);
- }
- else if (PyFloat_Check(obj)) {
- PyObject *encoded = encoder_encode_float(s, obj);
- if (encoded != NULL)
- rv = _steal_list_append(rval, encoded);
- }
- else if (PyList_Check(obj) || PyTuple_Check(obj)) {
- rv = encoder_listencode_list(s, rval, obj, indent_level);
- }
- else if (PyDict_Check(obj)) {
- rv = encoder_listencode_dict(s, rval, obj, indent_level);
- }
- else if (s->use_decimal && Decimal_Check(obj)) {
- PyObject *encoded = PyObject_Str(obj);
- if (encoded != NULL)
- rv = _steal_list_append(rval, encoded);
- }
- else {
- PyObject *ident = NULL;
- PyObject *newobj;
- if (s->markers != Py_None) {
- int has_key;
- ident = PyLong_FromVoidPtr(obj);
- if (ident == NULL)
- break;
- has_key = PyDict_Contains(s->markers, ident);
- if (has_key) {
- if (has_key != -1)
- PyErr_SetString(PyExc_ValueError, "Circular reference detected");
- Py_DECREF(ident);
- break;
- }
- if (PyDict_SetItem(s->markers, ident, obj)) {
- Py_DECREF(ident);
- break;
- }
- }
- newobj = PyObject_CallFunctionObjArgs(s->defaultfn, obj, NULL);
- if (newobj == NULL) {
- Py_XDECREF(ident);
- break;
- }
- rv = encoder_listencode_obj(s, rval, newobj, indent_level);
- Py_DECREF(newobj);
- if (rv) {
- Py_XDECREF(ident);
- rv = -1;
- }
- else if (ident != NULL) {
- if (PyDict_DelItem(s->markers, ident)) {
- Py_XDECREF(ident);
- rv = -1;
- }
- Py_XDECREF(ident);
- }
- }
- } while (0);
- Py_LeaveRecursiveCall();
- return rv;
-}
-
-static int
-encoder_listencode_dict(PyEncoderObject *s, PyObject *rval, PyObject *dct, Py_ssize_t indent_level)
-{
- /* Encode Python dict dct a JSON term, rval is a PyList */
- static PyObject *open_dict = NULL;
- static PyObject *close_dict = NULL;
- static PyObject *empty_dict = NULL;
- static PyObject *iteritems = NULL;
- PyObject *kstr = NULL;
- PyObject *ident = NULL;
- PyObject *iter = NULL;
- PyObject *item = NULL;
- PyObject *items = NULL;
- PyObject *encoded = NULL;
- int skipkeys;
- Py_ssize_t idx;
-
- if (open_dict == NULL || close_dict == NULL || empty_dict == NULL || iteritems == NULL) {
- open_dict = PyString_InternFromString("{");
- close_dict = PyString_InternFromString("}");
- empty_dict = PyString_InternFromString("{}");
- iteritems = PyString_InternFromString("iteritems");
- if (open_dict == NULL || close_dict == NULL || empty_dict == NULL || iteritems == NULL)
- return -1;
- }
- if (PyDict_Size(dct) == 0)
- return PyList_Append(rval, empty_dict);
-
- if (s->markers != Py_None) {
- int has_key;
- ident = PyLong_FromVoidPtr(dct);
- if (ident == NULL)
- goto bail;
- has_key = PyDict_Contains(s->markers, ident);
- if (has_key) {
- if (has_key != -1)
- PyErr_SetString(PyExc_ValueError, "Circular reference detected");
- goto bail;
- }
- if (PyDict_SetItem(s->markers, ident, dct)) {
- goto bail;
- }
- }
-
- if (PyList_Append(rval, open_dict))
- goto bail;
-
- if (s->indent != Py_None) {
- /* TODO: DOES NOT RUN */
- indent_level += 1;
- /*
- newline_indent = '\n' + (_indent * _current_indent_level)
- separator = _item_separator + newline_indent
- buf += newline_indent
- */
- }
-
- if (PyObject_IsTrue(s->sort_keys)) {
- /* First sort the keys then replace them with (key, value) tuples. */
- Py_ssize_t i, nitems;
- if (PyDict_CheckExact(dct))
- items = PyDict_Keys(dct);
- else
- items = PyMapping_Keys(dct);
- if (items == NULL)
- goto bail;
- if (!PyList_Check(items)) {
- PyErr_SetString(PyExc_ValueError, "keys must return list");
- goto bail;
- }
- if (PyList_Sort(items) < 0)
- goto bail;
- nitems = PyList_GET_SIZE(items);
- for (i = 0; i < nitems; i++) {
- PyObject *key, *value;
- key = PyList_GET_ITEM(items, i);
- value = PyDict_GetItem(dct, key);
- item = PyTuple_Pack(2, key, value);
- if (item == NULL)
- goto bail;
- PyList_SET_ITEM(items, i, item);
- Py_DECREF(key);
- }
- }
- else {
- if (PyDict_CheckExact(dct))
- items = PyDict_Items(dct);
- else
- items = PyMapping_Items(dct);
- }
- if (items == NULL)
- goto bail;
- iter = PyObject_GetIter(items);
- Py_DECREF(items);
- if (iter == NULL)
- goto bail;
-
- skipkeys = PyObject_IsTrue(s->skipkeys);
- idx = 0;
- while ((item = PyIter_Next(iter))) {
- PyObject *encoded, *key, *value;
- if (!PyTuple_Check(item) || Py_SIZE(item) != 2) {
- PyErr_SetString(PyExc_ValueError, "items must return 2-tuples");
- goto bail;
- }
- key = PyTuple_GET_ITEM(item, 0);
- if (key == NULL)
- goto bail;
- value = PyTuple_GET_ITEM(item, 1);
- if (value == NULL)
- goto bail;
-
- encoded = PyDict_GetItem(s->key_memo, key);
- if (encoded != NULL) {
- Py_INCREF(encoded);
- }
- else if (PyString_Check(key) || PyUnicode_Check(key)) {
- Py_INCREF(key);
- kstr = key;
- }
- else if (PyFloat_Check(key)) {
- kstr = encoder_encode_float(s, key);
- if (kstr == NULL)
- goto bail;
- }
- else if (key == Py_True || key == Py_False || key == Py_None) {
- /* This must come before the PyInt_Check because
- True and False are also 1 and 0.*/
- kstr = _encoded_const(key);
- if (kstr == NULL)
- goto bail;
- }
- else if (PyInt_Check(key) || PyLong_Check(key)) {
- kstr = PyObject_Str(key);
- if (kstr == NULL)
- goto bail;
- }
- else if (skipkeys) {
- Py_DECREF(item);
- continue;
- }
- else {
- /* TODO: include repr of key */
- PyErr_SetString(PyExc_TypeError, "keys must be a string");
- goto bail;
- }
-
- if (idx) {
- if (PyList_Append(rval, s->item_separator))
- goto bail;
- }
-
- if (encoded == NULL) {
- encoded = encoder_encode_string(s, kstr);
- Py_CLEAR(kstr);
- if (encoded == NULL)
- goto bail;
- if (PyDict_SetItem(s->key_memo, key, encoded))
- goto bail;
- }
- if (PyList_Append(rval, encoded)) {
- goto bail;
- }
- Py_CLEAR(encoded);
- if (PyList_Append(rval, s->key_separator))
- goto bail;
- if (encoder_listencode_obj(s, rval, value, indent_level))
- goto bail;
- Py_CLEAR(item);
- idx += 1;
- }
- Py_CLEAR(iter);
- if (PyErr_Occurred())
- goto bail;
- if (ident != NULL) {
- if (PyDict_DelItem(s->markers, ident))
- goto bail;
- Py_CLEAR(ident);
- }
- if (s->indent != Py_None) {
- /* TODO: DOES NOT RUN */
- indent_level -= 1;
- /*
- yield '\n' + (_indent * _current_indent_level)
- */
- }
- if (PyList_Append(rval, close_dict))
- goto bail;
- return 0;
-
-bail:
- Py_XDECREF(encoded);
- Py_XDECREF(items);
- Py_XDECREF(iter);
- Py_XDECREF(kstr);
- Py_XDECREF(ident);
- return -1;
-}
-
-
-static int
-encoder_listencode_list(PyEncoderObject *s, PyObject *rval, PyObject *seq, Py_ssize_t indent_level)
-{
- /* Encode Python list seq to a JSON term, rval is a PyList */
- static PyObject *open_array = NULL;
- static PyObject *close_array = NULL;
- static PyObject *empty_array = NULL;
- PyObject *ident = NULL;
- PyObject *iter = NULL;
- PyObject *obj = NULL;
- int is_true;
- int i = 0;
-
- if (open_array == NULL || close_array == NULL || empty_array == NULL) {
- open_array = PyString_InternFromString("[");
- close_array = PyString_InternFromString("]");
- empty_array = PyString_InternFromString("[]");
- if (open_array == NULL || close_array == NULL || empty_array == NULL)
- return -1;
- }
- ident = NULL;
- is_true = PyObject_IsTrue(seq);
- if (is_true == -1)
- return -1;
- else if (is_true == 0)
- return PyList_Append(rval, empty_array);
-
- if (s->markers != Py_None) {
- int has_key;
- ident = PyLong_FromVoidPtr(seq);
- if (ident == NULL)
- goto bail;
- has_key = PyDict_Contains(s->markers, ident);
- if (has_key) {
- if (has_key != -1)
- PyErr_SetString(PyExc_ValueError, "Circular reference detected");
- goto bail;
- }
- if (PyDict_SetItem(s->markers, ident, seq)) {
- goto bail;
- }
- }
-
- iter = PyObject_GetIter(seq);
- if (iter == NULL)
- goto bail;
-
- if (PyList_Append(rval, open_array))
- goto bail;
- if (s->indent != Py_None) {
- /* TODO: DOES NOT RUN */
- indent_level += 1;
- /*
- newline_indent = '\n' + (_indent * _current_indent_level)
- separator = _item_separator + newline_indent
- buf += newline_indent
- */
- }
- while ((obj = PyIter_Next(iter))) {
- if (i) {
- if (PyList_Append(rval, s->item_separator))
- goto bail;
- }
- if (encoder_listencode_obj(s, rval, obj, indent_level))
- goto bail;
- i++;
- Py_CLEAR(obj);
- }
- Py_CLEAR(iter);
- if (PyErr_Occurred())
- goto bail;
- if (ident != NULL) {
- if (PyDict_DelItem(s->markers, ident))
- goto bail;
- Py_CLEAR(ident);
- }
- if (s->indent != Py_None) {
- /* TODO: DOES NOT RUN */
- indent_level -= 1;
- /*
- yield '\n' + (_indent * _current_indent_level)
- */
- }
- if (PyList_Append(rval, close_array))
- goto bail;
- return 0;
-
-bail:
- Py_XDECREF(obj);
- Py_XDECREF(iter);
- Py_XDECREF(ident);
- return -1;
-}
-
-static void
-encoder_dealloc(PyObject *self)
-{
- /* Deallocate Encoder */
- encoder_clear(self);
- Py_TYPE(self)->tp_free(self);
-}
-
-static int
-encoder_traverse(PyObject *self, visitproc visit, void *arg)
-{
- PyEncoderObject *s;
- assert(PyEncoder_Check(self));
- s = (PyEncoderObject *)self;
- Py_VISIT(s->markers);
- Py_VISIT(s->defaultfn);
- Py_VISIT(s->encoder);
- Py_VISIT(s->indent);
- Py_VISIT(s->key_separator);
- Py_VISIT(s->item_separator);
- Py_VISIT(s->sort_keys);
- Py_VISIT(s->skipkeys);
- Py_VISIT(s->key_memo);
- return 0;
-}
-
-static int
-encoder_clear(PyObject *self)
-{
- /* Deallocate Encoder */
- PyEncoderObject *s;
- assert(PyEncoder_Check(self));
- s = (PyEncoderObject *)self;
- Py_CLEAR(s->markers);
- Py_CLEAR(s->defaultfn);
- Py_CLEAR(s->encoder);
- Py_CLEAR(s->indent);
- Py_CLEAR(s->key_separator);
- Py_CLEAR(s->item_separator);
- Py_CLEAR(s->sort_keys);
- Py_CLEAR(s->skipkeys);
- Py_CLEAR(s->key_memo);
- return 0;
-}
-
-PyDoc_STRVAR(encoder_doc, "_iterencode(obj, _current_indent_level) -> iterable");
-
-static
-PyTypeObject PyEncoderType = {
- PyObject_HEAD_INIT(NULL)
- 0, /* tp_internal */
- "simplejson._speedups.Encoder", /* tp_name */
- sizeof(PyEncoderObject), /* tp_basicsize */
- 0, /* tp_itemsize */
- encoder_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- 0, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- encoder_call, /* tp_call */
- 0, /* tp_str */
- 0, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
- encoder_doc, /* tp_doc */
- encoder_traverse, /* tp_traverse */
- encoder_clear, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- 0, /* tp_methods */
- encoder_members, /* tp_members */
- 0, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- encoder_init, /* tp_init */
- 0, /* tp_alloc */
- encoder_new, /* tp_new */
- 0, /* tp_free */
-};
-
-static PyMethodDef speedups_methods[] = {
- {"encode_basestring_ascii",
- (PyCFunction)py_encode_basestring_ascii,
- METH_O,
- pydoc_encode_basestring_ascii},
- {"scanstring",
- (PyCFunction)py_scanstring,
- METH_VARARGS,
- pydoc_scanstring},
- {NULL, NULL, 0, NULL}
-};
-
-PyDoc_STRVAR(module_doc,
-"simplejson speedups\n");
-
-void
-init_speedups(void)
-{
- PyObject *m, *decimal;
- PyScannerType.tp_new = PyType_GenericNew;
- if (PyType_Ready(&PyScannerType) < 0)
- return;
- PyEncoderType.tp_new = PyType_GenericNew;
- if (PyType_Ready(&PyEncoderType) < 0)
- return;
-
- decimal = PyImport_ImportModule("decimal");
- if (decimal == NULL)
- return;
- DecimalTypePtr = (PyTypeObject*)PyObject_GetAttrString(decimal, "Decimal");
- Py_DECREF(decimal);
- if (DecimalTypePtr == NULL)
- return;
-
- m = Py_InitModule3("_speedups", speedups_methods, module_doc);
- Py_INCREF((PyObject*)&PyScannerType);
- PyModule_AddObject(m, "make_scanner", (PyObject*)&PyScannerType);
- Py_INCREF((PyObject*)&PyEncoderType);
- PyModule_AddObject(m, "make_encoder", (PyObject*)&PyEncoderType);
-}
diff --git a/Tools/Scripts/webkitpy/thirdparty/simplejson/decoder.py b/Tools/Scripts/webkitpy/thirdparty/simplejson/decoder.py
deleted file mode 100644
index c2d4a0e0b..000000000
--- a/Tools/Scripts/webkitpy/thirdparty/simplejson/decoder.py
+++ /dev/null
@@ -1,421 +0,0 @@
-"""Implementation of JSONDecoder
-"""
-import re
-import sys
-import struct
-
-from scanner import make_scanner
-def _import_c_scanstring():
- try:
- from simplejson._speedups import scanstring
- return scanstring
- except ImportError:
- return None
-c_scanstring = _import_c_scanstring()
-
-__all__ = ['JSONDecoder']
-
-FLAGS = re.VERBOSE | re.MULTILINE | re.DOTALL
-
-def _floatconstants():
- _BYTES = '7FF80000000000007FF0000000000000'.decode('hex')
- # The struct module in Python 2.4 would get frexp() out of range here
- # when an endian is specified in the format string. Fixed in Python 2.5+
- if sys.byteorder != 'big':
- _BYTES = _BYTES[:8][::-1] + _BYTES[8:][::-1]
- nan, inf = struct.unpack('dd', _BYTES)
- return nan, inf, -inf
-
-NaN, PosInf, NegInf = _floatconstants()
-
-
-class JSONDecodeError(ValueError):
- """Subclass of ValueError with the following additional properties:
-
- msg: The unformatted error message
- doc: The JSON document being parsed
- pos: The start index of doc where parsing failed
- end: The end index of doc where parsing failed (may be None)
- lineno: The line corresponding to pos
- colno: The column corresponding to pos
- endlineno: The line corresponding to end (may be None)
- endcolno: The column corresponding to end (may be None)
-
- """
- def __init__(self, msg, doc, pos, end=None):
- ValueError.__init__(self, errmsg(msg, doc, pos, end=end))
- self.msg = msg
- self.doc = doc
- self.pos = pos
- self.end = end
- self.lineno, self.colno = linecol(doc, pos)
- if end is not None:
- self.endlineno, self.endcolno = linecol(doc, end)
- else:
- self.endlineno, self.endcolno = None, None
-
-
-def linecol(doc, pos):
- lineno = doc.count('\n', 0, pos) + 1
- if lineno == 1:
- colno = pos
- else:
- colno = pos - doc.rindex('\n', 0, pos)
- return lineno, colno
-
-
-def errmsg(msg, doc, pos, end=None):
- # Note that this function is called from _speedups
- lineno, colno = linecol(doc, pos)
- if end is None:
- #fmt = '{0}: line {1} column {2} (char {3})'
- #return fmt.format(msg, lineno, colno, pos)
- fmt = '%s: line %d column %d (char %d)'
- return fmt % (msg, lineno, colno, pos)
- endlineno, endcolno = linecol(doc, end)
- #fmt = '{0}: line {1} column {2} - line {3} column {4} (char {5} - {6})'
- #return fmt.format(msg, lineno, colno, endlineno, endcolno, pos, end)
- fmt = '%s: line %d column %d - line %d column %d (char %d - %d)'
- return fmt % (msg, lineno, colno, endlineno, endcolno, pos, end)
-
-
-_CONSTANTS = {
- '-Infinity': NegInf,
- 'Infinity': PosInf,
- 'NaN': NaN,
-}
-
-STRINGCHUNK = re.compile(r'(.*?)(["\\\x00-\x1f])', FLAGS)
-BACKSLASH = {
- '"': u'"', '\\': u'\\', '/': u'/',
- 'b': u'\b', 'f': u'\f', 'n': u'\n', 'r': u'\r', 't': u'\t',
-}
-
-DEFAULT_ENCODING = "utf-8"
-
-def py_scanstring(s, end, encoding=None, strict=True,
- _b=BACKSLASH, _m=STRINGCHUNK.match):
- """Scan the string s for a JSON string. End is the index of the
- character in s after the quote that started the JSON string.
- Unescapes all valid JSON string escape sequences and raises ValueError
- on attempt to decode an invalid string. If strict is False then literal
- control characters are allowed in the string.
-
- Returns a tuple of the decoded string and the index of the character in s
- after the end quote."""
- if encoding is None:
- encoding = DEFAULT_ENCODING
- chunks = []
- _append = chunks.append
- begin = end - 1
- while 1:
- chunk = _m(s, end)
- if chunk is None:
- raise JSONDecodeError(
- "Unterminated string starting at", s, begin)
- end = chunk.end()
- content, terminator = chunk.groups()
- # Content is contains zero or more unescaped string characters
- if content:
- if not isinstance(content, unicode):
- content = unicode(content, encoding)
- _append(content)
- # Terminator is the end of string, a literal control character,
- # or a backslash denoting that an escape sequence follows
- if terminator == '"':
- break
- elif terminator != '\\':
- if strict:
- msg = "Invalid control character %r at" % (terminator,)
- #msg = "Invalid control character {0!r} at".format(terminator)
- raise JSONDecodeError(msg, s, end)
- else:
- _append(terminator)
- continue
- try:
- esc = s[end]
- except IndexError:
- raise JSONDecodeError(
- "Unterminated string starting at", s, begin)
- # If not a unicode escape sequence, must be in the lookup table
- if esc != 'u':
- try:
- char = _b[esc]
- except KeyError:
- msg = "Invalid \\escape: " + repr(esc)
- raise JSONDecodeError(msg, s, end)
- end += 1
- else:
- # Unicode escape sequence
- esc = s[end + 1:end + 5]
- next_end = end + 5
- if len(esc) != 4:
- msg = "Invalid \\uXXXX escape"
- raise JSONDecodeError(msg, s, end)
- uni = int(esc, 16)
- # Check for surrogate pair on UCS-4 systems
- if 0xd800 <= uni <= 0xdbff and sys.maxunicode > 65535:
- msg = "Invalid \\uXXXX\\uXXXX surrogate pair"
- if not s[end + 5:end + 7] == '\\u':
- raise JSONDecodeError(msg, s, end)
- esc2 = s[end + 7:end + 11]
- if len(esc2) != 4:
- raise JSONDecodeError(msg, s, end)
- uni2 = int(esc2, 16)
- uni = 0x10000 + (((uni - 0xd800) << 10) | (uni2 - 0xdc00))
- next_end += 6
- char = unichr(uni)
- end = next_end
- # Append the unescaped character
- _append(char)
- return u''.join(chunks), end
-
-
-# Use speedup if available
-scanstring = c_scanstring or py_scanstring
-
-WHITESPACE = re.compile(r'[ \t\n\r]*', FLAGS)
-WHITESPACE_STR = ' \t\n\r'
-
-def JSONObject((s, end), encoding, strict, scan_once, object_hook,
- object_pairs_hook, memo=None,
- _w=WHITESPACE.match, _ws=WHITESPACE_STR):
- # Backwards compatibility
- if memo is None:
- memo = {}
- memo_get = memo.setdefault
- pairs = []
- # Use a slice to prevent IndexError from being raised, the following
- # check will raise a more specific ValueError if the string is empty
- nextchar = s[end:end + 1]
- # Normally we expect nextchar == '"'
- if nextchar != '"':
- if nextchar in _ws:
- end = _w(s, end).end()
- nextchar = s[end:end + 1]
- # Trivial empty object
- if nextchar == '}':
- if object_pairs_hook is not None:
- result = object_pairs_hook(pairs)
- return result, end + 1
- pairs = {}
- if object_hook is not None:
- pairs = object_hook(pairs)
- return pairs, end + 1
- elif nextchar != '"':
- raise JSONDecodeError("Expecting property name", s, end)
- end += 1
- while True:
- key, end = scanstring(s, end, encoding, strict)
- key = memo_get(key, key)
-
- # To skip some function call overhead we optimize the fast paths where
- # the JSON key separator is ": " or just ":".
- if s[end:end + 1] != ':':
- end = _w(s, end).end()
- if s[end:end + 1] != ':':
- raise JSONDecodeError("Expecting : delimiter", s, end)
-
- end += 1
-
- try:
- if s[end] in _ws:
- end += 1
- if s[end] in _ws:
- end = _w(s, end + 1).end()
- except IndexError:
- pass
-
- try:
- value, end = scan_once(s, end)
- except StopIteration:
- raise JSONDecodeError("Expecting object", s, end)
- pairs.append((key, value))
-
- try:
- nextchar = s[end]
- if nextchar in _ws:
- end = _w(s, end + 1).end()
- nextchar = s[end]
- except IndexError:
- nextchar = ''
- end += 1
-
- if nextchar == '}':
- break
- elif nextchar != ',':
- raise JSONDecodeError("Expecting , delimiter", s, end - 1)
-
- try:
- nextchar = s[end]
- if nextchar in _ws:
- end += 1
- nextchar = s[end]
- if nextchar in _ws:
- end = _w(s, end + 1).end()
- nextchar = s[end]
- except IndexError:
- nextchar = ''
-
- end += 1
- if nextchar != '"':
- raise JSONDecodeError("Expecting property name", s, end - 1)
-
- if object_pairs_hook is not None:
- result = object_pairs_hook(pairs)
- return result, end
- pairs = dict(pairs)
- if object_hook is not None:
- pairs = object_hook(pairs)
- return pairs, end
-
-def JSONArray((s, end), scan_once, _w=WHITESPACE.match, _ws=WHITESPACE_STR):
- values = []
- nextchar = s[end:end + 1]
- if nextchar in _ws:
- end = _w(s, end + 1).end()
- nextchar = s[end:end + 1]
- # Look-ahead for trivial empty array
- if nextchar == ']':
- return values, end + 1
- _append = values.append
- while True:
- try:
- value, end = scan_once(s, end)
- except StopIteration:
- raise JSONDecodeError("Expecting object", s, end)
- _append(value)
- nextchar = s[end:end + 1]
- if nextchar in _ws:
- end = _w(s, end + 1).end()
- nextchar = s[end:end + 1]
- end += 1
- if nextchar == ']':
- break
- elif nextchar != ',':
- raise JSONDecodeError("Expecting , delimiter", s, end)
-
- try:
- if s[end] in _ws:
- end += 1
- if s[end] in _ws:
- end = _w(s, end + 1).end()
- except IndexError:
- pass
-
- return values, end
-
-class JSONDecoder(object):
- """Simple JSON <http://json.org> decoder
-
- Performs the following translations in decoding by default:
-
- +---------------+-------------------+
- | JSON | Python |
- +===============+===================+
- | object | dict |
- +---------------+-------------------+
- | array | list |
- +---------------+-------------------+
- | string | unicode |
- +---------------+-------------------+
- | number (int) | int, long |
- +---------------+-------------------+
- | number (real) | float |
- +---------------+-------------------+
- | true | True |
- +---------------+-------------------+
- | false | False |
- +---------------+-------------------+
- | null | None |
- +---------------+-------------------+
-
- It also understands ``NaN``, ``Infinity``, and ``-Infinity`` as
- their corresponding ``float`` values, which is outside the JSON spec.
-
- """
-
- def __init__(self, encoding=None, object_hook=None, parse_float=None,
- parse_int=None, parse_constant=None, strict=True,
- object_pairs_hook=None):
- """
- *encoding* determines the encoding used to interpret any
- :class:`str` objects decoded by this instance (``'utf-8'`` by
- default). It has no effect when decoding :class:`unicode` objects.
-
- Note that currently only encodings that are a superset of ASCII work,
- strings of other encodings should be passed in as :class:`unicode`.
-
- *object_hook*, if specified, will be called with the result of every
- JSON object decoded and its return value will be used in place of the
- given :class:`dict`. This can be used to provide custom
- deserializations (e.g. to support JSON-RPC class hinting).
-
- *object_pairs_hook* is an optional function that will be called with
- the result of any object literal decode with an ordered list of pairs.
- The return value of *object_pairs_hook* will be used instead of the
- :class:`dict`. This feature can be used to implement custom decoders
- that rely on the order that the key and value pairs are decoded (for
- example, :func:`collections.OrderedDict` will remember the order of
- insertion). If *object_hook* is also defined, the *object_pairs_hook*
- takes priority.
-
- *parse_float*, if specified, will be called with the string of every
- JSON float to be decoded. By default, this is equivalent to
- ``float(num_str)``. This can be used to use another datatype or parser
- for JSON floats (e.g. :class:`decimal.Decimal`).
-
- *parse_int*, if specified, will be called with the string of every
- JSON int to be decoded. By default, this is equivalent to
- ``int(num_str)``. This can be used to use another datatype or parser
- for JSON integers (e.g. :class:`float`).
-
- *parse_constant*, if specified, will be called with one of the
- following strings: ``'-Infinity'``, ``'Infinity'``, ``'NaN'``. This
- can be used to raise an exception if invalid JSON numbers are
- encountered.
-
- *strict* controls the parser's behavior when it encounters an
- invalid control character in a string. The default setting of
- ``True`` means that unescaped control characters are parse errors, if
- ``False`` then control characters will be allowed in strings.
-
- """
- self.encoding = encoding
- self.object_hook = object_hook
- self.object_pairs_hook = object_pairs_hook
- self.parse_float = parse_float or float
- self.parse_int = parse_int or int
- self.parse_constant = parse_constant or _CONSTANTS.__getitem__
- self.strict = strict
- self.parse_object = JSONObject
- self.parse_array = JSONArray
- self.parse_string = scanstring
- self.memo = {}
- self.scan_once = make_scanner(self)
-
- def decode(self, s, _w=WHITESPACE.match):
- """Return the Python representation of ``s`` (a ``str`` or ``unicode``
- instance containing a JSON document)
-
- """
- obj, end = self.raw_decode(s, idx=_w(s, 0).end())
- end = _w(s, end).end()
- if end != len(s):
- raise JSONDecodeError("Extra data", s, end, len(s))
- return obj
-
- def raw_decode(self, s, idx=0):
- """Decode a JSON document from ``s`` (a ``str`` or ``unicode``
- beginning with a JSON document) and return a 2-tuple of the Python
- representation and the index in ``s`` where the document ended.
-
- This can be used to decode a JSON document from a string that may
- have extraneous data at the end.
-
- """
- try:
- obj, end = self.scan_once(s, idx)
- except StopIteration:
- raise JSONDecodeError("No JSON object could be decoded", s, idx)
- return obj, end
diff --git a/Tools/Scripts/webkitpy/thirdparty/simplejson/encoder.py b/Tools/Scripts/webkitpy/thirdparty/simplejson/encoder.py
deleted file mode 100644
index 7189d7f00..000000000
--- a/Tools/Scripts/webkitpy/thirdparty/simplejson/encoder.py
+++ /dev/null
@@ -1,503 +0,0 @@
-"""Implementation of JSONEncoder
-"""
-import re
-from decimal import Decimal
-
-def _import_speedups():
- try:
- from simplejson import _speedups
- return _speedups.encode_basestring_ascii, _speedups.make_encoder
- except ImportError:
- return None, None
-c_encode_basestring_ascii, c_make_encoder = _import_speedups()
-
-from decoder import PosInf
-
-ESCAPE = re.compile(r'[\x00-\x1f\\"\b\f\n\r\t]')
-ESCAPE_ASCII = re.compile(r'([\\"]|[^\ -~])')
-HAS_UTF8 = re.compile(r'[\x80-\xff]')
-ESCAPE_DCT = {
- '\\': '\\\\',
- '"': '\\"',
- '\b': '\\b',
- '\f': '\\f',
- '\n': '\\n',
- '\r': '\\r',
- '\t': '\\t',
-}
-for i in range(0x20):
- #ESCAPE_DCT.setdefault(chr(i), '\\u{0:04x}'.format(i))
- ESCAPE_DCT.setdefault(chr(i), '\\u%04x' % (i,))
-
-FLOAT_REPR = repr
-
-def encode_basestring(s):
- """Return a JSON representation of a Python string
-
- """
- if isinstance(s, str) and HAS_UTF8.search(s) is not None:
- s = s.decode('utf-8')
- def replace(match):
- return ESCAPE_DCT[match.group(0)]
- return u'"' + ESCAPE.sub(replace, s) + u'"'
-
-
-def py_encode_basestring_ascii(s):
- """Return an ASCII-only JSON representation of a Python string
-
- """
- if isinstance(s, str) and HAS_UTF8.search(s) is not None:
- s = s.decode('utf-8')
- def replace(match):
- s = match.group(0)
- try:
- return ESCAPE_DCT[s]
- except KeyError:
- n = ord(s)
- if n < 0x10000:
- #return '\\u{0:04x}'.format(n)
- return '\\u%04x' % (n,)
- else:
- # surrogate pair
- n -= 0x10000
- s1 = 0xd800 | ((n >> 10) & 0x3ff)
- s2 = 0xdc00 | (n & 0x3ff)
- #return '\\u{0:04x}\\u{1:04x}'.format(s1, s2)
- return '\\u%04x\\u%04x' % (s1, s2)
- return '"' + str(ESCAPE_ASCII.sub(replace, s)) + '"'
-
-
-encode_basestring_ascii = (
- c_encode_basestring_ascii or py_encode_basestring_ascii)
-
-class JSONEncoder(object):
- """Extensible JSON <http://json.org> encoder for Python data structures.
-
- Supports the following objects and types by default:
-
- +-------------------+---------------+
- | Python | JSON |
- +===================+===============+
- | dict | object |
- +-------------------+---------------+
- | list, tuple | array |
- +-------------------+---------------+
- | str, unicode | string |
- +-------------------+---------------+
- | int, long, float | number |
- +-------------------+---------------+
- | True | true |
- +-------------------+---------------+
- | False | false |
- +-------------------+---------------+
- | None | null |
- +-------------------+---------------+
-
- To extend this to recognize other objects, subclass and implement a
- ``.default()`` method with another method that returns a serializable
- object for ``o`` if possible, otherwise it should call the superclass
- implementation (to raise ``TypeError``).
-
- """
- item_separator = ', '
- key_separator = ': '
- def __init__(self, skipkeys=False, ensure_ascii=True,
- check_circular=True, allow_nan=True, sort_keys=False,
- indent=None, separators=None, encoding='utf-8', default=None,
- use_decimal=False):
- """Constructor for JSONEncoder, with sensible defaults.
-
- If skipkeys is false, then it is a TypeError to attempt
- encoding of keys that are not str, int, long, float or None. If
- skipkeys is True, such items are simply skipped.
-
- If ensure_ascii is true, the output is guaranteed to be str
- objects with all incoming unicode characters escaped. If
- ensure_ascii is false, the output will be unicode object.
-
- If check_circular is true, then lists, dicts, and custom encoded
- objects will be checked for circular references during encoding to
- prevent an infinite recursion (which would cause an OverflowError).
- Otherwise, no such check takes place.
-
- If allow_nan is true, then NaN, Infinity, and -Infinity will be
- encoded as such. This behavior is not JSON specification compliant,
- but is consistent with most JavaScript based encoders and decoders.
- Otherwise, it will be a ValueError to encode such floats.
-
- If sort_keys is true, then the output of dictionaries will be
- sorted by key; this is useful for regression tests to ensure
- that JSON serializations can be compared on a day-to-day basis.
-
- If indent is a string, then JSON array elements and object members
- will be pretty-printed with a newline followed by that string repeated
- for each level of nesting. ``None`` (the default) selects the most compact
- representation without any newlines. For backwards compatibility with
- versions of simplejson earlier than 2.1.0, an integer is also accepted
- and is converted to a string with that many spaces.
-
- If specified, separators should be a (item_separator, key_separator)
- tuple. The default is (', ', ': '). To get the most compact JSON
- representation you should specify (',', ':') to eliminate whitespace.
-
- If specified, default is a function that gets called for objects
- that can't otherwise be serialized. It should return a JSON encodable
- version of the object or raise a ``TypeError``.
-
- If encoding is not None, then all input strings will be
- transformed into unicode using that encoding prior to JSON-encoding.
- The default is UTF-8.
-
- If use_decimal is true (not the default), ``decimal.Decimal`` will
- be supported directly by the encoder. For the inverse, decode JSON
- with ``parse_float=decimal.Decimal``.
-
- """
-
- self.skipkeys = skipkeys
- self.ensure_ascii = ensure_ascii
- self.check_circular = check_circular
- self.allow_nan = allow_nan
- self.sort_keys = sort_keys
- self.use_decimal = use_decimal
- if isinstance(indent, (int, long)):
- indent = ' ' * indent
- self.indent = indent
- if separators is not None:
- self.item_separator, self.key_separator = separators
- elif indent is not None:
- self.item_separator = ','
- if default is not None:
- self.default = default
- self.encoding = encoding
-
- def default(self, o):
- """Implement this method in a subclass such that it returns
- a serializable object for ``o``, or calls the base implementation
- (to raise a ``TypeError``).
-
- For example, to support arbitrary iterators, you could
- implement default like this::
-
- def default(self, o):
- try:
- iterable = iter(o)
- except TypeError:
- pass
- else:
- return list(iterable)
- return JSONEncoder.default(self, o)
-
- """
- raise TypeError(repr(o) + " is not JSON serializable")
-
- def encode(self, o):
- """Return a JSON string representation of a Python data structure.
-
- >>> from simplejson import JSONEncoder
- >>> JSONEncoder().encode({"foo": ["bar", "baz"]})
- '{"foo": ["bar", "baz"]}'
-
- """
- # This is for extremely simple cases and benchmarks.
- if isinstance(o, basestring):
- if isinstance(o, str):
- _encoding = self.encoding
- if (_encoding is not None
- and not (_encoding == 'utf-8')):
- o = o.decode(_encoding)
- if self.ensure_ascii:
- return encode_basestring_ascii(o)
- else:
- return encode_basestring(o)
- # This doesn't pass the iterator directly to ''.join() because the
- # exceptions aren't as detailed. The list call should be roughly
- # equivalent to the PySequence_Fast that ''.join() would do.
- chunks = self.iterencode(o, _one_shot=True)
- if not isinstance(chunks, (list, tuple)):
- chunks = list(chunks)
- if self.ensure_ascii:
- return ''.join(chunks)
- else:
- return u''.join(chunks)
-
- def iterencode(self, o, _one_shot=False):
- """Encode the given object and yield each string
- representation as available.
-
- For example::
-
- for chunk in JSONEncoder().iterencode(bigobject):
- mysocket.write(chunk)
-
- """
- if self.check_circular:
- markers = {}
- else:
- markers = None
- if self.ensure_ascii:
- _encoder = encode_basestring_ascii
- else:
- _encoder = encode_basestring
- if self.encoding != 'utf-8':
- def _encoder(o, _orig_encoder=_encoder, _encoding=self.encoding):
- if isinstance(o, str):
- o = o.decode(_encoding)
- return _orig_encoder(o)
-
- def floatstr(o, allow_nan=self.allow_nan,
- _repr=FLOAT_REPR, _inf=PosInf, _neginf=-PosInf):
- # Check for specials. Note that this type of test is processor
- # and/or platform-specific, so do tests which don't depend on
- # the internals.
-
- if o != o:
- text = 'NaN'
- elif o == _inf:
- text = 'Infinity'
- elif o == _neginf:
- text = '-Infinity'
- else:
- return _repr(o)
-
- if not allow_nan:
- raise ValueError(
- "Out of range float values are not JSON compliant: " +
- repr(o))
-
- return text
-
-
- key_memo = {}
- if (_one_shot and c_make_encoder is not None
- and self.indent is None):
- _iterencode = c_make_encoder(
- markers, self.default, _encoder, self.indent,
- self.key_separator, self.item_separator, self.sort_keys,
- self.skipkeys, self.allow_nan, key_memo, self.use_decimal)
- else:
- _iterencode = _make_iterencode(
- markers, self.default, _encoder, self.indent, floatstr,
- self.key_separator, self.item_separator, self.sort_keys,
- self.skipkeys, _one_shot, self.use_decimal)
- try:
- return _iterencode(o, 0)
- finally:
- key_memo.clear()
-
-
-class JSONEncoderForHTML(JSONEncoder):
- """An encoder that produces JSON safe to embed in HTML.
-
- To embed JSON content in, say, a script tag on a web page, the
- characters &, < and > should be escaped. They cannot be escaped
- with the usual entities (e.g. &amp;) because they are not expanded
- within <script> tags.
- """
-
- def encode(self, o):
- # Override JSONEncoder.encode because it has hacks for
- # performance that make things more complicated.
- chunks = self.iterencode(o, True)
- if self.ensure_ascii:
- return ''.join(chunks)
- else:
- return u''.join(chunks)
-
- def iterencode(self, o, _one_shot=False):
- chunks = super(JSONEncoderForHTML, self).iterencode(o, _one_shot)
- for chunk in chunks:
- chunk = chunk.replace('&', '\\u0026')
- chunk = chunk.replace('<', '\\u003c')
- chunk = chunk.replace('>', '\\u003e')
- yield chunk
-
-
-def _make_iterencode(markers, _default, _encoder, _indent, _floatstr,
- _key_separator, _item_separator, _sort_keys, _skipkeys, _one_shot,
- _use_decimal,
- ## HACK: hand-optimized bytecode; turn globals into locals
- False=False,
- True=True,
- ValueError=ValueError,
- basestring=basestring,
- Decimal=Decimal,
- dict=dict,
- float=float,
- id=id,
- int=int,
- isinstance=isinstance,
- list=list,
- long=long,
- str=str,
- tuple=tuple,
- ):
-
- def _iterencode_list(lst, _current_indent_level):
- if not lst:
- yield '[]'
- return
- if markers is not None:
- markerid = id(lst)
- if markerid in markers:
- raise ValueError("Circular reference detected")
- markers[markerid] = lst
- buf = '['
- if _indent is not None:
- _current_indent_level += 1
- newline_indent = '\n' + (_indent * _current_indent_level)
- separator = _item_separator + newline_indent
- buf += newline_indent
- else:
- newline_indent = None
- separator = _item_separator
- first = True
- for value in lst:
- if first:
- first = False
- else:
- buf = separator
- if isinstance(value, basestring):
- yield buf + _encoder(value)
- elif value is None:
- yield buf + 'null'
- elif value is True:
- yield buf + 'true'
- elif value is False:
- yield buf + 'false'
- elif isinstance(value, (int, long)):
- yield buf + str(value)
- elif isinstance(value, float):
- yield buf + _floatstr(value)
- elif _use_decimal and isinstance(value, Decimal):
- yield buf + str(value)
- else:
- yield buf
- if isinstance(value, (list, tuple)):
- chunks = _iterencode_list(value, _current_indent_level)
- elif isinstance(value, dict):
- chunks = _iterencode_dict(value, _current_indent_level)
- else:
- chunks = _iterencode(value, _current_indent_level)
- for chunk in chunks:
- yield chunk
- if newline_indent is not None:
- _current_indent_level -= 1
- yield '\n' + (_indent * _current_indent_level)
- yield ']'
- if markers is not None:
- del markers[markerid]
-
- def _iterencode_dict(dct, _current_indent_level):
- if not dct:
- yield '{}'
- return
- if markers is not None:
- markerid = id(dct)
- if markerid in markers:
- raise ValueError("Circular reference detected")
- markers[markerid] = dct
- yield '{'
- if _indent is not None:
- _current_indent_level += 1
- newline_indent = '\n' + (_indent * _current_indent_level)
- item_separator = _item_separator + newline_indent
- yield newline_indent
- else:
- newline_indent = None
- item_separator = _item_separator
- first = True
- if _sort_keys:
- items = dct.items()
- items.sort(key=lambda kv: kv[0])
- else:
- items = dct.iteritems()
- for key, value in items:
- if isinstance(key, basestring):
- pass
- # JavaScript is weakly typed for these, so it makes sense to
- # also allow them. Many encoders seem to do something like this.
- elif isinstance(key, float):
- key = _floatstr(key)
- elif key is True:
- key = 'true'
- elif key is False:
- key = 'false'
- elif key is None:
- key = 'null'
- elif isinstance(key, (int, long)):
- key = str(key)
- elif _skipkeys:
- continue
- else:
- raise TypeError("key " + repr(key) + " is not a string")
- if first:
- first = False
- else:
- yield item_separator
- yield _encoder(key)
- yield _key_separator
- if isinstance(value, basestring):
- yield _encoder(value)
- elif value is None:
- yield 'null'
- elif value is True:
- yield 'true'
- elif value is False:
- yield 'false'
- elif isinstance(value, (int, long)):
- yield str(value)
- elif isinstance(value, float):
- yield _floatstr(value)
- elif _use_decimal and isinstance(value, Decimal):
- yield str(value)
- else:
- if isinstance(value, (list, tuple)):
- chunks = _iterencode_list(value, _current_indent_level)
- elif isinstance(value, dict):
- chunks = _iterencode_dict(value, _current_indent_level)
- else:
- chunks = _iterencode(value, _current_indent_level)
- for chunk in chunks:
- yield chunk
- if newline_indent is not None:
- _current_indent_level -= 1
- yield '\n' + (_indent * _current_indent_level)
- yield '}'
- if markers is not None:
- del markers[markerid]
-
- def _iterencode(o, _current_indent_level):
- if isinstance(o, basestring):
- yield _encoder(o)
- elif o is None:
- yield 'null'
- elif o is True:
- yield 'true'
- elif o is False:
- yield 'false'
- elif isinstance(o, (int, long)):
- yield str(o)
- elif isinstance(o, float):
- yield _floatstr(o)
- elif isinstance(o, (list, tuple)):
- for chunk in _iterencode_list(o, _current_indent_level):
- yield chunk
- elif isinstance(o, dict):
- for chunk in _iterencode_dict(o, _current_indent_level):
- yield chunk
- elif _use_decimal and isinstance(o, Decimal):
- yield str(o)
- else:
- if markers is not None:
- markerid = id(o)
- if markerid in markers:
- raise ValueError("Circular reference detected")
- markers[markerid] = o
- o = _default(o)
- for chunk in _iterencode(o, _current_indent_level):
- yield chunk
- if markers is not None:
- del markers[markerid]
-
- return _iterencode
diff --git a/Tools/Scripts/webkitpy/thirdparty/simplejson/jsonfilter.py b/Tools/Scripts/webkitpy/thirdparty/simplejson/jsonfilter.py
deleted file mode 100644
index 01ca21df6..000000000
--- a/Tools/Scripts/webkitpy/thirdparty/simplejson/jsonfilter.py
+++ /dev/null
@@ -1,40 +0,0 @@
-import simplejson
-import cgi
-
-class JSONFilter(object):
- def __init__(self, app, mime_type='text/x-json'):
- self.app = app
- self.mime_type = mime_type
-
- def __call__(self, environ, start_response):
- # Read JSON POST input to jsonfilter.json if matching mime type
- response = {'status': '200 OK', 'headers': []}
- def json_start_response(status, headers):
- response['status'] = status
- response['headers'].extend(headers)
- environ['jsonfilter.mime_type'] = self.mime_type
- if environ.get('REQUEST_METHOD', '') == 'POST':
- if environ.get('CONTENT_TYPE', '') == self.mime_type:
- args = [_ for _ in [environ.get('CONTENT_LENGTH')] if _]
- data = environ['wsgi.input'].read(*map(int, args))
- environ['jsonfilter.json'] = simplejson.loads(data)
- res = simplejson.dumps(self.app(environ, json_start_response))
- jsonp = cgi.parse_qs(environ.get('QUERY_STRING', '')).get('jsonp')
- if jsonp:
- content_type = 'text/javascript'
- res = ''.join(jsonp + ['(', res, ')'])
- elif 'Opera' in environ.get('HTTP_USER_AGENT', ''):
- # Opera has bunk XMLHttpRequest support for most mime types
- content_type = 'text/plain'
- else:
- content_type = self.mime_type
- headers = [
- ('Content-type', content_type),
- ('Content-length', len(res)),
- ]
- headers.extend(response['headers'])
- start_response(response['status'], headers)
- return [res]
-
-def factory(app, global_conf, **kw):
- return JSONFilter(app, **kw)
diff --git a/Tools/Scripts/webkitpy/thirdparty/simplejson/ordered_dict.py b/Tools/Scripts/webkitpy/thirdparty/simplejson/ordered_dict.py
deleted file mode 100644
index 87ad88824..000000000
--- a/Tools/Scripts/webkitpy/thirdparty/simplejson/ordered_dict.py
+++ /dev/null
@@ -1,119 +0,0 @@
-"""Drop-in replacement for collections.OrderedDict by Raymond Hettinger
-
-http://code.activestate.com/recipes/576693/
-
-"""
-from UserDict import DictMixin
-
-# Modified from original to support Python 2.4, see
-# http://code.google.com/p/simplejson/issues/detail?id=53
-try:
- all
-except NameError:
- def all(seq):
- for elem in seq:
- if not elem:
- return False
- return True
-
-class OrderedDict(dict, DictMixin):
-
- def __init__(self, *args, **kwds):
- if len(args) > 1:
- raise TypeError('expected at most 1 arguments, got %d' % len(args))
- try:
- self.__end
- except AttributeError:
- self.clear()
- self.update(*args, **kwds)
-
- def clear(self):
- self.__end = end = []
- end += [None, end, end] # sentinel node for doubly linked list
- self.__map = {} # key --> [key, prev, next]
- dict.clear(self)
-
- def __setitem__(self, key, value):
- if key not in self:
- end = self.__end
- curr = end[1]
- curr[2] = end[1] = self.__map[key] = [key, curr, end]
- dict.__setitem__(self, key, value)
-
- def __delitem__(self, key):
- dict.__delitem__(self, key)
- key, prev, next = self.__map.pop(key)
- prev[2] = next
- next[1] = prev
-
- def __iter__(self):
- end = self.__end
- curr = end[2]
- while curr is not end:
- yield curr[0]
- curr = curr[2]
-
- def __reversed__(self):
- end = self.__end
- curr = end[1]
- while curr is not end:
- yield curr[0]
- curr = curr[1]
-
- def popitem(self, last=True):
- if not self:
- raise KeyError('dictionary is empty')
- # Modified from original to support Python 2.4, see
- # http://code.google.com/p/simplejson/issues/detail?id=53
- if last:
- key = reversed(self).next()
- else:
- key = iter(self).next()
- value = self.pop(key)
- return key, value
-
- def __reduce__(self):
- items = [[k, self[k]] for k in self]
- tmp = self.__map, self.__end
- del self.__map, self.__end
- inst_dict = vars(self).copy()
- self.__map, self.__end = tmp
- if inst_dict:
- return (self.__class__, (items,), inst_dict)
- return self.__class__, (items,)
-
- def keys(self):
- return list(self)
-
- setdefault = DictMixin.setdefault
- update = DictMixin.update
- pop = DictMixin.pop
- values = DictMixin.values
- items = DictMixin.items
- iterkeys = DictMixin.iterkeys
- itervalues = DictMixin.itervalues
- iteritems = DictMixin.iteritems
-
- def __repr__(self):
- if not self:
- return '%s()' % (self.__class__.__name__,)
- return '%s(%r)' % (self.__class__.__name__, self.items())
-
- def copy(self):
- return self.__class__(self)
-
- @classmethod
- def fromkeys(cls, iterable, value=None):
- d = cls()
- for key in iterable:
- d[key] = value
- return d
-
- def __eq__(self, other):
- if isinstance(other, OrderedDict):
- return len(self)==len(other) and \
- all(p==q for p, q in zip(self.items(), other.items()))
- return dict.__eq__(self, other)
-
- def __ne__(self, other):
- return not self == other
diff --git a/Tools/Scripts/webkitpy/thirdparty/simplejson/scanner.py b/Tools/Scripts/webkitpy/thirdparty/simplejson/scanner.py
deleted file mode 100644
index 54593a371..000000000
--- a/Tools/Scripts/webkitpy/thirdparty/simplejson/scanner.py
+++ /dev/null
@@ -1,77 +0,0 @@
-"""JSON token scanner
-"""
-import re
-def _import_c_make_scanner():
- try:
- from simplejson._speedups import make_scanner
- return make_scanner
- except ImportError:
- return None
-c_make_scanner = _import_c_make_scanner()
-
-__all__ = ['make_scanner']
-
-NUMBER_RE = re.compile(
- r'(-?(?:0|[1-9]\d*))(\.\d+)?([eE][-+]?\d+)?',
- (re.VERBOSE | re.MULTILINE | re.DOTALL))
-
-def py_make_scanner(context):
- parse_object = context.parse_object
- parse_array = context.parse_array
- parse_string = context.parse_string
- match_number = NUMBER_RE.match
- encoding = context.encoding
- strict = context.strict
- parse_float = context.parse_float
- parse_int = context.parse_int
- parse_constant = context.parse_constant
- object_hook = context.object_hook
- object_pairs_hook = context.object_pairs_hook
- memo = context.memo
-
- def _scan_once(string, idx):
- try:
- nextchar = string[idx]
- except IndexError:
- raise StopIteration
-
- if nextchar == '"':
- return parse_string(string, idx + 1, encoding, strict)
- elif nextchar == '{':
- return parse_object((string, idx + 1), encoding, strict,
- _scan_once, object_hook, object_pairs_hook, memo)
- elif nextchar == '[':
- return parse_array((string, idx + 1), _scan_once)
- elif nextchar == 'n' and string[idx:idx + 4] == 'null':
- return None, idx + 4
- elif nextchar == 't' and string[idx:idx + 4] == 'true':
- return True, idx + 4
- elif nextchar == 'f' and string[idx:idx + 5] == 'false':
- return False, idx + 5
-
- m = match_number(string, idx)
- if m is not None:
- integer, frac, exp = m.groups()
- if frac or exp:
- res = parse_float(integer + (frac or '') + (exp or ''))
- else:
- res = parse_int(integer)
- return res, m.end()
- elif nextchar == 'N' and string[idx:idx + 3] == 'NaN':
- return parse_constant('NaN'), idx + 3
- elif nextchar == 'I' and string[idx:idx + 8] == 'Infinity':
- return parse_constant('Infinity'), idx + 8
- elif nextchar == '-' and string[idx:idx + 9] == '-Infinity':
- return parse_constant('-Infinity'), idx + 9
- else:
- raise StopIteration
-
- def scan_once(string, idx):
- try:
- return _scan_once(string, idx)
- finally:
- memo.clear()
-
- return scan_once
-
-make_scanner = c_make_scanner or py_make_scanner
diff --git a/Tools/Scripts/webkitpy/thirdparty/simplejson/tool.py b/Tools/Scripts/webkitpy/thirdparty/simplejson/tool.py
deleted file mode 100644
index 73370db55..000000000
--- a/Tools/Scripts/webkitpy/thirdparty/simplejson/tool.py
+++ /dev/null
@@ -1,39 +0,0 @@
-r"""Command-line tool to validate and pretty-print JSON
-
-Usage::
-
- $ echo '{"json":"obj"}' | python -m simplejson.tool
- {
- "json": "obj"
- }
- $ echo '{ 1.2:3.4}' | python -m simplejson.tool
- Expecting property name: line 1 column 2 (char 2)
-
-"""
-import sys
-import simplejson as json
-
-def main():
- if len(sys.argv) == 1:
- infile = sys.stdin
- outfile = sys.stdout
- elif len(sys.argv) == 2:
- infile = open(sys.argv[1], 'rb')
- outfile = sys.stdout
- elif len(sys.argv) == 3:
- infile = open(sys.argv[1], 'rb')
- outfile = open(sys.argv[2], 'wb')
- else:
- raise SystemExit(sys.argv[0] + " [infile [outfile]]")
- try:
- obj = json.load(infile,
- object_pairs_hook=json.OrderedDict,
- use_decimal=True)
- except ValueError, e:
- raise SystemExit(e)
- json.dump(obj, outfile, sort_keys=True, indent=' ', use_decimal=True)
- outfile.write('\n')
-
-
-if __name__ == '__main__':
- main()
diff --git a/Tools/Scripts/webkitpy/to_be_moved/rebaseline_chromium_webkit_tests.py b/Tools/Scripts/webkitpy/to_be_moved/rebaseline_chromium_webkit_tests.py
index 9e886d5a5..2219879f2 100644
--- a/Tools/Scripts/webkitpy/to_be_moved/rebaseline_chromium_webkit_tests.py
+++ b/Tools/Scripts/webkitpy/to_be_moved/rebaseline_chromium_webkit_tests.py
@@ -41,8 +41,6 @@ The script does the following for each platform specified:
At the end, the script generates a html that compares old and new baselines.
"""
-from __future__ import with_statement
-
import copy
import logging
import optparse
@@ -247,7 +245,7 @@ class Rebaseliner(object):
fs = self._target_port._filesystem
for test in self._rebaselining_tests:
- if self._target_port.is_reftest(test):
+ if self._target_port.reference_files(test):
_log.error('%s seems to be a reftest. We can not rebase for reftests.', test)
self._rebaselining_tests = set()
return False
diff --git a/Tools/Scripts/webkitpy/to_be_moved/update_webgl_conformance_tests.py b/Tools/Scripts/webkitpy/to_be_moved/update_webgl_conformance_tests.py
index 1196980b2..68c2fb7f5 100755
--- a/Tools/Scripts/webkitpy/to_be_moved/update_webgl_conformance_tests.py
+++ b/Tools/Scripts/webkitpy/to_be_moved/update_webgl_conformance_tests.py
@@ -23,8 +23,6 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-from __future__ import with_statement
-
import glob
import logging
import optparse
diff --git a/Tools/Scripts/webkitpy/tool/bot/queueengine.py b/Tools/Scripts/webkitpy/tool/bot/queueengine.py
index 2f087bfcd..752ef748a 100644
--- a/Tools/Scripts/webkitpy/tool/bot/queueengine.py
+++ b/Tools/Scripts/webkitpy/tool/bot/queueengine.py
@@ -28,6 +28,7 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import os
+import sys
import time
import traceback
@@ -86,7 +87,7 @@ class QueueEngine:
@classmethod
def exit_after_handled_error(cls, error):
log(error)
- exit(cls.handled_error_code)
+ sys.exit(cls.handled_error_code)
def run(self):
self._begin_logging()
diff --git a/Tools/Scripts/webkitpy/tool/commands/abstractsequencedcommand.py b/Tools/Scripts/webkitpy/tool/commands/abstractsequencedcommand.py
index fd1089056..5eaf249c5 100644
--- a/Tools/Scripts/webkitpy/tool/commands/abstractsequencedcommand.py
+++ b/Tools/Scripts/webkitpy/tool/commands/abstractsequencedcommand.py
@@ -46,6 +46,6 @@ class AbstractSequencedCommand(AbstractDeclarativeCommand):
state = self._prepare_state(options, args, tool)
except ScriptError, e:
log(e.message_with_output())
- exit(e.exit_code or 2)
+ self._exit(e.exit_code or 2)
self._sequence.run_and_handle_errors(tool, options, state)
diff --git a/Tools/Scripts/webkitpy/tool/commands/analyzechangelog.py b/Tools/Scripts/webkitpy/tool/commands/analyzechangelog.py
index 2fe34ade5..b88b61f55 100644
--- a/Tools/Scripts/webkitpy/tool/commands/analyzechangelog.py
+++ b/Tools/Scripts/webkitpy/tool/commands/analyzechangelog.py
@@ -26,8 +26,6 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-from __future__ import with_statement
-
import json
import re
import time
diff --git a/Tools/Scripts/webkitpy/tool/commands/download.py b/Tools/Scripts/webkitpy/tool/commands/download.py
index 82a570a25..f18bf31a5 100644
--- a/Tools/Scripts/webkitpy/tool/commands/download.py
+++ b/Tools/Scripts/webkitpy/tool/commands/download.py
@@ -187,6 +187,12 @@ class ProcessBugsMixin(object):
patches = tool.bugs.fetch_bug(bug_id).reviewed_patches()
log("%s found on bug %s." % (pluralize("reviewed patch", len(patches)), bug_id))
all_patches += patches
+ if not all_patches:
+ log("No reviewed patches found, looking for unreviewed patches.")
+ for bug_id in args:
+ patches = tool.bugs.fetch_bug(bug_id).patches()
+ log("%s found on bug %s." % (pluralize("patch", len(patches)), bug_id))
+ all_patches += patches
return all_patches
diff --git a/Tools/Scripts/webkitpy/tool/commands/download_unittest.py b/Tools/Scripts/webkitpy/tool/commands/download_unittest.py
index 55a22869e..eab8461b9 100644
--- a/Tools/Scripts/webkitpy/tool/commands/download_unittest.py
+++ b/Tools/Scripts/webkitpy/tool/commands/download_unittest.py
@@ -104,10 +104,14 @@ class DownloadCommandsTest(CommandsTest):
expected_stderr = "Updating working directory\nProcessing 1 patch from 1 bug.\nProcessing patch 10000 from bug 50000.\n"
self.assert_execute_outputs(ApplyAttachment(), [10000], options=options, expected_stderr=expected_stderr)
- def test_apply_patches(self):
+ def test_apply_from_bug(self):
options = self._default_options()
options.update = True
options.local_commit = True
+
+ expected_stderr = "Updating working directory\n0 reviewed patches found on bug 50001.\nNo reviewed patches found, looking for unreviewed patches.\n1 patch found on bug 50001.\nProcessing 1 patch from 1 bug.\nProcessing patch 10002 from bug 50001.\n"
+ self.assert_execute_outputs(ApplyFromBug(), [50001], options=options, expected_stderr=expected_stderr)
+
expected_stderr = "Updating working directory\n2 reviewed patches found on bug 50000.\nProcessing 2 patches from 1 bug.\nProcessing patch 10000 from bug 50000.\nProcessing patch 10001 from bug 50000.\n"
self.assert_execute_outputs(ApplyFromBug(), [50000], options=options, expected_stderr=expected_stderr)
diff --git a/Tools/Scripts/webkitpy/tool/commands/queues.py b/Tools/Scripts/webkitpy/tool/commands/queues.py
index f61a63991..ed851781c 100644
--- a/Tools/Scripts/webkitpy/tool/commands/queues.py
+++ b/Tools/Scripts/webkitpy/tool/commands/queues.py
@@ -27,12 +27,11 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-from __future__ import with_statement
-
import codecs
+import os
+import sys
import time
import traceback
-import os
from datetime import datetime
from optparse import make_option
@@ -440,4 +439,4 @@ class StyleQueue(AbstractReviewQueue):
QueueEngine.exit_after_handled_error(script_error)
message = "Attachment %s did not pass %s:\n\n%s\n\nIf any of these errors are false positives, please file a bug against check-webkit-style." % (state["patch"].id(), cls.name, script_error.message_with_output(output_limit=3*1024))
tool.bugs.post_comment_to_bug(state["patch"].bug_id(), message, cc=cls.watchers)
- exit(1)
+ sys.exit(1)
diff --git a/Tools/Scripts/webkitpy/tool/commands/queues_unittest.py b/Tools/Scripts/webkitpy/tool/commands/queues_unittest.py
index eea8e56a4..8f8f19835 100644
--- a/Tools/Scripts/webkitpy/tool/commands/queues_unittest.py
+++ b/Tools/Scripts/webkitpy/tool/commands/queues_unittest.py
@@ -118,12 +118,6 @@ class AbstractQueueTest(CommandsTest):
def test_log_from_script_error_for_upload(self):
self._assert_log_message(ScriptError("test"), "test")
- # In python 2.5 unicode(Exception) is busted. See:
- # http://bugs.python.org/issue2517
- # With no good workaround, we just ignore these tests.
- if not hasattr(Exception, "__unicode__"):
- return
-
unicode_tor = u"WebKit \u2661 Tor Arne Vestb\u00F8!"
utf8_tor = unicode_tor.encode("utf-8")
self._assert_log_message(ScriptError(unicode_tor), utf8_tor)
diff --git a/Tools/Scripts/webkitpy/tool/commands/upload.py b/Tools/Scripts/webkitpy/tool/commands/upload.py
index 1436a9378..ff6d22eae 100644
--- a/Tools/Scripts/webkitpy/tool/commands/upload.py
+++ b/Tools/Scripts/webkitpy/tool/commands/upload.py
@@ -410,7 +410,7 @@ class MarkBugFixed(AbstractDeclarativeCommand):
if needs_prompt:
if not tool.user.confirm("Is this correct?"):
- exit(1)
+ self._exit(1)
bug_comment = bug_comment_from_svn_revision(svn_revision)
if options.comment:
diff --git a/Tools/Scripts/webkitpy/tool/multicommandtool.py b/Tools/Scripts/webkitpy/tool/multicommandtool.py
index 4848ae532..38c410cf8 100644
--- a/Tools/Scripts/webkitpy/tool/multicommandtool.py
+++ b/Tools/Scripts/webkitpy/tool/multicommandtool.py
@@ -58,6 +58,9 @@ class Command(object):
# This default parser will be used for standalone_help printing.
self.option_parser = HelpPrintingOptionParser(usage=SUPPRESS_USAGE, add_help_option=False, option_list=self.options)
+ def _exit(self, code):
+ sys.exit(code)
+
# This design is slightly awkward, but we need the
# the tool to be able to create and modify the option_parser
# before it knows what Command to run.
diff --git a/Tools/Scripts/webkitpy/tool/servers/gardeningserver_unittest.py b/Tools/Scripts/webkitpy/tool/servers/gardeningserver_unittest.py
index 34486a378..9d99835f1 100644
--- a/Tools/Scripts/webkitpy/tool/servers/gardeningserver_unittest.py
+++ b/Tools/Scripts/webkitpy/tool/servers/gardeningserver_unittest.py
@@ -26,12 +26,7 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-try:
- import json
-except ImportError:
- # python 2.5 compatibility
- import webkitpy.thirdparty.simplejson as json
-
+import json
import unittest
from webkitpy.common.system.outputcapture import OutputCapture
diff --git a/Tools/Scripts/webkitpy/tool/servers/rebaselineserver_unittest.py b/Tools/Scripts/webkitpy/tool/servers/rebaselineserver_unittest.py
index 0b9bc43af..ae4a05eb0 100644
--- a/Tools/Scripts/webkitpy/tool/servers/rebaselineserver_unittest.py
+++ b/Tools/Scripts/webkitpy/tool/servers/rebaselineserver_unittest.py
@@ -26,15 +26,9 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+import json
import unittest
-try:
- import json
-except ImportError:
- # python 2.5 compatibility
- import webkitpy.thirdparty.simplejson as json
-
-
from webkitpy.common.net import resultsjsonparser_unittest
from webkitpy.common.host_mock import MockHost
from webkitpy.layout_tests.layout_package.json_results_generator import strip_json_wrapper
diff --git a/Tools/Scripts/webkitpy/tool/servers/reflectionhandler.py b/Tools/Scripts/webkitpy/tool/servers/reflectionhandler.py
index db118afa6..9b73c4efe 100644
--- a/Tools/Scripts/webkitpy/tool/servers/reflectionhandler.py
+++ b/Tools/Scripts/webkitpy/tool/servers/reflectionhandler.py
@@ -26,20 +26,13 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-from __future__ import with_statement
-
-try:
- import json
-except ImportError:
- # python 2.5 compatibility
- import webkitpy.thirdparty.simplejson as json
-
import BaseHTTPServer
import cgi
import codecs
import datetime
import fnmatch
+import json
import mimetypes
import os
import os.path
diff --git a/Tools/Scripts/webkitpy/tool/steps/abstractstep.py b/Tools/Scripts/webkitpy/tool/steps/abstractstep.py
index 5ac976f9e..db0c0d5a8 100644
--- a/Tools/Scripts/webkitpy/tool/steps/abstractstep.py
+++ b/Tools/Scripts/webkitpy/tool/steps/abstractstep.py
@@ -26,6 +26,8 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+import sys
+
from webkitpy.common.system.executive import ScriptError
from webkitpy.common.config.ports import WebKitPort
from webkitpy.tool.steps.options import Options
@@ -36,6 +38,9 @@ class AbstractStep(object):
self._tool = tool
self._options = options
+ def _exit(self, code):
+ sys.exit(code)
+
def _changed_files(self, state):
return self.cached_lookup(state, "changed_files")
diff --git a/Tools/Scripts/webkitpy/tool/steps/checkstyle.py b/Tools/Scripts/webkitpy/tool/steps/checkstyle.py
index a1a318134..f600d17d0 100644
--- a/Tools/Scripts/webkitpy/tool/steps/checkstyle.py
+++ b/Tools/Scripts/webkitpy/tool/steps/checkstyle.py
@@ -67,4 +67,4 @@ class CheckStyle(AbstractStep):
# style-queue do the right thing.
raise e
if not self._tool.user.confirm("Are you sure you want to continue?"):
- exit(1)
+ self._exit(1)
diff --git a/Tools/Scripts/webkitpy/tool/steps/commit.py b/Tools/Scripts/webkitpy/tool/steps/commit.py
index e8fc392ba..9e69e7980 100644
--- a/Tools/Scripts/webkitpy/tool/steps/commit.py
+++ b/Tools/Scripts/webkitpy/tool/steps/commit.py
@@ -26,6 +26,8 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+import sys
+
from webkitpy.common.checkout.scm import AuthenticationError, AmbiguousCommitError
from webkitpy.common.config import urls
from webkitpy.common.system.deprecated_logging import log
@@ -65,7 +67,7 @@ class Commit(AbstractStep):
self._tool.executive.run_and_throw_if_fail(self._tool.port().check_webkit_style_command() + args, cwd=self._tool.scm().checkout_root)
except ScriptError, e:
if not self._tool.user.confirm("Are you sure you want to continue?", default="n"):
- exit(1)
+ self._exit(1)
def run(self, state):
self._commit_message = self._tool.checkout().commit_message_for_this_commit(self._options.git_commit).message()
diff --git a/Tools/Scripts/webkitpy/tool/steps/confirmdiff.py b/Tools/Scripts/webkitpy/tool/steps/confirmdiff.py
index 7e8e34898..86c8a2c8d 100644
--- a/Tools/Scripts/webkitpy/tool/steps/confirmdiff.py
+++ b/Tools/Scripts/webkitpy/tool/steps/confirmdiff.py
@@ -74,4 +74,4 @@ class ConfirmDiff(AbstractStep):
if pretty_diff_file:
pretty_diff_file.close()
if not diff_correct:
- exit(1)
+ self._exit(1)
diff --git a/Tools/Scripts/webkitpy/tool/steps/preparechangelogforrevert_unittest.py b/Tools/Scripts/webkitpy/tool/steps/preparechangelogforrevert_unittest.py
index aa9d5e981..b5f2d1b4f 100644
--- a/Tools/Scripts/webkitpy/tool/steps/preparechangelogforrevert_unittest.py
+++ b/Tools/Scripts/webkitpy/tool/steps/preparechangelogforrevert_unittest.py
@@ -26,8 +26,6 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-from __future__ import with_statement
-
import codecs
import os
import tempfile
diff --git a/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj b/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj
index 6c403a844..ea44c5e38 100644
--- a/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj
+++ b/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj
@@ -41,13 +41,22 @@
52E5CE4614D21E9D003B2BD8 /* ParentFrame.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 52E5CE4514D21E9D003B2BD8 /* ParentFrame.cpp */; };
52E5CE4914D21EAB003B2BD8 /* ParentFrame_Bundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 52E5CE4814D21EAB003B2BD8 /* ParentFrame_Bundle.cpp */; };
81B50193140F232300D9EB58 /* StringBuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 81B50192140F232300D9EB58 /* StringBuilder.cpp */; };
+ 9361002914DC95A70061379D /* lots-of-iframes.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 9361002814DC957B0061379D /* lots-of-iframes.html */; };
939BA91714103412001A01BD /* DeviceScaleFactorOnBack.mm in Sources */ = {isa = PBXBuildFile; fileRef = 939BA91614103412001A01BD /* DeviceScaleFactorOnBack.mm */; };
+ 93F1DB3114DA20760024C362 /* NewFirstVisuallyNonEmptyLayout.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93F1DB3014DA20760024C362 /* NewFirstVisuallyNonEmptyLayout.cpp */; };
+ 93F1DB3414DA20870024C362 /* NewFirstVisuallyNonEmptyLayout_Bundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93F1DB3314DA20870024C362 /* NewFirstVisuallyNonEmptyLayout_Bundle.cpp */; };
+ 93F1DB5514DB1B730024C362 /* NewFirstVisuallyNonEmptyLayoutFails.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93F1DB5414DB1B730024C362 /* NewFirstVisuallyNonEmptyLayoutFails.cpp */; };
+ 93F1DB5714DB1B840024C362 /* NewFirstVisuallyNonEmptyLayoutFails_Bundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93F1DB5614DB1B840024C362 /* NewFirstVisuallyNonEmptyLayoutFails_Bundle.cpp */; };
+ 93F7E86C14DC8E4D00C84A99 /* NewFirstVisuallyNonEmptyLayoutFrames.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93F7E86B14DC8E4D00C84A99 /* NewFirstVisuallyNonEmptyLayoutFrames.cpp */; };
+ 93F7E86F14DC8E5C00C84A99 /* NewFirstVisuallyNonEmptyLayoutFrames_Bundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93F7E86E14DC8E5B00C84A99 /* NewFirstVisuallyNonEmptyLayoutFrames_Bundle.cpp */; };
A7A966DB140ECCC8005EF9B4 /* CheckedArithmeticOperations.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7A966DA140ECCC8005EF9B4 /* CheckedArithmeticOperations.cpp */; };
BC029B181486AD6400817DA9 /* RetainPtr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC029B161486AD6400817DA9 /* RetainPtr.cpp */; };
BC029B1C1486B25900817DA9 /* RetainPtr.mm in Sources */ = {isa = PBXBuildFile; fileRef = BC029B1B1486B25900817DA9 /* RetainPtr.mm */; };
BC131885117114B600B69727 /* PlatformUtilitiesMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = BC131884117114B600B69727 /* PlatformUtilitiesMac.mm */; };
BC131A9B1171316900B69727 /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = BC131A9A1171316900B69727 /* main.mm */; };
BC131AA9117131FC00B69727 /* TestsController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC131AA8117131FC00B69727 /* TestsController.cpp */; };
+ BC22D31514DC689800FFB1DD /* UserMessage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC22D31314DC689800FFB1DD /* UserMessage.cpp */; };
+ BC22D31914DC68B900FFB1DD /* UserMessage_Bundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC22D31714DC68B800FFB1DD /* UserMessage_Bundle.cpp */; };
BC246D8E132F115A00B56D7C /* AboutBlankLoad.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC246D8C132F115A00B56D7C /* AboutBlankLoad.cpp */; };
BC246D9A132F1FE100B56D7C /* CanHandleRequest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC246D98132F1FE100B56D7C /* CanHandleRequest.cpp */; };
BC246D9C132F1FF000B56D7C /* CanHandleRequest_Bundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC246D97132F1FE100B56D7C /* CanHandleRequest_Bundle.cpp */; };
@@ -108,6 +117,7 @@
C0C5D3BE14598B6F00A802A6 /* GetBackingScaleFactor.mm in Sources */ = {isa = PBXBuildFile; fileRef = C0C5D3BC14598B6F00A802A6 /* GetBackingScaleFactor.mm */; };
C0C5D3C61459912900A802A6 /* GetBackingScaleFactor_Bundle.mm in Sources */ = {isa = PBXBuildFile; fileRef = C0C5D3BD14598B6F00A802A6 /* GetBackingScaleFactor_Bundle.mm */; };
C507E8A714C6545B005D6B3B /* InspectorBar.mm in Sources */ = {isa = PBXBuildFile; fileRef = C507E8A614C6545B005D6B3B /* InspectorBar.mm */; };
+ E490296814E2E3A4002BEDD1 /* TypingStyleCrash.mm in Sources */ = {isa = PBXBuildFile; fileRef = E490296714E2E3A4002BEDD1 /* TypingStyleCrash.mm */; };
F3FC3EE313678B7300126A65 /* libgtest.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F3FC3EE213678B7300126A65 /* libgtest.a */; };
F6F3F29113342FEB00A6BF19 /* CookieManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F6F3F29013342FEB00A6BF19 /* CookieManager.cpp */; };
F6FDDDD314241AD4004F1729 /* PrivateBrowsingPushStateNoHistoryCallback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F6FDDDD214241AD4004F1729 /* PrivateBrowsingPushStateNoHistoryCallback.cpp */; };
@@ -143,6 +153,7 @@
33DC8912141955FE00747EF7 /* simple-iframe.html in Copy Resources */,
1A9E52C913E65EF4006917F5 /* 18-characters.html in Copy Resources */,
C07E6CB213FD73930038B22B /* devicePixelRatio.html in Copy Resources */,
+ 9361002914DC95A70061379D /* lots-of-iframes.html in Copy Resources */,
33E79E06137B5FD900E32D99 /* mouse-move-listener.html in Copy Resources */,
F6FDDDD614241C6F004F1729 /* push-state.html in Copy Resources */,
BCBD3737125ABBEB00D2C29F /* icon.png in Copy Resources */,
@@ -196,7 +207,14 @@
52E5CE4814D21EAB003B2BD8 /* ParentFrame_Bundle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ParentFrame_Bundle.cpp; sourceTree = "<group>"; };
81B50192140F232300D9EB58 /* StringBuilder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StringBuilder.cpp; path = WTF/StringBuilder.cpp; sourceTree = "<group>"; };
8DD76FA10486AA7600D96B5E /* TestWebKitAPI */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = TestWebKitAPI; sourceTree = BUILT_PRODUCTS_DIR; };
+ 9361002814DC957B0061379D /* lots-of-iframes.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "lots-of-iframes.html"; sourceTree = "<group>"; };
939BA91614103412001A01BD /* DeviceScaleFactorOnBack.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DeviceScaleFactorOnBack.mm; sourceTree = "<group>"; };
+ 93F1DB3014DA20760024C362 /* NewFirstVisuallyNonEmptyLayout.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NewFirstVisuallyNonEmptyLayout.cpp; sourceTree = "<group>"; };
+ 93F1DB3314DA20870024C362 /* NewFirstVisuallyNonEmptyLayout_Bundle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NewFirstVisuallyNonEmptyLayout_Bundle.cpp; sourceTree = "<group>"; };
+ 93F1DB5414DB1B730024C362 /* NewFirstVisuallyNonEmptyLayoutFails.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NewFirstVisuallyNonEmptyLayoutFails.cpp; sourceTree = "<group>"; };
+ 93F1DB5614DB1B840024C362 /* NewFirstVisuallyNonEmptyLayoutFails_Bundle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NewFirstVisuallyNonEmptyLayoutFails_Bundle.cpp; sourceTree = "<group>"; };
+ 93F7E86B14DC8E4D00C84A99 /* NewFirstVisuallyNonEmptyLayoutFrames.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NewFirstVisuallyNonEmptyLayoutFrames.cpp; sourceTree = "<group>"; };
+ 93F7E86E14DC8E5B00C84A99 /* NewFirstVisuallyNonEmptyLayoutFrames_Bundle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NewFirstVisuallyNonEmptyLayoutFrames_Bundle.cpp; sourceTree = "<group>"; };
A7A966DA140ECCC8005EF9B4 /* CheckedArithmeticOperations.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CheckedArithmeticOperations.cpp; path = WTF/CheckedArithmeticOperations.cpp; sourceTree = "<group>"; };
BC029B161486AD6400817DA9 /* RetainPtr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RetainPtr.cpp; sourceTree = "<group>"; };
BC029B1B1486B25900817DA9 /* RetainPtr.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = RetainPtr.mm; path = WTF/ns/RetainPtr.mm; sourceTree = "<group>"; };
@@ -205,6 +223,8 @@
BC131A9A1171316900B69727 /* main.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = main.mm; sourceTree = "<group>"; };
BC131A9E1171317C00B69727 /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = config.h; sourceTree = "<group>"; };
BC131AA8117131FC00B69727 /* TestsController.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; path = TestsController.cpp; sourceTree = "<group>"; };
+ BC22D31314DC689800FFB1DD /* UserMessage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UserMessage.cpp; sourceTree = "<group>"; };
+ BC22D31714DC68B800FFB1DD /* UserMessage_Bundle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UserMessage_Bundle.cpp; sourceTree = "<group>"; };
BC246D8C132F115A00B56D7C /* AboutBlankLoad.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AboutBlankLoad.cpp; sourceTree = "<group>"; };
BC246D97132F1FE100B56D7C /* CanHandleRequest_Bundle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CanHandleRequest_Bundle.cpp; sourceTree = "<group>"; };
BC246D98132F1FE100B56D7C /* CanHandleRequest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CanHandleRequest.cpp; sourceTree = "<group>"; };
@@ -277,6 +297,7 @@
C0C5D3BC14598B6F00A802A6 /* GetBackingScaleFactor.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = GetBackingScaleFactor.mm; sourceTree = "<group>"; };
C0C5D3BD14598B6F00A802A6 /* GetBackingScaleFactor_Bundle.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = GetBackingScaleFactor_Bundle.mm; sourceTree = "<group>"; };
C507E8A614C6545B005D6B3B /* InspectorBar.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = InspectorBar.mm; sourceTree = "<group>"; };
+ E490296714E2E3A4002BEDD1 /* TypingStyleCrash.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = TypingStyleCrash.mm; sourceTree = "<group>"; };
F3FC3EE213678B7300126A65 /* libgtest.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgtest.a; sourceTree = BUILT_PRODUCTS_DIR; };
F6F3F29013342FEB00A6BF19 /* CookieManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CookieManager.cpp; sourceTree = "<group>"; };
F6FDDDD214241AD4004F1729 /* PrivateBrowsingPushStateNoHistoryCallback.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PrivateBrowsingPushStateNoHistoryCallback.cpp; sourceTree = "<group>"; };
@@ -439,6 +460,12 @@
33DC89131419579F00747EF7 /* LoadCanceledNoServerRedirectCallback_Bundle.cpp */,
33BE5AF4137B5A6C00705813 /* MouseMoveAfterCrash.cpp */,
33BE5AF8137B5AAE00705813 /* MouseMoveAfterCrash_Bundle.cpp */,
+ 93F1DB3014DA20760024C362 /* NewFirstVisuallyNonEmptyLayout.cpp */,
+ 93F1DB3314DA20870024C362 /* NewFirstVisuallyNonEmptyLayout_Bundle.cpp */,
+ 93F1DB5414DB1B730024C362 /* NewFirstVisuallyNonEmptyLayoutFails.cpp */,
+ 93F1DB5614DB1B840024C362 /* NewFirstVisuallyNonEmptyLayoutFails_Bundle.cpp */,
+ 93F7E86B14DC8E4D00C84A99 /* NewFirstVisuallyNonEmptyLayoutFrames.cpp */,
+ 93F7E86E14DC8E5B00C84A99 /* NewFirstVisuallyNonEmptyLayoutFrames_Bundle.cpp */,
BC909779125571AB00083756 /* PageLoadBasic.cpp */,
BC2D004812A9FDFA00E732A3 /* PageLoadDidChangeLocationWithinPageForFrame.cpp */,
52E5CE4514D21E9D003B2BD8 /* ParentFrame.cpp */,
@@ -449,6 +476,8 @@
C0BD669E131D3CFF00E18F2A /* ResponsivenessTimerDoesntFireEarly_Bundle.cpp */,
C0ADBE8212FCA6AA00D2C129 /* RestoreSessionStateContainingFormData.cpp */,
C02B77F1126612140026BF0F /* SpacebarScrolling.cpp */,
+ BC22D31314DC689800FFB1DD /* UserMessage.cpp */,
+ BC22D31714DC68B800FFB1DD /* UserMessage_Bundle.cpp */,
520BCF4B141EB09E00937EA8 /* WebArchive.cpp */,
520BCF4A141EB09E00937EA8 /* WebArchive_Bundle.cpp */,
BC901E221492ADCE0074A667 /* WKConnection.cpp */,
@@ -487,6 +516,7 @@
BC2D004A12A9FEB300E732A3 /* file-with-anchor.html */,
1A02C84B125D4A5E00E3F4BD /* find.html */,
BCBD372E125ABBE600D2C29F /* icon.png */,
+ 9361002814DC957B0061379D /* lots-of-iframes.html */,
33E79E05137B5FCE00E32D99 /* mouse-move-listener.html */,
F6FDDDD514241C48004F1729 /* push-state.html */,
1ADBEFBC130C6A0100D61D19 /* simple-accelerated-compositing.html */,
@@ -541,6 +571,7 @@
3722C8681461E03E00C45D00 /* RenderedImageFromDOMRange.mm */,
3799AD3914120A43005EB0C6 /* StringByEvaluatingJavaScriptFromString.mm */,
37A6895D148A9B50005100FA /* SubresourceErrorCrash.mm */,
+ E490296714E2E3A4002BEDD1 /* TypingStyleCrash.mm */,
);
path = mac;
sourceTree = "<group>";
@@ -736,6 +767,11 @@
440A1D3914A0103A008A66F2 /* KURL.cpp in Sources */,
C507E8A714C6545B005D6B3B /* InspectorBar.mm in Sources */,
52E5CE4614D21E9D003B2BD8 /* ParentFrame.cpp in Sources */,
+ 93F1DB3114DA20760024C362 /* NewFirstVisuallyNonEmptyLayout.cpp in Sources */,
+ 93F1DB5514DB1B730024C362 /* NewFirstVisuallyNonEmptyLayoutFails.cpp in Sources */,
+ 93F7E86C14DC8E4D00C84A99 /* NewFirstVisuallyNonEmptyLayoutFrames.cpp in Sources */,
+ BC22D31514DC689800FFB1DD /* UserMessage.cpp in Sources */,
+ E490296814E2E3A4002BEDD1 /* TypingStyleCrash.mm in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -759,6 +795,10 @@
C0C5D3C61459912900A802A6 /* GetBackingScaleFactor_Bundle.mm in Sources */,
BC901E331492AF390074A667 /* WKConnection_Bundle.cpp in Sources */,
52E5CE4914D21EAB003B2BD8 /* ParentFrame_Bundle.cpp in Sources */,
+ 93F1DB3414DA20870024C362 /* NewFirstVisuallyNonEmptyLayout_Bundle.cpp in Sources */,
+ 93F1DB5714DB1B840024C362 /* NewFirstVisuallyNonEmptyLayoutFails_Bundle.cpp in Sources */,
+ 93F7E86F14DC8E5C00C84A99 /* NewFirstVisuallyNonEmptyLayoutFrames_Bundle.cpp in Sources */,
+ BC22D31914DC68B900FFB1DD /* UserMessage_Bundle.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayout.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayout.cpp
new file mode 100644
index 000000000..d4939ce67
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayout.cpp
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "PlatformUtilities.h"
+#include "PlatformWebView.h"
+#include <WebKit2/WKContextPrivate.h>
+
+namespace TestWebKitAPI {
+
+static bool didNewFirstVisuallyNonEmptyLayoutSucceed;
+
+static void didNewFirstVisuallyNonEmptyLayout(WKPageRef, WKTypeRef, const void *)
+{
+ didNewFirstVisuallyNonEmptyLayoutSucceed = true;
+}
+
+static void setPageLoaderClient(WKPageRef page)
+{
+ WKPageLoaderClient loaderClient;
+ memset(&loaderClient, 0, sizeof(loaderClient));
+ loaderClient.version = kWKPageLoaderClientCurrentVersion;
+ loaderClient.didNewFirstVisuallyNonEmptyLayout = didNewFirstVisuallyNonEmptyLayout;
+
+ WKPageSetPageLoaderClient(page, &loaderClient);
+}
+
+TEST(WebKit2, NewFirstVisuallyNonEmptyLayout)
+{
+ WKRetainPtr<WKContextRef> context(AdoptWK, Util::createContextForInjectedBundleTest("NewFirstVisuallyNonEmptyLayoutTest"));
+
+ PlatformWebView webView(context.get());
+ setPageLoaderClient(webView.page());
+
+ WKPageLoadURL(webView.page(), adoptWK(Util::createURLForResource("simple", "html")).get());
+
+ Util::run(&didNewFirstVisuallyNonEmptyLayoutSucceed);
+ EXPECT_TRUE(didNewFirstVisuallyNonEmptyLayoutSucceed);
+}
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFails.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFails.cpp
new file mode 100644
index 000000000..b651ed43d
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFails.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "PlatformUtilities.h"
+#include "PlatformWebView.h"
+#include "Test.h"
+#include <WebKit2/WKContextPrivate.h>
+#include <WebKit2/WKRetainPtr.h>
+
+namespace TestWebKitAPI {
+
+static bool didNewFirstVisuallyNonEmptyLayoutSucceed;
+static bool test1Done;
+static bool test2Done;
+
+static void didForceRepaint(WKErrorRef error, void*)
+{
+ EXPECT_NULL(error);
+ test2Done = true;
+}
+
+static void didFinishLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void* clientInfo)
+{
+ test1Done = true;
+ WKPageForceRepaint(page, 0, didForceRepaint);
+}
+
+static void didNewFirstVisuallyNonEmptyLayout(WKPageRef, WKTypeRef, const void *)
+{
+ didNewFirstVisuallyNonEmptyLayoutSucceed = true;
+}
+
+static void setPageLoaderClient(WKPageRef page)
+{
+ WKPageLoaderClient loaderClient;
+ memset(&loaderClient, 0, sizeof(loaderClient));
+ loaderClient.version = kWKPageLoaderClientCurrentVersion;
+ loaderClient.didFinishLoadForFrame = didFinishLoadForFrame;
+ loaderClient.didNewFirstVisuallyNonEmptyLayout = didNewFirstVisuallyNonEmptyLayout;
+
+ WKPageSetPageLoaderClient(page, &loaderClient);
+}
+
+TEST(WebKit2, NewFirstVisuallyNonEmptyLayoutFails)
+{
+ WKRetainPtr<WKContextRef> context(AdoptWK, Util::createContextForInjectedBundleTest("NewFirstVisuallyNonEmptyLayoutFailsTest"));
+
+ PlatformWebView webView(context.get());
+ setPageLoaderClient(webView.page());
+
+ WKPageLoadURL(webView.page(), adoptWK(Util::createURLForResource("simple", "html")).get());
+
+ Util::run(&test1Done);
+ Util::run(&test2Done);
+
+ // By the time the forced repaint has finished, the counter would have been hit
+ // if it was sized reasonably for the page.
+ EXPECT_FALSE(didNewFirstVisuallyNonEmptyLayoutSucceed);
+}
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFails_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFails_Bundle.cpp
new file mode 100644
index 000000000..5d6848e7c
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFails_Bundle.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "InjectedBundleTest.h"
+
+#include "PlatformUtilities.h"
+#include <WebKit2/WKBundlePage.h>
+#include <WebKit2/WKBundlePagePrivate.h>
+
+namespace TestWebKitAPI {
+
+class NewFirstVisuallyNonEmptyLayoutFailsTest : public InjectedBundleTest {
+public:
+ NewFirstVisuallyNonEmptyLayoutFailsTest(const std::string& identifier)
+ : InjectedBundleTest(identifier)
+ {
+ }
+
+ virtual void didCreatePage(WKBundleRef bundle, WKBundlePageRef page)
+ {
+ // Set the painted objects counter to something huge that should not
+ // cause didNewFirstVisuallyNonEmptyLayout to fire.
+ WKBundlePageSetPaintedObjectsCounterThreshold(page, 1000);
+ }
+
+};
+
+static InjectedBundleTest::Register<NewFirstVisuallyNonEmptyLayoutFailsTest> registrar("NewFirstVisuallyNonEmptyLayoutFailsTest");
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFrames.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFrames.cpp
new file mode 100644
index 000000000..d9f61d40b
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFrames.cpp
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "PlatformUtilities.h"
+#include "PlatformWebView.h"
+#include "Test.h"
+#include <WebKit2/WKContextPrivate.h>
+#include <WebKit2/WKRetainPtr.h>
+
+namespace TestWebKitAPI {
+
+static bool didNewFirstVisuallyNonEmptyLayoutFireMoreThanOnce;
+static unsigned newVisuallyNonEmptyLayoutCounter;
+static bool test1Done;
+static bool test2Done;
+
+static void didForceRepaint(WKErrorRef error, void*)
+{
+ EXPECT_NULL(error);
+ test2Done = true;
+}
+
+static void didFinishLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void* clientInfo)
+{
+ test1Done = true;
+ WKPageForceRepaint(page, 0, didForceRepaint);
+}
+
+static void didNewFirstVisuallyNonEmptyLayout(WKPageRef, WKTypeRef, const void *)
+{
+ ++newVisuallyNonEmptyLayoutCounter;
+ if (newVisuallyNonEmptyLayoutCounter > 1)
+ didNewFirstVisuallyNonEmptyLayoutFireMoreThanOnce = true;
+}
+
+static void setPageLoaderClient(WKPageRef page)
+{
+ WKPageLoaderClient loaderClient;
+ memset(&loaderClient, 0, sizeof(loaderClient));
+ loaderClient.version = kWKPageLoaderClientCurrentVersion;
+ loaderClient.didFinishLoadForFrame = didFinishLoadForFrame;
+ loaderClient.didNewFirstVisuallyNonEmptyLayout = didNewFirstVisuallyNonEmptyLayout;
+
+ WKPageSetPageLoaderClient(page, &loaderClient);
+}
+
+TEST(WebKit2, NewFirstVisuallyNonEmptyLayoutFrames)
+{
+ newVisuallyNonEmptyLayoutCounter = 0;
+ WKRetainPtr<WKContextRef> context(AdoptWK, Util::createContextForInjectedBundleTest("NewFirstVisuallyNonEmptyLayoutFramesTest"));
+
+ PlatformWebView webView(context.get());
+ setPageLoaderClient(webView.page());
+
+ WKPageLoadURL(webView.page(), adoptWK(Util::createURLForResource("lots-of-iframes", "html")).get());
+
+ Util::run(&test1Done);
+ Util::run(&test2Done);
+
+ // By the time the forced repaint has finished, the counter would have been hit
+ // if it was sized reasonably for the page.
+ EXPECT_FALSE(didNewFirstVisuallyNonEmptyLayoutFireMoreThanOnce);
+}
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFrames_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFrames_Bundle.cpp
new file mode 100644
index 000000000..8ee8b27e2
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFrames_Bundle.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "InjectedBundleTest.h"
+
+#include "PlatformUtilities.h"
+#include <WebKit2/WKBundlePage.h>
+#include <WebKit2/WKBundlePagePrivate.h>
+
+namespace TestWebKitAPI {
+
+class NewFirstVisuallyNonEmptyLayoutFramesTest : public InjectedBundleTest {
+public:
+ NewFirstVisuallyNonEmptyLayoutFramesTest(const std::string& identifier)
+ : InjectedBundleTest(identifier)
+ {
+ }
+
+ virtual void didCreatePage(WKBundleRef bundle, WKBundlePageRef page)
+ {
+ // Set the painted objects counter to something small that will
+ // cause didNewFirstVisuallyNonEmptyLayout to fire.
+ WKBundlePageSetPaintedObjectsCounterThreshold(page, 1);
+ }
+
+};
+
+static InjectedBundleTest::Register<NewFirstVisuallyNonEmptyLayoutFramesTest> registrar("NewFirstVisuallyNonEmptyLayoutFramesTest");
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayout_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayout_Bundle.cpp
new file mode 100644
index 000000000..efeddc01e
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayout_Bundle.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "InjectedBundleTest.h"
+
+#include "PlatformUtilities.h"
+#include <WebKit2/WKBundlePage.h>
+#include <WebKit2/WKBundlePagePrivate.h>
+
+namespace TestWebKitAPI {
+
+class NewFirstVisuallyNonEmptyLayoutTest : public InjectedBundleTest {
+public:
+ NewFirstVisuallyNonEmptyLayoutTest(const std::string& identifier)
+ : InjectedBundleTest(identifier)
+ {
+ }
+
+ virtual void didCreatePage(WKBundleRef bundle, WKBundlePageRef page)
+ {
+ // Set the painted objects counter to something low that should definintely
+ // cause didNewFirstVisuallyNonEmptyLayout to fire.
+ WKBundlePageSetPaintedObjectsCounterThreshold(page, 1);
+ }
+
+};
+
+static InjectedBundleTest::Register<NewFirstVisuallyNonEmptyLayoutTest> registrar("NewFirstVisuallyNonEmptyLayoutTest");
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/UserMessage.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/UserMessage.cpp
new file mode 100644
index 000000000..bc02dc878
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/UserMessage.cpp
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "Test.h"
+
+#include "PlatformUtilities.h"
+#include "PlatformWebView.h"
+#include <wtf/OwnPtr.h>
+#include <wtf/PassOwnPtr.h>
+
+namespace TestWebKitAPI {
+
+class WebKit2UserMessageRoundTripTest : public ::testing::Test {
+public:
+ WebKit2UserMessageRoundTripTest()
+ : didFinishLoad(false)
+ , didReceiveMessage(false)
+ {
+ }
+
+ WKRetainPtr<WKContextRef> context;
+ OwnPtr<PlatformWebView> webView;
+
+ WKRetainPtr<WKTypeRef> recievedBody;
+
+ bool didFinishLoad;
+ bool didReceiveMessage;
+
+ static void didReceiveMessageFromInjectedBundle(WKContextRef, WKStringRef messageName, WKTypeRef messageBody, const void* clientInfo)
+ {
+ if (!WKStringIsEqualToUTF8CString(messageName, "RoundTripReturn"))
+ return;
+
+ ((WebKit2UserMessageRoundTripTest*)clientInfo)->recievedBody = messageBody;
+ ((WebKit2UserMessageRoundTripTest*)clientInfo)->didReceiveMessage = true;
+ }
+
+ static void didFinishLoadForFrame(WKPageRef, WKFrameRef, WKTypeRef, const void* clientInfo)
+ {
+ ((WebKit2UserMessageRoundTripTest*)clientInfo)->didFinishLoad = true;
+ }
+
+ static void setInjectedBundleClient(WKContextRef context, const void* clientInfo)
+ {
+ WKContextInjectedBundleClient injectedBundleClient;
+ memset(&injectedBundleClient, 0, sizeof(injectedBundleClient));
+ injectedBundleClient.version = kWKContextInjectedBundleClientCurrentVersion;
+ injectedBundleClient.clientInfo = clientInfo;
+ injectedBundleClient.didReceiveMessageFromInjectedBundle = didReceiveMessageFromInjectedBundle;
+
+ WKContextSetInjectedBundleClient(context, &injectedBundleClient);
+ }
+
+ static void setPageLoaderClient(WKPageRef page, const void* clientInfo)
+ {
+ WKPageLoaderClient loaderClient;
+ memset(&loaderClient, 0, sizeof(loaderClient));
+ loaderClient.version = kWKPageLoaderClientCurrentVersion;
+ loaderClient.clientInfo = clientInfo;
+ loaderClient.didFinishLoadForFrame = didFinishLoadForFrame;
+
+ WKPageSetPageLoaderClient(page, &loaderClient);
+ }
+
+ virtual void SetUp()
+ {
+ context = adoptWK(Util::createContextForInjectedBundleTest("UserMessageTest"));
+ setInjectedBundleClient(context.get(), this);
+
+ webView = adoptPtr(new PlatformWebView(context.get()));
+ setPageLoaderClient(webView->page(), this);
+
+ didFinishLoad = false;
+ didReceiveMessage = false;
+
+ // Force the creation of the
+ WKPageLoadURL(webView->page(), adoptWK(Util::createURLForResource("simple", "html")).get());
+ Util::run(&didFinishLoad);
+
+ }
+
+ // Used to test sending a WKType round trip to the WebProcess and back.
+ // Result is stored into the recievedBody member variable.
+ void roundTrip(WKTypeRef object)
+ {
+ WKTypeID storedTypeID = WKGetTypeID(object);
+
+ recievedBody.clear();
+ didReceiveMessage = false;
+ WKContextPostMessageToInjectedBundle(context.get(), Util::toWK("RoundTrip").get(), object);
+ Util::run(&didReceiveMessage);
+
+ EXPECT_NOT_NULL(recievedBody);
+ EXPECT_EQ(storedTypeID, WKGetTypeID(recievedBody.get()));
+ }
+};
+
+
+TEST_F(WebKit2UserMessageRoundTripTest, WKURLRequestRef)
+{
+ WKRetainPtr<WKURLRef> url = adoptWK(WKURLCreateWithUTF8CString("http://webkit.org/"));
+ WKRetainPtr<WKURLRequestRef> request = adoptWK(WKURLRequestCreateWithWKURL(url.get()));
+
+ roundTrip(request.get());
+ WKTypeRef roundTrippedTypeRef = recievedBody.get();
+
+ WKRetainPtr<WKURLRequestRef> roundTrippedRequest = static_cast<WKURLRequestRef>(roundTrippedTypeRef);
+ WKRetainPtr<WKURLRef> roundTrippedURL = adoptWK(WKURLRequestCopyURL(roundTrippedRequest.get()));
+ EXPECT_TRUE(WKURLIsEqual(roundTrippedURL.get(), url.get()));
+}
+
+TEST_F(WebKit2UserMessageRoundTripTest, WKURL)
+{
+ WKRetainPtr<WKURLRef> url = adoptWK(WKURLCreateWithUTF8CString("http://webkit.org/"));
+
+ roundTrip(url.get());
+ WKTypeRef roundTrippedTypeRef = recievedBody.get();
+
+ WKRetainPtr<WKURLRef> roundTrippedURL = static_cast<WKURLRef>(roundTrippedTypeRef);
+ EXPECT_TRUE(WKURLIsEqual(roundTrippedURL.get(), url.get()));
+}
+
+TEST_F(WebKit2UserMessageRoundTripTest, WKString)
+{
+ WKRetainPtr<WKStringRef> string = adoptWK(WKStringCreateWithUTF8CString("An important string"));
+
+ roundTrip(string.get());
+ WKTypeRef roundTrippedTypeRef = recievedBody.get();
+
+ WKRetainPtr<WKStringRef> roundTrippedString = static_cast<WKStringRef>(roundTrippedTypeRef);
+ EXPECT_TRUE(WKStringIsEqual(roundTrippedString.get(), string.get()));
+}
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/UserMessage_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/UserMessage_Bundle.cpp
new file mode 100644
index 000000000..29ede3d83
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/UserMessage_Bundle.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "InjectedBundleTest.h"
+
+#include "PlatformUtilities.h"
+
+namespace TestWebKitAPI {
+
+class UserMessageTest : public InjectedBundleTest {
+public:
+ UserMessageTest(const std::string& identifier)
+ : InjectedBundleTest(identifier)
+ {
+ }
+
+private:
+ virtual void didReceiveMessage(WKBundleRef bundle, WKStringRef messageName, WKTypeRef messageBody)
+ {
+ if (!WKStringIsEqualToUTF8CString(messageName, "RoundTrip"))
+ return;
+
+ WKBundlePostMessage(bundle, Util::toWK("RoundTripReturn").get(), messageBody);
+ }
+};
+
+static InjectedBundleTest::Register<UserMessageTest> registrar("UserMessageTest");
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/WKPreferences.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/WKPreferences.cpp
index 8a0a7cfc5..2a181ddea 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/WKPreferences.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/WKPreferences.cpp
@@ -97,4 +97,18 @@ TEST(WebKit2, WKPreferencesDefaults)
WKRelease(preference);
}
+TEST(WebKit2, WKPreferencesCopying)
+{
+ WKRetainPtr<WKStringRef> identifier(AdoptWK, WKStringCreateWithUTF8CString("identifier"));
+
+ WKRetainPtr<WKPreferencesRef> preferences(AdoptWK, WKPreferencesCreateWithIdentifier(identifier.get()));
+ WKPreferencesSetDefaultFontSize(preferences.get(), 36);
+
+ WKRetainPtr<WKPreferencesRef> copy(AdoptWK, WKPreferencesCreateCopy(preferences.get()));
+
+ WKPreferencesSetDefaultFontSize(preferences.get(), 24);
+ EXPECT_EQ(24u, WKPreferencesGetDefaultFontSize(preferences.get()));
+ EXPECT_EQ(36u, WKPreferencesGetDefaultFontSize(copy.get()));
+}
+
} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/lots-of-iframes.html b/Tools/TestWebKitAPI/Tests/WebKit2/lots-of-iframes.html
new file mode 100644
index 000000000..5436310c8
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/lots-of-iframes.html
@@ -0,0 +1,35 @@
+<html>
+<head>
+<script type="text/javascript">
+ var maxNumberOfFrames = 100;
+
+ function createIFrames() {
+ var str = "<div id=\"status\"></div>";
+ for (var i = 0; i < maxNumberOfFrames + 1; i++) {
+ str += "<iframe id=\"i" + i + "\" src=\"data:text/html,iframe_" + i + "\"></iframe>";
+ }
+ document.getElementsByTagName("body")[0].innerHTML = str;
+
+ var results = "";
+
+ var f = document.getElementById("i" + (maxNumberOfFrames - 1));
+ if (f && f.contentWindow) {
+ results += "Sucessfully created " + maxNumberOfFrames + " frames.<br>";
+ } else {
+ results += "Failed to create " + maxNumberOfFrames + " frames.<br>";
+ }
+
+ var g = document.getElementById("i" + maxNumberOfFrames);
+ if (g && g.contentWindow) {
+ results += "Failed to block creation of frame number " + (maxNumberOfFrames + 1) + ".";
+ } else {
+ results += "Successfully blocked creation of frame number " + (maxNumberOfFrames + 1) + ".";
+ }
+
+ document.getElementById("status").innerHTML = results;
+ }
+</script>
+</head>
+<body onLoad="createIFrames()">
+</body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/mac/TypingStyleCrash.mm b/Tools/TestWebKitAPI/Tests/mac/TypingStyleCrash.mm
new file mode 100644
index 000000000..a23623bb0
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/mac/TypingStyleCrash.mm
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+namespace TestWebKitAPI {
+
+TEST(WebKit1, TypingStyleCrash)
+{
+ WebView *webView = [[WebView alloc] init];
+ [webView typingStyle];
+ [webView release];
+}
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/mac/PlatformWebViewMac.mm b/Tools/TestWebKitAPI/mac/PlatformWebViewMac.mm
index 7e3dce4f1..1661074b2 100644
--- a/Tools/TestWebKitAPI/mac/PlatformWebViewMac.mm
+++ b/Tools/TestWebKitAPI/mac/PlatformWebViewMac.mm
@@ -55,11 +55,6 @@ PlatformWebView::PlatformWebView(WKContextRef contextRef, WKPageGroupRef pageGro
[m_window setReleasedWhenClosed:NO];
}
-void PlatformWebView::resizeTo(unsigned width, unsigned height)
-{
- [m_view setFrame:NSMakeRect(0, 0, width, height)];
-}
-
PlatformWebView::~PlatformWebView()
{
[m_window close];
@@ -67,6 +62,12 @@ PlatformWebView::~PlatformWebView()
[m_view release];
}
+void PlatformWebView::resizeTo(unsigned width, unsigned height)
+{
+ [m_view setFrame:NSMakeRect(0, 0, width, height)];
+}
+
+
WKPageRef PlatformWebView::page() const
{
return [m_view pageRef];
diff --git a/Tools/TestWebKitAPI/win/TestWebKitAPI.vcproj b/Tools/TestWebKitAPI/win/TestWebKitAPI.vcproj
index ca5b753e7..000f15e18 100644
--- a/Tools/TestWebKitAPI/win/TestWebKitAPI.vcproj
+++ b/Tools/TestWebKitAPI/win/TestWebKitAPI.vcproj
@@ -560,6 +560,10 @@
>
</File>
<File
+ RelativePath="..\Tests\WebKit2\UserMessage.cpp"
+ >
+ </File>
+ <File
RelativePath="..\Tests\WebKit2\WebArchive.cpp"
>
</File>
diff --git a/Tools/TestWebKitAPI/win/TestWebKitAPIInjectedBundle.vcproj b/Tools/TestWebKitAPI/win/TestWebKitAPIInjectedBundle.vcproj
index b05ca8318..c1ed01d00 100644
--- a/Tools/TestWebKitAPI/win/TestWebKitAPIInjectedBundle.vcproj
+++ b/Tools/TestWebKitAPI/win/TestWebKitAPIInjectedBundle.vcproj
@@ -432,6 +432,10 @@
>
</File>
<File
+ RelativePath="..\Tests\WebKit2\UserMessage_Bundle.cpp"
+ >
+ </File>
+ <File
RelativePath="..\Tests\WebKit2\WebArchive_Bundle.cpp"
>
</File>
diff --git a/Tools/Tools.pro b/Tools/Tools.pro
index 27a2537d6..4e7414fef 100644
--- a/Tools/Tools.pro
+++ b/Tools/Tools.pro
@@ -14,8 +14,8 @@ SUBDIRS += DumpRenderTree/qt/DumpRenderTree.pro
SUBDIRS += DumpRenderTree/qt/ImageDiff.pro
!no_webkit2 {
- SUBDIRS += MiniBrowser/qt/MiniBrowser.pro
- linux-g++*: SUBDIRS += WebKitTestRunner/WebKitTestRunner.pro
+ SUBDIRS += MiniBrowser/qt/MiniBrowser.pro \
+ WebKitTestRunner/WebKitTestRunner.pro
}
!win32:contains(DEFINES, ENABLE_NETSCAPE_PLUGIN_API=1) {
diff --git a/Tools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp b/Tools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp
index 25a6d9233..84f90d804 100644
--- a/Tools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp
+++ b/Tools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp
@@ -227,7 +227,9 @@ InjectedBundlePage::InjectedBundlePage(WKBundlePageRef page)
didReceiveResponseForResource,
didReceiveContentLengthForResource,
didFinishLoadForResource,
- didFailLoadForResource
+ didFailLoadForResource,
+ 0, // shouldCacheResponse
+ 0 // shouldUseCredentialStorage
};
WKBundlePageSetResourceLoadClient(m_page, &resourceLoadClient);
diff --git a/Tools/WebKitTestRunner/TestController.cpp b/Tools/WebKitTestRunner/TestController.cpp
index 0e5db19cf..db6e914f8 100644
--- a/Tools/WebKitTestRunner/TestController.cpp
+++ b/Tools/WebKitTestRunner/TestController.cpp
@@ -63,6 +63,7 @@ TestController& TestController::shared()
TestController::TestController(int argc, const char* argv[])
: m_dumpPixels(false)
+ , m_skipPixelTestOption(false)
, m_verbose(false)
, m_printSeparators(false)
, m_usingServerMode(false)
@@ -246,6 +247,12 @@ void TestController::initialize(int argc, const char* argv[])
m_shortTimeout = defaultShortTimeout * m_longTimeout / defaultLongTimeout;
continue;
}
+
+ if (argument == "--skip-pixel-test-if-no-baseline") {
+ m_skipPixelTestOption = true;
+ continue;
+ }
+
if (argument == "--pixel-tests") {
m_dumpPixels = true;
continue;
@@ -489,6 +496,7 @@ bool TestController::runTest(const char* test)
m_state = RunningTest;
m_currentInvocation = adoptPtr(new TestInvocation(pathOrURL));
+ m_currentInvocation->setSkipPixelTestOption(m_skipPixelTestOption);
if (m_dumpPixels)
m_currentInvocation->setIsPixelTest(expectedPixelHash);
diff --git a/Tools/WebKitTestRunner/TestController.h b/Tools/WebKitTestRunner/TestController.h
index d0d21514e..32b4ade4b 100644
--- a/Tools/WebKitTestRunner/TestController.h
+++ b/Tools/WebKitTestRunner/TestController.h
@@ -104,6 +104,7 @@ private:
OwnPtr<TestInvocation> m_currentInvocation;
bool m_dumpPixels;
+ bool m_skipPixelTestOption;
bool m_verbose;
bool m_printSeparators;
bool m_usingServerMode;
diff --git a/Tools/WebKitTestRunner/TestInvocation.cpp b/Tools/WebKitTestRunner/TestInvocation.cpp
index 8e3c22957..42a88512c 100644
--- a/Tools/WebKitTestRunner/TestInvocation.cpp
+++ b/Tools/WebKitTestRunner/TestInvocation.cpp
@@ -93,6 +93,7 @@ TestInvocation::TestInvocation(const std::string& pathOrURL)
: m_url(AdoptWK, createWKURL(pathOrURL.c_str()))
, m_pathOrURL(pathOrURL)
, m_dumpPixels(false)
+ , m_skipPixelTestOption(false)
, m_gotInitialResponse(false)
, m_gotFinalMessage(false)
, m_gotRepaint(false)
@@ -106,6 +107,8 @@ TestInvocation::~TestInvocation()
void TestInvocation::setIsPixelTest(const std::string& expectedPixelHash)
{
+ if (m_skipPixelTestOption && !expectedPixelHash.length())
+ return;
m_dumpPixels = true;
m_expectedPixelHash = expectedPixelHash;
}
diff --git a/Tools/WebKitTestRunner/TestInvocation.h b/Tools/WebKitTestRunner/TestInvocation.h
index 5ff7ea0a8..af9f38fc0 100644
--- a/Tools/WebKitTestRunner/TestInvocation.h
+++ b/Tools/WebKitTestRunner/TestInvocation.h
@@ -39,7 +39,8 @@ public:
~TestInvocation();
void setIsPixelTest(const std::string& expectedPixelHash);
-
+ void setSkipPixelTestOption(bool option) { m_skipPixelTestOption = option; }
+
void invoke();
void didReceiveMessageFromInjectedBundle(WKStringRef messageName, WKTypeRef messageBody);
WKRetainPtr<WKTypeRef> didReceiveSynchronousMessageFromInjectedBundle(WKStringRef messageName, WKTypeRef messageBody);
@@ -54,6 +55,7 @@ private:
bool m_dumpPixels;
std::string m_expectedPixelHash;
+ bool m_skipPixelTestOption;
// Invocation state
bool m_gotInitialResponse;
diff --git a/Tools/WebKitTestRunner/qt/PlatformWebViewQt.cpp b/Tools/WebKitTestRunner/qt/PlatformWebViewQt.cpp
index 425991324..1c3cf697a 100644
--- a/Tools/WebKitTestRunner/qt/PlatformWebViewQt.cpp
+++ b/Tools/WebKitTestRunner/qt/PlatformWebViewQt.cpp
@@ -75,7 +75,6 @@ PlatformWebView::PlatformWebView(WKContextRef contextRef, WKPageGroupRef pageGro
, m_modalEventLoop(0)
{
QQuickWebViewExperimental experimental(m_view);
- experimental.setUseTraditionalDesktopBehaviour(true);
experimental.setRenderToOffscreenBuffer(true);
}
diff --git a/Tools/WebKitTestRunner/qt/main.cpp b/Tools/WebKitTestRunner/qt/main.cpp
index bdbafd4c9..6c447bda5 100644
--- a/Tools/WebKitTestRunner/qt/main.cpp
+++ b/Tools/WebKitTestRunner/qt/main.cpp
@@ -27,6 +27,7 @@
#include "config.h"
#include "TestController.h"
+#include "qquickwebview_p.h"
#include <stdio.h>
@@ -91,6 +92,7 @@ int main(int argc, char** argv)
qputenv("QT_WEBKIT_SUPPRESS_WEB_PROCESS_OUTPUT", "1");
}
+ QQuickWebViewExperimental::setFlickableViewportEnabled(false);
QApplication app(argc, argv);
Launcher launcher(argc, argv);
QTimer::singleShot(0, &launcher, SLOT(launch()));
diff --git a/Tools/gtk/common.py b/Tools/gtk/common.py
index 7941e1300..2a5ea375b 100644
--- a/Tools/gtk/common.py
+++ b/Tools/gtk/common.py
@@ -42,6 +42,15 @@ def get_build_path():
def is_valid_build_directory(path):
return os.path.exists(os.path.join(path, 'GNUmakefile'))
+ # Debian and Ubuntu build both flavours of the library (with gtk2
+ # and with gtk3); they use directories build-2.0 and build-3.0 for
+ # that, which is not handled by the above cases; we check that the
+ # directory where we are called from is a valid build directory,
+ # which should handle pretty much all other non-standard cases.
+ build_dir = os.getcwd()
+ if is_valid_build_directory(build_dir):
+ return build_dir
+
build_types = ['Release', 'Debug']
if '--debug' in sys.argv:
build_types.reverse()
@@ -76,3 +85,22 @@ def number_of_cpus():
process = subprocess.Popen([script_path('num-cpus')], stdout=subprocess.PIPE)
stdout = process.communicate()[0]
return int(stdout)
+
+
+def prefix_of_pkg_config_file(package):
+ process = subprocess.Popen(['pkg-config', '--variable=prefix', package],
+ stdout=subprocess.PIPE)
+ stdout = process.communicate()[0]
+ if process.returncode != 0:
+ return None
+ return stdout.strip()
+
+
+def gtk_version_of_pkg_config_file(pkg_config_path):
+ process = subprocess.Popen(['pkg-config', pkg_config_path, '--print-requires'],
+ stdout=subprocess.PIPE)
+ stdout = process.communicate()[0]
+
+ if 'gtk+-3.0' in stdout:
+ return 3
+ return 2
diff --git a/Tools/gtk/generate-gtkdoc b/Tools/gtk/generate-gtkdoc
index 2b8c6eac7..04f0bda2d 100755
--- a/Tools/gtk/generate-gtkdoc
+++ b/Tools/gtk/generate-gtkdoc
@@ -34,11 +34,42 @@ def configure_logging():
else:
handler.setFormatter(logging.Formatter('%(message)s'))
+
+def get_gtkdoc_module_paths(xref_dep_packages):
+ deps = []
+ html_dir = os.path.join('share', 'gtk-doc', 'html')
+
+ for package in xref_dep_packages:
+ prefix = common.prefix_of_pkg_config_file(package)
+ if prefix is None:
+ continue
+ for module in xref_dep_packages[package]:
+ deps.append(os.path.join(prefix, html_dir, module))
+
+ return deps
+
+
def get_common_options():
+ # TODO: We should consider using an arguments parsing library if
+ # we need more of these complex ones.
+ virtual_root = ''
+ for argument in sys.argv:
+ if argument.startswith('--virtual-root='):
+ virtual_root = argument.split('=')[1]
+ break
+
return {
'decorator': 'WEBKIT_API',
'deprecation_guard': 'WEBKIT_DISABLE_DEPRECATED',
'library_path' : common.build_path('.libs'),
+ 'virtual_root' : virtual_root,
+ }
+
+def get_common_xref_deps():
+ return {
+ 'glib-2.0' : ['glib', 'gobject', 'gio'],
+ 'libsoup-2.4' : ['libsoup-2.4'],
+ 'gdk-pixbuf-2.0': ['gdk-pixbuf']
}
def get_webkit2_options():
@@ -47,6 +78,11 @@ def get_webkit2_options():
def src_path(*args):
return common.top_level_path(*(('Source', 'WebKit2', 'UIProcess', 'API', 'gtk') + args))
+ xref_deps = get_common_xref_deps().copy()
+ xref_deps.update({
+ 'gtk+-3.0' : ['gtk3', 'gdk3']
+ })
+
options = get_common_options().copy()
options.update({
'module_name' : 'webkit2gtk',
@@ -58,6 +94,7 @@ def get_webkit2_options():
' -I' + derived_sources_path('include') + \
' -I' + common.top_level_path('Source') + \
' -I' + src_path(),
+ 'cross_reference_deps' : get_gtkdoc_module_paths(xref_deps),
'ignored_files': glob.glob(src_path('*Private.h')) + \
glob.glob(src_path('*Client*')) + \
glob.glob(src_path('WebKitWebViewBaseAccessible.*')) + \
@@ -65,10 +102,20 @@ def get_webkit2_options():
})
return options
-def get_webkit1_options():
+def get_webkit1_options(gtk_version):
def src_path(*args):
return common.top_level_path(*(('Source', 'WebKit', 'gtk') + args))
+ xref_deps = get_common_xref_deps().copy()
+ if gtk_version == 3:
+ xref_deps.update({
+ 'gtk+-3.0' : ['gtk3', 'gdk3']
+ })
+ else:
+ xref_deps.update({
+ 'gtk+-2.0' : ['gtk', 'gdk']
+ })
+
options = get_common_options().copy()
options.update({
'module_name' : 'webkitgtk',
@@ -80,7 +127,9 @@ def get_webkit1_options():
' -I' + src_path() + \
' -I' + common.top_level_path('Source') + \
' -I' + common.top_level_path('Source', 'JavaScriptCore', 'ForwardingHeaders'),
- 'ignored_files': glob.glob(src_path('webkit', '*private.*'))
+ 'cross_reference_deps' : get_gtkdoc_module_paths(xref_deps),
+ 'ignored_files': glob.glob(src_path('webkit', '*private.*')) + \
+ glob.glob(src_path('webkit', 'webkitspellcheckerenchant.*'))
})
return options
@@ -89,6 +138,10 @@ def generate_doc(pkg_config_path, options):
generator.generate(html='--skip-html' not in sys.argv)
return generator.saw_warnings
+def rebase_installed_docs(pkg_config_path, options):
+ generator = gtkdoc.PkgConfigGTKDoc(pkg_config_path, options)
+ generator.rebase_installed_docs()
+
configure_logging()
# We need to add the JavaScriptCore build directory to the PKG_CONFIG_PATH
@@ -102,15 +155,25 @@ saw_webkit1_warnings = saw_webkit2_warnings = False
pkg_config_path = common.build_path('Source', 'WebKit', 'gtk', 'webkitgtk-3.0.pc')
if not os.path.exists(pkg_config_path):
- pkg_config_path = common.build_path('Source', 'WebKit', 'gtk', 'webkitgtk-1.0.pc')
+ pkg_config_path = common.build_path('Source', 'WebKit', 'gtk', 'webkit-1.0.pc')
if os.path.exists(pkg_config_path):
- print "Generating WebKit1 documentation..."
- saw_webkit1_warnings = generate_doc(pkg_config_path, get_webkit1_options())
+ options = get_webkit1_options(common.gtk_version_of_pkg_config_file(pkg_config_path))
+ if '--rebase' not in sys.argv:
+ print "Generating WebKit1 documentation..."
+ saw_webkit1_warnings = generate_doc(pkg_config_path, options)
+ else:
+ print "Rebasing WebKit1 documentation..."
+ rebase_installed_docs(pkg_config_path, options)
# WebKit2 might not be enabled, so check for the pkg-config file before building documentation.
pkg_config_path = common.build_path('Source', 'WebKit2', 'webkit2gtk-3.0.pc')
if os.path.exists(pkg_config_path):
- print "\nGenerating WebKit2 documentation..."
- saw_webkit2_warnings = generate_doc(pkg_config_path, get_webkit2_options())
+ options = get_webkit2_options()
+ if '--rebase' not in sys.argv:
+ print "\nGenerating WebKit2 documentation..."
+ saw_webkit2_warnings = generate_doc(pkg_config_path, options)
+ else:
+ print "\nRebasing WebKit2 documentation..."
+ rebase_installed_docs(pkg_config_path, options)
sys.exit(saw_webkit1_warnings or saw_webkit2_warnings)
diff --git a/Tools/gtk/gtkdoc.py b/Tools/gtk/gtkdoc.py
index 58de0dae1..a2586ac5c 100644
--- a/Tools/gtk/gtkdoc.py
+++ b/Tools/gtk/gtkdoc.py
@@ -74,6 +74,11 @@ class GTKDoc(object):
interactive -- Whether or not errors or warnings should prompt the user
to continue or not. When this value is false, generation
will continue despite warnings. (default False)
+
+ virtual_root -- A temporary installation directory which is used as the root
+ where the actual installation prefix lives; this is mostly
+ useful for packagers, and should be set to what is given to
+ make install as DESTDIR.
"""
def __init__(self, args):
@@ -95,6 +100,9 @@ class GTKDoc(object):
self.doc_dir = ''
self.main_sgml_file = ''
+ # Parameters specific to gtkdoc-fixxref.
+ self.cross_reference_deps = []
+
self.interactive = False
self.logger = logging.getLogger('gtkdoc')
@@ -253,6 +261,9 @@ class GTKDoc(object):
output_file.write(self.version)
output_file.close()
+ def _ignored_files_basenames(self):
+ return ' '.join([os.path.basename(x) for x in self.ignored_files])
+
def _run_gtkdoc_scan(self):
args = ['gtkdoc-scan',
'--module=%s' % self.module_name,
@@ -271,10 +282,9 @@ class GTKDoc(object):
# gtkdoc-scan wants the basenames of ignored headers, so strip the
# dirname. Different from "--source-dir", the headers should be
# specified as one long string.
- if self.ignored_files:
- ignored_files_basenames = \
- [os.path.basename(x) for x in self.ignored_files]
- args.append('--ignore-headers=%s' % ' '.join(ignored_files_basenames))
+ ignored_files_basenames = self._ignored_files_basenames()
+ if ignored_files_basenames:
+ args.append('--ignore-headers=%s' % ignored_files_basenames)
self._run_command(args)
@@ -318,6 +328,10 @@ class GTKDoc(object):
'--output-format=xml',
'--sgml-mode']
+ ignored_files_basenames = self._ignored_files_basenames()
+ if ignored_files_basenames:
+ args.append('--ignore-files=%s' % ignored_files_basenames)
+
# Each directory should be have its own "--source-dir=" prefix.
args.extend(['--source-dir=%s' % path for path in self.source_dirs])
self._run_command(args, cwd=self.output_dir)
@@ -340,11 +354,23 @@ class GTKDoc(object):
cwd=html_dest_dir)
def _run_gtkdoc_fixxref(self):
- self._run_command(['gtkdoc-fixxref',
- '--module-dir=html',
- '--html-dir=html'],
- cwd=self.output_dir,
- ignore_warnings=True)
+ args = ['gtkdoc-fixxref',
+ '--module-dir=html',
+ '--html-dir=html']
+ args.extend(['--extra-dir=%s' % extra_dir for extra_dir in self.cross_reference_deps])
+ self._run_command(args, cwd=self.output_dir, ignore_warnings=True)
+
+ def rebase_installed_docs(self):
+ html_dir = os.path.join(self.virtual_root + self.prefix, 'share', 'gtk-doc', 'html', self.module_name)
+ if not os.path.isdir(html_dir):
+ return
+ args = ['gtkdoc-rebase',
+ '--relative',
+ '--html-dir=%s' % html_dir]
+ args.extend(['--other-dir=%s' % extra_dir for extra_dir in self.cross_reference_deps])
+ if self.virtual_root:
+ args.extend(['--dest-dir=%s' % self.virtual_root])
+ self._run_command(args, cwd=self.output_dir)
class PkgConfigGTKDoc(GTKDoc):
@@ -376,3 +402,6 @@ class PkgConfigGTKDoc(GTKDoc):
self.version = self._run_command(['pkg-config',
pkg_config_path,
'--modversion'], print_output=False)
+ self.prefix = self._run_command(['pkg-config',
+ pkg_config_path,
+ '--variable=prefix'], print_output=False)
diff --git a/Tools/gtk/jhbuild.modules b/Tools/gtk/jhbuild.modules
index 19910d58c..e0c9e38cd 100644
--- a/Tools/gtk/jhbuild.modules
+++ b/Tools/gtk/jhbuild.modules
@@ -9,6 +9,7 @@
<dep package="fonts"/>
<dep package="fontconfig"/>
<dep package="freetype6"/>
+ <dep package="gdk-pixbuf"/>
<dep package="gtk+"/>
<dep package="glib"/>
<dep package="glib-networking"/>
@@ -93,10 +94,21 @@
md5sum="79390673f5d07a8fb342bc09b5055b6f"/>
</autotools>
+ <autotools id="gdk-pixbuf" autogen-sh="configure">
+ <dependencies>
+ <dep package="glib"/>
+ </dependencies>
+ <branch module="/pub/GNOME/sources/gdk-pixbuf/2.23/gdk-pixbuf-2.23.5.tar.xz" version="2.23.5"
+ repo="ftp.gnome.org"
+ hash="sha256:7a6c3550426f38f6b0eeeb49295654d9e706ce8f1786a4d0932f9d2c0d0bc500"
+ md5sum="066e30277cadc225a7cef4c258da830b"/>
+ </autotools>
+
<autotools id="gtk+">
<dependencies>
<dep package="glib"/>
<dep package="cairo"/>
+ <dep package="gdk-pixbuf"/>
</dependencies>
<branch module="/pub/GNOME/sources/gtk+/3.0/gtk+-3.0.12.tar.xz" version="3.0.12"
repo="ftp.gnome.org"
diff --git a/Tools/qmake/mkspecs/features/default_post.prf b/Tools/qmake/mkspecs/features/default_post.prf
index b63709e1c..b5d879e48 100644
--- a/Tools/qmake/mkspecs/features/default_post.prf
+++ b/Tools/qmake/mkspecs/features/default_post.prf
@@ -76,7 +76,7 @@ for(library, WEBKIT) {
# Help keep the build tree clean
MOC_DIR = moc
RCC_DIR = rcc
-OBJECTS_DIR = obj/$$activeBuildConfig()
+isEmpty(OBJECTS_DIR): OBJECTS_DIR = obj/$$activeBuildConfig()
# General default build tweaks
DEFINES += \
diff --git a/Tools/qmake/mkspecs/features/features.prf b/Tools/qmake/mkspecs/features/features.prf
index 8fd82b47d..e7190ceeb 100644
--- a/Tools/qmake/mkspecs/features/features.prf
+++ b/Tools/qmake/mkspecs/features/features.prf
@@ -207,6 +207,11 @@ contains(MOBILITY_CONFIG, sensors) {
!contains(DEFINES, ENABLE_FULLSCREEN_API=.): DEFINES += ENABLE_FULLSCREEN_API=0
+contains(DEFINES, ENABLE_INSPECTOR=0) {
+ DEFINES -= ENABLE_JAVASCRIPT_DEBUGGER=1
+ DEFINES += ENABLE_JAVASCRIPT_DEBUGGER=0
+}
+
## Forward enabled feature macros to JavaScript enabled features macros
FEATURE_DEFINES_JAVASCRIPT = LANGUAGE_JAVASCRIPT=1
v8: FEATURE_DEFINES_JAVASCRIPT += V8_BINDING=1