-
Notifications
You must be signed in to change notification settings - Fork 257
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Polyfills for Node.js v18 and JSDOM runtimes (#875)
Adds a new `@php-wasm/node-polyfills` package to polyfill the features missing in Node 18 and/or JSDOM environments. The goal is to make wp-now and other Playground-based Node.js packages work in Node 18, which is the current LTS release. The polyfilled JavaScript features are: * `CustomEvent` class * `File` class * `Blob.text()` and `Blob.arrayBuffer()` methods * `Blob.arrayBuffer()` and `File.text()` methods * `Blob.stream()` and `File.stream()` methods * Ensures `File.stream().getReader({ mode: 'byob' })` is supported – this is relevant for #851 I adapted the Blob methods from https://github.com/bjornstar/blob-polyfill/blob/master/Blob.js as they seemed to provide just the logic needed here and they also worked right away. This PR is a part of #851 split out into a separate PR to make it easier to review and reason about. Supersedes #865 ## Testing instructions Confirm the unit tests pass. This PR ships a set of vite tests to confirm the polyfills work both in vanilla Node.js and in jsdom runtime environments.
- Loading branch information
Showing
22 changed files
with
579 additions
and
46 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
{ | ||
"extends": ["../../../.eslintrc.json"], | ||
"ignorePatterns": ["!**/*"], | ||
"overrides": [ | ||
{ | ||
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"], | ||
"rules": {} | ||
}, | ||
{ | ||
"files": ["*.ts", "*.tsx"], | ||
"rules": {} | ||
}, | ||
{ | ||
"files": ["*.js", "*.jsx"], | ||
"rules": {} | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
# php-wasm-node-polyfills | ||
|
||
Polyfills JavaScript classes and methods required by WordPress Playground. | ||
|
||
Ensures compatibility with the following environments: | ||
|
||
- Node.js >= 18 | ||
- JSDom | ||
|
||
## Building | ||
|
||
Run `nx build php-wasm-node-polyfills` to build the library. | ||
|
||
## Running unit tests | ||
|
||
Run `nx test php-wasm-node-polyfills` to execute the unit tests via [Jest](https://jestjs.io). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
{ | ||
"name": "@php-wasm/node-polyfills", | ||
"version": "0.0.1", | ||
"description": "PHP.wasm – polyfills for Node.js", | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/WordPress/wordpress-playground" | ||
}, | ||
"homepage": "https://developer.wordpress.org/playground", | ||
"author": "The WordPress contributors", | ||
"contributors": [ | ||
{ | ||
"name": "Adam Zielinski", | ||
"email": "[email protected]", | ||
"url": "https://github.com/adamziel" | ||
} | ||
], | ||
"type": "module", | ||
"main": "./index.cjs", | ||
"module": "./index.js", | ||
"exports": { | ||
".": { | ||
"import": "./index.js", | ||
"require": "./index.cjs" | ||
}, | ||
"./package.json": "./package.json" | ||
}, | ||
"publishConfig": { | ||
"access": "public", | ||
"directory": "../../../dist/packages/php-wasm/node-polyfills" | ||
}, | ||
"license": "GPL-2.0-or-later" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
{ | ||
"name": "php-wasm-node-polyfills", | ||
"$schema": "../../../node_modules/nx/schemas/project-schema.json", | ||
"sourceRoot": "packages/php-wasm/node-polyfills/src", | ||
"projectType": "library", | ||
"targets": { | ||
"build": { | ||
"executor": "@nx/vite:build", | ||
"outputs": ["{options.outputPath}"], | ||
"options": { | ||
"outputPath": "dist/packages/php-wasm/node-polyfills" | ||
} | ||
}, | ||
"test": { | ||
"executor": "nx:noop", | ||
"dependsOn": ["test:vite:node", "test:vite:jsdom"] | ||
}, | ||
"test:esmcjs": { | ||
"executor": "@wp-playground/nx-extensions:assert-built-esm-and-cjs", | ||
"options": { | ||
"outputPath": "dist/packages/php-wasm/node-polyfills" | ||
}, | ||
"dependsOn": ["build"] | ||
}, | ||
"test:vite:node": { | ||
"executor": "@nx/vite:test", | ||
"outputs": ["{options.reportsDirectory}"], | ||
"options": { | ||
"config": "packages/php-wasm/node-polyfills/vitest-node.config.ts", | ||
"passWithNoTests": true, | ||
"reportsDirectory": "../../../coverage/packages/php-wasm/node-polyfills" | ||
} | ||
}, | ||
"test:vite:jsdom": { | ||
"executor": "@nx/vite:test", | ||
"outputs": ["{options.reportsDirectory}"], | ||
"options": { | ||
"config": "packages/php-wasm/node-polyfills/vitest-jsdom.config.ts", | ||
"passWithNoTests": true, | ||
"reportsDirectory": "../../../coverage/packages/php-wasm/node-polyfills" | ||
} | ||
}, | ||
"lint": { | ||
"executor": "@nx/linter:eslint", | ||
"outputs": ["{options.outputFile}"], | ||
"options": { | ||
"lintFilePatterns": [ | ||
"packages/php-wasm/node-polyfills/**/*.ts", | ||
"packages/php-wasm/node-polyfills/package.json" | ||
] | ||
} | ||
} | ||
}, | ||
"tags": [] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
import './lib/blob'; | ||
import './lib/custom-event'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
import './blob'; | ||
|
||
describe('File class', () => { | ||
it('Should exist', () => { | ||
expect(File).not.toBe(undefined); | ||
}); | ||
}); | ||
|
||
describe('File.arrayBuffer() method', () => { | ||
it('should exist', async () => { | ||
expect(typeof File.prototype.arrayBuffer).toBe('function'); | ||
}); | ||
it('should resolve to a valid array buffer', async () => { | ||
const inputBytes = new Uint8Array([1, 2, 3, 4]); | ||
const file = new File([inputBytes], 'test'); | ||
const outputBuffer = await file.arrayBuffer(); | ||
const outputBytes = new Uint8Array(outputBuffer); | ||
expect(outputBytes).toEqual(inputBytes); | ||
}); | ||
}); | ||
|
||
describe('File.stream() method', () => { | ||
it('should exist', async () => { | ||
expect(typeof File.prototype.stream).toBe('function'); | ||
}); | ||
it('should returns a valid stream', async () => { | ||
const inputBytes = new Uint8Array([1, 2, 3, 4]); | ||
const file = new File([inputBytes], 'test'); | ||
const stream = file.stream(); | ||
const reader = stream.getReader(); | ||
|
||
const firstRead = await reader.read(); | ||
expect(firstRead.value).toEqual(inputBytes); | ||
expect(firstRead.done).toBe(false); | ||
|
||
const secondRead = await reader.read(); | ||
expect(secondRead.done).toBe(true); | ||
}); | ||
it('should be a valid BYOB stream that allows reading an arbitrary number of bytes', async () => { | ||
const inputBytes = new Uint8Array([1, 2, 3, 4]); | ||
const file = new File([inputBytes], 'test'); | ||
const stream = file.stream(); | ||
const reader = stream.getReader({ mode: 'byob' }); | ||
|
||
const firstRead = await reader.read(new Uint8Array(3)); | ||
expect(firstRead.value).toEqual(inputBytes.slice(0, 3)); | ||
expect(firstRead.done).toBe(false); | ||
|
||
const secondRead = await reader.read(new Uint8Array(2)); | ||
expect(secondRead.value).toEqual(inputBytes.slice(3)); | ||
expect(secondRead.done).toBe(false); | ||
|
||
const thirdRead = await reader.read(new Uint8Array(2)); | ||
expect(thirdRead.done).toBe(true); | ||
}); | ||
}); |
Oops, something went wrong.