Skip to content

Commit

Permalink
add file class to node:buffer
Browse files Browse the repository at this point in the history
  • Loading branch information
anonrig committed Aug 8, 2024
1 parent 0685eec commit 13bc622
Show file tree
Hide file tree
Showing 7 changed files with 126 additions and 33 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"devDependencies": {
"@bazel/bazelisk": "~1.19.0",
"@types/debug": "^4.1.10",
"@types/node": "^20.11.6",
"@types/node": "^20.14.8",
"@types/prettier": "^2.7.1",
"@typescript-eslint/eslint-plugin": "^7.3.1",
"@typescript-eslint/parser": "^7.3.1",
Expand Down
8 changes: 4 additions & 4 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 5 additions & 6 deletions src/node/buffer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// Licensed under the Apache 2.0 license found in the LICENSE file or at:
// https://opensource.org/licenses/Apache-2.0

/* eslint-disable @typescript-eslint/no-unsafe-assignment */

import {
constants,
kMaxLength,
Expand All @@ -13,12 +15,10 @@ import {
transcode,
} from 'node-internal:internal_buffer';

// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const atob = globalThis.atob;
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const btoa = globalThis.btoa;
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const Blob = globalThis.Blob;
const File = globalThis.File;

export {
atob,
Expand All @@ -28,23 +28,22 @@ export {
kStringMaxLength,
Blob,
Buffer,
File,
SlowBuffer,
isAscii,
isUtf8,
transcode,
};

export default {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
atob,
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
btoa,
constants,
kMaxLength,
kStringMaxLength,
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
Blob,
Buffer,
File,
SlowBuffer,
isAscii,
isUtf8,
Expand Down
26 changes: 13 additions & 13 deletions src/node/internal/crypto_random.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export function randomBytes(size: number, callback?: RandomBytesCallback) : Uint
}

export function randomFillSync(
buffer: ArrayBufferView|ArrayBuffer,
buffer: NodeJS.ArrayBufferView,
offset?: number,
size?: number) {
if (!isAnyArrayBuffer(buffer) && !isArrayBufferView(buffer)) {
Expand All @@ -79,7 +79,7 @@ export function randomFillSync(
'DataView',
'ArrayBuffer',
'SharedArrayBuffer'
],buffer);
], buffer);
}
const maxLength = (buffer as Uint8Array).length;
if (offset !== undefined) {
Expand All @@ -89,23 +89,23 @@ export function randomFillSync(
validateInteger(size!, 'size', 0, maxLength - offset);
} else size = maxLength;
if (isAnyArrayBuffer(buffer)) {
buffer = Buffer.from(buffer as ArrayBuffer);
buffer = Buffer.from(buffer);
}
buffer = (buffer as Buffer).subarray(offset, offset + size);
return crypto.getRandomValues(buffer as ArrayBufferView);
return crypto.getRandomValues(buffer);
}

export type RandomFillCallback = (err: any|null, buf?: ArrayBufferView|ArrayBuffer) => void;
export function randomFill(buffer: ArrayBufferView|ArrayBuffer,
export type RandomFillCallback = (err: any|null, buf?: NodeJS.ArrayBufferView) => void;
export function randomFill(buffer: NodeJS.ArrayBufferView,
callback?: RandomFillCallback) : void;
export function randomFill(buffer: ArrayBufferView|ArrayBuffer,
export function randomFill(buffer: NodeJS.ArrayBufferView,
offset: number,
callback?: RandomFillCallback) : void;
export function randomFill(buffer: ArrayBufferView|ArrayBuffer,
export function randomFill(buffer: NodeJS.ArrayBufferView,
offset: number,
size: number,
callback?: RandomFillCallback) : void;
export function randomFill(buffer: ArrayBufferView|ArrayBuffer,
export function randomFill(buffer: NodeJS.ArrayBufferView,
offsetOrCallback?: number|RandomFillCallback,
sizeOrCallback?: number|RandomFillCallback,
callback?: RandomFillCallback) {
Expand All @@ -115,7 +115,7 @@ export function randomFill(buffer: ArrayBufferView|ArrayBuffer,
'DataView',
'ArrayBuffer',
'SharedArrayBuffer'
],buffer);
], buffer);
}

let offset = 0;
Expand Down Expand Up @@ -203,17 +203,17 @@ export function randomInt(minOrMax: number,
if (typeof callback === 'function') {
validateInteger(minOrMax, 'min');
validateInteger(maxOrCallback, 'max');
min = minOrMax as number;
min = minOrMax;
max = maxOrCallback as number;
} else if (typeof maxOrCallback === 'function') {
min = 0;
validateInteger(minOrMax, 'max');
max = minOrMax as number;
max = minOrMax;
callback = maxOrCallback as RandomIntCallback;
} else if (arguments.length === 2) {
validateInteger(minOrMax, 'min');
validateInteger(maxOrCallback, 'max');
min = minOrMax as number;
min = minOrMax;
max = maxOrCallback as number;
} else {
min = 0;
Expand Down
8 changes: 0 additions & 8 deletions src/node/internal/web_crypto.d.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,4 @@
// Just enough of web crypto api to write the code in node-compat

declare namespace crypto {
function getRandomValues<T extends ArrayBufferView | null>(array: T): T;
function randomUUID(): string;

const subtle: SubtleCrypto;
}

type SubtleCrypto = unknown;

type CryptoKey = unknown;
Expand Down
2 changes: 1 addition & 1 deletion src/workerd/api/blob.c++
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@ jsg::Ref<File> File::constructor(jsg::Lock& js, jsg::Optional<Bits> bits,

double lastModified;
KJ_IF_SOME(m, maybeLastModified) {
lastModified = m;
lastModified = kj::isNaN(m) ? 0 : m;
} else {
lastModified = dateNow();
}
Expand Down
102 changes: 102 additions & 0 deletions src/workerd/api/node/tests/buffer-nodejs-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import {
isAscii,
isUtf8,
transcode,
File,
} from 'node:buffer';

import * as buffer from 'node:buffer';
Expand Down Expand Up @@ -5792,3 +5793,104 @@ export const transcodeTest = {
}
}
};

// Tests are taken from Node.js
// https://github.com/nodejs/node/blob/a4f609fa/test/parallel/test-file.js
export const fileTest = {
test() {
throws(() => new File(), TypeError);
throws(() => new File([]), TypeError);
throws(() => File.prototype.name, TypeError);
throws(() => File.prototype.lastModified, TypeError);

{
const keys = Object.keys(File.prototype).sort();
deepStrictEqual(keys, ['lastModified', 'name']);
}

{
const file = new File([], 'dummy.txt.exe');
strictEqual(file.name, 'dummy.txt.exe');
strictEqual(file.size, 0);
strictEqual(typeof file.lastModified, 'number');
ok(file.lastModified <= Date.now());
}

{
const toPrimitive = {
[Symbol.toPrimitive]() {
return 'NaN';
}
};

const invalidLastModified = [
null,
'string',
false,
toPrimitive,
];

for (const lastModified of invalidLastModified) {
const file = new File([], '', { lastModified });
strictEqual(file.lastModified, 0);
}
}

{
const file = new File([], '', { lastModified: undefined });
notStrictEqual(file.lastModified, 0);
}

{
const toPrimitive = {
[Symbol.toPrimitive]() {
throw new TypeError('boom');
}
};

const throwValues = [
BigInt(3n),
toPrimitive,
];

for (const lastModified of throwValues) {
throws(() => new File([], '', { lastModified }), TypeError);
}
}

{
const valid = [
{
[Symbol.toPrimitive]() {
return 10;
}
},
new Number(10),
10,
];

for (const lastModified of valid) {
strictEqual(new File([], '', { lastModified }).lastModified, 10);
}
}

{
function MyClass() {}
MyClass.prototype.lastModified = 10;

const file = new File([], '', new MyClass());
strictEqual(file.lastModified, 10);
}

{
let counter = 0;
new File([], '', {
get lastModified() {
counter++;
return 10;
}
});
strictEqual(counter, 1);
}
}
}

0 comments on commit 13bc622

Please sign in to comment.