mirror of
https://github.com/servo/servo.git
synced 2025-08-14 01:45:33 +01:00
Update web-platform-tests to revision be5419e845d39089ba6dc338c1bd0fa279108317
This commit is contained in:
parent
aa199307c8
commit
2b6f573eb5
3440 changed files with 109438 additions and 41750 deletions
|
@ -0,0 +1,41 @@
|
|||
<!doctype html>
|
||||
<title>Revoking blob URL used with Request/fetch</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
|
||||
<script>
|
||||
promise_test(function(t) {
|
||||
const blob = new Blob(["test"]);
|
||||
const url = URL.createObjectURL(blob);
|
||||
const request = new Request(url);
|
||||
|
||||
// Revoke the object URL. Request should take a reference to the blob as
|
||||
// soon as it receives it in open(), so the request succeeds even though we
|
||||
// revoke the URL before calling fetch().
|
||||
URL.revokeObjectURL(url);
|
||||
|
||||
return fetch(request).then(response => response.text()).then(text => {
|
||||
assert_equals(text, 'test');
|
||||
});
|
||||
}, "Revoke blob URL after creating Request, will fetch");
|
||||
|
||||
promise_test(function(t) {
|
||||
const blob = new Blob(["test"]);
|
||||
const url = URL.createObjectURL(blob);
|
||||
|
||||
return fetch(url).then(response => response.text()).then(text => {
|
||||
assert_equals(text, 'test');
|
||||
});
|
||||
|
||||
// Revoke the object URL. fetch should have already resolved the blob URL.
|
||||
URL.revokeObjectURL(url);
|
||||
}, "Revoke blob URL after fetch, will fetch");
|
||||
|
||||
promise_test(t => {
|
||||
const blob = new Blob(["test"]);
|
||||
const url = URL.createObjectURL(blob);
|
||||
URL.revokeObjectURL(url);
|
||||
const request = new Request(url);
|
||||
return promise_rejects(t, new TypeError, fetch(request));
|
||||
}, "Revoke blob URL before creating Request, network error (after fetch)")
|
||||
</script>
|
|
@ -0,0 +1,104 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<title>Blob constructor: endings option</title>
|
||||
<link rel=help href="https://w3c.github.io/FileAPI/#constructorBlob">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script>
|
||||
|
||||
// Windows platforms use CRLF as the native line ending. All others use LF.
|
||||
const crlf = navigator.platform.startsWith('Win');
|
||||
const native_ending = crlf ? '\r\n' : '\n';
|
||||
|
||||
function readBlobAsPromise(blob) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const reader = new FileReader();
|
||||
reader.readAsText(blob);
|
||||
reader.onload = e => resolve(reader.result);
|
||||
reader.onerror = e => reject(reader.error);
|
||||
});
|
||||
}
|
||||
|
||||
[
|
||||
'transparent',
|
||||
'native'
|
||||
].forEach(value => test(t => {
|
||||
assert_class_string(new Blob([], {endings: value}), 'Blob',
|
||||
`Constructor should allow "${value}" endings`);
|
||||
}, `Valid "endings" value: ${JSON.stringify(value)}`));
|
||||
|
||||
[
|
||||
null,
|
||||
'',
|
||||
'invalidEnumValue',
|
||||
'Transparent',
|
||||
'NATIVE',
|
||||
0,
|
||||
{}
|
||||
].forEach(value => test(t => {
|
||||
assert_throws(new TypeError(), () => new Blob([], {endings: value}),
|
||||
'Blob constructor should throw');
|
||||
}, `Invalid "endings" value: ${JSON.stringify(value)}`));
|
||||
|
||||
test(t => {
|
||||
const test_error = {name: 'test'};
|
||||
assert_throws(
|
||||
test_error,
|
||||
() => new Blob([], { get endings() { throw test_error; }}),
|
||||
'Blob constructor should propagate exceptions from "endings" property');
|
||||
}, 'Exception propagation from options');
|
||||
|
||||
test(t => {
|
||||
let got = false;
|
||||
new Blob([], { get endings() { got = true; } });
|
||||
assert_true(got, 'The "endings" property was accessed during construction.');
|
||||
}, 'The "endings" options property is used');
|
||||
|
||||
[
|
||||
{name: 'LF', input: '\n', native: native_ending},
|
||||
{name: 'CR', input: '\r', native: native_ending},
|
||||
|
||||
{name: 'CRLF', input: '\r\n', native: native_ending},
|
||||
{name: 'CRCR', input: '\r\r', native: native_ending.repeat(2)},
|
||||
{name: 'LFCR', input: '\n\r', native: native_ending.repeat(2)},
|
||||
{name: 'LFLF', input: '\n\n', native: native_ending.repeat(2)},
|
||||
|
||||
{name: 'CRCRLF', input: '\r\r\n', native: native_ending.repeat(2)},
|
||||
{name: 'CRLFLF', input: '\r\n\n', native: native_ending.repeat(2)},
|
||||
{name: 'CRLFCR', input: '\r\n\r\n', native: native_ending.repeat(2)},
|
||||
|
||||
{name: 'CRLFCRLF', input: '\r\n\r\n', native: native_ending.repeat(2)},
|
||||
{name: 'LFCRLFCR', input: '\n\r\n\r', native: native_ending.repeat(3)},
|
||||
|
||||
].forEach(testCase => {
|
||||
promise_test(async t => {
|
||||
const blob = new Blob([testCase.input]);
|
||||
assert_equals(
|
||||
await readBlobAsPromise(blob), testCase.input,
|
||||
'Newlines should not change with endings unspecified');
|
||||
}, `Input ${testCase.name} with endings unspecified`);
|
||||
|
||||
promise_test(async t => {
|
||||
const blob = new Blob([testCase.input], {endings: 'transparent'});
|
||||
assert_equals(
|
||||
await readBlobAsPromise(blob), testCase.input,
|
||||
'Newlines should not change with endings "transparent"');
|
||||
}, `Input ${testCase.name} with endings 'transparent'`);
|
||||
|
||||
promise_test(async t => {
|
||||
const blob = new Blob([testCase.input], {endings: 'native'});
|
||||
assert_equals(
|
||||
await readBlobAsPromise(blob), testCase.native,
|
||||
'Newlines should match the platform with endings "native"');
|
||||
}, `Input ${testCase.name} with endings 'native'`);
|
||||
});
|
||||
|
||||
promise_test(async t => {
|
||||
const blob = new Blob(['\r', '\n'], {endings: 'native'});
|
||||
const expected = native_ending.repeat(2);
|
||||
assert_equals(
|
||||
await readBlobAsPromise(blob), expected,
|
||||
'CR/LF in adjacent strings should be converted to two platform newlines');
|
||||
}, `CR/LF in adjacent input strings`);
|
||||
|
||||
</script>
|
|
@ -74,6 +74,20 @@ test_blob(function() {
|
|||
type: "",
|
||||
desc: "A plain object with @@iterator should be treated as a sequence for the blobParts argument."
|
||||
});
|
||||
test(t => {
|
||||
const blob = new Blob({
|
||||
[Symbol.iterator]() {
|
||||
var i = 0;
|
||||
return {next: () => [
|
||||
{done:false, value:'ab'},
|
||||
{done:false, value:'cde'},
|
||||
{done:true}
|
||||
][i++]
|
||||
};
|
||||
}
|
||||
});
|
||||
assert_equals(blob.size, 5, 'Custom @@iterator should be treated as a sequence');
|
||||
}, "A plain object with custom @@iterator should be treated as a sequence for the blobParts argument.");
|
||||
test_blob(function() {
|
||||
return new Blob({
|
||||
[Symbol.iterator]: Array.prototype[Symbol.iterator],
|
||||
|
@ -392,26 +406,20 @@ test_blob(function() {
|
|||
desc: "Array with mixed types"
|
||||
});
|
||||
|
||||
// options argument
|
||||
test(function() {
|
||||
new Blob([], { endings: "invalidEnumValue" });
|
||||
new Blob([], { endings: null });
|
||||
new Blob([], { endings: undefined });
|
||||
new Blob([], { endings: 0 });
|
||||
new Blob([], { get endings() { assert_unreached("Should not call getter"); } });
|
||||
}, "The 'endings' property should be ignored.");
|
||||
const accessed = [];
|
||||
const stringified = [];
|
||||
|
||||
test(function() {
|
||||
assert_throws(test_error, function() {
|
||||
new Blob([], {
|
||||
get type() { throw test_error; }
|
||||
});
|
||||
new Blob([], {
|
||||
get type() { accessed.push('type'); },
|
||||
get endings() { accessed.push('endings'); }
|
||||
});
|
||||
assert_throws(test_error, function() {
|
||||
new Blob([], {
|
||||
type: { toString: function() { throw test_error; } }
|
||||
});
|
||||
new Blob([], {
|
||||
type: { toString: () => { stringified.push('type'); return ''; } },
|
||||
endings: { toString: () => { stringified.push('endings'); return 'transparent'; } }
|
||||
});
|
||||
assert_array_equals(accessed, ['endings', 'type']);
|
||||
assert_array_equals(stringified, ['endings', 'type']);
|
||||
}, "options properties should be accessed in lexicographic order.");
|
||||
|
||||
test(function() {
|
||||
|
@ -449,19 +457,16 @@ test(function() {
|
|||
});
|
||||
});
|
||||
|
||||
test_blob(function() {
|
||||
return new Blob(["\na\r\nb\n\rc\r"], { endings: "transparent" });
|
||||
}, {
|
||||
expected: "\na\r\nb\n\rc\r",
|
||||
type: "",
|
||||
desc: "Newlines should not change when endings is 'transparent'."
|
||||
});
|
||||
test_blob(function() {
|
||||
return new Blob(["\na\r\nb\n\rc\r"], { endings: "native" });
|
||||
}, {
|
||||
expected: "\na\r\nb\n\rc\r",
|
||||
type: "",
|
||||
desc: "Newlines should not change when endings is 'native'."
|
||||
[
|
||||
123,
|
||||
123.4,
|
||||
true,
|
||||
'abc'
|
||||
].forEach(arg => {
|
||||
test(t => {
|
||||
assert_throws(new TypeError(), () => new Blob([], arg),
|
||||
'Blob constructor should throw with invalid property bag');
|
||||
}, `Passing ${JSON.stringify(arg)} for options should throw`);
|
||||
});
|
||||
|
||||
var type_tests = [
|
||||
|
@ -471,6 +476,7 @@ var type_tests = [
|
|||
[[], 'A', 'a'],
|
||||
[[], 'text/html', 'text/html'],
|
||||
[[], 'TEXT/HTML', 'text/html'],
|
||||
[[], 'text/plain;charset=utf-8', 'text/plain;charset=utf-8'],
|
||||
[[], '\u00E5', ''],
|
||||
[[], '\uD801\uDC7E', ''], // U+1047E
|
||||
[[], ' image/gif ', ' image/gif '],
|
||||
|
|
|
@ -0,0 +1,104 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<title>File constructor: endings option</title>
|
||||
<link rel=help href="https://w3c.github.io/FileAPI/#file-constructor">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script>
|
||||
|
||||
// Windows platforms use CRLF as the native line ending. All others use LF.
|
||||
const crlf = navigator.platform.startsWith('Win');
|
||||
const native_ending = crlf ? '\r\n' : '\n';
|
||||
|
||||
function readBlobAsPromise(blob) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const reader = new FileReader();
|
||||
reader.readAsText(blob);
|
||||
reader.onload = e => resolve(reader.result);
|
||||
reader.onerror = e => reject(reader.error);
|
||||
});
|
||||
}
|
||||
|
||||
[
|
||||
'transparent',
|
||||
'native'
|
||||
].forEach(value => test(t => {
|
||||
assert_class_string(new File([], "name", {endings: value}), 'File',
|
||||
`Constructor should allow "${value}" endings`);
|
||||
}, `Valid "endings" value: ${JSON.stringify(value)}`));
|
||||
|
||||
[
|
||||
null,
|
||||
'',
|
||||
'invalidEnumValue',
|
||||
'Transparent',
|
||||
'NATIVE',
|
||||
0,
|
||||
{}
|
||||
].forEach(value => test(t => {
|
||||
assert_throws(new TypeError(), () => new File([], "name", {endings: value}),
|
||||
'File constructor should throw');
|
||||
}, `Invalid "endings" value: ${JSON.stringify(value)}`));
|
||||
|
||||
test(t => {
|
||||
const test_error = {name: 'test'};
|
||||
assert_throws(
|
||||
test_error,
|
||||
() => new File([], "name", { get endings() { throw test_error; }}),
|
||||
'File constructor should propagate exceptions from "endings" property');
|
||||
}, 'Exception propagation from options');
|
||||
|
||||
test(t => {
|
||||
let got = false;
|
||||
new File([], "name", { get endings() { got = true; } });
|
||||
assert_true(got, 'The "endings" property was accessed during construction.');
|
||||
}, 'The "endings" options property is used');
|
||||
|
||||
[
|
||||
{name: 'LF', input: '\n', native: native_ending},
|
||||
{name: 'CR', input: '\r', native: native_ending},
|
||||
|
||||
{name: 'CRLF', input: '\r\n', native: native_ending},
|
||||
{name: 'CRCR', input: '\r\r', native: native_ending.repeat(2)},
|
||||
{name: 'LFCR', input: '\n\r', native: native_ending.repeat(2)},
|
||||
{name: 'LFLF', input: '\n\n', native: native_ending.repeat(2)},
|
||||
|
||||
{name: 'CRCRLF', input: '\r\r\n', native: native_ending.repeat(2)},
|
||||
{name: 'CRLFLF', input: '\r\n\n', native: native_ending.repeat(2)},
|
||||
{name: 'CRLFCR', input: '\r\n\r\n', native: native_ending.repeat(2)},
|
||||
|
||||
{name: 'CRLFCRLF', input: '\r\n\r\n', native: native_ending.repeat(2)},
|
||||
{name: 'LFCRLFCR', input: '\n\r\n\r', native: native_ending.repeat(3)},
|
||||
|
||||
].forEach(testCase => {
|
||||
promise_test(async t => {
|
||||
const file = new File([testCase.input], "name");
|
||||
assert_equals(
|
||||
await readBlobAsPromise(file), testCase.input,
|
||||
'Newlines should not change with endings unspecified');
|
||||
}, `Input ${testCase.name} with endings unspecified`);
|
||||
|
||||
promise_test(async t => {
|
||||
const file = new File([testCase.input], "name", {endings: 'transparent'});
|
||||
assert_equals(
|
||||
await readBlobAsPromise(file), testCase.input,
|
||||
'Newlines should not change with endings "transparent"');
|
||||
}, `Input ${testCase.name} with endings 'transparent'`);
|
||||
|
||||
promise_test(async t => {
|
||||
const file = new File([testCase.input], "name", {endings: 'native'});
|
||||
assert_equals(
|
||||
await readBlobAsPromise(file), testCase.native,
|
||||
'Newlines should match the platform with endings "native"');
|
||||
}, `Input ${testCase.name} with endings 'native'`);
|
||||
});
|
||||
|
||||
promise_test(async t => {
|
||||
const file = new File(['\r', '\n'], "name", {endings: 'native'});
|
||||
const expected = native_ending.repeat(2);
|
||||
assert_equals(
|
||||
await readBlobAsPromise(file), expected,
|
||||
'CR/LF in adjacent strings should be converted to two platform newlines');
|
||||
}, `CR/LF in adjacent input strings`);
|
||||
|
||||
</script>
|
|
@ -6,10 +6,20 @@
|
|||
<script src="/resources/testharnessreport.js"></script>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
const to_string_obj = { toString: () => 'a string' };
|
||||
const to_string_throws = { toString: () => { throw new Error('expected'); } };
|
||||
|
||||
test(function() {
|
||||
assert_true("File" in window, "window should have a File property.");
|
||||
}, "File interface object exists");
|
||||
|
||||
test(t => {
|
||||
assert_throws(new TypeError(), () => new File(),
|
||||
'Bits argument is required');
|
||||
assert_throws(new TypeError(), () => new File([]),
|
||||
'Name argument is required');
|
||||
}, 'Required arguments');
|
||||
|
||||
function test_first_argument(arg1, expectedSize, testName) {
|
||||
test(function() {
|
||||
var file = new File(arg1, "dummy");
|
||||
|
@ -22,14 +32,48 @@ function test_first_argument(arg1, expectedSize, testName) {
|
|||
}, testName);
|
||||
}
|
||||
|
||||
test_first_argument([], 0, "empty fileBits");
|
||||
test_first_argument(["bits"], 4, "DOMString fileBits");
|
||||
test_first_argument(["𝓽𝓮𝔁𝓽"], 16, "Unicode DOMString fileBits");
|
||||
test_first_argument([new String('string object')], 13, "String object fileBits");
|
||||
test_first_argument([new Blob()], 0, "Empty Blob fileBits");
|
||||
test_first_argument([new Blob(["bits"])], 4, "Blob fileBits");
|
||||
test_first_argument([new File([], 'world.txt')], 0, "Empty File fileBits");
|
||||
test_first_argument([new File(["bits"], 'world.txt')], 4, "File fileBits");
|
||||
test_first_argument([new ArrayBuffer(8)], 8, "ArrayBuffer fileBits");
|
||||
test_first_argument([new Uint8Array([0x50, 0x41, 0x53, 0x53])], 4, "Typed array fileBits");
|
||||
test_first_argument(["bits", new Blob(["bits"]), new Blob(), new Uint8Array([0x50, 0x41]),
|
||||
new Uint16Array([0x5353]), new Uint32Array([0x53534150])], 16, "Various fileBits");
|
||||
test_first_argument([12], 2, "Number in fileBits");
|
||||
test_first_argument([[1,2,3]], 5, "Array in fileBits");
|
||||
test_first_argument([{}], 15, "Object in fileBits"); // "[object Object]"
|
||||
test_first_argument([document], 21, "HTMLDocument in fileBits"); // "[object HTMLDocument]"
|
||||
test_first_argument([to_string_obj], 8, "Object with toString in fileBits");
|
||||
test_first_argument({[Symbol.iterator]() {
|
||||
let i = 0;
|
||||
return {next: () => [
|
||||
{done:false, value:'ab'},
|
||||
{done:false, value:'cde'},
|
||||
{done:true}
|
||||
][i++]};
|
||||
}}, 5, 'Custom @@iterator');
|
||||
|
||||
[
|
||||
'hello',
|
||||
0,
|
||||
null
|
||||
].forEach(arg => {
|
||||
test(t => {
|
||||
assert_throws(new TypeError(), () => new File(arg, 'world.html'),
|
||||
'Constructor should throw for invalid bits argument');
|
||||
}, `Invalid bits argument: ${JSON.stringify(arg)}`);
|
||||
});
|
||||
|
||||
test(t => {
|
||||
assert_throws(new Error(), () => new File([to_string_throws], 'name.txt'),
|
||||
'Constructor should propagate exceptions');
|
||||
}, 'Bits argument: object that throws');
|
||||
|
||||
|
||||
function test_second_argument(arg2, expectedFileName, testName) {
|
||||
test(function() {
|
||||
|
@ -41,23 +85,29 @@ function test_second_argument(arg2, expectedFileName, testName) {
|
|||
|
||||
test_second_argument("dummy", "dummy", "Using fileName");
|
||||
test_second_argument("dummy/foo", "dummy:foo", "Using special character in fileName");
|
||||
test_second_argument(null, "null", "Using null fileName");
|
||||
test_second_argument(1, "1", "Using number fileName");
|
||||
test_second_argument('', '', "Using empty string fileName");
|
||||
test_second_argument(document, '[object HTMLDocument]', "Using object fileName");
|
||||
|
||||
// testing the third argument
|
||||
test(function() {
|
||||
var file = new File(["bits"], "dummy", { type: "text/plain"});
|
||||
assert_true(file instanceof File);
|
||||
assert_equals(file.type, "text/plain");
|
||||
}, "Using type on the File constructor");
|
||||
test(function() {
|
||||
var file = new File(["bits"], "dummy", { type: "TEXT/PLAIN"});
|
||||
assert_true(file instanceof File);
|
||||
assert_equals(file.type, "text/plain");
|
||||
}, "Using uppercase characters in type");
|
||||
test(function() {
|
||||
var file = new File(["bits"], "dummy", { type: "𝓽𝓮𝔁𝓽/𝔭𝔩𝔞𝔦𝔫"});
|
||||
assert_true(file instanceof File);
|
||||
assert_equals(file.type, "");
|
||||
}, "Using illegal character for type");
|
||||
[
|
||||
{type: 'text/plain', expected: 'text/plain'},
|
||||
{type: 'text/plain;charset=UTF-8', expected: 'text/plain;charset=utf-8'},
|
||||
{type: 'TEXT/PLAIN', expected: 'text/plain'},
|
||||
{type: '𝓽𝓮𝔁𝓽/𝔭𝔩𝔞𝔦𝔫', expected: ''},
|
||||
{type: 'ascii/nonprintable\u001F', expected: ''},
|
||||
{type: 'ascii/nonprintable\u007F', expected: ''},
|
||||
{type: 'nonascii\u00EE', expected: ''},
|
||||
{type: 'nonascii\u1234', expected: ''},
|
||||
{type: 'nonparsable', expected: 'nonparsable'}
|
||||
].forEach(testCase => {
|
||||
test(t => {
|
||||
var file = new File(["bits"], "dummy", { type: testCase.type});
|
||||
assert_true(file instanceof File);
|
||||
assert_equals(file.type, testCase.expected);
|
||||
}, `Using type in File constructor: ${testCase.type}`);
|
||||
});
|
||||
test(function() {
|
||||
var file = new File(["bits"], "dummy", { lastModified: 42 });
|
||||
assert_true(file instanceof File);
|
||||
|
@ -68,5 +118,41 @@ test(function() {
|
|||
assert_true(file instanceof File);
|
||||
assert_equals(file.name, "dummy");
|
||||
}, "Misusing name");
|
||||
test(function() {
|
||||
var file = new File(["bits"], "dummy", { unknownKey: "value" });
|
||||
assert_true(file instanceof File);
|
||||
assert_equals(file.name, "dummy");
|
||||
}, "Unknown properties are ignored");
|
||||
|
||||
[
|
||||
123,
|
||||
123.4,
|
||||
true,
|
||||
'abc'
|
||||
].forEach(arg => {
|
||||
test(t => {
|
||||
assert_throws(new TypeError(), () => new File(['bits'], 'name.txt', arg),
|
||||
'Constructor should throw for invalid property bag type');
|
||||
}, `Invalid property bag: ${JSON.stringify(arg)}`);
|
||||
});
|
||||
|
||||
[
|
||||
null,
|
||||
undefined,
|
||||
[1,2,3],
|
||||
/regex/,
|
||||
function() {}
|
||||
].forEach(arg => {
|
||||
test(t => {
|
||||
assert_equals(new File(['bits'], 'name.txt', arg).size, 4,
|
||||
'Constructor should accept object-ish property bag type');
|
||||
}, `Unusual but valid property bag: ${arg}`);
|
||||
});
|
||||
|
||||
test(t => {
|
||||
assert_throws(new Error(),
|
||||
() => new File(['bits'], 'name.txt', {type: to_string_throws}),
|
||||
'Constructor should propagate exceptions');
|
||||
}, 'Property bag propagates exceptions');
|
||||
|
||||
</script>
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<title>Upload files in ISO-2022-JP form (tentative)</title>
|
||||
<!--
|
||||
NOTE: This test is tentative because encoding for filename
|
||||
characters unrepresentable in the form charset is not yet
|
||||
standardized.
|
||||
-->
|
||||
<link rel="help"
|
||||
href="https://github.com/whatwg/html/issues/3223">
|
||||
<link rel="help"
|
||||
href="https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#multipart-form-data">
|
||||
<link rel="help"
|
||||
href="https://html.spec.whatwg.org/multipage/dnd.html#datatransferitemlist">
|
||||
<link rel="help"
|
||||
href="https://w3c.github.io/FileAPI/#file-constructor">
|
||||
<link rel="author" title="Benjamin C. Wiley Sittler"
|
||||
href="mailto:bsittler@chromium.org">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../support/send-file-form-helper.js"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: 'ASCII',
|
||||
fileBaseName: 'file-for-upload-in-form.txt',
|
||||
formEncoding: 'ISO-2022-JP',
|
||||
expectedEncodedBaseName: 'file-for-upload-in-form.txt',
|
||||
});
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: 'x-user-defined',
|
||||
fileBaseName: 'file-for-upload-in-form-\uF7F0\uF793\uF783\uF7A0.txt',
|
||||
formEncoding: 'ISO-2022-JP',
|
||||
expectedEncodedBaseName: (
|
||||
'file-for-upload-in-form-.txt'),
|
||||
});
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: 'windows-1252',
|
||||
fileBaseName: 'file-for-upload-in-form-☺😂.txt',
|
||||
formEncoding: 'ISO-2022-JP',
|
||||
expectedEncodedBaseName: (
|
||||
'file-for-upload-in-form-☺😂.txt'),
|
||||
});
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: 'JIS X 0201 and JIS X 0208',
|
||||
fileBaseName: 'file-for-upload-in-form-★星★.txt',
|
||||
formEncoding: 'ISO-2022-JP',
|
||||
expectedEncodedBaseName: 'file-for-upload-in-form-\x1B$B!z@1!z\x1B(B.txt',
|
||||
});
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: 'Unicode',
|
||||
fileBaseName: 'file-for-upload-in-form-☺😂.txt',
|
||||
formEncoding: 'ISO-2022-JP',
|
||||
expectedEncodedBaseName: 'file-for-upload-in-form-☺😂.txt',
|
||||
});
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: 'Unicode',
|
||||
fileBaseName: `file-for-upload-in-form-${kTestChars}.txt`,
|
||||
formEncoding: 'ISO-2022-JP',
|
||||
expectedEncodedBaseName: `file-for-upload-in-form-${
|
||||
kTestFallbackIso2022jp
|
||||
}.txt`,
|
||||
});
|
||||
|
||||
</script>
|
|
@ -0,0 +1,61 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<title>Upload files in UTF-8 form</title>
|
||||
<link rel="help"
|
||||
href="https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#multipart-form-data">
|
||||
<link rel="help"
|
||||
href="https://html.spec.whatwg.org/multipage/dnd.html#datatransferitemlist">
|
||||
<link rel="help"
|
||||
href="https://w3c.github.io/FileAPI/#file-constructor">
|
||||
<link rel="author" title="Benjamin C. Wiley Sittler"
|
||||
href="mailto:bsittler@chromium.org">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../support/send-file-form-helper.js"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: 'ASCII',
|
||||
fileBaseName: 'file-for-upload-in-form.txt',
|
||||
formEncoding: 'UTF-8',
|
||||
expectedEncodedBaseName: 'file-for-upload-in-form.txt',
|
||||
});
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: 'x-user-defined',
|
||||
fileBaseName: 'file-for-upload-in-form-\uF7F0\uF793\uF783\uF7A0.txt',
|
||||
formEncoding: 'UTF-8',
|
||||
expectedEncodedBaseName: (
|
||||
'file-for-upload-in-form-\uF7F0\uF793\uF783\uF7A0.txt'),
|
||||
});
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: 'windows-1252',
|
||||
fileBaseName: 'file-for-upload-in-form-☺😂.txt',
|
||||
formEncoding: 'UTF-8',
|
||||
expectedEncodedBaseName: 'file-for-upload-in-form-☺😂.txt',
|
||||
});
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: 'JIS X 0201 and JIS X 0208',
|
||||
fileBaseName: 'file-for-upload-in-form-★星★.txt',
|
||||
formEncoding: 'UTF-8',
|
||||
expectedEncodedBaseName: 'file-for-upload-in-form-★星★.txt',
|
||||
});
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: 'Unicode',
|
||||
fileBaseName: 'file-for-upload-in-form-☺😂.txt',
|
||||
formEncoding: 'UTF-8',
|
||||
expectedEncodedBaseName: 'file-for-upload-in-form-☺😂.txt',
|
||||
});
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: 'Unicode',
|
||||
fileBaseName: `file-for-upload-in-form-${kTestChars}.txt`,
|
||||
formEncoding: 'UTF-8',
|
||||
expectedEncodedBaseName: `file-for-upload-in-form-${kTestChars}.txt`,
|
||||
});
|
||||
|
||||
</script>
|
|
@ -0,0 +1,70 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<title>Upload files in Windows-1252 form (tentative)</title>
|
||||
<!--
|
||||
NOTE: This test is tentative because encoding for filename
|
||||
characters unrepresentable in the form charset is not yet
|
||||
standardized.
|
||||
-->
|
||||
<link rel="help"
|
||||
href="https://github.com/whatwg/html/issues/3223">
|
||||
<link rel="help"
|
||||
href="https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#multipart-form-data">
|
||||
<link rel="help"
|
||||
href="https://html.spec.whatwg.org/multipage/dnd.html#datatransferitemlist">
|
||||
<link rel="help"
|
||||
href="https://w3c.github.io/FileAPI/#file-constructor">
|
||||
<link rel="author" title="Benjamin C. Wiley Sittler"
|
||||
href="mailto:bsittler@chromium.org">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../support/send-file-form-helper.js"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: 'ASCII',
|
||||
fileBaseName: 'file-for-upload-in-form.txt',
|
||||
formEncoding: 'windows-1252',
|
||||
expectedEncodedBaseName: 'file-for-upload-in-form.txt',
|
||||
});
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: 'x-user-defined',
|
||||
fileBaseName: 'file-for-upload-in-form-\uF7F0\uF793\uF783\uF7A0.txt',
|
||||
formEncoding: 'windows-1252',
|
||||
expectedEncodedBaseName: (
|
||||
'file-for-upload-in-form-.txt'),
|
||||
});
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: 'windows-1252',
|
||||
fileBaseName: 'file-for-upload-in-form-☺😂.txt',
|
||||
formEncoding: 'windows-1252',
|
||||
expectedEncodedBaseName: 'file-for-upload-in-form-☺😂.txt',
|
||||
});
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: 'JIS X 0201 and JIS X 0208',
|
||||
fileBaseName: 'file-for-upload-in-form-★星★.txt',
|
||||
formEncoding: 'windows-1252',
|
||||
expectedEncodedBaseName: 'file-for-upload-in-form-★星★.txt',
|
||||
});
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: 'Unicode',
|
||||
fileBaseName: 'file-for-upload-in-form-☺😂.txt',
|
||||
formEncoding: 'windows-1252',
|
||||
expectedEncodedBaseName: 'file-for-upload-in-form-☺😂.txt',
|
||||
});
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: 'Unicode',
|
||||
fileBaseName: `file-for-upload-in-form-${kTestChars}.txt`,
|
||||
formEncoding: 'windows-1252',
|
||||
expectedEncodedBaseName: `file-for-upload-in-form-${
|
||||
kTestFallbackWindows1252
|
||||
}.txt`,
|
||||
});
|
||||
|
||||
</script>
|
|
@ -0,0 +1,70 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<title>Upload files in x-user-defined form (tentative)</title>
|
||||
<!--
|
||||
NOTE: This test is tentative because encoding for filename
|
||||
characters unrepresentable in the form charset is not yet
|
||||
standardized.
|
||||
-->
|
||||
<link rel="help"
|
||||
href="https://github.com/whatwg/html/issues/3223">
|
||||
<link rel="help"
|
||||
href="https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#multipart-form-data">
|
||||
<link rel="help"
|
||||
href="https://html.spec.whatwg.org/multipage/dnd.html#datatransferitemlist">
|
||||
<link rel="help"
|
||||
href="https://w3c.github.io/FileAPI/#file-constructor">
|
||||
<link rel="author" title="Benjamin C. Wiley Sittler"
|
||||
href="mailto:bsittler@chromium.org">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../support/send-file-form-helper.js"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: 'ASCII',
|
||||
fileBaseName: 'file-for-upload-in-form.txt',
|
||||
formEncoding: 'x-user-defined',
|
||||
expectedEncodedBaseName: 'file-for-upload-in-form.txt',
|
||||
});
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: 'x-user-defined',
|
||||
fileBaseName: 'file-for-upload-in-form-\uF7F0\uF793\uF783\uF7A0.txt',
|
||||
formEncoding: 'x-user-defined',
|
||||
expectedEncodedBaseName: 'file-for-upload-in-form-𓃠.txt',
|
||||
});
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: 'windows-1252',
|
||||
fileBaseName: 'file-for-upload-in-form-☺😂.txt',
|
||||
formEncoding: 'x-user-defined',
|
||||
expectedEncodedBaseName: ('file-for-upload-in-form-' +
|
||||
'☺😂.txt'),
|
||||
});
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: 'JIS X 0201 and JIS X 0208',
|
||||
fileBaseName: 'file-for-upload-in-form-★星★.txt',
|
||||
formEncoding: 'x-user-defined',
|
||||
expectedEncodedBaseName: 'file-for-upload-in-form-★星★.txt',
|
||||
});
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: 'Unicode',
|
||||
fileBaseName: 'file-for-upload-in-form-☺😂.txt',
|
||||
formEncoding: 'x-user-defined',
|
||||
expectedEncodedBaseName: 'file-for-upload-in-form-☺😂.txt',
|
||||
});
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: 'Unicode',
|
||||
fileBaseName: `file-for-upload-in-form-${kTestChars}.txt`,
|
||||
formEncoding: 'x-user-defined',
|
||||
expectedEncodedBaseName: `file-for-upload-in-form-${
|
||||
kTestFallbackXUserDefined
|
||||
}.txt`,
|
||||
});
|
||||
|
||||
</script>
|
|
@ -0,0 +1,25 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<title>Upload ASCII-named file in UTF-8 form</title>
|
||||
<link rel="help"
|
||||
href="https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#multipart-form-data">
|
||||
<link rel="help"
|
||||
href="https://html.spec.whatwg.org/multipage/dnd.html#datatransferitemlist">
|
||||
<link rel="help"
|
||||
href="https://w3c.github.io/FileAPI/#file-constructor">
|
||||
<link rel="author" title="Benjamin C. Wiley Sittler"
|
||||
href="mailto:bsittler@chromium.org">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../support/send-file-form-helper.js"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: 'ASCII',
|
||||
fileBaseName: 'file-for-upload-in-form.txt',
|
||||
formEncoding: 'UTF-8',
|
||||
expectedEncodedBaseName: 'file-for-upload-in-form.txt',
|
||||
});
|
||||
|
||||
</script>
|
|
@ -30,8 +30,6 @@ setup(function() {
|
|||
request.onload = function() {
|
||||
var idls = request.responseText;
|
||||
|
||||
idl_array.add_untested_idls("[PrimaryGlobal] interface Window { };");
|
||||
|
||||
idl_array.add_untested_idls("[Exposed=(Window,Worker)] interface ArrayBuffer {};");
|
||||
idl_array.add_untested_idls("interface URL {};");
|
||||
idl_array.add_untested_idls("[Exposed=(Window,Worker)] interface EventTarget {};");
|
||||
|
|
|
@ -0,0 +1,249 @@
|
|||
'use strict';
|
||||
|
||||
// Rationale for this particular test character sequence, which is
|
||||
// used in filenames and also in file contents:
|
||||
//
|
||||
// - ABC~ ensures the string starts with something we can read to
|
||||
// ensure it is from the correct source; ~ is used because even
|
||||
// some 1-byte otherwise-ASCII-like parts of ISO-2022-JP
|
||||
// interpret it differently.
|
||||
// - ‾¥ are inside a single-byte range of ISO-2022-JP and help
|
||||
// diagnose problems due to filesystem encoding or locale
|
||||
// - ≈ is inside IBM437 and helps diagnose problems due to filesystem
|
||||
// encoding or locale
|
||||
// - ¤ is inside Latin-1 and helps diagnose problems due to
|
||||
// filesystem encoding or locale; it is also the "simplest" case
|
||||
// needing substitution in ISO-2022-JP
|
||||
// - ・ is inside a single-byte range of ISO-2022-JP in some variants
|
||||
// and helps diagnose problems due to filesystem encoding or locale;
|
||||
// on the web it is distinct when decoding but unified when encoding
|
||||
// - ・ is inside a double-byte range of ISO-2022-JP and helps
|
||||
// diagnose problems due to filesystem encoding or locale
|
||||
// - • is inside Windows-1252 and helps diagnose problems due to
|
||||
// filesystem encoding or locale and also ensures these aren't
|
||||
// accidentally turned into e.g. control codes
|
||||
// - ∙ is inside IBM437 and helps diagnose problems due to filesystem
|
||||
// encoding or locale
|
||||
// - · is inside Latin-1 and helps diagnose problems due to
|
||||
// filesystem encoding or locale and also ensures HTML named
|
||||
// character references (e.g. ·) are not used
|
||||
// - ☼ is inside IBM437 shadowing C0 and helps diagnose problems due to
|
||||
// filesystem encoding or locale and also ensures these aren't
|
||||
// accidentally turned into e.g. control codes
|
||||
// - ★ is inside ISO-2022-JP on a non-Kanji page and makes correct
|
||||
// output easier to spot
|
||||
// - 星 is inside ISO-2022-JP on a Kanji page and makes correct
|
||||
// output easier to spot
|
||||
// - 🌟 is outside the BMP and makes incorrect surrogate pair
|
||||
// substitution detectable and ensures substitutions work
|
||||
// correctly immediately after Kanji 2-byte ISO-2022-JP
|
||||
// - 星 repeated here ensures the correct codec state is used
|
||||
// after a non-BMP substitution
|
||||
// - ★ repeated here also makes correct output easier to spot
|
||||
// - ☼ is inside IBM437 shadowing C0 and helps diagnose problems due to
|
||||
// filesystem encoding or locale and also ensures these aren't
|
||||
// accidentally turned into e.g. control codes and also ensures
|
||||
// substitutions work correctly immediately after non-Kanji
|
||||
// 2-byte ISO-2022-JP
|
||||
// - · is inside Latin-1 and helps diagnose problems due to
|
||||
// filesystem encoding or locale and also ensures HTML named
|
||||
// character references (e.g. ·) are not used
|
||||
// - ∙ is inside IBM437 and helps diagnose problems due to filesystem
|
||||
// encoding or locale
|
||||
// - • is inside Windows-1252 and again helps diagnose problems
|
||||
// due to filesystem encoding or locale
|
||||
// - ・ is inside a double-byte range of ISO-2022-JP and helps
|
||||
// diagnose problems due to filesystem encoding or locale
|
||||
// - ・ is inside a single-byte range of ISO-2022-JP in some variants
|
||||
// and helps diagnose problems due to filesystem encoding or locale;
|
||||
// on the web it is distinct when decoding but unified when encoding
|
||||
// - ¤ is inside Latin-1 and helps diagnose problems due to
|
||||
// filesystem encoding or locale; again it is a "simple"
|
||||
// substitution case
|
||||
// - ≈ is inside IBM437 and helps diagnose problems due to filesystem
|
||||
// encoding or locale
|
||||
// - ¥‾ are inside a single-byte range of ISO-2022-JP and help
|
||||
// diagnose problems due to filesystem encoding or locale
|
||||
// - ~XYZ ensures earlier errors don't lead to misencoding of
|
||||
// simple ASCII
|
||||
//
|
||||
// Overall the near-symmetry makes common I18N mistakes like
|
||||
// off-by-1-after-non-BMP easier to spot. All the characters
|
||||
// are also allowed in Windows Unicode filenames.
|
||||
const kTestChars = 'ABC~‾¥≈¤・・•∙·☼★星🌟星★☼·∙•・・¤≈¥‾~XYZ';
|
||||
|
||||
// NOTE: The expected interpretation of ISO-2022-JP according to
|
||||
// https://encoding.spec.whatwg.org/#iso-2022-jp-encoder unifies
|
||||
// single-byte and double-byte katakana.
|
||||
const kTestFallbackIso2022jp =
|
||||
('ABC~\x1B(J~\\≈¤\x1B$B!&!&\x1B(B•∙·☼\x1B$B!z@1\x1B(B🌟' +
|
||||
'\x1B$B@1!z\x1B(B☼·∙•\x1B$B!&!&\x1B(B¤≈\x1B(J\\~\x1B(B~XYZ').replace(
|
||||
/[^\0-\x7F]/gu,
|
||||
x => `&#${x.codePointAt(0)};`);
|
||||
|
||||
// NOTE: \uFFFD is used here to replace Windows-1252 bytes to match
|
||||
// how we will see them in the reflected POST bytes in a frame using
|
||||
// UTF-8 byte interpretation. The bytes will actually be intact, but
|
||||
// this code cannot tell and does not really care.
|
||||
const kTestFallbackWindows1252 =
|
||||
'ABC~‾\xA5≈\xA4・・\x95∙\xB7☼★星🌟星★☼\xB7∙\x95・・\xA4≈\xA5‾~XYZ'.replace(
|
||||
/[^\0-\xFF]/gu,
|
||||
x => `&#${x.codePointAt(0)};`).replace(/[\x80-\xFF]/g, '\uFFFD');
|
||||
|
||||
const kTestFallbackXUserDefined =
|
||||
kTestChars.replace(/[^\0-\x7F]/gu, x => `&#${x.codePointAt(0)};`);
|
||||
|
||||
// formPostFileUploadTest - verifies multipart upload structure and
|
||||
// numeric character reference replacement for filenames, field names,
|
||||
// and field values.
|
||||
//
|
||||
// Uses /fetch/api/resources/echo-content.py to echo the upload
|
||||
// POST with UTF-8 byte interpretation, leading to the "UTF-8 goggles"
|
||||
// behavior documented below for expectedEncodedBaseName when non-
|
||||
// UTF-8-compatible byte sequences appear in the formEncoding-encoded
|
||||
// uploaded data.
|
||||
//
|
||||
// Fields in the parameter object:
|
||||
//
|
||||
// - fileNameSource: purely explanatory and gives a clue about which
|
||||
// character encoding is the source for the non-7-bit-ASCII parts of
|
||||
// the fileBaseName, or Unicode if no smaller-than-Unicode source
|
||||
// contains all the characters. Used in the test name.
|
||||
// - fileBaseName: the not-necessarily-just-7-bit-ASCII file basename
|
||||
// used for the constructed test file. Used in the test name.
|
||||
// - formEncoding: the acceptCharset of the form used to submit the
|
||||
// test file. Used in the test name.
|
||||
// - expectedEncodedBaseName: the expected formEncoding-encoded
|
||||
// version of fileBaseName with unencodable characters replaced by
|
||||
// numeric character references and non-7-bit-ASCII bytes seen
|
||||
// through UTF-8 goggles; subsequences not interpretable as UTF-8
|
||||
// have each byte represented here by \uFFFD REPLACEMENT CHARACTER.
|
||||
const formPostFileUploadTest = ({
|
||||
fileNameSource,
|
||||
fileBaseName,
|
||||
formEncoding,
|
||||
expectedEncodedBaseName,
|
||||
}) => {
|
||||
promise_test(async testCase => {
|
||||
|
||||
if (document.readyState !== 'complete') {
|
||||
await new Promise(resolve => addEventListener('load', resolve));
|
||||
}
|
||||
|
||||
const formTargetFrame = Object.assign(document.createElement('iframe'), {
|
||||
name: 'formtargetframe',
|
||||
});
|
||||
document.body.append(formTargetFrame);
|
||||
testCase.add_cleanup(() => {
|
||||
document.body.removeChild(formTargetFrame);
|
||||
});
|
||||
|
||||
const form = Object.assign(document.createElement('form'), {
|
||||
acceptCharset: formEncoding,
|
||||
action: '/fetch/api/resources/echo-content.py',
|
||||
method: 'POST',
|
||||
enctype: 'multipart/form-data',
|
||||
target: formTargetFrame.name,
|
||||
});
|
||||
document.body.append(form);
|
||||
testCase.add_cleanup(() => {
|
||||
document.body.removeChild(form);
|
||||
});
|
||||
|
||||
// Used to verify that the browser agrees with the test about
|
||||
// which form charset is used.
|
||||
form.append(Object.assign(document.createElement('input'), {
|
||||
type: 'hidden',
|
||||
name: '_charset_',
|
||||
}));
|
||||
|
||||
// Used to verify that the browser agrees with the test about
|
||||
// field value replacement and encoding independently of file system
|
||||
// idiosyncracies.
|
||||
form.append(Object.assign(document.createElement('input'), {
|
||||
type: 'hidden',
|
||||
name: 'filename',
|
||||
value: fileBaseName,
|
||||
}));
|
||||
|
||||
// Same, but with name and value reversed to ensure field names
|
||||
// get the same treatment.
|
||||
form.append(Object.assign(document.createElement('input'), {
|
||||
type: 'hidden',
|
||||
name: fileBaseName,
|
||||
value: 'filename',
|
||||
}));
|
||||
|
||||
const fileInput = Object.assign(document.createElement('input'), {
|
||||
type: 'file',
|
||||
name: 'file',
|
||||
});
|
||||
form.append(fileInput);
|
||||
|
||||
// Removes c:\fakepath\ or other pseudofolder and returns just the
|
||||
// final component of filePath; allows both / and \ as segment
|
||||
// delimiters.
|
||||
const baseNameOfFilePath = filePath => filePath.split(/[\/\\]/).pop();
|
||||
await new Promise(resolve => {
|
||||
const dataTransfer = new DataTransfer;
|
||||
dataTransfer.items.add(
|
||||
new File([kTestChars], fileBaseName, {type: 'text/plain'}));
|
||||
fileInput.files = dataTransfer.files;
|
||||
// For historical reasons .value will be prefixed with
|
||||
// c:\fakepath\, but the basename should match the file name
|
||||
// exposed through the newer .files[0].name API. This check
|
||||
// verifies that assumption.
|
||||
assert_equals(
|
||||
fileInput.files[0].name,
|
||||
baseNameOfFilePath(fileInput.value),
|
||||
`The basename of the field's value should match its files[0].name`);
|
||||
form.submit();
|
||||
formTargetFrame.onload = resolve;
|
||||
});
|
||||
|
||||
const formDataText = formTargetFrame.contentDocument.body.textContent;
|
||||
const formDataLines = formDataText.split('\n');
|
||||
if (formDataLines.length && !formDataLines[formDataLines.length - 1]) {
|
||||
--formDataLines.length;
|
||||
}
|
||||
assert_greater_than(
|
||||
formDataLines.length,
|
||||
2,
|
||||
`${fileBaseName}: multipart form data must have at least 3 lines: ${
|
||||
JSON.stringify(formDataText)
|
||||
}`);
|
||||
const boundary = formDataLines[0];
|
||||
assert_equals(
|
||||
formDataLines[formDataLines.length - 1],
|
||||
boundary + '--',
|
||||
`${fileBaseName}: multipart form data must end with ${boundary}--: ${
|
||||
JSON.stringify(formDataText)
|
||||
}`);
|
||||
const expectedText = [
|
||||
boundary,
|
||||
'Content-Disposition: form-data; name="_charset_"',
|
||||
'',
|
||||
formEncoding,
|
||||
boundary,
|
||||
'Content-Disposition: form-data; name="filename"',
|
||||
'',
|
||||
expectedEncodedBaseName,
|
||||
boundary,
|
||||
`Content-Disposition: form-data; name="${expectedEncodedBaseName}"`,
|
||||
'',
|
||||
'filename',
|
||||
boundary,
|
||||
`Content-Disposition: form-data; name="file"; ` +
|
||||
`filename="${expectedEncodedBaseName}"`,
|
||||
'Content-Type: text/plain',
|
||||
'',
|
||||
kTestChars,
|
||||
boundary + '--',
|
||||
].join('\n');
|
||||
assert_true(
|
||||
formDataText.startsWith(expectedText),
|
||||
`Unexpected multipart-shaped form data received:\n${
|
||||
formDataText
|
||||
}\nExpected:\n${expectedText}`);
|
||||
}, `Upload ${fileBaseName} (${fileNameSource}) in ${formEncoding} form`);
|
||||
};
|
46
tests/wpt/web-platform-tests/FileAPI/unicode.html
Normal file
46
tests/wpt/web-platform-tests/FileAPI/unicode.html
Normal file
|
@ -0,0 +1,46 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<title>Blob/Unicode interaction: normalization and encoding</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
|
||||
const OMICRON_WITH_OXIA = '\u1F79'; // NFC normalized to U+3CC
|
||||
const CONTAINS_UNPAIRED_SURROGATES = 'abc\uDC00def\uD800ghi';
|
||||
const REPLACED = 'abc\uFFFDdef\uFFFDghi';
|
||||
|
||||
function readBlobAsPromise(blob) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const reader = new FileReader();
|
||||
reader.readAsText(blob);
|
||||
reader.onload = () => resolve(reader.result);
|
||||
reader.onerror = () => reject(reader.error);
|
||||
});
|
||||
}
|
||||
|
||||
promise_test(async t => {
|
||||
const blob = new Blob([OMICRON_WITH_OXIA]);
|
||||
const result = await readBlobAsPromise(blob);
|
||||
assert_equals(result, OMICRON_WITH_OXIA, 'String should not be normalized');
|
||||
}, 'Test that strings are not NFC normalized by Blob constructor');
|
||||
|
||||
promise_test(async t => {
|
||||
const file = new File([OMICRON_WITH_OXIA], 'name');
|
||||
const result = await readBlobAsPromise(file);
|
||||
assert_equals(result, OMICRON_WITH_OXIA, 'String should not be normalized');
|
||||
}, 'Test that strings are not NFC normalized by File constructor');
|
||||
|
||||
promise_test(async t => {
|
||||
const blob = new Blob([CONTAINS_UNPAIRED_SURROGATES]);
|
||||
const result = await readBlobAsPromise(blob);
|
||||
assert_equals(result, REPLACED, 'Unpaired surrogates should be replaced.');
|
||||
}, 'Test that unpaired surrogates are replaced by Blob constructor');
|
||||
|
||||
promise_test(async t => {
|
||||
const file = new File([CONTAINS_UNPAIRED_SURROGATES], 'name');
|
||||
const result = await readBlobAsPromise(file);
|
||||
assert_equals(result, REPLACED, 'Unpaired surrogates should be replaced.');
|
||||
}, 'Test that unpaired surrogates are replaced by File constructor');
|
||||
|
||||
</script>
|
|
@ -20,9 +20,8 @@
|
|||
http.onloadend = function() {
|
||||
var fileDisplay = document.querySelector("#fileDisplay");
|
||||
fileDisplay.src = window.URL.createObjectURL(http.response);
|
||||
takeScreenshot();
|
||||
fileDisplay.onload = takeScreenshot;
|
||||
};
|
||||
http.send();
|
||||
</script>
|
||||
</html>
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue