diff --git a/lib/fetch/response.js b/lib/fetch/response.js
index 66c0e50e32b..88deb71a062 100644
--- a/lib/fetch/response.js
+++ b/lib/fetch/response.js
@@ -49,7 +49,7 @@ class Response {
}
// https://fetch.spec.whatwg.org/#dom-response-json
- static json (data = undefined, init = {}) {
+ static json (data, init = {}) {
webidl.argumentLengthCheck(arguments, 1, { header: 'Response.json' })
if (init !== null) {
diff --git a/lib/fetch/util.js b/lib/fetch/util.js
index 98a049dc79d..fcbba84bc9a 100644
--- a/lib/fetch/util.js
+++ b/lib/fetch/util.js
@@ -556,16 +556,37 @@ function bytesMatch (bytes, metadataList) {
const algorithm = item.algo
// 2. Let expectedValue be the val component of item.
- const expectedValue = item.hash
+ let expectedValue = item.hash
+
+ // See https://github.com/web-platform-tests/wpt/commit/e4c5cc7a5e48093220528dfdd1c4012dc3837a0e
+ // "be liberal with padding". This is annoying, and it's not even in the spec.
+
+ if (expectedValue.endsWith('==')) {
+ expectedValue = expectedValue.slice(0, -2)
+ }
// 3. Let actualValue be the result of applying algorithm to bytes.
- const actualValue = crypto.createHash(algorithm).update(bytes).digest('base64')
+ let actualValue = crypto.createHash(algorithm).update(bytes).digest('base64')
+
+ if (actualValue.endsWith('==')) {
+ actualValue = actualValue.slice(0, -2)
+ }
// 4. If actualValue is a case-sensitive match for expectedValue,
// return true.
if (actualValue === expectedValue) {
return true
}
+
+ let actualBase64URL = crypto.createHash(algorithm).update(bytes).digest('base64url')
+
+ if (actualBase64URL.endsWith('==')) {
+ actualBase64URL = actualBase64URL.slice(0, -2)
+ }
+
+ if (actualBase64URL === expectedValue) {
+ return true
+ }
}
// 6. Return false.
diff --git a/test/wpt/runner/runner.mjs b/test/wpt/runner/runner.mjs
index 0b66f58466b..5bec326d3e1 100644
--- a/test/wpt/runner/runner.mjs
+++ b/test/wpt/runner/runner.mjs
@@ -312,6 +312,8 @@ export class WPTRunner extends EventEmitter {
`unexpected failures: ${failed - expectedFailures}, ` +
`skipped: ${skipped}`
)
+
+ process.exit(0)
}
addInitScript (code) {
diff --git a/test/wpt/status/fetch.status.json b/test/wpt/status/fetch.status.json
index cb5949579cf..5910bf37f6f 100644
--- a/test/wpt/status/fetch.status.json
+++ b/test/wpt/status/fetch.status.json
@@ -2,11 +2,13 @@
"api": {
"abort": {
"general.any.js": {
+ "note": "TODO(@KhafraDev): Clone aborts with original controller can probably be fixed",
"fail": [
"Already aborted signal rejects immediately",
"Underlying connection is closed when aborting after receiving response - no-cors",
"Stream errors once aborted. Underlying connection closed.",
- "Readable stream synchronously cancels with AbortError if aborted before reading"
+ "Readable stream synchronously cancels with AbortError if aborted before reading",
+ "Clone aborts with original controller"
]
},
"cache.https.any.js": {
@@ -128,6 +130,10 @@
]
}
},
+ "fetch-later": {
+ "note": "this is not part of the spec, only a proposal",
+ "skip": true
+ },
"headers": {
"header-setcookie.any.js": {
"note": "undici doesn't filter headers",
diff --git a/test/wpt/tests/.azure-pipelines.yml b/test/wpt/tests/.azure-pipelines.yml
index 20d5ec0f431..75a87df90f0 100644
--- a/test/wpt/tests/.azure-pipelines.yml
+++ b/test/wpt/tests/.azure-pipelines.yml
@@ -21,6 +21,7 @@ trigger:
- triggers/edge_canary
- triggers/safari_stable
- triggers/safari_preview
+- triggers/wktr_preview
# Set safaridriver_diagnose to true to enable safaridriver diagnostics. The
# logs won't appear in `./wpt run` output but will be uploaded as an artifact.
@@ -34,11 +35,11 @@ jobs:
displayName: 'affected tests: Safari Technology Preview'
condition: eq(variables['Build.Reason'], 'PullRequest')
pool:
- vmImage: 'macOS-12'
+ vmImage: 'macOS-13'
steps:
- task: UsePythonVersion@0
inputs:
- versionSpec: '3.10'
+ versionSpec: '3.11'
- template: tools/ci/azure/affected_tests.yml
parameters:
artifactName: 'safari-preview-affected-tests'
@@ -51,11 +52,11 @@ jobs:
displayName: 'affected tests without changes: Safari Technology Preview'
condition: eq(variables['Build.Reason'], 'PullRequest')
pool:
- vmImage: 'macOS-12'
+ vmImage: 'macOS-13'
steps:
- task: UsePythonVersion@0
inputs:
- versionSpec: '3.10'
+ versionSpec: '3.11'
- template: tools/ci/azure/affected_tests.yml
parameters:
checkoutCommit: 'HEAD^1'
@@ -76,7 +77,7 @@ jobs:
steps:
- task: UsePythonVersion@0
inputs:
- versionSpec: '3.10'
+ versionSpec: '3.11'
- template: tools/ci/azure/checkout.yml
- script: |
set -eux -o pipefail
@@ -93,17 +94,18 @@ jobs:
dependsOn: decision
condition: dependencies.decision.outputs['test_jobs.wptrunner_infrastructure']
pool:
- vmImage: 'macOS-12'
+ vmImage: 'macOS-13'
steps:
- task: UsePythonVersion@0
inputs:
- versionSpec: '3.10'
+ versionSpec: '3.11'
- template: tools/ci/azure/checkout.yml
- template: tools/ci/azure/pip_install.yml
parameters:
packages: virtualenv
- template: tools/ci/azure/install_fonts.yml
- template: tools/ci/azure/install_certs.yml
+ - template: tools/ci/azure/color_profile.yml
- template: tools/ci/azure/install_chrome.yml
- template: tools/ci/azure/install_firefox.yml
- template: tools/ci/azure/install_safari.yml
@@ -111,20 +113,25 @@ jobs:
- template: tools/ci/azure/update_manifest.yml
- script: |
set -eux -o pipefail
- ./wpt run --yes --no-manifest-update --manifest MANIFEST.json --metadata infrastructure/metadata/ --log-mach - --log-mach-level info --channel dev chrome infrastructure/
+ ./wpt run --yes --no-manifest-update --manifest MANIFEST.json --metadata infrastructure/metadata/ --log-mach - --log-mach-level info --log-wptreport $(Build.ArtifactStagingDirectory)/wpt_report_macos_chrome.json --channel dev chrome infrastructure/
condition: succeededOrFailed()
displayName: 'Run tests (Chrome Dev)'
- script: |
set -eux -o pipefail
- ./wpt run --yes --no-manifest-update --manifest MANIFEST.json --metadata infrastructure/metadata/ --log-mach - --log-mach-level info --channel nightly firefox infrastructure/
+ ./wpt run --yes --no-manifest-update --manifest MANIFEST.json --metadata infrastructure/metadata/ --log-mach - --log-mach-level info --log-wptreport $(Build.ArtifactStagingDirectory)/wpt_report_macos_firefox.json --channel nightly firefox infrastructure/
condition: succeededOrFailed()
displayName: 'Run tests (Firefox Nightly)'
- script: |
set -eux -o pipefail
export SYSTEM_VERSION_COMPAT=0
- ./wpt run --yes --no-manifest-update --manifest MANIFEST.json --metadata infrastructure/metadata/ --log-mach - --log-mach-level info --channel preview safari infrastructure/
+ ./wpt run --yes --no-manifest-update --manifest MANIFEST.json --metadata infrastructure/metadata/ --log-mach - --log-mach-level info --log-wptreport $(Build.ArtifactStagingDirectory)/wpt_report_macos_safari.json --channel preview safari infrastructure/
condition: succeededOrFailed()
displayName: 'Run tests (Safari Technology Preview)'
+ - task: PublishBuildArtifacts@1
+ condition: succeededOrFailed()
+ displayName: 'Publish results'
+ inputs:
+ artifactName: 'infrastructure-results'
- template: tools/ci/azure/publish_logs.yml
- template: tools/ci/azure/sysdiagnose.yml
@@ -133,76 +140,79 @@ jobs:
dependsOn: decision
condition: dependencies.decision.outputs['test_jobs.tools_unittest']
pool:
- vmImage: 'macOS-12'
+ vmImage: 'macOS-13'
steps:
- task: UsePythonVersion@0
inputs:
- versionSpec: '3.7'
+ # TODO(#40525): Revert back to 3.7 once the Mac agent's Python v3.7 contains bz2 again.
+ versionSpec: '3.7.16'
- template: tools/ci/azure/checkout.yml
- template: tools/ci/azure/tox_pytest.yml
parameters:
directory: tools/
toxenv: py37
-- job: tools_unittest_mac_py310
- displayName: 'tools/ unittests: macOS + Python 3.10'
+- job: tools_unittest_mac_py311
+ displayName: 'tools/ unittests: macOS + Python 3.11'
dependsOn: decision
condition: dependencies.decision.outputs['test_jobs.tools_unittest']
pool:
- vmImage: 'macOS-12'
+ vmImage: 'macOS-13'
steps:
- task: UsePythonVersion@0
inputs:
- versionSpec: '3.10'
+ versionSpec: '3.11'
- template: tools/ci/azure/checkout.yml
- template: tools/ci/azure/tox_pytest.yml
parameters:
directory: tools/
- toxenv: py310
+ toxenv: py311
- job: wptrunner_unittest_mac_py37
displayName: 'tools/wptrunner/ unittests: macOS + Python 3.7'
dependsOn: decision
condition: dependencies.decision.outputs['test_jobs.wptrunner_unittest']
pool:
- vmImage: 'macOS-12'
+ vmImage: 'macOS-13'
steps:
- task: UsePythonVersion@0
inputs:
- versionSpec: '3.7'
+ # TODO(#40525): Revert back to 3.7 once the Mac agent's Python v3.7 contains bz2 again.
+ versionSpec: '3.7.16'
- template: tools/ci/azure/checkout.yml
- template: tools/ci/azure/tox_pytest.yml
parameters:
directory: tools/wptrunner/
toxenv: py37
-- job: wptrunner_unittest_mac_py310
- displayName: 'tools/wptrunner/ unittests: macOS + Python 3.10'
+- job: wptrunner_unittest_mac_py311
+ displayName: 'tools/wptrunner/ unittests: macOS + Python 3.11'
dependsOn: decision
condition: dependencies.decision.outputs['test_jobs.wptrunner_unittest']
pool:
- vmImage: 'macOS-12'
+ vmImage: 'macOS-13'
steps:
- task: UsePythonVersion@0
inputs:
- versionSpec: '3.10'
+ versionSpec: '3.11'
- template: tools/ci/azure/checkout.yml
- template: tools/ci/azure/tox_pytest.yml
parameters:
directory: tools/wptrunner/
- toxenv: py310
+ toxenv: py311
- job: wpt_integration_mac_py37
displayName: 'tools/wpt/ tests: macOS + Python 3.7'
dependsOn: decision
condition: dependencies.decision.outputs['test_jobs.wpt_integration']
pool:
- vmImage: 'macOS-12'
+ vmImage: 'macOS-13'
steps:
# full checkout required
- task: UsePythonVersion@0
inputs:
- versionSpec: '3.7'
+ # TODO(#40525): Revert back to 3.7 once the Mac agent's Python v3.7 contains bz2 again.
+ versionSpec: '3.7.16'
- template: tools/ci/azure/install_chrome.yml
- template: tools/ci/azure/install_firefox.yml
- template: tools/ci/azure/update_hosts.yml
@@ -212,17 +222,17 @@ jobs:
directory: tools/wpt/
toxenv: py37
-- job: wpt_integration_mac_py310
- displayName: 'tools/wpt/ tests: macOS + Python 3.10'
+- job: wpt_integration_mac_py311
+ displayName: 'tools/wpt/ tests: macOS + Python 3.11'
dependsOn: decision
condition: dependencies.decision.outputs['test_jobs.wpt_integration']
pool:
- vmImage: 'macOS-12'
+ vmImage: 'macOS-13'
steps:
# full checkout required
- task: UsePythonVersion@0
inputs:
- versionSpec: '3.10'
+ versionSpec: '3.11'
- template: tools/ci/azure/install_chrome.yml
- template: tools/ci/azure/install_firefox.yml
- template: tools/ci/azure/update_hosts.yml
@@ -230,7 +240,7 @@ jobs:
- template: tools/ci/azure/tox_pytest.yml
parameters:
directory: tools/wpt/
- toxenv: py310
+ toxenv: py311
- job: tools_unittest_win_py37
displayName: 'tools/ unittests: Windows + Python 3.7'
@@ -251,8 +261,8 @@ jobs:
directory: tools/
toxenv: py37
-- job: tools_unittest_win_py310
- displayName: 'tools/ unittests: Windows + Python 3.10'
+- job: tools_unittest_win_py311
+ displayName: 'tools/ unittests: Windows + Python 3.11'
dependsOn: decision
condition: dependencies.decision.outputs['test_jobs.tools_unittest']
pool:
@@ -260,13 +270,13 @@ jobs:
steps:
- task: UsePythonVersion@0
inputs:
- versionSpec: '3.10'
+ versionSpec: '3.11'
addToPath: false
- template: tools/ci/azure/checkout.yml
- template: tools/ci/azure/tox_pytest.yml
parameters:
directory: tools/
- toxenv: py310
+ toxenv: py311
- job: wptrunner_unittest_win_py37
displayName: 'tools/wptrunner/ unittests: Windows + Python 3.7'
@@ -285,8 +295,8 @@ jobs:
directory: tools/wptrunner/
toxenv: py37
-- job: wptrunner_unittest_win_py310
- displayName: 'tools/wptrunner/ unittests: Windows + Python 3.10'
+- job: wptrunner_unittest_win_py311
+ displayName: 'tools/wptrunner/ unittests: Windows + Python 3.11'
dependsOn: decision
condition: dependencies.decision.outputs['test_jobs.wptrunner_unittest']
pool:
@@ -294,13 +304,13 @@ jobs:
steps:
- task: UsePythonVersion@0
inputs:
- versionSpec: '3.10'
+ versionSpec: '3.11'
addToPath: false
- template: tools/ci/azure/checkout.yml
- template: tools/ci/azure/tox_pytest.yml
parameters:
directory: tools/wptrunner/
- toxenv: py310
+ toxenv: py311
- job: wpt_integration_win_py37
displayName: 'tools/wpt/ tests: Windows + Python 3.7'
@@ -324,8 +334,8 @@ jobs:
directory: tools/wpt/
toxenv: py37
-- job: wpt_integration_win_py310
- displayName: 'tools/wpt/ tests: Windows + Python 3.10'
+- job: wpt_integration_win_py311
+ displayName: 'tools/wpt/ tests: Windows + Python 3.11'
dependsOn: decision
condition: dependencies.decision.outputs['test_jobs.wpt_integration']
pool:
@@ -334,7 +344,7 @@ jobs:
# full checkout required
- task: UsePythonVersion@0
inputs:
- versionSpec: '3.10'
+ versionSpec: '3.11'
# currently just using the outdated Chrome/Firefox on the VM rather than
# figuring out how to install Chrome Dev channel on Windows
# - template: tools/ci/azure/install_chrome.yml
@@ -344,7 +354,7 @@ jobs:
- template: tools/ci/azure/tox_pytest.yml
parameters:
directory: tools/wpt/
- toxenv: py310
+ toxenv: py311
- job: results_edge_stable
displayName: 'all tests: Edge Stable'
@@ -360,7 +370,7 @@ jobs:
steps:
- task: UsePythonVersion@0
inputs:
- versionSpec: '3.10'
+ versionSpec: '3.11'
- template: tools/ci/azure/system_info.yml
- template: tools/ci/azure/checkout.yml
- template: tools/ci/azure/pip_install.yml
@@ -399,7 +409,7 @@ jobs:
steps:
- task: UsePythonVersion@0
inputs:
- versionSpec: '3.10'
+ versionSpec: '3.11'
- template: tools/ci/azure/system_info.yml
- template: tools/ci/azure/checkout.yml
- template: tools/ci/azure/pip_install.yml
@@ -438,7 +448,7 @@ jobs:
steps:
- task: UsePythonVersion@0
inputs:
- versionSpec: '3.10'
+ versionSpec: '3.11'
- template: tools/ci/azure/checkout.yml
- template: tools/ci/azure/pip_install.yml
parameters:
@@ -472,16 +482,17 @@ jobs:
parallel: 8 # chosen to make runtime ~2h
timeoutInMinutes: 180
pool:
- vmImage: 'macOS-12'
+ vmImage: 'macOS-13'
steps:
- task: UsePythonVersion@0
inputs:
- versionSpec: '3.10'
+ versionSpec: '3.11'
- template: tools/ci/azure/checkout.yml
- template: tools/ci/azure/pip_install.yml
parameters:
packages: virtualenv
- template: tools/ci/azure/install_certs.yml
+ - template: tools/ci/azure/color_profile.yml
- template: tools/ci/azure/install_safari.yml
parameters:
channel: stable
@@ -490,8 +501,9 @@ jobs:
- script: |
set -eux -o pipefail
export SYSTEM_VERSION_COMPAT=0
- ./wpt run --no-manifest-update --no-restart-on-unexpected --no-fail-on-unexpected --this-chunk=$(System.JobPositionInPhase) --total-chunks=$(System.TotalJobsInPhase) --chunk-type hash --log-wptreport $(Build.ArtifactStagingDirectory)/wpt_report_$(System.JobPositionInPhase).json --log-wptscreenshot $(Build.ArtifactStagingDirectory)/wpt_screenshot_$(System.JobPositionInPhase).txt --log-mach - --log-mach-level info --channel stable --kill-safari safari
+ ./wpt run --no-manifest-update --no-restart-on-unexpected --no-fail-on-unexpected --this-chunk=$(System.JobPositionInPhase) --total-chunks=$(System.TotalJobsInPhase) --chunk-type hash --log-wptreport $(Build.ArtifactStagingDirectory)/wpt_report_$(System.JobPositionInPhase).json --log-wptscreenshot $(Build.ArtifactStagingDirectory)/wpt_screenshot_$(System.JobPositionInPhase).txt --log-mach - --log-mach-level info --channel stable --kill-safari --max-restarts 100 safari
displayName: 'Run tests'
+ retryCountOnTaskFailure: 2
- task: PublishBuildArtifacts@1
displayName: 'Publish results'
inputs:
@@ -513,24 +525,26 @@ jobs:
parallel: 8 # chosen to make runtime ~2h
timeoutInMinutes: 180
pool:
- vmImage: 'macOS-12'
+ vmImage: 'macOS-13'
steps:
- task: UsePythonVersion@0
inputs:
- versionSpec: '3.10'
+ versionSpec: '3.11'
- template: tools/ci/azure/checkout.yml
- template: tools/ci/azure/pip_install.yml
parameters:
packages: virtualenv
- template: tools/ci/azure/install_certs.yml
+ - template: tools/ci/azure/color_profile.yml
- template: tools/ci/azure/install_safari.yml
- template: tools/ci/azure/update_hosts.yml
- template: tools/ci/azure/update_manifest.yml
- script: |
set -eux -o pipefail
export SYSTEM_VERSION_COMPAT=0
- ./wpt run --no-manifest-update --no-restart-on-unexpected --no-fail-on-unexpected --this-chunk=$(System.JobPositionInPhase) --total-chunks=$(System.TotalJobsInPhase) --chunk-type hash --log-wptreport $(Build.ArtifactStagingDirectory)/wpt_report_$(System.JobPositionInPhase).json --log-wptscreenshot $(Build.ArtifactStagingDirectory)/wpt_screenshot_$(System.JobPositionInPhase).txt --log-mach - --log-mach-level info --channel preview --kill-safari safari
+ ./wpt run --no-manifest-update --no-restart-on-unexpected --no-fail-on-unexpected --this-chunk=$(System.JobPositionInPhase) --total-chunks=$(System.TotalJobsInPhase) --chunk-type hash --log-wptreport $(Build.ArtifactStagingDirectory)/wpt_report_$(System.JobPositionInPhase).json --log-wptscreenshot $(Build.ArtifactStagingDirectory)/wpt_screenshot_$(System.JobPositionInPhase).txt --log-mach - --log-mach-level info --channel preview --kill-safari --max-restarts 100 safari
displayName: 'Run tests'
+ retryCountOnTaskFailure: 2
- task: PublishBuildArtifacts@1
displayName: 'Publish results'
inputs:
@@ -551,22 +565,23 @@ jobs:
parallel: 8 # chosen to make runtime ~2h
timeoutInMinutes: 180
pool:
- vmImage: 'macOS-12'
+ vmImage: 'macOS-13'
steps:
- task: UsePythonVersion@0
inputs:
- versionSpec: '3.10'
+ versionSpec: '3.11'
- template: tools/ci/azure/checkout.yml
- template: tools/ci/azure/pip_install.yml
parameters:
packages: virtualenv
- template: tools/ci/azure/install_certs.yml
+ - template: tools/ci/azure/color_profile.yml
- template: tools/ci/azure/update_hosts.yml
- template: tools/ci/azure/update_manifest.yml
- script: |
set -eux -o pipefail
export SYSTEM_VERSION_COMPAT=0
- ./wpt run --no-manifest-update --no-restart-on-unexpected --no-fail-on-unexpected --this-chunk=$(System.JobPositionInPhase) --total-chunks=$(System.TotalJobsInPhase) --chunk-type hash --log-wptreport $(Build.ArtifactStagingDirectory)/wpt_report_$(System.JobPositionInPhase).json --log-wptscreenshot $(Build.ArtifactStagingDirectory)/wpt_screenshot_$(System.JobPositionInPhase).txt --log-mach - --log-mach-level info --channel main --install-browser wktr
+ ./wpt run --no-manifest-update --no-restart-on-unexpected --no-fail-on-unexpected --this-chunk=$(System.JobPositionInPhase) --total-chunks=$(System.TotalJobsInPhase) --chunk-type hash --log-wptreport $(Build.ArtifactStagingDirectory)/wpt_report_$(System.JobPositionInPhase).json --log-wptscreenshot $(Build.ArtifactStagingDirectory)/wpt_screenshot_$(System.JobPositionInPhase).txt --log-mach - --log-mach-level info --channel experimental --install-browser --yes wktr
displayName: 'Run tests'
- task: PublishBuildArtifacts@1
displayName: 'Publish results'
diff --git a/test/wpt/tests/.taskcluster.yml b/test/wpt/tests/.taskcluster.yml
index c80e92af204..c817999b8e6 100644
--- a/test/wpt/tests/.taskcluster.yml
+++ b/test/wpt/tests/.taskcluster.yml
@@ -57,7 +57,7 @@ tasks:
owner: ${owner}
source: ${event.repository.clone_url}
payload:
- image: webplatformtests/wpt:0.53
+ image: webplatformtests/wpt:0.54
maxRunTime: 7200
artifacts:
public/results:
diff --git a/test/wpt/tests/FileAPI/reading-data-section/filereader_readAsDataURL.any.js b/test/wpt/tests/FileAPI/reading-data-section/filereader_readAsDataURL.any.js
index d6812121295..4f9dbf7a754 100644
--- a/test/wpt/tests/FileAPI/reading-data-section/filereader_readAsDataURL.any.js
+++ b/test/wpt/tests/FileAPI/reading-data-section/filereader_readAsDataURL.any.js
@@ -39,4 +39,16 @@ async_test(function(testCase) {
testCase.done();
});
reader.readAsDataURL(blob);
-}, 'readAsDataURL result for Blob with unspecified MIME type');
\ No newline at end of file
+}, 'readAsDataURL result for Blob with unspecified MIME type');
+
+async_test(function(testCase) {
+ var blob = new Blob([]);
+ var reader = new FileReader();
+
+ reader.onload = this.step_func(function() {
+ assert_equals(reader.result,
+ "data:application/octet-stream;base64,");
+ testCase.done();
+ });
+ reader.readAsDataURL(blob);
+}, 'readAsDataURL result for empty Blob');
\ No newline at end of file
diff --git a/test/wpt/tests/common/media.js b/test/wpt/tests/common/media.js
index f2dc8612660..800593f5343 100644
--- a/test/wpt/tests/common/media.js
+++ b/test/wpt/tests/common/media.js
@@ -9,10 +9,15 @@ function getVideoURI(base)
var videotag = document.createElement("video");
- if ( videotag.canPlayType &&
- videotag.canPlayType('video/ogg; codecs="theora, vorbis"') )
+ if ( videotag.canPlayType )
{
- extension = '.ogv';
+ if (videotag.canPlayType('video/webm; codecs="vp9, opus"') )
+ {
+ extension = '.webm';
+ } else if ( videotag.canPlayType('video/ogg; codecs="theora, vorbis"') )
+ {
+ extension = '.ogv';
+ }
}
return base + extension;
@@ -46,10 +51,11 @@ function getAudioURI(base)
function getMediaContentType(url) {
var extension = new URL(url, location).pathname.split(".").pop();
var map = {
- "mp4": "video/mp4",
- "ogv": "application/ogg",
- "mp3": "audio/mp3",
- "oga": "application/ogg",
+ "mp4" : "video/mp4",
+ "ogv" : "application/ogg",
+ "webm": "video/webm",
+ "mp3" : "audio/mp3",
+ "oga" : "application/ogg",
};
return map[extension];
}
diff --git a/test/wpt/tests/common/rendering-utils.js b/test/wpt/tests/common/rendering-utils.js
index 8027cd5f848..46283bd5d07 100644
--- a/test/wpt/tests/common/rendering-utils.js
+++ b/test/wpt/tests/common/rendering-utils.js
@@ -7,14 +7,12 @@
*/
function waitForAtLeastOneFrame() {
return new Promise(resolve => {
- // Different web engines work slightly different on this area but 1) waiting
- // for two requestAnimationFrames() to happen one after another and 2)
- // adding a step_timeout(0) to guarantee events have finished should be
+ // Different web engines work slightly different on this area but waiting
+ // for two requestAnimationFrames() to happen, one after another, should be
// sufficient to ensure at least one frame has been generated anywhere.
- // See https://bugzilla.mozilla.org/show_bug.cgi?id=1785615
window.requestAnimationFrame(() => {
window.requestAnimationFrame(() => {
- setTimeout(resolve, 0);
+ resolve();
});
});
});
diff --git a/test/wpt/tests/fetch/api/abort/general.any.js b/test/wpt/tests/fetch/api/abort/general.any.js
index 7bf98ba9b24..3727bb42afe 100644
--- a/test/wpt/tests/fetch/api/abort/general.any.js
+++ b/test/wpt/tests/fetch/api/abort/general.any.js
@@ -566,7 +566,7 @@ test(() => {
controller.abort();
- assert_array_equals(log, ['clone-aborted', 'original-aborted'], "Abort events fired in correct order");
+ assert_array_equals(log, ['original-aborted', 'clone-aborted'], "Abort events fired in correct order");
assert_true(request.signal.aborted, 'Signal aborted');
assert_true(clonedRequest.signal.aborted, 'Signal aborted');
}, "Clone aborts with original controller");
diff --git a/test/wpt/tests/fetch/api/basic/integrity.sub.any.js b/test/wpt/tests/fetch/api/basic/integrity.sub.any.js
index 56dbd4909f6..e3cfd1b2f6e 100644
--- a/test/wpt/tests/fetch/api/basic/integrity.sub.any.js
+++ b/test/wpt/tests/fetch/api/basic/integrity.sub.any.js
@@ -28,6 +28,9 @@ function integrity(desc, url, integrity, initRequestMode, shouldPass) {
const topSha256 = "sha256-KHIDZcXnR2oBHk9DrAA+5fFiR6JjudYjqoXtMR1zvzk=";
const topSha384 = "sha384-MgZYnnAzPM/MjhqfOIMfQK5qcFvGZsGLzx4Phd7/A8fHTqqLqXqKo8cNzY3xEPTL";
const topSha512 = "sha512-D6yns0qxG0E7+TwkevZ4Jt5t7Iy3ugmAajG/dlf6Pado1JqTyneKXICDiqFIkLMRExgtvg8PlxbKTkYfRejSOg==";
+const topSha512wrongpadding = "sha512-D6yns0qxG0E7+TwkevZ4Jt5t7Iy3ugmAajG/dlf6Pado1JqTyneKXICDiqFIkLMRExgtvg8PlxbKTkYfRejSOg";
+const topSha512base64url = "sha512-D6yns0qxG0E7-TwkevZ4Jt5t7Iy3ugmAajG_dlf6Pado1JqTyneKXICDiqFIkLMRExgtvg8PlxbKTkYfRejSOg==";
+const topSha512base64url_nopadding = "sha512-D6yns0qxG0E7-TwkevZ4Jt5t7Iy3ugmAajG_dlf6Pado1JqTyneKXICDiqFIkLMRExgtvg8PlxbKTkYfRejSOg";
const invalidSha256 = "sha256-dKUcPOn/AlUjWIwcHeHNqYXPlvyGiq+2dWOdFcE+24I=";
const invalidSha512 = "sha512-oUceBRNxPxnY60g/VtPCj2syT4wo4EZh2CgYdWy9veW8+OsReTXoh7dizMGZafvx9+QhMS39L/gIkxnPIn41Zg==";
@@ -38,13 +41,20 @@ const corsUrl =
const corsUrl2 = `https://{{host}}:{{ports[https][0]}}${path}`
integrity("Empty string integrity", url, "", /* initRequestMode */ undefined,
- /* shouldPass */ true);
+ /* shouldPass */ true);
integrity("SHA-256 integrity", url, topSha256, /* initRequestMode */ undefined,
/* shouldPass */ true);
integrity("SHA-384 integrity", url, topSha384, /* initRequestMode */ undefined,
/* shouldPass */ true);
integrity("SHA-512 integrity", url, topSha512, /* initRequestMode */ undefined,
/* shouldPass */ true);
+integrity("SHA-512 integrity with missing padding", url, topSha512wrongpadding,
+ /* initRequestMode */ undefined, /* shouldPass */ true);
+integrity("SHA-512 integrity base64url encoded", url, topSha512base64url,
+ /* initRequestMode */ undefined, /* shouldPass */ true);
+integrity("SHA-512 integrity base64url encoded with missing padding", url,
+ topSha512base64url_nopadding, /* initRequestMode */ undefined,
+ /* shouldPass */ true);
integrity("Invalid integrity", url, invalidSha256,
/* initRequestMode */ undefined, /* shouldPass */ false);
integrity("Multiple integrities: valid stronger than invalid", url,
diff --git a/test/wpt/tests/fetch/api/basic/keepalive.any.js b/test/wpt/tests/fetch/api/basic/keepalive.any.js
index 4f33284d0c7..899d41d676a 100644
--- a/test/wpt/tests/fetch/api/basic/keepalive.any.js
+++ b/test/wpt/tests/fetch/api/basic/keepalive.any.js
@@ -14,16 +14,30 @@ const {
HTTP_REMOTE_ORIGIN_WITH_DIFFERENT_PORT
} = get_host_info();
-for (const method of ['GET', 'POST']) {
- promise_test(async (test) => {
- const token1 = token();
- const iframe = document.createElement('iframe');
- iframe.src = getKeepAliveIframeUrl(token1, method);
- document.body.appendChild(iframe);
- await iframeLoaded(iframe);
- assert_equals(await getTokenFromMessage(), token1);
- iframe.remove();
+/**
+ * In a different-site iframe, test to fetch a keepalive URL on the specified
+ * document event.
+ */
+function keepaliveSimpleRequestTest(method) {
+ for (const evt of ['load', 'pagehide', 'unload']) {
+ const desc =
+ `[keepalive] simple ${method} request on '${evt}' [no payload]`;
+ promise_test(async (test) => {
+ const token1 = token();
+ const iframe = document.createElement('iframe');
+ iframe.src = getKeepAliveIframeUrl(token1, method, {sendOn: evt});
+ document.body.appendChild(iframe);
+ await iframeLoaded(iframe);
+ if (evt != 'load') {
+ iframe.remove();
+ }
+ assert_equals(await getTokenFromMessage(), token1);
+
+ assertStashedTokenAsync(desc, token1);
+ }, `${desc}; setting up`);
+ }
+}
- assertStashedTokenAsync(`simple ${method} request: no payload`, token1);
- }, `simple ${method} request: no payload; setting up`);
+for (const method of ['GET', 'POST']) {
+ keepaliveSimpleRequestTest(method);
}
diff --git a/test/wpt/tests/fetch/api/basic/scheme-blob.sub.any.js b/test/wpt/tests/fetch/api/basic/scheme-blob.sub.any.js
index a6059ea93d9..8afdc033c9d 100644
--- a/test/wpt/tests/fetch/api/basic/scheme-blob.sub.any.js
+++ b/test/wpt/tests/fetch/api/basic/scheme-blob.sub.any.js
@@ -57,6 +57,10 @@ let empty_data_blob = new Blob([], {type: "text/plain"});
checkFetchResponse(URL.createObjectURL(empty_data_blob), "", "text/plain", 0,
"Fetching URL.createObjectURL(empty_data_blob) is OK");
+let invalid_type_blob = new Blob([], {type: "invalid"});
+checkFetchResponse(URL.createObjectURL(invalid_type_blob), "", "", 0,
+ "Fetching URL.createObjectURL(invalid_type_blob) is OK");
+
promise_test(function(test) {
return fetch("/images/blue.png").then(function(resp) {
return resp.arrayBuffer();
diff --git a/test/wpt/tests/fetch/api/cors/cors-basic.any.js b/test/wpt/tests/fetch/api/cors/cors-basic.any.js
index 23f5f91c87d..95de0af2d8f 100644
--- a/test/wpt/tests/fetch/api/cors/cors-basic.any.js
+++ b/test/wpt/tests/fetch/api/cors/cors-basic.any.js
@@ -1,37 +1,43 @@
// META: script=../resources/utils.js
// META: script=/common/get-host-info.sub.js
+const {
+ HTTPS_ORIGIN,
+ HTTP_ORIGIN_WITH_DIFFERENT_PORT,
+ HTTP_REMOTE_ORIGIN,
+ HTTP_REMOTE_ORIGIN_WITH_DIFFERENT_PORT,
+ HTTPS_REMOTE_ORIGIN,
+} = get_host_info();
+
function cors(desc, origin) {
- var url = origin + dirname(location.pathname);
- var urlParameters = "?pipe=header(Access-Control-Allow-Origin,*)";
+ const url = `${origin}${dirname(location.pathname)}${RESOURCES_DIR}top.txt`;
+ const urlAllowCors = `${url}?pipe=header(Access-Control-Allow-Origin,*)`;
- promise_test(function(test) {
- return fetch(url + RESOURCES_DIR + "top.txt" + urlParameters, {"mode": "no-cors"} ).then(function(resp) {
+ promise_test((test) => {
+ return fetch(urlAllowCors, {'mode': 'no-cors'}).then((resp) => {
assert_equals(resp.status, 0, "Opaque filter: status is 0");
assert_equals(resp.statusText, "", "Opaque filter: statusText is \"\"");
assert_equals(resp.type , "opaque", "Opaque filter: response's type is opaque");
- return resp.text().then(function(value) {
+ return resp.text().then((value) => {
assert_equals(value, "", "Opaque response should have an empty body");
});
});
- }, desc + " [no-cors mode]");
+ }, `${desc} [no-cors mode]`);
- promise_test(function(test) {
- return promise_rejects_js(test, TypeError, fetch(url + RESOURCES_DIR + "top.txt", {"mode": "cors"}));
- }, desc + " [server forbid CORS]");
+ promise_test((test) => {
+ return promise_rejects_js(test, TypeError, fetch(url, {'mode': 'cors'}));
+ }, `${desc} [server forbid CORS]`);
- promise_test(function(test) {
- return fetch(url + RESOURCES_DIR + "top.txt" + urlParameters, {"mode": "cors"} ).then(function(resp) {
+ promise_test((test) => {
+ return fetch(urlAllowCors, {'mode': 'cors'}).then((resp) => {
assert_equals(resp.status, 200, "Fetch's response's status is 200");
assert_equals(resp.type , "cors", "CORS response's type is cors");
});
- }, desc + " [cors mode]");
+ }, `${desc} [cors mode]`);
}
-var host_info = get_host_info();
-
-cors("Same domain different port", host_info.HTTP_ORIGIN_WITH_DIFFERENT_PORT);
-cors("Same domain different protocol different port", host_info.HTTPS_ORIGIN);
-cors("Cross domain basic usage", host_info.HTTP_REMOTE_ORIGIN);
-cors("Cross domain different port", host_info.HTTP_REMOTE_ORIGIN_WITH_DIFFERENT_PORT);
-cors("Cross domain different protocol", host_info.HTTPS_REMOTE_ORIGIN);
+cors('Same domain different port', HTTP_ORIGIN_WITH_DIFFERENT_PORT);
+cors('Same domain different protocol different port', HTTPS_ORIGIN);
+cors('Cross domain basic usage', HTTP_REMOTE_ORIGIN);
+cors('Cross domain different port', HTTP_REMOTE_ORIGIN_WITH_DIFFERENT_PORT);
+cors('Cross domain different protocol', HTTPS_REMOTE_ORIGIN);
diff --git a/test/wpt/tests/fetch/api/cors/cors-keepalive.any.js b/test/wpt/tests/fetch/api/cors/cors-keepalive.any.js
new file mode 100644
index 00000000000..f68d90ef9aa
--- /dev/null
+++ b/test/wpt/tests/fetch/api/cors/cors-keepalive.any.js
@@ -0,0 +1,118 @@
+// META: global=window
+// META: timeout=long
+// META: title=Fetch API: keepalive handling
+// META: script=/resources/testharness.js
+// META: script=/resources/testharnessreport.js
+// META: script=/common/utils.js
+// META: script=/common/get-host-info.sub.js
+// META: script=../resources/keepalive-helper.js
+// META: script=../resources/utils.js
+
+'use strict';
+
+const {
+ HTTP_NOTSAMESITE_ORIGIN,
+ HTTPS_ORIGIN,
+ HTTP_ORIGIN_WITH_DIFFERENT_PORT,
+ HTTP_REMOTE_ORIGIN,
+ HTTP_REMOTE_ORIGIN_WITH_DIFFERENT_PORT,
+ HTTPS_REMOTE_ORIGIN,
+} = get_host_info();
+
+/**
+ * Tests to cover the basic behaviors of keepalive + cors/no-cors mode requests
+ * to different `origin` when the initiator document is still alive. They should
+ * behave the same as without setting keepalive.
+ */
+function keepaliveCorsBasicTest(desc, origin) {
+ const url = `${origin}${dirname(location.pathname)}${RESOURCES_DIR}top.txt`;
+ const urlAllowCors = `${url}?pipe=header(Access-Control-Allow-Origin,*)`;
+
+ promise_test((test) => {
+ return fetch(urlAllowCors, {keepalive: true, 'mode': 'no-cors'})
+ .then((resp) => {
+ assert_equals(resp.status, 0, 'Opaque filter: status is 0');
+ assert_equals(resp.statusText, '', 'Opaque filter: statusText is ""');
+ assert_equals(
+ resp.type, 'opaque', 'Opaque filter: response\'s type is opaque');
+ return resp.text().then((value) => {
+ assert_equals(
+ value, '', 'Opaque response should have an empty body');
+ });
+ });
+ }, `${desc} [no-cors mode]`);
+
+ promise_test((test) => {
+ return promise_rejects_js(
+ test, TypeError, fetch(url, {keepalive: true, 'mode': 'cors'}));
+ }, `${desc} [cors mode, server forbid CORS]`);
+
+ promise_test((test) => {
+ return fetch(urlAllowCors, {keepalive: true, 'mode': 'cors'})
+ .then((resp) => {
+ assert_equals(resp.status, 200, 'Fetch\'s response\'s status is 200');
+ assert_equals(resp.type, 'cors', 'CORS response\'s type is cors');
+ });
+ }, `${desc} [cors mode]`);
+}
+
+keepaliveCorsBasicTest(
+ `[keepalive] Same domain different port`, HTTP_ORIGIN_WITH_DIFFERENT_PORT);
+keepaliveCorsBasicTest(
+ `[keepalive] Same domain different protocol different port`, HTTPS_ORIGIN);
+keepaliveCorsBasicTest(
+ `[keepalive] Cross domain basic usage`, HTTP_REMOTE_ORIGIN);
+keepaliveCorsBasicTest(
+ `[keepalive] Cross domain different port`,
+ HTTP_REMOTE_ORIGIN_WITH_DIFFERENT_PORT);
+keepaliveCorsBasicTest(
+ `[keepalive] Cross domain different protocol`, HTTPS_REMOTE_ORIGIN);
+
+/**
+ * In a same-site iframe, and in `unload` event handler, test to fetch
+ * a keepalive URL that involves in different cors modes.
+ */
+function keepaliveCorsInUnloadTest(description, origin, method) {
+ const evt = 'unload';
+ for (const mode of ['no-cors', 'cors']) {
+ for (const disallowOrigin of [false, true]) {
+ const desc = `${description} ${method} request in ${evt} [${mode} mode` +
+ (disallowOrigin ? `, server forbid CORS]` : `]`);
+ const shouldPass = !disallowOrigin || mode === 'no-cors';
+ promise_test(async (test) => {
+ const token1 = token();
+ const iframe = document.createElement('iframe');
+ iframe.src = getKeepAliveIframeUrl(token1, method, {
+ frameOrigin: '',
+ requestOrigin: origin,
+ sendOn: evt,
+ mode: mode,
+ disallowOrigin
+ });
+ document.body.appendChild(iframe);
+ await iframeLoaded(iframe);
+ iframe.remove();
+ assert_equals(await getTokenFromMessage(), token1);
+
+ assertStashedTokenAsync(desc, token1, {shouldPass});
+ }, `${desc}; setting up`);
+ }
+ }
+}
+
+for (const method of ['GET', 'POST']) {
+ keepaliveCorsInUnloadTest(
+ '[keepalive] Same domain different port', HTTP_ORIGIN_WITH_DIFFERENT_PORT,
+ method);
+ keepaliveCorsInUnloadTest(
+ `[keepalive] Same domain different protocol different port`, HTTPS_ORIGIN,
+ method);
+ keepaliveCorsInUnloadTest(
+ `[keepalive] Cross domain basic usage`, HTTP_REMOTE_ORIGIN, method);
+ keepaliveCorsInUnloadTest(
+ `[keepalive] Cross domain different port`,
+ HTTP_REMOTE_ORIGIN_WITH_DIFFERENT_PORT, method);
+ keepaliveCorsInUnloadTest(
+ `[keepalive] Cross domain different protocol`, HTTPS_REMOTE_ORIGIN,
+ method);
+}
diff --git a/test/wpt/tests/fetch/api/cors/cors-preflight-star.any.js b/test/wpt/tests/fetch/api/cors/cors-preflight-star.any.js
index e8cbc80b808..f9fb20469cf 100644
--- a/test/wpt/tests/fetch/api/cors/cors-preflight-star.any.js
+++ b/test/wpt/tests/fetch/api/cors/cors-preflight-star.any.js
@@ -80,3 +80,7 @@ preflightTest(true, true, "PATCH", "*", "PATCH", [])
preflightTest(false, true, "PATCH", "*", "patch", [])
preflightTest(false, true, "patch", "*", "PATCH", [])
preflightTest(true, true, "patch", "*", "patch", [])
+
+// "Authorization" header can't be wildcarded.
+preflightTest(false, false, "*", "*", "POST", ["Authorization", "123"])
+preflightTest(true, false, "*", "*, Authorization", "POST", ["Authorization", "123"])
diff --git a/test/wpt/tests/fetch/api/crashtests/body-window-destroy.html b/test/wpt/tests/fetch/api/crashtests/body-window-destroy.html
new file mode 100644
index 00000000000..646d3c5f8ce
--- /dev/null
+++ b/test/wpt/tests/fetch/api/crashtests/body-window-destroy.html
@@ -0,0 +1,11 @@
+
+
+
diff --git a/test/wpt/tests/fetch/api/request/destination/resources/dummy_video.webm b/test/wpt/tests/fetch/api/request/destination/resources/dummy_video.webm
new file mode 100644
index 00000000000..c3d433a3e02
Binary files /dev/null and b/test/wpt/tests/fetch/api/request/destination/resources/dummy_video.webm differ
diff --git a/test/wpt/tests/fetch/api/request/multi-globals/construct-in-detached-frame.window.js b/test/wpt/tests/fetch/api/request/multi-globals/construct-in-detached-frame.window.js
new file mode 100644
index 00000000000..b0d6ba5b80d
--- /dev/null
+++ b/test/wpt/tests/fetch/api/request/multi-globals/construct-in-detached-frame.window.js
@@ -0,0 +1,11 @@
+// This is a regression test for Chromium issue https://crbug.com/1427266.
+test(() => {
+ const iframe = document.createElement('iframe');
+ document.body.append(iframe);
+ const otherRequest = iframe.contentWindow.Request;
+ iframe.remove();
+ const r1 = new otherRequest('resource', { method: 'POST', body: 'string' });
+ const r2 = new otherRequest(r1);
+ assert_true(r1.bodyUsed);
+ assert_false(r2.bodyUsed);
+}, 'creating a request from another request in a detached realm should work');
diff --git a/test/wpt/tests/fetch/api/resources/keepalive-helper.js b/test/wpt/tests/fetch/api/resources/keepalive-helper.js
index c7048d1ff33..ad1d4b2c7c3 100644
--- a/test/wpt/tests/fetch/api/resources/keepalive-helper.js
+++ b/test/wpt/tests/fetch/api/resources/keepalive-helper.js
@@ -1,19 +1,35 @@
// Utility functions to help testing keepalive requests.
-// Returns a different-site URL to an iframe that loads a keepalive URL.
+// Returns a URL to an iframe that loads a keepalive URL on iframe loaded.
//
// The keepalive URL points to a target that stores `token`. The token will then
-// be posted back to parent document.
+// be posted back on iframe loaded to the parent document.
// `method` defaults to GET.
-// `sendOnPagehide` to tell if request should be sent on pagehide instead.
-function getKeepAliveIframeUrl(token, method, sendOnPagehide = false) {
+// `frameOrigin` to specify the origin of the iframe to load. If not set,
+// default to a different site origin.
+// `requestOrigin` to specify the origin of the fetch request target.
+// `sendOn` to specify the name of the event when the keepalive request should
+// be sent instead of the default 'load'.
+// `mode` to specify the fetch request's CORS mode.
+// `disallowOrigin` to ask the iframe to set up a server that forbids CORS
+// requests.
+function getKeepAliveIframeUrl(token, method, {
+ frameOrigin = 'DEFAULT',
+ requestOrigin = '',
+ sendOn = 'load',
+ mode = 'cors',
+ disallowOrigin = false
+} = {}) {
const https = location.protocol.startsWith('https');
- const frameOrigin =
- get_host_info()[https ? 'HTTPS_NOTSAMESITE_ORIGIN' : 'HTTP_NOTSAMESITE_ORIGIN'];
+ frameOrigin = frameOrigin === 'DEFAULT' ?
+ get_host_info()[https ? 'HTTPS_NOTSAMESITE_ORIGIN' : 'HTTP_NOTSAMESITE_ORIGIN'] :
+ frameOrigin;
return `${frameOrigin}/fetch/api/resources/keepalive-iframe.html?` +
`token=${token}&` +
`method=${method}&` +
- `sendOnPagehide=${sendOnPagehide}`;
+ `sendOn=${sendOn}&` +
+ `mode=${mode}&` + (disallowOrigin ? `disallowOrigin=1&` : ``) +
+ `origin=${requestOrigin}`;
}
// Returns a different-site URL to an iframe that loads a keepalive URL.
diff --git a/test/wpt/tests/fetch/api/resources/keepalive-iframe.html b/test/wpt/tests/fetch/api/resources/keepalive-iframe.html
index ac00f3a331a..335a1f8e318 100644
--- a/test/wpt/tests/fetch/api/resources/keepalive-iframe.html
+++ b/test/wpt/tests/fetch/api/resources/keepalive-iframe.html
@@ -3,12 +3,18 @@
diff --git a/test/wpt/tests/fetch/api/resources/stash-put.py b/test/wpt/tests/fetch/api/resources/stash-put.py
index dbc7ceebb88..0530e1ba5b4 100644
--- a/test/wpt/tests/fetch/api/resources/stash-put.py
+++ b/test/wpt/tests/fetch/api/resources/stash-put.py
@@ -1,17 +1,19 @@
from wptserve.utils import isomorphic_decode
def main(request, response):
- if request.method == u'OPTIONS':
- # CORS preflight
- response.headers.set(b'Access-Control-Allow-Origin', b'*')
- response.headers.set(b'Access-Control-Allow-Methods', b'*')
- response.headers.set(b'Access-Control-Allow-Headers', b'*')
- return 'done'
+ if request.method == u'OPTIONS':
+ # CORS preflight
+ response.headers.set(b'Access-Control-Allow-Origin', b'*')
+ response.headers.set(b'Access-Control-Allow-Methods', b'*')
+ response.headers.set(b'Access-Control-Allow-Headers', b'*')
+ return 'done'
+
+ url_dir = u'/'.join(request.url_parts.path.split(u'/')[:-1]) + u'/'
+ key = request.GET.first(b'key')
+ value = request.GET.first(b'value')
+ # value here must be a text string. It will be json.dump()'ed in stash-take.py.
+ request.server.stash.put(key, isomorphic_decode(value), url_dir)
- url_dir = u'/'.join(request.url_parts.path.split(u'/')[:-1]) + u'/'
- key = request.GET.first(b"key")
- value = request.GET.first(b"value")
- # value here must be a text string. It will be json.dump()'ed in stash-take.py.
- request.server.stash.put(key, isomorphic_decode(value), url_dir)
+ if b'disallow_origin' not in request.GET:
response.headers.set(b'Access-Control-Allow-Origin', b'*')
- return "done"
+ return 'done'
diff --git a/test/wpt/tests/fetch/api/response/response-body-read-task-handling.html b/test/wpt/tests/fetch/api/response/response-body-read-task-handling.html
index c2c90eaa8bd..64b07556661 100644
--- a/test/wpt/tests/fetch/api/response/response-body-read-task-handling.html
+++ b/test/wpt/tests/fetch/api/response/response-body-read-task-handling.html
@@ -35,9 +35,7 @@
// The fulfill handler above shouldn't have run yet. If it has run,
// throw to reject this promise and fail the test.
- if (executed) {
- throw "shouldn't have run microtasks yet";
- }
+ assert_false(executed, "shouldn't have run microtasks yet");
// Otherwise act as if there's no "then" property so the promise
// fulfills and the test passes.
@@ -49,6 +47,40 @@
return response.body.getReader().read();
});
}, "reading from a body stream should occur in a microtask scope");
+
+promise_test(function() {
+ return fetch("../resources/data.json").then(function(response) {
+ // Add a getter for "then" that will incidentally be invoked
+ // during promise resolution.
+ Object.prototype.__defineGetter__('then', () => {
+ // Clean up behind ourselves.
+ delete Object.prototype.then;
+
+ // This promise should (like all promises) be resolved
+ // asynchronously.
+ var executed = false;
+ Promise.resolve().then(_ => { executed = true; });
+
+ // This shouldn't run microtasks! They should only run
+ // after the fetch is resolved.
+ performMicrotaskCheckpoint();
+
+ // The fulfill handler above shouldn't have run yet. If it has run,
+ // throw to reject this promise and fail the test.
+ assert_false(executed, "shouldn't have run microtasks yet");
+
+ // Otherwise act as if there's no "then" property so the promise
+ // fulfills and the test passes.
+ return undefined;
+ });
+
+ // Create a read request, incidentally resolving a promise with an
+ // object value, thereby invoking the getter installed above.
+ return response.body.pipeTo(new WritableStream({
+ write(chunk) {}
+ }))
+ });
+}, "piping from a body stream to a JS-written WritableStream should occur in a microtask scope");