diff options
author | Simon Hausmann <simon.hausmann@nokia.com> | 2012-02-09 14:16:12 +0100 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2012-02-09 14:16:12 +0100 |
commit | 03e12282df9aa1e1fb05a8b90f1cfc2e08764cec (patch) | |
tree | 52599cd0ab782b1768e23ad176f7618f98333cb6 /Tools | |
parent | cd44dc59cdfc39534aef4d417e9f3c412e3be139 (diff) | |
download | qtwebkit-03e12282df9aa1e1fb05a8b90f1cfc2e08764cec.tar.gz |
Imported WebKit commit e09a82039aa4273ab318b71122e92d8e5f233525 (http://svn.webkit.org/repository/webkit/trunk@107223)
Diffstat (limited to 'Tools')
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. &) 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 |