From f2b56aa51d85ff2d76c3fff225dcee2b5b6b9bde Mon Sep 17 00:00:00 2001 From: Paul Berberian Date: Fri, 8 Mar 2024 15:36:59 +0100 Subject: [PATCH] Provide ES5 version of the worker file The `MULTI_THREAD` experimental feature rely on a Worker file which use ES2017 features. The most relied on way to import this file is through its "embedded version", which is usually not processed by bundlers/compilers of the application so it could be translated to a more compatible (usually older) version of JavaScript. Yet, we're encountering on the PlayStation 4 a case where the `MULTI_THREAD` feature may be used, the device is compatible to the WebWorker web API, but does not understand all of ES2017 features (let alone ES2015 features). For those devices, and because we could still want to be able to rely on ES2017 for the vast majority of devices that do support it, I propose a solution where we provide a supplementary Worker file that is compiled down to ES5. I rel on webpack instead of esbuild for this because esbuild does not target es5 easily. I'm not very confident of my webpack skills - even more considering that Worker environments have some constraints and I'm not sure of every web+JS features that babel + webpack might use, but hopefully, this should work (I'll test it). There are several downsides coming with this commit: 1. Webpack takes several seconds on my PC to compile the worker files. As our building process was before relatively fast, this "slowness" is now visible during build, where "Bundling worker files..." is the slowest step on my PC. 2. Because I'm not that confident on the file outputted, I decided to re-run all integration tests running in `MULTI_THREAD` mode both on the regular and the ES5 version of that script. This means that integration tests will take much more time to complete. --- doc/api/Miscellaneous/MultiThreading.md | 29 ++++ package-lock.json | 137 ++++++++++++----- package.json | 4 +- scripts/bundle_worker.mjs | 144 +++++++++++++++++- scripts/generate_build.mjs | 24 ++- scripts/generate_embeds.mjs | 23 ++- .../scenarios/dash_multi_periods.js | 1 + tests/integration/scenarios/dash_static.js | 20 +++ tests/integration/scenarios/idle.js | 8 +- .../integration/scenarios/initial_playback.js | 8 +- .../scenarios/loadVideo_options.js | 7 +- .../utils/launch_tests_for_content.js | 10 +- webpack.config.mjs | 4 - 13 files changed, 352 insertions(+), 67 deletions(-) diff --git a/doc/api/Miscellaneous/MultiThreading.md b/doc/api/Miscellaneous/MultiThreading.md index 3c78977859..8f55afe657 100644 --- a/doc/api/Miscellaneous/MultiThreading.md +++ b/doc/api/Miscellaneous/MultiThreading.md @@ -380,3 +380,32 @@ if (currentModeInfo === null) { console.info("We're running completely in main thread."); } ``` + +## Note about ES5 Environment + +By default, the Worker file will use es2017 features which should be compatible to a +majority of devices. + +However, some older devices might not be compatible with it yet still compatible to the +WebWorker API (and thus the `MULTI_THREAD` feature), yet not with ES2017. For those +platforms, the RxPlayer also provide an ES5 variant of the Worker file: + +- The easiest way is to just import in your application its "embedded" version, exported + through the `"rx-player/experimental/features/embeds"` path: + + ```js + import { EMBEDDED_WORKER_ES5 } from "rx-player/experimental/features/embeds"; + ``` + + This allows to bypass the need to store and serve separately that file. + + If you would prefer more control and a smaller bundle size, you may instead consider the + other following ways to it as a separate file. + +- With every release note published on GitHub as `worker.es5.js` (you should only use the + file linked to the RxPlayer's version you're using), + +- It is also available as `dist/worker.es5.js` from the root directory of the project + published on npm. As such, it might already be found in your project's directory, for + example in the `node_modules` directory (most probably in `node_modules/rx-player/dist/` + depending on your project). diff --git a/package-lock.json b/package-lock.json index fc04287a37..b2fb88728a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -59,8 +59,8 @@ "ts-jest": "29.1.1", "ts-loader": "9.5.1", "typescript": "5.3.3", - "webpack": "5.89.0", - "webpack-cli": "5.1.4" + "webpack": "^5.90.3", + "webpack-cli": "^5.1.4" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -3363,9 +3363,9 @@ "dev": true }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.19", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", - "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dev": true, "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -3565,9 +3565,9 @@ } }, "node_modules/@types/estree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz", - "integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", "dev": true }, "node_modules/@types/graceful-fs": { @@ -13447,13 +13447,13 @@ } }, "node_modules/terser": { - "version": "5.16.8", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.8.tgz", - "integrity": "sha512-QI5g1E/ef7d+PsDifb+a6nnVgC4F22Bg6T0xrBrz6iloVB4PUkkunp6V8nzoOOZJIzjWVdAGqCdlKlhLq/TbIA==", + "version": "5.29.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.29.1.tgz", + "integrity": "sha512-lZQ/fyaIGxsbGxApKmoPTODIzELy3++mXhS5hOqaAWZjQtpq/hFHAc+rm29NND1rYRxRWKcjuARNwULNXa5RtQ==", "dev": true, "dependencies": { - "@jridgewell/source-map": "^0.3.2", - "acorn": "^8.5.0", + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, @@ -14263,19 +14263,19 @@ } }, "node_modules/webpack": { - "version": "5.89.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.89.0.tgz", - "integrity": "sha512-qyfIC10pOr70V+jkmud8tMfajraGCZMBWJtrmuBymQKCrLTRejBI8STDp1MCyZu/QTdZSeacCQYpYNQVOzX5kw==", + "version": "5.90.3", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.90.3.tgz", + "integrity": "sha512-h6uDYlWCctQRuXBs1oYpVe6sFcWedl0dpcVaTf/YF67J9bKvwJajFulMVSYKHrksMB3I/pIagRzDxwxkebuzKA==", "dev": true, "dependencies": { "@types/eslint-scope": "^3.7.3", - "@types/estree": "^1.0.0", + "@types/estree": "^1.0.5", "@webassemblyjs/ast": "^1.11.5", "@webassemblyjs/wasm-edit": "^1.11.5", "@webassemblyjs/wasm-parser": "^1.11.5", "acorn": "^8.7.1", "acorn-import-assertions": "^1.9.0", - "browserslist": "^4.14.5", + "browserslist": "^4.21.10", "chrome-trace-event": "^1.0.2", "enhanced-resolve": "^5.15.0", "es-module-lexer": "^1.2.1", @@ -14289,7 +14289,7 @@ "neo-async": "^2.6.2", "schema-utils": "^3.2.0", "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.7", + "terser-webpack-plugin": "^5.3.10", "watchpack": "^2.4.0", "webpack-sources": "^3.2.3" }, @@ -14403,6 +14403,49 @@ "url": "https://opencollective.com/webpack" } }, + "node_modules/webpack/node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/webpack/node_modules/terser-webpack-plugin": { + "version": "5.3.10", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", + "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.20", + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.1", + "terser": "^5.26.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, "node_modules/whatwg-encoding": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", @@ -17050,9 +17093,9 @@ "dev": true }, "@jridgewell/trace-mapping": { - "version": "0.3.19", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", - "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dev": true, "requires": { "@jridgewell/resolve-uri": "^3.1.0", @@ -17239,9 +17282,9 @@ } }, "@types/estree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz", - "integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", "dev": true }, "@types/graceful-fs": { @@ -24613,13 +24656,13 @@ "dev": true }, "terser": { - "version": "5.16.8", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.8.tgz", - "integrity": "sha512-QI5g1E/ef7d+PsDifb+a6nnVgC4F22Bg6T0xrBrz6iloVB4PUkkunp6V8nzoOOZJIzjWVdAGqCdlKlhLq/TbIA==", + "version": "5.29.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.29.1.tgz", + "integrity": "sha512-lZQ/fyaIGxsbGxApKmoPTODIzELy3++mXhS5hOqaAWZjQtpq/hFHAc+rm29NND1rYRxRWKcjuARNwULNXa5RtQ==", "dev": true, "requires": { - "@jridgewell/source-map": "^0.3.2", - "acorn": "^8.5.0", + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, @@ -25194,19 +25237,19 @@ "dev": true }, "webpack": { - "version": "5.89.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.89.0.tgz", - "integrity": "sha512-qyfIC10pOr70V+jkmud8tMfajraGCZMBWJtrmuBymQKCrLTRejBI8STDp1MCyZu/QTdZSeacCQYpYNQVOzX5kw==", + "version": "5.90.3", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.90.3.tgz", + "integrity": "sha512-h6uDYlWCctQRuXBs1oYpVe6sFcWedl0dpcVaTf/YF67J9bKvwJajFulMVSYKHrksMB3I/pIagRzDxwxkebuzKA==", "dev": true, "requires": { "@types/eslint-scope": "^3.7.3", - "@types/estree": "^1.0.0", + "@types/estree": "^1.0.5", "@webassemblyjs/ast": "^1.11.5", "@webassemblyjs/wasm-edit": "^1.11.5", "@webassemblyjs/wasm-parser": "^1.11.5", "acorn": "^8.7.1", "acorn-import-assertions": "^1.9.0", - "browserslist": "^4.14.5", + "browserslist": "^4.21.10", "chrome-trace-event": "^1.0.2", "enhanced-resolve": "^5.15.0", "es-module-lexer": "^1.2.1", @@ -25220,7 +25263,7 @@ "neo-async": "^2.6.2", "schema-utils": "^3.2.0", "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.7", + "terser-webpack-plugin": "^5.3.10", "watchpack": "^2.4.0", "webpack-sources": "^3.2.3" }, @@ -25235,6 +25278,28 @@ "ajv": "^6.12.5", "ajv-keywords": "^3.5.2" } + }, + "serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "terser-webpack-plugin": { + "version": "5.3.10", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", + "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", + "dev": true, + "requires": { + "@jridgewell/trace-mapping": "^0.3.20", + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.1", + "terser": "^5.26.0" + } } } }, diff --git a/package.json b/package.json index 1217de5e20..014b9ffb1f 100644 --- a/package.json +++ b/package.json @@ -243,8 +243,8 @@ "ts-jest": "29.1.1", "ts-loader": "9.5.1", "typescript": "5.3.3", - "webpack": "5.89.0", - "webpack-cli": "5.1.4" + "webpack": "^5.90.3", + "webpack-cli": "^5.1.4" }, "scripts-list": { "Build a demo page (e.g. to test a code change)": { diff --git a/scripts/bundle_worker.mjs b/scripts/bundle_worker.mjs index 81fc84ff61..45e0fd1e51 100755 --- a/scripts/bundle_worker.mjs +++ b/scripts/bundle_worker.mjs @@ -11,9 +11,11 @@ * right options. */ -import { join } from "path"; +import * as path from "path"; import { pathToFileURL } from "url"; import esbuild from "esbuild"; +import TerserPlugin from "terser-webpack-plugin"; +import webpack from "webpack"; import rootDirectory from "./utils/project_root_directory.mjs"; import getHumanReadableHours from "./utils/get_human_readable_hours.mjs"; @@ -34,6 +36,12 @@ if (import.meta.url === pathToFileURL(process.argv[1]).href) { production, silent, }); + buildWorkerEs5({ + watch: shouldWatch, + minify: shouldMinify, + production, + silent, + }); } /** @@ -54,7 +62,7 @@ export default function buildWorker(options) { const watch = !!options.watch; const isDevMode = !options.production; const isSilent = options.silent; - const outfile = options.outfile ?? join(rootDirectory, "dist/worker.js"); + const outfile = options.outfile ?? path.join(rootDirectory, "dist/worker.js"); /** Declare a plugin to anounce when a build begins and ends */ const consolePlugin = { @@ -62,7 +70,8 @@ export default function buildWorker(options) { setup(build) { build.onStart(() => { console.log( - `\x1b[33m[${getHumanReadableHours()}]\x1b[0m ` + "New worker build started", + `\x1b[33m[${getHumanReadableHours()}]\x1b[0m ` + + "New Worker file build started", ); }); build.onEnd((result) => { @@ -70,14 +79,14 @@ export default function buildWorker(options) { const { errors, warnings } = result; console.log( `\x1b[33m[${getHumanReadableHours()}]\x1b[0m ` + - `Worker re-built with ${errors.length} error(s) and ` + + `Worker file re-built with ${errors.length} error(s) and ` + ` ${warnings.length} warning(s) `, ); return; } console.log( `\x1b[32m[${getHumanReadableHours()}]\x1b[0m ` + - `Worker updated at ${outfile}!`, + `Worker file updated at ${outfile}!`, ); }); }, @@ -87,7 +96,7 @@ export default function buildWorker(options) { // Create a context for incremental builds return esbuild[meth]({ - entryPoints: [join(rootDirectory, "src/worker_entry_point.ts")], + entryPoints: [path.join(rootDirectory, "src/worker_entry_point.ts")], bundle: true, target: "es2017", minify, @@ -111,7 +120,7 @@ export default function buildWorker(options) { .catch((err) => { if (!isSilent) { console.error( - `\x1b[31m[${getHumanReadableHours()}]\x1b[0m Worker build failed:`, + `\x1b[31m[${getHumanReadableHours()}]\x1b[0m Worker file build failed:`, err, ); } @@ -119,6 +128,127 @@ export default function buildWorker(options) { }); } +export function buildWorkerEs5(options) { + const shouldMinify = !!options.minify; + const watch = !!options.watch; + const isDevMode = !options.production; + const isSilent = options.silent; + const outfile = options.outfile ?? path.join(rootDirectory, "dist/worker.es5.js"); + const outputPath = path.dirname(outfile); + const filename = path.basename(outfile); + + const plugins = [ + new webpack.DefinePlugin({ + __ENVIRONMENT__: { + PRODUCTION: 0, + DEV: 1, + CURRENT_ENV: isDevMode ? 1 : 0, + }, + __LOGGER_LEVEL__: JSON.stringify({ CURRENT_LEVEL: "NONE" }), + }), + ]; + + if (!isSilent) { + console.log( + `\x1b[33m[${getHumanReadableHours()}]\x1b[0m ` + + "New ES5 Worker file build started", + ); + } + + const compiler = webpack({ + mode: isDevMode ? "development" : "production", + entry: [path.join(rootDirectory, "src/worker_entry_point.ts")], + output: { + path: outputPath, + filename, + environment: { + arrowFunction: false, + asyncFunction: false, + bigIntLiteral: false, + const: false, + destructuring: false, + dynamicImport: false, + dynamicImportInWorker: false, + forOf: false, + globalThis: false, + module: false, + optionalChaining: false, + templateLiteral: false, + }, + }, + optimization: { + minimize: shouldMinify, + minimizer: shouldMinify ? [new TerserPlugin()] : [], + }, + performance: { + maxEntrypointSize: shouldMinify ? 600000 : 2500000, + maxAssetSize: shouldMinify ? 600000 : 2500000, + }, + resolve: { + extensions: [".ts", ".tsx", ".js", ".jsx", ".json"], + }, + module: { + rules: [ + { + test: /\.tsx?$/, + use: [ + { + loader: "babel-loader", + options: { + cacheDirectory: true, + presets: [["@babel/env", { loose: true, modules: false }]], + plugins: [["@babel/plugin-transform-runtime"]], + }, + }, + { loader: "ts-loader" }, + ], + }, + ], + }, + plugins, + }); + + return new Promise((res, rej) => { + if (watch) { + compiler.watch({}, (err) => { + if (err) { + if (!isSilent) { + console.error( + `\x1b[31m[${getHumanReadableHours()}]\x1b[0m ES5 Worker file build failed:`, + err, + ); + } + rej(err); + } else if (!isSilent) { + console.log( + `\x1b[32m[${getHumanReadableHours()}]\x1b[0m ` + + `ES5 Worker file updated at ${outfile}!`, + ); + } + res(); + }); + return; + } + compiler.run((err) => { + if (err) { + if (!isSilent) { + console.error( + `\x1b[31m[${getHumanReadableHours()}]\x1b[0m ES5 Worker file build failed:`, + err, + ); + } + rej(err); + } else if (!isSilent) { + console.log( + `\x1b[32m[${getHumanReadableHours()}]\x1b[0m ` + + `ES5 Worker file written at ${outfile}!`, + ); + } + res(); + }); + }); +} + /** * Display through `console.log` an helping message relative to how to run this * script. diff --git a/scripts/generate_build.mjs b/scripts/generate_build.mjs index 5f50f43111..20819abca5 100755 --- a/scripts/generate_build.mjs +++ b/scripts/generate_build.mjs @@ -24,7 +24,7 @@ import * as path from "path"; import { fileURLToPath, pathToFileURL } from "url"; import { rimraf } from "rimraf"; import generateEmbeds from "./generate_embeds.mjs"; -import buildWorker from "./bundle_worker.mjs"; +import buildWorker, { buildWorkerEs5 } from "./bundle_worker.mjs"; const currentDirectory = path.dirname(fileURLToPath(import.meta.url)); @@ -77,13 +77,21 @@ async function generateBuild(options = {}) { ); } - console.log(" 👷 Bundling worker code..."); - await buildWorker({ - watch: false, - minify: !devMode, - production: !devMode, - silent: true, - }); + console.log(" 👷 Bundling worker files..."); + await Promise.all([ + buildWorker({ + watch: false, + minify: !devMode, + production: !devMode, + silent: true, + }), + buildWorkerEs5({ + watch: false, + minify: !devMode, + production: !devMode, + silent: true, + }), + ]); console.log(" 🤖 Generating embedded code..."); await generateEmbeds(); diff --git a/scripts/generate_embeds.mjs b/scripts/generate_embeds.mjs index 9405c2b057..d160ed07e9 100644 --- a/scripts/generate_embeds.mjs +++ b/scripts/generate_embeds.mjs @@ -50,11 +50,13 @@ import { fileURLToPath, pathToFileURL } from "url"; const currentDir = dirname(fileURLToPath(import.meta.url)); const originalWasmFilePath = join(currentDir, "../dist/mpd-parser.wasm"); const originalWorkerFilePath = join(currentDir, "../dist/worker.js"); +const originalWorkerEs5FilePath = join(currentDir, "../dist/worker.es5.js"); const codeGenDir = join(currentDir, "../src/__GENERATED_CODE"); const indexPath = join(codeGenDir, "./index.ts"); const mpdEmbedPath = join(codeGenDir, "./embedded_dash_wasm.ts"); const workerEmbedPath = join(codeGenDir, "./embedded_worker.ts"); +const workerEs5EmbedPath = join(codeGenDir, "./embedded_worker_es5.ts"); // If true, this script is called directly if (import.meta.url === pathToFileURL(process.argv[1]).href) { @@ -68,7 +70,12 @@ async function generateEmbeds() { if (!fs.existsSync(codeGenDir)) { fs.mkdirSync(codeGenDir); } - await Promise.all([writeWebAssemblyEmbed(), writeWorkerEmbed(), writeIndexCode()]); + await Promise.all([ + writeWebAssemblyEmbed(), + writeWorkerEmbed(), + writeWorkerEs5Embed(), + writeIndexCode(), + ]); } catch (err) { console.log(err); return Promise.reject(err); @@ -98,10 +105,22 @@ export default blob;`; await writeFile(workerEmbedPath, workerEmbedCode); } +async function writeWorkerEs5Embed() { + const workerEs5Data = await readFile(originalWorkerEs5FilePath, "utf-8"); + const workerEs5EmbedCode = + "const blob = new Blob([" + + `"(function(){" + ${JSON.stringify(workerEs5Data)} + "})()"` + + `], { type: "application/javascript" }); +export { blob as EMBEDDED_WORKER_ES5 }; +export default blob;`; + await writeFile(workerEs5EmbedPath, workerEs5EmbedCode); +} + async function writeIndexCode() { // Hardcode the code declaring and exporting the embedded URL: const indexCode = `export { EMBEDDED_DASH_WASM } from "./embedded_dash_wasm"; -export { EMBEDDED_WORKER } from "./embedded_worker";`; +export { EMBEDDED_WORKER } from "./embedded_worker"; +export { EMBEDDED_WORKER_ES5 } from "./embedded_worker_es5";`; await writeFile(indexPath, indexCode); } diff --git a/tests/integration/scenarios/dash_multi_periods.js b/tests/integration/scenarios/dash_multi_periods.js index ac81715b4e..de95d24de8 100644 --- a/tests/integration/scenarios/dash_multi_periods.js +++ b/tests/integration/scenarios/dash_multi_periods.js @@ -16,6 +16,7 @@ import { checkAfterSleepWithBackoff } from "../../utils/checkAfterSleepWithBacko describe("DASH non-linear multi-periods content (SegmentTemplate)", function () { launchTestsForContent(manifestInfos); launchTestsForContent(manifestInfos, { multithread: true }); + launchTestsForContent(manifestInfos, { multithread: true, es5Worker: true }); }); describe("DASH multi-Period with different choices", function () { diff --git a/tests/integration/scenarios/dash_static.js b/tests/integration/scenarios/dash_static.js index 06dbd4257c..a0fe319427 100644 --- a/tests/integration/scenarios/dash_static.js +++ b/tests/integration/scenarios/dash_static.js @@ -21,16 +21,28 @@ import { checkAfterSleepWithBackoff } from "../../utils/checkAfterSleepWithBacko describe("DASH non-linear content (SegmentTimeline)", function () { launchTestsForContent(segmentTimelineManifestInfos); launchTestsForContent(segmentTimelineManifestInfos, { multithread: true }); + launchTestsForContent(segmentTimelineManifestInfos, { + multithread: true, + es5Worker: true, + }); }); describe("DASH non-linear content multi-codecs (SegmentBase)", function () { launchTestsForContent(segmentBaseMultiCodecsInfos); launchTestsForContent(segmentBaseMultiCodecsInfos, { multithread: true }); + launchTestsForContent(segmentBaseMultiCodecsInfos, { + multithread: true, + es5Worker: true, + }); }); describe("DASH non-linear content not starting at 0 (SegmentTimeline)", function () { launchTestsForContent(notStartingAt0ManifestInfos); launchTestsForContent(notStartingAt0ManifestInfos, { multithread: true }); + launchTestsForContent(notStartingAt0ManifestInfos, { + multithread: true, + es5Worker: true, + }); }); describe("DASH non-linear content with SegmentTemplate inheritance (Period-AdaptationSet)", function () { @@ -38,11 +50,19 @@ describe("DASH non-linear content with SegmentTemplate inheritance (Period-Adapt launchTestsForContent(segmentTemplateInheritancePeriodAS, { multithread: true, }); + launchTestsForContent(segmentTemplateInheritancePeriodAS, { + multithread: true, + es5Worker: true, + }); }); describe("DASH non-linear content with SegmentTemplate inheritance (AdaptationSet-Representation)", function () { launchTestsForContent(segmentTemplateInheritanceASRep); launchTestsForContent(segmentTemplateInheritanceASRep, { multithread: true }); + launchTestsForContent(segmentTemplateInheritanceASRep, { + multithread: true, + es5Worker: true, + }); }); describe("DASH content CENC wrong version in MPD", function () { diff --git a/tests/integration/scenarios/idle.js b/tests/integration/scenarios/idle.js index f0ebf7b170..e6c94f7631 100644 --- a/tests/integration/scenarios/idle.js +++ b/tests/integration/scenarios/idle.js @@ -3,11 +3,13 @@ import RxPlayer from "../../../dist/es2017"; import { MULTI_THREAD } from "../../../dist/es2017/experimental/features/index.js"; import { EMBEDDED_WORKER, + EMBEDDED_WORKER_ES5, EMBEDDED_DASH_WASM, } from "../../../dist/es2017/__GENERATED_CODE/index.js"; runIdleTests(); runIdleTests({ multithread: true }); +runIdleTests({ multithread: true, es5Worker: true }); /** * Test every methods at an initial, idle state. @@ -18,8 +20,10 @@ runIdleTests({ multithread: true }); * @param {Boolean} [options.multithread] - If `true`, those tests will be run * if the RxPlayer runs in multithread mode. * In any other cases, tests will run in monothread mode. + * @param {Boolean} [options.es5Worker] - If `true`, multithread tests will be + * run in the ES5 version of the WebWorker file. */ -function runIdleTests({ multithread } = {}) { +function runIdleTests({ multithread, es5Worker } = {}) { let title = "initial idle state"; if (multithread === true) { RxPlayer.addFeatures([MULTI_THREAD]); @@ -32,7 +36,7 @@ function runIdleTests({ multithread } = {}) { const player = new RxPlayer(); if (multithread === true) { player.attachWorker({ - workerUrl: EMBEDDED_WORKER, + workerUrl: es5Worker ? EMBEDDED_WORKER_ES5 : EMBEDDED_WORKER, dashWasmUrl: EMBEDDED_DASH_WASM, }); } diff --git a/tests/integration/scenarios/initial_playback.js b/tests/integration/scenarios/initial_playback.js index 613c6a9132..72d859a7d3 100644 --- a/tests/integration/scenarios/initial_playback.js +++ b/tests/integration/scenarios/initial_playback.js @@ -20,6 +20,7 @@ import { MULTI_THREAD } from "../../../dist/es2017/experimental/features/index.j import { EMBEDDED_WORKER, EMBEDDED_DASH_WASM, + EMBEDDED_WORKER_ES5, } from "../../../dist/es2017/__GENERATED_CODE/index.js"; import { manifestInfos } from "../../contents/DASH_static_SegmentTimeline"; import sleep from "../../utils/sleep.js"; @@ -30,6 +31,7 @@ import { checkAfterSleepWithBackoff } from "../../utils/checkAfterSleepWithBacko runInitialPlaybackTests(); runInitialPlaybackTests({ multithread: true }); +runInitialPlaybackTests({ multithread: true, es5Worker: true }); /** * Test various cases of errors linked to starting playback. @@ -37,8 +39,10 @@ runInitialPlaybackTests({ multithread: true }); * @param {Boolean} [options.multithread] - If `true`, those tests will be run * if the RxPlayer runs in multithread mode. * In any other cases, tests will run in monothread mode. + * @param {Boolean} [options.es5Worker] - If `true`, multithread tests will be + * run in the ES5 version of the WebWorker file. */ -function runInitialPlaybackTests({ multithread } = {}) { +function runInitialPlaybackTests({ multithread, es5Worker } = {}) { let title = "basic playback use cases: non-linear DASH SegmentTimeline"; if (multithread === true) { RxPlayer.addFeatures([MULTI_THREAD]); @@ -52,7 +56,7 @@ function runInitialPlaybackTests({ multithread } = {}) { player = new RxPlayer(); if (multithread === true) { player.attachWorker({ - workerUrl: EMBEDDED_WORKER, + workerUrl: es5Worker ? EMBEDDED_WORKER_ES5 : EMBEDDED_WORKER, dashWasmUrl: EMBEDDED_DASH_WASM, }); } diff --git a/tests/integration/scenarios/loadVideo_options.js b/tests/integration/scenarios/loadVideo_options.js index a43c22a6df..3853784a27 100644 --- a/tests/integration/scenarios/loadVideo_options.js +++ b/tests/integration/scenarios/loadVideo_options.js @@ -19,6 +19,7 @@ import RxPlayer from "../../../dist/es2017"; import { MULTI_THREAD } from "../../../dist/es2017/experimental/features/index.js"; import { EMBEDDED_WORKER, + EMBEDDED_WORKER_ES5, EMBEDDED_DASH_WASM, } from "../../../dist/es2017/__GENERATED_CODE/index.js"; import { manifestInfos } from "../../contents/DASH_static_SegmentTimeline"; @@ -37,8 +38,10 @@ runLoadVideoOptionsTests({ multithread: true }); * @param {Boolean} [options.multithread] - If `true`, those tests will be run * if the RxPlayer runs in multithread mode. * In any other cases, tests will run in monothread mode. + * @param {Boolean} [options.es5Worker] - If `true`, multithread tests will be + * run in the ES5 version of the WebWorker file. */ -function runLoadVideoOptionsTests({ multithread } = {}) { +function runLoadVideoOptionsTests({ multithread, es5Worker } = {}) { let title = "loadVideo options"; if (multithread === true) { RxPlayer.addFeatures([MULTI_THREAD]); @@ -52,7 +55,7 @@ function runLoadVideoOptionsTests({ multithread } = {}) { player = new RxPlayer(); if (multithread === true) { player.attachWorker({ - workerUrl: EMBEDDED_WORKER, + workerUrl: es5Worker ? EMBEDDED_WORKER_ES5 : EMBEDDED_WORKER, dashWasmUrl: EMBEDDED_DASH_WASM, }); } diff --git a/tests/integration/utils/launch_tests_for_content.js b/tests/integration/utils/launch_tests_for_content.js index 3abdee2268..d30347676f 100644 --- a/tests/integration/utils/launch_tests_for_content.js +++ b/tests/integration/utils/launch_tests_for_content.js @@ -4,6 +4,7 @@ import { MULTI_THREAD } from "../../../dist/es2017/experimental/features/index.j import { EMBEDDED_WORKER, EMBEDDED_DASH_WASM, + EMBEDDED_WORKER_ES5, } from "../../../dist/es2017/__GENERATED_CODE/index.js"; import sleep from "../../utils/sleep.js"; import waitForState, { @@ -57,8 +58,13 @@ import { checkAfterSleepWithBackoff } from "../../utils/checkAfterSleepWithBacko * @param {Boolean} [options.multithread] - If `true`, those tests will be run * if the RxPlayer runs in multithread mode. * In any other cases, tests will run in monothread mode. + * @param {Boolean} [options.es5Worker] - If `true`, multithread tests will be + * run in the ES5 version of the WebWorker file. */ -export default function launchTestsForContent(manifestInfos, { multithread } = {}) { +export default function launchTestsForContent( + manifestInfos, + { multithread, es5Worker } = {}, +) { let player; if (multithread === true) { @@ -80,7 +86,7 @@ export default function launchTestsForContent(manifestInfos, { multithread } = { player = new RxPlayer(); if (multithread === true) { player.attachWorker({ - workerUrl: EMBEDDED_WORKER, + workerUrl: es5Worker ? EMBEDDED_WORKER_ES5 : EMBEDDED_WORKER, dashWasmUrl: EMBEDDED_DASH_WASM, }); } diff --git a/webpack.config.mjs b/webpack.config.mjs index d22be87ff8..0c130c4916 100644 --- a/webpack.config.mjs +++ b/webpack.config.mjs @@ -72,7 +72,6 @@ export default (env) => { rules: [ { test: /\.tsx?$/, - exclude: /node_modules/, use: [ { loader: "babel-loader", @@ -88,8 +87,5 @@ export default (env) => { ], }, plugins, - watchOptions: { - ignored: /node_modules/, - }, }; };