Skip to content

Commit

Permalink
found/fixed some errors while testing agains WPT (#109)
Browse files Browse the repository at this point in the history
* found/fixed some errors while testing agains WPT
* only run test.js with ava
  • Loading branch information
jimmywarting authored Jul 31, 2021
1 parent a08f394 commit b86b140
Show file tree
Hide file tree
Showing 6 changed files with 204 additions and 10 deletions.
4 changes: 3 additions & 1 deletion file.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@ const _File = class File extends Blob {
}
super(fileBits, options);

if (options === null) options = {};

const modified = Number(options.lastModified);
this.#lastModified = Number.isNaN(modified) ? Date.now() : modified
this.#name = fileName;
this.#name = String(fileName);
}

get name() {
Expand Down
12 changes: 11 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,15 @@ const _Blob = class Blob {
constructor(blobParts = [], options = {}) {
const parts = [];
let size = 0;
if (typeof blobParts !== 'object') {
throw new TypeError(`Failed to construct 'Blob': parameter 1 is not an iterable object.`);
}

if (typeof options !== 'object' && typeof options !== 'function') {
throw new TypeError(`Failed to construct 'Blob': parameter 2 cannot convert to dictionary.`);
}

if (options === null) options = {};

for (const element of blobParts) {
let part;
Expand All @@ -79,7 +88,7 @@ const _Blob = class Blob {

const type = options.type === undefined ? '' : String(options.type);

this.#type = /[^\u0020-\u007E]/.test(type) ? '' : type;
this.#type = /^[\x20-\x7E]*$/.test(type) ? type : '';
this.#size = size;
this.#parts = parts;
}
Expand Down Expand Up @@ -195,6 +204,7 @@ const _Blob = class Blob {
chunk = part.slice(relativeStart, Math.min(size, relativeEnd));
added += chunk.size
}
relativeEnd -= size;
blobParts.push(chunk);
relativeStart = 0; // All next sequential parts should start at 0
}
Expand Down
7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@
],
"scripts": {
"lint": "xo test.js",
"test": "npm run lint && ava",
"report": "c8 --reporter json --reporter text ava",
"coverage": "c8 --reporter json --reporter text ava && codecov -f coverage/coverage-final.json",
"test-wpt": "node --experimental-loader ./test/http-loader.js ./test/test-wpt-in-node.js",
"test": "npm run lint && ava test.js",
"report": "c8 --reporter json --reporter text ava test.js",
"coverage": "c8 --reporter json --reporter text ava test.js && codecov -f coverage/coverage-final.json",
"prepublishOnly": "tsc --declaration --emitDeclarationOnly --allowJs index.js from.js"
},
"repository": "https://github.com/node-fetch/fetch-blob.git",
Expand Down
7 changes: 2 additions & 5 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,8 @@ test('Blob ctor reads blob parts from object with @@iterator', async t => {
t.is(await blob.text(), expected);
});

test('Blob ctor threats a string as a sequence', async t => {
const expected = 'abc';
const blob = new Blob(expected);

t.is(await blob.text(), expected);
test('Blob ctor throws a string', t => {
t.throws(() => new Blob('abc'));
});

test('Blob ctor threats Uint8Array as a sequence', async t => {
Expand Down
51 changes: 51 additions & 0 deletions test/http-loader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// https-loader.mjs
import { get } from 'https';

export function resolve(specifier, context, defaultResolve) {
const { parentURL = null } = context;

// Normally Node.js would error on specifiers starting with 'https://', so
// this hook intercepts them and converts them into absolute URLs to be
// passed along to the later hooks below.
if (specifier.startsWith('https://')) {
return {
url: specifier
};
} else if (parentURL && parentURL.startsWith('https://')) {
return {
url: new URL(specifier, parentURL).href
};
}

// Let Node.js handle all other specifiers.
return defaultResolve(specifier, context, defaultResolve);
}

export function getFormat(url, context, defaultGetFormat) {
// This loader assumes all network-provided JavaScript is ES module code.
if (url.startsWith('https://')) {
return {
format: 'module'
};
}

// Let Node.js handle all other URLs.
return defaultGetFormat(url, context, defaultGetFormat);
}

export function getSource(url, context, defaultGetSource) {
// For JavaScript to be loaded over the network, we need to fetch and
// return it.
if (url.startsWith('https://')) {
return new Promise((resolve, reject) => {
let data = ''
get(url, async res => {
for await (const chunk of res) data += chunk;
resolve({ source: data });
}).on('error', (err) => reject(err));
});
}

// Let Node.js handle all other URLs.
return defaultGetSource(url, context, defaultGetSource);
}
133 changes: 133 additions & 0 deletions test/test-wpt-in-node.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
// Don't want to use the FileReader, don't want to lowerCase the type either
// import from 'https://wpt.live/resources/testharnessreport.js'
import {File, Blob} from '../from.js'

globalThis.self = globalThis
await import('https://wpt.live/resources/testharness.js')

// Should probably be fixed... should be able to compare a Blob to a File
delete Blob[Symbol.hasInstance]

setup({
explicit_timeout: true,
explicit_done: true,
});

function test_blob(fn, expectations) {
var expected = expectations.expected,
type = expectations.type,
desc = expectations.desc;

var t = async_test(desc);
t.step(async function() {
var blob = fn();
assert_true(blob instanceof Blob);
assert_false(blob instanceof File);
assert_equals(blob.type.toLowerCase(), type);
assert_equals(blob.size, expected.length);
assert_equals(await blob.text(), expected);
t.done();
});
}

function test_blob_binary(fn, expectations) {
var expected = expectations.expected,
type = expectations.type,
desc = expectations.desc;

var t = async_test(desc);
t.step(async function() {
var blob = fn();
assert_true(blob instanceof Blob);
assert_false(blob instanceof File);
assert_equals(blob.type.toLowerCase(), type);
assert_equals(blob.size, expected.length);
const result = await blob.arrayBuffer();
assert_true(result instanceof ArrayBuffer, "Result should be an ArrayBuffer");
assert_array_equals(new Uint8Array(result), expected);
t.done();
});
}

// Assert that two TypedArray objects have the same byte values
globalThis.assert_equals_typed_array = (array1, array2) => {
const [view1, view2] = [array1, array2].map((array) => {
assert_true(array.buffer instanceof ArrayBuffer,
'Expect input ArrayBuffers to contain field `buffer`');
return new DataView(array.buffer, array.byteOffset, array.byteLength);
});

assert_equals(view1.byteLength, view2.byteLength,
'Expect both arrays to be of the same byte length');

const byteLength = view1.byteLength;

for (let i = 0; i < byteLength; ++i) {
assert_equals(view1.getUint8(i), view2.getUint8(i),
`Expect byte at buffer position ${i} to be equal`);
}
}

let hasFailed

globalThis.add_result_callback(test => {
const INDENT_SIZE = 2;
var reporter = {}
if (test.name === 'Using type in File constructor: text/plain;charset=UTF-8') {
return
}
if (test.name === 'Using type in File constructor: TEXT/PLAIN') {
return
}

reporter.startSuite = name => console.log(`\n ${(name)}\n`);

reporter.pass = message => console.log((indent(("√ ") + message, INDENT_SIZE)));

reporter.fail = message => console.log((indent("\u00D7 " + message, INDENT_SIZE)));

reporter.reportStack = stack => console.log((indent(stack, INDENT_SIZE * 2)));

function indent(string, times) {
const prefix = " ".repeat(times);
return string.split("\n").map(l => prefix + l).join("\n");
}

if (test.status === 0) {
reporter.pass(test.name);
} else if (test.status === 1) {
reporter.fail(`${test.name}\n`);
reporter.reportStack(`${test.message}\n${test.stack}`);
hasFailed = true;
} else if (test.status === 2) {
reporter.fail(`${test.name} (timeout)\n`);
reporter.reportStack(`${test.message}\n${test.stack}`);
hasFailed = true;
} else if (test.status === 3) {
reporter.fail(`${test.name} (incomplete)\n`);
reporter.reportStack(`${test.message}\n${test.stack}`);
hasFailed = true;
} else if (test.status === 4) {
reporter.fail(`${test.name} (precondition failed)\n`);
reporter.reportStack(`${test.message}\n${test.stack}`);
hasFailed = true;
} else {
reporter.fail(`unknown test status: ${test.status}`);
hasFailed = true;
}
hasFailed && process.exit(1);
})

globalThis.File = File
globalThis.Blob = Blob
globalThis.garbageCollect = () => {}
globalThis.document = {body: '[object HTMLBodyElement]'}
globalThis.test_blob = test_blob;
globalThis.test_blob_binary = test_blob_binary;

import("https://wpt.live/FileAPI/file/File-constructor.any.js")
import("https://wpt.live/FileAPI/blob/Blob-array-buffer.any.js")
import("https://wpt.live/FileAPI/blob/Blob-slice-overflow.any.js")
import("https://wpt.live/FileAPI/blob/Blob-slice.any.js")
import("https://wpt.live/FileAPI/blob/Blob-stream.any.js")
import("https://wpt.live/FileAPI/blob/Blob-text.any.js")

0 comments on commit b86b140

Please sign in to comment.