• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// META: title=File constructor
2
3const to_string_obj = { toString: () => 'a string' };
4const to_string_throws = { toString: () => { throw new Error('expected'); } };
5
6test(function() {
7  assert_true("File" in globalThis, "globalThis should have a File property.");
8}, "File interface object exists");
9
10test(t => {
11  assert_throws_js(TypeError, () => new File(),
12                   'Bits argument is required');
13  assert_throws_js(TypeError, () => new File([]),
14                   'Name argument is required');
15}, 'Required arguments');
16
17function test_first_argument(arg1, expectedSize, testName) {
18  test(function() {
19    var file = new File(arg1, "dummy");
20    assert_true(file instanceof File);
21    assert_equals(file.name, "dummy");
22    assert_equals(file.size, expectedSize);
23    assert_equals(file.type, "");
24    // assert_false(file.isClosed); XXX: File.isClosed doesn't seem to be implemented
25    assert_not_equals(file.lastModified, "");
26  }, testName);
27}
28
29test_first_argument([], 0, "empty fileBits");
30test_first_argument(["bits"], 4, "DOMString fileBits");
31test_first_argument(["��������"], 16, "Unicode DOMString fileBits");
32test_first_argument([new String('string object')], 13, "String object fileBits");
33test_first_argument([new Blob()], 0, "Empty Blob fileBits");
34test_first_argument([new Blob(["bits"])], 4, "Blob fileBits");
35test_first_argument([new File([], 'world.txt')], 0, "Empty File fileBits");
36test_first_argument([new File(["bits"], 'world.txt')], 4, "File fileBits");
37test_first_argument([new ArrayBuffer(8)], 8, "ArrayBuffer fileBits");
38test_first_argument([new Uint8Array([0x50, 0x41, 0x53, 0x53])], 4, "Typed array fileBits");
39test_first_argument(["bits", new Blob(["bits"]), new Blob(), new Uint8Array([0x50, 0x41]),
40                     new Uint16Array([0x5353]), new Uint32Array([0x53534150])], 16, "Various fileBits");
41test_first_argument([12], 2, "Number in fileBits");
42test_first_argument([[1,2,3]], 5, "Array in fileBits");
43test_first_argument([{}], 15, "Object in fileBits"); // "[object Object]"
44if (globalThis.document !== undefined) {
45  test_first_argument([document.body], 24, "HTMLBodyElement in fileBits"); // "[object HTMLBodyElement]"
46}
47test_first_argument([to_string_obj], 8, "Object with toString in fileBits");
48test_first_argument({[Symbol.iterator]() {
49  let i = 0;
50  return {next: () => [
51    {done:false, value:'ab'},
52    {done:false, value:'cde'},
53    {done:true}
54  ][i++]};
55}}, 5, 'Custom @@iterator');
56
57[
58  'hello',
59  0,
60  null
61].forEach(arg => {
62  test(t => {
63    assert_throws_js(TypeError, () => new File(arg, 'world.html'),
64                     'Constructor should throw for invalid bits argument');
65  }, `Invalid bits argument: ${JSON.stringify(arg)}`);
66});
67
68test(t => {
69  assert_throws_js(Error, () => new File([to_string_throws], 'name.txt'),
70                   'Constructor should propagate exceptions');
71}, 'Bits argument: object that throws');
72
73
74function test_second_argument(arg2, expectedFileName, testName) {
75  test(function() {
76    var file = new File(["bits"], arg2);
77    assert_true(file instanceof File);
78    assert_equals(file.name, expectedFileName);
79  }, testName);
80}
81
82test_second_argument("dummy", "dummy", "Using fileName");
83test_second_argument("dummy/foo", "dummy/foo",
84                     "No replacement when using special character in fileName");
85test_second_argument(null, "null", "Using null fileName");
86test_second_argument(1, "1", "Using number fileName");
87test_second_argument('', '', "Using empty string fileName");
88if (globalThis.document !== undefined) {
89  test_second_argument(document.body, '[object HTMLBodyElement]', "Using object fileName");
90}
91
92// testing the third argument
93[
94  {type: 'text/plain', expected: 'text/plain'},
95  {type: 'text/plain;charset=UTF-8', expected: 'text/plain;charset=utf-8'},
96  {type: 'TEXT/PLAIN', expected: 'text/plain'},
97  {type: '��������/����������', expected: ''},
98  {type: 'ascii/nonprintable\u001F', expected: ''},
99  {type: 'ascii/nonprintable\u007F', expected: ''},
100  {type: 'nonascii\u00EE', expected: ''},
101  {type: 'nonascii\u1234', expected: ''},
102  {type: 'nonparsable', expected: 'nonparsable'}
103].forEach(testCase => {
104  test(t => {
105    var file = new File(["bits"], "dummy", { type: testCase.type});
106    assert_true(file instanceof File);
107    assert_equals(file.type, testCase.expected);
108  }, `Using type in File constructor: ${testCase.type}`);
109});
110test(function() {
111  var file = new File(["bits"], "dummy", { lastModified: 42 });
112  assert_true(file instanceof File);
113  assert_equals(file.lastModified, 42);
114}, "Using lastModified");
115test(function() {
116  var file = new File(["bits"], "dummy", { name: "foo" });
117  assert_true(file instanceof File);
118  assert_equals(file.name, "dummy");
119}, "Misusing name");
120test(function() {
121  var file = new File(["bits"], "dummy", { unknownKey: "value" });
122  assert_true(file instanceof File);
123  assert_equals(file.name, "dummy");
124}, "Unknown properties are ignored");
125
126[
127  123,
128  123.4,
129  true,
130  'abc'
131].forEach(arg => {
132  test(t => {
133    assert_throws_js(TypeError, () => new File(['bits'], 'name.txt', arg),
134                     'Constructor should throw for invalid property bag type');
135  }, `Invalid property bag: ${JSON.stringify(arg)}`);
136});
137
138[
139  null,
140  undefined,
141  [1,2,3],
142  /regex/,
143  function() {}
144].forEach(arg => {
145  test(t => {
146    assert_equals(new File(['bits'], 'name.txt', arg).size, 4,
147                  'Constructor should accept object-ish property bag type');
148  }, `Unusual but valid property bag: ${arg}`);
149});
150
151test(t => {
152  assert_throws_js(Error,
153                   () => new File(['bits'], 'name.txt', {type: to_string_throws}),
154                   'Constructor should propagate exceptions');
155}, 'Property bag propagates exceptions');
156