From b7b6880dbc64bcbce56743a588ee2f1bd7220f7b Mon Sep 17 00:00:00 2001 From: Shane Osbourne Date: Thu, 27 Feb 2025 08:50:17 +0000 Subject: [PATCH 01/11] injected: replace rollup with esbuild --- injected/entry-points/chrome.js | 3 +- injected/package.json | 18 +- injected/scripts/entry-points.js | 78 ++--- injected/scripts/utils/build.js | 243 +++++++------- injected/src/globals.d.ts | 4 + package-lock.json | 546 +------------------------------ package.json | 1 + special-pages/package.json | 1 - 8 files changed, 167 insertions(+), 727 deletions(-) diff --git a/injected/entry-points/chrome.js b/injected/entry-points/chrome.js index ebae03cd2..311e8f8f2 100644 --- a/injected/entry-points/chrome.js +++ b/injected/entry-points/chrome.js @@ -3,6 +3,7 @@ */ import { isTrackerOrigin } from '../src/trackers'; import { computeLimitedSiteObject } from '../src/utils'; +import contentScopeFeatures from 'ddg:contentScopeFeatures' /** * Inject all the overwrites into the page. @@ -48,7 +49,7 @@ function init() { const reusableMethodName = '_rm' + randomString(); const reusableSecret = '_r' + randomString(); const siteObject = computeLimitedSiteObject(); - const initialScript = ` + const initialScript = contentScopeFeatures + ` /* global contentScopeFeatures */ contentScopeFeatures.load({ platform: { diff --git a/injected/package.json b/injected/package.json index 5e11f8cd4..2b75bb0e6 100644 --- a/injected/package.json +++ b/injected/package.json @@ -3,16 +3,10 @@ "scripts": { "postinstall": "npm run copy-sjcl", "copy-sjcl": "node scripts/generateSJCL.js", + "build": "npm run build-types && npm run build-locales && npm run bundle-trackers && npm run bundle-entry-points", "bundle-config": "node scripts/bundleConfig.mjs", - "build": "npm run build-types && npm run build-locales && npm run bundle-trackers && npm run build-firefox && npm run build-chrome && npm run build-apple && npm run build-android && npm run build-windows && npm run build-integration && npm run build-chrome-mv3", + "bundle-entry-points": "node scripts/entry-points.js", "build-locales": "node scripts/buildLocales.js", - "build-firefox": "node scripts/entry-points.js --platform firefox", - "build-chrome": "node scripts/entry-points.js --platform chrome", - "build-chrome-mv3": "node scripts/entry-points.js --platform chrome-mv3", - "build-apple": "node scripts/entry-points.js --platform apple && node scripts/entry-points.js --platform apple-isolated", - "build-android": "node scripts/entry-points.js --platform android && node scripts/entry-points.js --platform android-autofill-password-import && node scripts/entry-points.js --platform android-broker-protection", - "build-windows": "node scripts/entry-points.js --platform windows", - "build-integration": "node scripts/entry-points.js --platform integration", "build-types": "node scripts/types.mjs", "bundle-trackers": "node scripts/bundleTrackers.mjs --output ../build/tracker-lookup.json", "test-unit": "jasmine --config=unit-test/config.json", @@ -39,18 +33,12 @@ "@canvas/image-data": "^1.0.0", "@duckduckgo/privacy-configuration": "github:duckduckgo/privacy-configuration#main", "@fingerprintjs/fingerprintjs": "^4.5.1", - "@rollup/plugin-commonjs": "^28.0.2", - "@rollup/plugin-node-resolve": "^16.0.0", - "@rollup/plugin-replace": "^6.0.2", "@types/chrome": "^0.0.306", "@types/jasmine": "^5.1.7", "@types/node": "^22.13.5", "@typescript-eslint/eslint-plugin": "^8.20.0", "fast-check": "^3.23.2", "jasmine": "^5.6.0", - "minimist": "^1.2.8", - "rollup": "^4.34.8", - "rollup-plugin-import-css": "^3.5.8", - "rollup-plugin-svg-import": "^3.0.0" + "minimist": "^1.2.8" } } diff --git a/injected/scripts/entry-points.js b/injected/scripts/entry-points.js index 6ba06e7d8..2d6092262 100644 --- a/injected/scripts/entry-points.js +++ b/injected/scripts/entry-points.js @@ -1,9 +1,5 @@ -import { postProcess, rollupScript } from './utils/build.js'; +import { bundle } from './utils/build.js' import { parseArgs, write } from '../../scripts/script-utils.js'; -import { camelcase } from '../src/utils.js'; - -const contentScopePath = 'src/content-scope-features.js'; -const contentScopeName = 'contentScopeFeatures'; /** * @typedef Build @@ -34,11 +30,11 @@ const builds = { output: ['../build/android/contentScope.js'], }, 'android-broker-protection': { - input: 'entry-points/android', + input: 'entry-points/android.js', output: ['../build/android/brokerProtection.js'], }, 'android-autofill-password-import': { - input: 'entry-points/android', + input: 'entry-points/android.js', output: ['../build/android/autofillPasswordImport.js'], }, windows: { @@ -63,59 +59,31 @@ const builds = { }, }; -async function initOther(injectScriptPath, platformName) { - const identName = `inject${camelcase(platformName)}`; - const injectScript = await rollupScript({ - scriptPath: injectScriptPath, - name: identName, - platform: platformName, - }); - const outputScript = injectScript; - return outputScript; -} +async function init () { + // verify the input + const requiredFields = [] + const args = parseArgs(process.argv.slice(2), requiredFields) -/** - * @param {string} entry - * @param {string} platformName - */ -async function initChrome(entry, platformName) { - const replaceString = '/* global contentScopeFeatures */'; - const injectScript = await rollupScript({ scriptPath: entry, platform: platformName }); - const contentScope = await rollupScript({ - scriptPath: contentScopePath, - name: contentScopeName, - platform: platformName, - }); - // Encode in URI format to prevent breakage (we could choose to just escape ` instead) - // NB: .replace(/\r\n/g, "\n") is needed because in Windows rollup generates CRLF line endings - const encodedString = encodeURI(contentScope.toString().replace(/\r\n/g, '\n')); - const outputScript = injectScript.toString().replace(replaceString, '${decodeURI("' + encodedString + '")}'); - return outputScript; -} + // if a platform was given as an argument, just build that platform + if (args.platform) { + const build = builds[args.platform] + if (!build) { + throw new Error('unsupported platform: ' + args.platform) + } + const output = await bundle({ scriptPath: build.input, platform: args.platform }) -async function init() { - // verify the input - const requiredFields = ['platform']; - const args = parseArgs(process.argv.slice(2), requiredFields); - const build = builds[args.platform]; + // bundle and write the output + write([build.output], output) - if (!build) { - throw new Error('unsupported platform: ' + args.platform); + return } - let output; - if (args.platform === 'chrome') { - output = await initChrome(build.input, args.platform); - } else { - output = await initOther(build.input, args.platform); - if (build.postProcess) { - const processResult = await postProcess(output); - output = processResult.code; - } + // otherwise, just build them all + for (const [injectName, build] of Object.entries(builds)) { + const output = await bundle({ scriptPath: build.input, platform: injectName }) + write(build.output, output) + console.log('✅', injectName, build.output[0]); } - - // bundle and write the output - write([build.output], output); } -init(); +init() \ No newline at end of file diff --git a/injected/scripts/utils/build.js b/injected/scripts/utils/build.js index bfca08680..b10b9f203 100644 --- a/injected/scripts/utils/build.js +++ b/injected/scripts/utils/build.js @@ -1,32 +1,15 @@ -import * as rollup from 'rollup'; -import * as esbuild from 'esbuild'; -import commonjs from '@rollup/plugin-commonjs'; -import replace from '@rollup/plugin-replace'; -import resolve from '@rollup/plugin-node-resolve'; -import css from 'rollup-plugin-import-css'; -import svg from 'rollup-plugin-svg-import'; -import { platformSupport } from '../../src/features.js'; -import { readFileSync } from 'fs'; - -function prefixPlugin(prefixMessage) { - return { - name: 'prefix-plugin', - renderChunk(code) { - return `${prefixMessage}\n${code}`; - }, - }; -} +import { platformSupport } from '../../src/features.js' +import { readFileSync } from 'fs' +import { cwd } from '../../../scripts/script-utils.js' +import { join } from 'path' +import * as esbuild from 'esbuild' +const ROOT = join(cwd(import.meta.url), '..', '..') +const DEBUG = false -function suffixPlugin(suffixMessage) { - return { - name: 'suffix-plugin', - renderChunk(code) { - return `${code}\n${suffixMessage}`; - }, - }; -} +const contentScopePath = 'src/content-scope-features.js'; +const contentScopeName = 'contentScopeFeatures'; -const prefixMessage = '/*! © DuckDuckGo ContentScopeScripts protections https://github.com/duckduckgo/content-scope-scripts/ */'; +const prefixMessage = '/*! © DuckDuckGo ContentScopeScripts protections https://github.com/duckduckgo/content-scope-scripts/ */' /** * @param {object} params @@ -36,55 +19,66 @@ const prefixMessage = '/*! © DuckDuckGo ContentScopeScripts protections https:/ * @param {string} [params.name] * @return {Promise} */ -export async function rollupScript(params) { - const { scriptPath, platform, name, featureNames } = params; +export async function bundle (params) { + const { + scriptPath, + platform, + name, + featureNames, + } = params - const extensions = ['firefox', 'chrome', 'chrome-mv3']; - const isExtension = extensions.includes(platform); - let trackerLookup = '$TRACKER_LOOKUP$'; + const extensions = ['firefox', 'chrome', 'chrome-mv3'] + const isExtension = extensions.includes(platform) + let trackerLookup = '$TRACKER_LOOKUP$' if (!isExtension) { - const trackerLookupData = readFileSync('../build/tracker-lookup.json', 'utf8'); - trackerLookup = trackerLookupData; + const trackerLookupData = readFileSync('../build/tracker-lookup.json', 'utf8') + trackerLookup = trackerLookupData } - const suffixMessage = `/*# sourceURL=duckduckgo-privacy-protection.js?scope=${name} */`; - const plugins = [ - css(), - svg({ - stringify: true, - }), - loadFeatures(platform, featureNames), - resolve(), - commonjs(), - replace({ - preventAssignment: true, - values: { - 'import.meta.injectName': JSON.stringify(platform), - // To be replaced by the extension, but prevents tree shaking - 'import.meta.trackerLookup': trackerLookup, - }, - }), - prefixPlugin(prefixMessage), - ]; - - if (platform === 'firefox') { - plugins.push(suffixPlugin(suffixMessage)); + const suffixMessage = platform === 'firefox' ? `/*# sourceURL=duckduckgo-privacy-protection.js?scope=${name} */` : '' + const loadFeaturesPlugin = loadFeatures(platform, featureNames) + // The code is using a global, that we define here which means once tree shaken we get a browser specific output. + + /** @type {import("esbuild").BuildOptions} */ + const buildOptions = { + entryPoints: [scriptPath], + write: false, + outdir: 'build', + target: 'safari15', + logOverride: { 'unsupported-css-nesting': 'silent' }, + bundle: true, + metafile: true, + globalName: name, + loader: { + '.css': 'text', + '.svg': 'text' + }, + define: { + 'import.meta.env': 'development', + 'import.meta.injectName': JSON.stringify(platform), + 'import.meta.trackerLookup': trackerLookup + }, + plugins: [loadFeaturesPlugin, contentFeaturesAsString(platform)], + footer: { + js: suffixMessage + }, + banner: { + js: prefixMessage + } } - const bundle = await rollup.rollup({ - input: scriptPath, - plugins, - }); + const result = await esbuild.build(buildOptions) - const generated = await bundle.generate({ - dir: 'build', - format: 'iife', - inlineDynamicImports: true, - name, - // This if for seedrandom causing build issues - globals: { crypto: 'undefined' }, - }); + if (result.metafile && DEBUG) { + console.log(await esbuild.analyzeMetafile(result.metafile)) + } - return generated.output[0].code; + if (result.errors.length === 0 && result.outputFiles) { + return result.outputFiles[0].text || '' + } else { + console.log(result.errors) + console.log(result.warnings) + throw new Error('could not continue') + } } /** @@ -92,38 +86,80 @@ export async function rollupScript(params) { * * @param {string} platform * @param {string[]} featureNames + * @returns {import("esbuild").Plugin} */ -function loadFeatures(platform, featureNames = platformSupport[platform]) { - const pluginId = 'ddg:platformFeatures'; +function loadFeatures (platform, featureNames = platformSupport[platform]) { + const pluginId = 'ddg:platformFeatures' return { - name: pluginId, - resolveId(id) { - if (id === pluginId) return id; - return null; - }, - load(id) { - if (id !== pluginId) return null; - - // convert a list of feature names to - const imports = featureNames.map((featureName) => { - const fileName = getFileName(featureName); - const path = `./src/features/${fileName}.js`; - const ident = `ddg_feature_${featureName}`; + name: 'ddg:platformFeatures', + setup (build) { + build.onResolve({ filter: new RegExp(pluginId) }, (args) => { return { - ident, - importPath: path, - }; - }); - - const importString = imports.map((imp) => `import ${imp.ident} from ${JSON.stringify(imp.importPath)}`).join(';\n'); + path: args.path, + namespace: pluginId + } + }) + build.onLoad({ filter: /.*/, namespace: pluginId }, () => { + // convert a list of feature names to + const imports = featureNames.map((featureName) => { + const fileName = getFileName(featureName) + const path = `./src/features/${fileName}.js` + const ident = `ddg_feature_${featureName}` + return { + ident, + importPath: path + } + }) + + const importString = imports.map(imp => `import ${imp.ident} from ${JSON.stringify(imp.importPath)}`) + .join(';\n') + + const exportsString = imports.map(imp => `${imp.ident}`) + .join(',\n ') + + const exportString = `export default {\n ${exportsString}\n}` - const exportsString = imports.map((imp) => `${imp.ident}`).join(',\n '); + return { + loader: 'js', + resolveDir: ROOT, + contents: [importString, exportString].join('\n') + } + }) + } + } +} - const exportString = `export default {\n ${exportsString}\n}`; +function contentFeaturesAsString (platform) { + const pluginId = 'ddg:contentScopeFeatures' + return { + /** + * Load all platform features based on current + */ + name: pluginId, + setup (build) { + build.onResolve({ filter: new RegExp(pluginId) }, (args) => { + return { + path: args.path, + namespace: pluginId + } + }) + build.onLoad({ filter: /.*/, namespace: pluginId }, async () => { + const result = await bundle({ + scriptPath: contentScopePath, + name: contentScopeName, + platform + }) + + const encodedString = result.replace(/\r\n/g, '\n') - return [importString, exportString].join('\n'); - }, - }; + return { + loader: 'text', + resolveDir: ROOT, + contents: encodedString + } + }) + } + } } /** @@ -134,19 +170,4 @@ function loadFeatures(platform, featureNames = platformSupport[platform]) { */ function getFileName(featureName) { return featureName.replace(/([a-zA-Z])(?=[A-Z0-9])/g, '$1-').toLowerCase(); -} - -/** - * Apply additional processing to a bundle. This was - * added to solve an issue where certain syntax caused - * parsing to fail in macOS Catalina. - * - * `target: "es2021"` seems to be a 'low enough' target - it's also what's - * used in Autoconsent too. - * - * @param {string} content - * @return {Promise} - */ -export function postProcess(content) { - return esbuild.transform(content, { target: 'es2021', format: 'iife' }); -} +} \ No newline at end of file diff --git a/injected/src/globals.d.ts b/injected/src/globals.d.ts index cb14b677a..57210f551 100644 --- a/injected/src/globals.d.ts +++ b/injected/src/globals.d.ts @@ -47,3 +47,7 @@ declare module 'ddg:platformFeatures' { const output: Record import('./content-feature').default>; export default output; } +declare module 'ddg:contentScopeFeatures' { + const output: string + export default output; +} diff --git a/package-lock.json b/package-lock.json index a0c4727c5..7c3413c6e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,6 +18,7 @@ "devDependencies": { "@duckduckgo/eslint-config": "github:duckduckgo/eslint-config#v0.1.0", "@playwright/test": "^1.50.1", + "esbuild": "^0.25.0", "eslint": "^9.21.0", "minimist": "^1.2.8", "prettier": "3.4.2", @@ -40,19 +41,13 @@ "@canvas/image-data": "^1.0.0", "@duckduckgo/privacy-configuration": "github:duckduckgo/privacy-configuration#main", "@fingerprintjs/fingerprintjs": "^4.5.1", - "@rollup/plugin-commonjs": "^28.0.2", - "@rollup/plugin-node-resolve": "^16.0.0", - "@rollup/plugin-replace": "^6.0.2", "@types/chrome": "^0.0.306", "@types/jasmine": "^5.1.7", "@types/node": "^22.13.5", "@typescript-eslint/eslint-plugin": "^8.20.0", "fast-check": "^3.23.2", "jasmine": "^5.6.0", - "minimist": "^1.2.8", - "rollup": "^4.34.8", - "rollup-plugin-import-css": "^3.5.8", - "rollup-plugin-svg-import": "^3.0.0" + "minimist": "^1.2.8" } }, "messaging": { @@ -983,13 +978,6 @@ "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", - "dev": true, - "license": "MIT" - }, "node_modules/@jsdevtools/ono": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz", @@ -1093,407 +1081,6 @@ "integrity": "sha512-g5exYbB96NW7+BqtMJ35xFZzgYMijCp4HxQbJtt5UtYCZivMdRl7Hnz7s5Z4jRvX9iBm3goip60eCT7pK96BnQ==", "license": "MIT" }, - "node_modules/@rollup/plugin-commonjs": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-28.0.2.tgz", - "integrity": "sha512-BEFI2EDqzl+vA1rl97IDRZ61AIwGH093d9nz8+dThxJNH8oSoB7MjWvPCX3dkaK1/RCJ/1v/R1XB15FuSs0fQw==", - "dev": true, - "dependencies": { - "@rollup/pluginutils": "^5.0.1", - "commondir": "^1.0.1", - "estree-walker": "^2.0.2", - "fdir": "^6.2.0", - "is-reference": "1.2.1", - "magic-string": "^0.30.3", - "picomatch": "^4.0.2" - }, - "engines": { - "node": ">=16.0.0 || 14 >= 14.17" - }, - "peerDependencies": { - "rollup": "^2.68.0||^3.0.0||^4.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } - } - }, - "node_modules/@rollup/plugin-commonjs/node_modules/fdir": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.2.tgz", - "integrity": "sha512-KnhMXsKSPZlAhp7+IjUkRZKPb4fUyccpDrdFXbi4QL1qkmFh9kVY09Yox+n4MaOb3lHZ1Tv829C3oaaXoMYPDQ==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, - "node_modules/@rollup/plugin-commonjs/node_modules/picomatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", - "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/@rollup/plugin-node-resolve": { - "version": "16.0.0", - "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-16.0.0.tgz", - "integrity": "sha512-0FPvAeVUT/zdWoO0jnb/V5BlBsUSNfkIOtFHzMO4H9MOklrmQFY6FduVHKucNb/aTFxvnGhj4MNj/T1oNdDfNg==", - "dev": true, - "dependencies": { - "@rollup/pluginutils": "^5.0.1", - "@types/resolve": "1.20.2", - "deepmerge": "^4.2.2", - "is-module": "^1.0.0", - "resolve": "^1.22.1" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "rollup": "^2.78.0||^3.0.0||^4.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } - } - }, - "node_modules/@rollup/plugin-replace": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-6.0.2.tgz", - "integrity": "sha512-7QaYCf8bqF04dOy7w/eHmJeNExxTYwvKAmlSAH/EaWWUzbT0h5sbF6bktFoX/0F/0qwng5/dWFMyf3gzaM8DsQ==", - "dev": true, - "dependencies": { - "@rollup/pluginutils": "^5.0.1", - "magic-string": "^0.30.3" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } - } - }, - "node_modules/@rollup/pluginutils": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.3.tgz", - "integrity": "sha512-Pnsb6f32CD2W3uCaLZIzDmeFyQ2b8UWMFI7xtwUezpcGBDVDW6y9XgAWIlARiGAo6eNF5FK5aQTr0LFyNyqq5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0", - "estree-walker": "^2.0.2", - "picomatch": "^4.0.2" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } - } - }, - "node_modules/@rollup/pluginutils/node_modules/picomatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", - "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.34.8.tgz", - "integrity": "sha512-q217OSE8DTp8AFHuNHXo0Y86e1wtlfVrXiAlwkIvGRQv9zbc6mE3sjIVfwI8sYUyNxwOg0j/Vm1RKM04JcWLJw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.34.8.tgz", - "integrity": "sha512-Gigjz7mNWaOL9wCggvoK3jEIUUbGul656opstjaUSGC3eT0BM7PofdAJaBfPFWWkXNVAXbaQtC99OCg4sJv70Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.34.8.tgz", - "integrity": "sha512-02rVdZ5tgdUNRxIUrFdcMBZQoaPMrxtwSb+/hOfBdqkatYHR3lZ2A2EGyHq2sGOd0Owk80oV3snlDASC24He3Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.34.8.tgz", - "integrity": "sha512-qIP/elwR/tq/dYRx3lgwK31jkZvMiD6qUtOycLhTzCvrjbZ3LjQnEM9rNhSGpbLXVJYQ3rq39A6Re0h9tU2ynw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.34.8.tgz", - "integrity": "sha512-IQNVXL9iY6NniYbTaOKdrlVP3XIqazBgJOVkddzJlqnCpRi/yAeSOa8PLcECFSQochzqApIOE1GHNu3pCz+BDA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.34.8.tgz", - "integrity": "sha512-TYXcHghgnCqYFiE3FT5QwXtOZqDj5GmaFNTNt3jNC+vh22dc/ukG2cG+pi75QO4kACohZzidsq7yKTKwq/Jq7Q==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.34.8.tgz", - "integrity": "sha512-A4iphFGNkWRd+5m3VIGuqHnG3MVnqKe7Al57u9mwgbyZ2/xF9Jio72MaY7xxh+Y87VAHmGQr73qoKL9HPbXj1g==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.34.8.tgz", - "integrity": "sha512-S0lqKLfTm5u+QTxlFiAnb2J/2dgQqRy/XvziPtDd1rKZFXHTyYLoVL58M/XFwDI01AQCDIevGLbQrMAtdyanpA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.34.8.tgz", - "integrity": "sha512-jpz9YOuPiSkL4G4pqKrus0pn9aYwpImGkosRKwNi+sJSkz+WU3anZe6hi73StLOQdfXYXC7hUfsQlTnjMd3s1A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.34.8.tgz", - "integrity": "sha512-KdSfaROOUJXgTVxJNAZ3KwkRc5nggDk+06P6lgi1HLv1hskgvxHUKZ4xtwHkVYJ1Rep4GNo+uEfycCRRxht7+Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.34.8.tgz", - "integrity": "sha512-NyF4gcxwkMFRjgXBM6g2lkT58OWztZvw5KkV2K0qqSnUEqCVcqdh2jN4gQrTn/YUpAcNKyFHfoOZEer9nwo6uQ==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.34.8.tgz", - "integrity": "sha512-LMJc999GkhGvktHU85zNTDImZVUCJ1z/MbAJTnviiWmmjyckP5aQsHtcujMjpNdMZPT2rQEDBlJfubhs3jsMfw==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.34.8.tgz", - "integrity": "sha512-xAQCAHPj8nJq1PI3z8CIZzXuXCstquz7cIOL73HHdXiRcKk8Ywwqtx2wrIy23EcTn4aZ2fLJNBB8d0tQENPCmw==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.34.8.tgz", - "integrity": "sha512-DdePVk1NDEuc3fOe3dPPTb+rjMtuFw89gw6gVWxQFAuEqqSdDKnrwzZHrUYdac7A7dXl9Q2Vflxpme15gUWQFA==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.34.8.tgz", - "integrity": "sha512-8y7ED8gjxITUltTUEJLQdgpbPh1sUQ0kMTmufRF/Ns5tI9TNMNlhWtmPKKHCU0SilX+3MJkZ0zERYYGIVBYHIA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.34.8.tgz", - "integrity": "sha512-SCXcP0ZpGFIe7Ge+McxY5zKxiEI5ra+GT3QRxL0pMMtxPfpyLAKleZODi1zdRHkz5/BhueUrYtYVgubqe9JBNQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.34.8.tgz", - "integrity": "sha512-YHYsgzZgFJzTRbth4h7Or0m5O74Yda+hLin0irAIobkLQFRQd1qWmnoVfwmKm9TXIZVAD0nZ+GEb2ICicLyCnQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.34.8.tgz", - "integrity": "sha512-r3NRQrXkHr4uWy5TOjTpTYojR9XmF0j/RYgKCef+Ag46FWUTltm5ziticv8LdNsDMehjJ543x/+TJAek/xBA2w==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.34.8.tgz", - "integrity": "sha512-U0FaE5O1BCpZSeE6gBl3c5ObhePQSfk9vDRToMmTkbhCOgW4jqvtS5LGyQ76L1fH8sM0keRp4uDTsbjiUyjk0g==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, "node_modules/@rtsao/scc": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", @@ -1630,13 +1217,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/resolve": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz", - "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/unist": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", @@ -2298,13 +1878,6 @@ "dev": true, "license": "MIT" }, - "node_modules/commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", - "dev": true, - "license": "MIT" - }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -2539,16 +2112,6 @@ "dev": true, "license": "MIT" }, - "node_modules/deepmerge": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", - "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/define-data-property": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", @@ -3380,13 +2943,6 @@ "node": ">=4.0" } }, - "node_modules/estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "dev": true, - "license": "MIT" - }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", @@ -4439,13 +3995,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", - "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==", - "dev": true, - "license": "MIT" - }, "node_modules/is-negative-zero": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", @@ -4505,16 +4054,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-reference": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", - "integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "*" - } - }, "node_modules/is-regex": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", @@ -4873,16 +4412,6 @@ "dev": true, "license": "MIT" }, - "node_modules/magic-string": { - "version": "0.30.12", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.12.tgz", - "integrity": "sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0" - } - }, "node_modules/map-obj": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", @@ -5954,76 +5483,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/rollup": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.34.8.tgz", - "integrity": "sha512-489gTVMzAYdiZHFVA/ig/iYFllCcWFHMvUHI1rpFmkoUtRlQxqh6/yiNqnYibjMZ2b/+FUQwldG+aLsEt6bglQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "1.0.6" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.34.8", - "@rollup/rollup-android-arm64": "4.34.8", - "@rollup/rollup-darwin-arm64": "4.34.8", - "@rollup/rollup-darwin-x64": "4.34.8", - "@rollup/rollup-freebsd-arm64": "4.34.8", - "@rollup/rollup-freebsd-x64": "4.34.8", - "@rollup/rollup-linux-arm-gnueabihf": "4.34.8", - "@rollup/rollup-linux-arm-musleabihf": "4.34.8", - "@rollup/rollup-linux-arm64-gnu": "4.34.8", - "@rollup/rollup-linux-arm64-musl": "4.34.8", - "@rollup/rollup-linux-loongarch64-gnu": "4.34.8", - "@rollup/rollup-linux-powerpc64le-gnu": "4.34.8", - "@rollup/rollup-linux-riscv64-gnu": "4.34.8", - "@rollup/rollup-linux-s390x-gnu": "4.34.8", - "@rollup/rollup-linux-x64-gnu": "4.34.8", - "@rollup/rollup-linux-x64-musl": "4.34.8", - "@rollup/rollup-win32-arm64-msvc": "4.34.8", - "@rollup/rollup-win32-ia32-msvc": "4.34.8", - "@rollup/rollup-win32-x64-msvc": "4.34.8", - "fsevents": "~2.3.2" - } - }, - "node_modules/rollup-plugin-import-css": { - "version": "3.5.8", - "resolved": "https://registry.npmjs.org/rollup-plugin-import-css/-/rollup-plugin-import-css-3.5.8.tgz", - "integrity": "sha512-a3YsZnwHz66mRHCKHjaPCSfWczczvS/HTkgDc+Eogn0mt/0JZXz0WjK0fzM5WwBpVtOqHB4/gHdmEY40ILsaVg==", - "dev": true, - "dependencies": { - "@rollup/pluginutils": "^5.1.3" - }, - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "rollup": "^2.x.x || ^3.x.x || ^4.x.x" - } - }, - "node_modules/rollup-plugin-svg-import": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/rollup-plugin-svg-import/-/rollup-plugin-svg-import-3.0.0.tgz", - "integrity": "sha512-5fUESTM5hdqJojrwO53JQUO7NespLNx4iLeMsToQfuaGGqGT5sz85Ns5gCDNxLO6yBPbn7p0A/6YA+Rq3clg4Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@rollup/pluginutils": "^5.0.1" - }, - "engines": { - "node": ">=18.0.0" - }, - "peerDependencies": { - "rollup": "^3.0.0||^4.0.0" - } - }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -7495,7 +6954,6 @@ "devDependencies": { "@duckduckgo/messaging": "*", "chokidar": "^4.0.3", - "esbuild": "^0.25.0", "fast-check": "^3.23.2", "http-server": "^14.1.1", "web-resource-inliner": "^6.0.1" diff --git a/package.json b/package.json index 0fc2009ec..987778d9b 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ "devDependencies": { "@duckduckgo/eslint-config": "github:duckduckgo/eslint-config#v0.1.0", "@playwright/test": "^1.50.1", + "esbuild": "^0.25.0", "eslint": "^9.21.0", "minimist": "^1.2.8", "prettier": "3.4.2", diff --git a/special-pages/package.json b/special-pages/package.json index 0bac7b631..2f44ed817 100644 --- a/special-pages/package.json +++ b/special-pages/package.json @@ -28,7 +28,6 @@ "devDependencies": { "@duckduckgo/messaging": "*", "chokidar": "^4.0.3", - "esbuild": "^0.25.0", "fast-check": "^3.23.2", "http-server": "^14.1.1", "web-resource-inliner": "^6.0.1" From 096d747e7f97b5e73ae415dff9cebe32589788e7 Mon Sep 17 00:00:00 2001 From: Shane Osbourne Date: Thu, 27 Feb 2025 08:52:03 +0000 Subject: [PATCH 02/11] linting --- injected/entry-points/chrome.js | 6 +- injected/scripts/entry-points.js | 24 +++--- injected/scripts/utils/build.js | 137 +++++++++++++++---------------- injected/src/globals.d.ts | 2 +- 4 files changed, 82 insertions(+), 87 deletions(-) diff --git a/injected/entry-points/chrome.js b/injected/entry-points/chrome.js index 311e8f8f2..424d03ab2 100644 --- a/injected/entry-points/chrome.js +++ b/injected/entry-points/chrome.js @@ -3,7 +3,7 @@ */ import { isTrackerOrigin } from '../src/trackers'; import { computeLimitedSiteObject } from '../src/utils'; -import contentScopeFeatures from 'ddg:contentScopeFeatures' +import contentScopeFeatures from 'ddg:contentScopeFeatures'; /** * Inject all the overwrites into the page. @@ -49,7 +49,9 @@ function init() { const reusableMethodName = '_rm' + randomString(); const reusableSecret = '_r' + randomString(); const siteObject = computeLimitedSiteObject(); - const initialScript = contentScopeFeatures + ` + const initialScript = + contentScopeFeatures + + ` /* global contentScopeFeatures */ contentScopeFeatures.load({ platform: { diff --git a/injected/scripts/entry-points.js b/injected/scripts/entry-points.js index 2d6092262..64465cf37 100644 --- a/injected/scripts/entry-points.js +++ b/injected/scripts/entry-points.js @@ -1,4 +1,4 @@ -import { bundle } from './utils/build.js' +import { bundle } from './utils/build.js'; import { parseArgs, write } from '../../scripts/script-utils.js'; /** @@ -59,31 +59,31 @@ const builds = { }, }; -async function init () { +async function init() { // verify the input - const requiredFields = [] - const args = parseArgs(process.argv.slice(2), requiredFields) + const requiredFields = []; + const args = parseArgs(process.argv.slice(2), requiredFields); // if a platform was given as an argument, just build that platform if (args.platform) { - const build = builds[args.platform] + const build = builds[args.platform]; if (!build) { - throw new Error('unsupported platform: ' + args.platform) + throw new Error('unsupported platform: ' + args.platform); } - const output = await bundle({ scriptPath: build.input, platform: args.platform }) + const output = await bundle({ scriptPath: build.input, platform: args.platform }); // bundle and write the output - write([build.output], output) + write([build.output], output); - return + return; } // otherwise, just build them all for (const [injectName, build] of Object.entries(builds)) { - const output = await bundle({ scriptPath: build.input, platform: injectName }) - write(build.output, output) + const output = await bundle({ scriptPath: build.input, platform: injectName }); + write(build.output, output); console.log('✅', injectName, build.output[0]); } } -init() \ No newline at end of file +init(); diff --git a/injected/scripts/utils/build.js b/injected/scripts/utils/build.js index b10b9f203..7e6426150 100644 --- a/injected/scripts/utils/build.js +++ b/injected/scripts/utils/build.js @@ -1,15 +1,15 @@ -import { platformSupport } from '../../src/features.js' -import { readFileSync } from 'fs' -import { cwd } from '../../../scripts/script-utils.js' -import { join } from 'path' -import * as esbuild from 'esbuild' -const ROOT = join(cwd(import.meta.url), '..', '..') -const DEBUG = false +import { platformSupport } from '../../src/features.js'; +import { readFileSync } from 'fs'; +import { cwd } from '../../../scripts/script-utils.js'; +import { join } from 'path'; +import * as esbuild from 'esbuild'; +const ROOT = join(cwd(import.meta.url), '..', '..'); +const DEBUG = false; const contentScopePath = 'src/content-scope-features.js'; const contentScopeName = 'contentScopeFeatures'; -const prefixMessage = '/*! © DuckDuckGo ContentScopeScripts protections https://github.com/duckduckgo/content-scope-scripts/ */' +const prefixMessage = '/*! © DuckDuckGo ContentScopeScripts protections https://github.com/duckduckgo/content-scope-scripts/ */'; /** * @param {object} params @@ -19,23 +19,18 @@ const prefixMessage = '/*! © DuckDuckGo ContentScopeScripts protections https:/ * @param {string} [params.name] * @return {Promise} */ -export async function bundle (params) { - const { - scriptPath, - platform, - name, - featureNames, - } = params - - const extensions = ['firefox', 'chrome', 'chrome-mv3'] - const isExtension = extensions.includes(platform) - let trackerLookup = '$TRACKER_LOOKUP$' +export async function bundle(params) { + const { scriptPath, platform, name, featureNames } = params; + + const extensions = ['firefox', 'chrome', 'chrome-mv3']; + const isExtension = extensions.includes(platform); + let trackerLookup = '$TRACKER_LOOKUP$'; if (!isExtension) { - const trackerLookupData = readFileSync('../build/tracker-lookup.json', 'utf8') - trackerLookup = trackerLookupData + const trackerLookupData = readFileSync('../build/tracker-lookup.json', 'utf8'); + trackerLookup = trackerLookupData; } - const suffixMessage = platform === 'firefox' ? `/*# sourceURL=duckduckgo-privacy-protection.js?scope=${name} */` : '' - const loadFeaturesPlugin = loadFeatures(platform, featureNames) + const suffixMessage = platform === 'firefox' ? `/*# sourceURL=duckduckgo-privacy-protection.js?scope=${name} */` : ''; + const loadFeaturesPlugin = loadFeatures(platform, featureNames); // The code is using a global, that we define here which means once tree shaken we get a browser specific output. /** @type {import("esbuild").BuildOptions} */ @@ -50,34 +45,34 @@ export async function bundle (params) { globalName: name, loader: { '.css': 'text', - '.svg': 'text' + '.svg': 'text', }, define: { 'import.meta.env': 'development', 'import.meta.injectName': JSON.stringify(platform), - 'import.meta.trackerLookup': trackerLookup + 'import.meta.trackerLookup': trackerLookup, }, plugins: [loadFeaturesPlugin, contentFeaturesAsString(platform)], footer: { - js: suffixMessage + js: suffixMessage, }, banner: { - js: prefixMessage - } - } + js: prefixMessage, + }, + }; - const result = await esbuild.build(buildOptions) + const result = await esbuild.build(buildOptions); if (result.metafile && DEBUG) { - console.log(await esbuild.analyzeMetafile(result.metafile)) + console.log(await esbuild.analyzeMetafile(result.metafile)); } if (result.errors.length === 0 && result.outputFiles) { - return result.outputFiles[0].text || '' + return result.outputFiles[0].text || ''; } else { - console.log(result.errors) - console.log(result.warnings) - throw new Error('could not continue') + console.log(result.errors); + console.log(result.warnings); + throw new Error('could not continue'); } } @@ -88,78 +83,76 @@ export async function bundle (params) { * @param {string[]} featureNames * @returns {import("esbuild").Plugin} */ -function loadFeatures (platform, featureNames = platformSupport[platform]) { - const pluginId = 'ddg:platformFeatures' +function loadFeatures(platform, featureNames = platformSupport[platform]) { + const pluginId = 'ddg:platformFeatures'; return { name: 'ddg:platformFeatures', - setup (build) { + setup(build) { build.onResolve({ filter: new RegExp(pluginId) }, (args) => { return { path: args.path, - namespace: pluginId - } - }) + namespace: pluginId, + }; + }); build.onLoad({ filter: /.*/, namespace: pluginId }, () => { // convert a list of feature names to const imports = featureNames.map((featureName) => { - const fileName = getFileName(featureName) - const path = `./src/features/${fileName}.js` - const ident = `ddg_feature_${featureName}` + const fileName = getFileName(featureName); + const path = `./src/features/${fileName}.js`; + const ident = `ddg_feature_${featureName}`; return { ident, - importPath: path - } - }) + importPath: path, + }; + }); - const importString = imports.map(imp => `import ${imp.ident} from ${JSON.stringify(imp.importPath)}`) - .join(';\n') + const importString = imports.map((imp) => `import ${imp.ident} from ${JSON.stringify(imp.importPath)}`).join(';\n'); - const exportsString = imports.map(imp => `${imp.ident}`) - .join(',\n ') + const exportsString = imports.map((imp) => `${imp.ident}`).join(',\n '); - const exportString = `export default {\n ${exportsString}\n}` + const exportString = `export default {\n ${exportsString}\n}`; return { loader: 'js', resolveDir: ROOT, - contents: [importString, exportString].join('\n') - } - }) - } - } + contents: [importString, exportString].join('\n'), + }; + }); + }, + }; } -function contentFeaturesAsString (platform) { - const pluginId = 'ddg:contentScopeFeatures' +function contentFeaturesAsString(platform) { + const pluginId = 'ddg:contentScopeFeatures'; return { /** * Load all platform features based on current */ name: pluginId, - setup (build) { + setup(build) { build.onResolve({ filter: new RegExp(pluginId) }, (args) => { return { path: args.path, - namespace: pluginId - } - }) + namespace: pluginId, + }; + }); build.onLoad({ filter: /.*/, namespace: pluginId }, async () => { const result = await bundle({ scriptPath: contentScopePath, name: contentScopeName, - platform - }) + platform, + }); - const encodedString = result.replace(/\r\n/g, '\n') + const encodedString = result.replace(/\r\n/g, '\n'); return { loader: 'text', resolveDir: ROOT, - contents: encodedString - } - }) - } - } + contents: encodedString, + }; + }); + }, + }; } /** @@ -170,4 +163,4 @@ function contentFeaturesAsString (platform) { */ function getFileName(featureName) { return featureName.replace(/([a-zA-Z])(?=[A-Z0-9])/g, '$1-').toLowerCase(); -} \ No newline at end of file +} diff --git a/injected/src/globals.d.ts b/injected/src/globals.d.ts index 57210f551..f8c8fe5c6 100644 --- a/injected/src/globals.d.ts +++ b/injected/src/globals.d.ts @@ -48,6 +48,6 @@ declare module 'ddg:platformFeatures' { export default output; } declare module 'ddg:contentScopeFeatures' { - const output: string + const output: string; export default output; } From ae62ee925c9d053b4538c5cc1c581a9339196dd1 Mon Sep 17 00:00:00 2001 From: Shane Osbourne Date: Thu, 27 Feb 2025 09:09:12 +0000 Subject: [PATCH 03/11] fixing tests --- injected/scripts/utils/build.js | 5 ++++- injected/unit-test/verify-artifacts.js | 8 ++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/injected/scripts/utils/build.js b/injected/scripts/utils/build.js index 7e6426150..f717e1cd1 100644 --- a/injected/scripts/utils/build.js +++ b/injected/scripts/utils/build.js @@ -39,7 +39,10 @@ export async function bundle(params) { write: false, outdir: 'build', target: 'safari15', - logOverride: { 'unsupported-css-nesting': 'silent' }, + format: 'iife', + supported: { + "class-private-field": false + }, bundle: true, metafile: true, globalName: name, diff --git a/injected/unit-test/verify-artifacts.js b/injected/unit-test/verify-artifacts.js index 144d12970..c68179b93 100644 --- a/injected/unit-test/verify-artifacts.js +++ b/injected/unit-test/verify-artifacts.js @@ -19,7 +19,7 @@ const checks = { file: join(BUILD, 'android/contentScope.js'), tests: [ { kind: 'maxFileSize', value: CSS_OUTPUT_SIZE }, - { kind: 'containsString', text: 'output.trackerLookup = {', includes: true }, + { kind: 'containsString', text: 'define_import_meta_trackerLookup_default', includes: true } ], }, chrome: { @@ -45,20 +45,20 @@ const checks = { }, integration: { file: join(BUILD, 'integration/contentScope.js'), - tests: [{ kind: 'containsString', text: 'const trackerLookup = {', includes: true }], + tests: [{ kind: 'containsString', text: 'define_import_meta_trackerLookup_default', includes: true }], }, windows: { file: join(BUILD, 'windows/contentScope.js'), tests: [ { kind: 'maxFileSize', value: CSS_OUTPUT_SIZE }, - { kind: 'containsString', text: 'output.trackerLookup = {', includes: true }, + { kind: 'containsString', text: 'define_import_meta_trackerLookup_default', includes: true } ], }, apple: { file: join(APPLE_BUILD, 'contentScope.js'), tests: [ { kind: 'maxFileSize', value: CSS_OUTPUT_SIZE }, - { kind: 'containsString', text: 'output.trackerLookup = {', includes: true }, + { kind: 'containsString', text: 'output.trackerLookup = define_import_meta_trackerLookup_default', includes: true }, { kind: 'containsString', text: '#bundledConfig', includes: false }, ], }, From fe7281542ef656e18616166f1946683447428e0d Mon Sep 17 00:00:00 2001 From: Shane Osbourne Date: Thu, 27 Feb 2025 09:26:27 +0000 Subject: [PATCH 04/11] linting --- injected/scripts/utils/build.js | 2 +- injected/unit-test/verify-artifacts.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/injected/scripts/utils/build.js b/injected/scripts/utils/build.js index f717e1cd1..fa41023e3 100644 --- a/injected/scripts/utils/build.js +++ b/injected/scripts/utils/build.js @@ -41,7 +41,7 @@ export async function bundle(params) { target: 'safari15', format: 'iife', supported: { - "class-private-field": false + 'class-private-field': false, }, bundle: true, metafile: true, diff --git a/injected/unit-test/verify-artifacts.js b/injected/unit-test/verify-artifacts.js index c68179b93..7898f8bb8 100644 --- a/injected/unit-test/verify-artifacts.js +++ b/injected/unit-test/verify-artifacts.js @@ -19,7 +19,7 @@ const checks = { file: join(BUILD, 'android/contentScope.js'), tests: [ { kind: 'maxFileSize', value: CSS_OUTPUT_SIZE }, - { kind: 'containsString', text: 'define_import_meta_trackerLookup_default', includes: true } + { kind: 'containsString', text: 'define_import_meta_trackerLookup_default', includes: true }, ], }, chrome: { @@ -51,7 +51,7 @@ const checks = { file: join(BUILD, 'windows/contentScope.js'), tests: [ { kind: 'maxFileSize', value: CSS_OUTPUT_SIZE }, - { kind: 'containsString', text: 'define_import_meta_trackerLookup_default', includes: true } + { kind: 'containsString', text: 'define_import_meta_trackerLookup_default', includes: true }, ], }, apple: { From fe46fae503e654adfcb0974fa9efbdbd666794b0 Mon Sep 17 00:00:00 2001 From: Shane Osbourne Date: Thu, 27 Feb 2025 09:39:07 +0000 Subject: [PATCH 05/11] scripts --- injected/package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/injected/package.json b/injected/package.json index 2b75bb0e6..75277a9a3 100644 --- a/injected/package.json +++ b/injected/package.json @@ -17,11 +17,11 @@ "playwright": "playwright test --grep-invert '@screenshots'", "playwright-screenshots": "playwright test --grep '@screenshots'", "playwright-headed": "playwright test --headed", - "preplaywright": "npm run build-windows && npm run build-apple && npm run build-android", - "preplaywright-headed": "npm run build-windows && npm run build-apple && npm run build-android", + "preplaywright": "npm run bundle-entry-points", + "preplaywright-headed": "npm run bundle-entry-points", "playwright-e2e": "playwright test -c playwright-e2e.config.js --project duckplayer-e2e", "playwright-e2e-headed": "npm run playwright-e2e -- --headed", - "preplaywright-e2e": "npm run build-windows && npm run build-apple" + "preplaywright-e2e": "npm run bundle-entry-points" }, "type": "module", "dependencies": { From 37778716ecfe7eda17df9884a8f05599fc3f9861 Mon Sep 17 00:00:00 2001 From: Shane Osbourne Date: Thu, 27 Feb 2025 09:50:15 +0000 Subject: [PATCH 06/11] always build bundles before playwright --- injected/package.json | 8 ++------ injected/playwright.config.js | 2 +- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/injected/package.json b/injected/package.json index 75277a9a3..7da635c6e 100644 --- a/injected/package.json +++ b/injected/package.json @@ -10,18 +10,14 @@ "build-types": "node scripts/types.mjs", "bundle-trackers": "node scripts/bundleTrackers.mjs --output ../build/tracker-lookup.json", "test-unit": "jasmine --config=unit-test/config.json", - "test-int": "npm run build-integration && npm run playwright", + "test-int": "npm run playwright", "test-int-x": "xvfb-run --server-args='-screen 0 1024x768x24' npm run test-int", "test": "npm run lint && npm run test-unit && npm run test-int && npm run playwright", "serve": "http-server -c-1 --port 3220 integration-test/test-pages", "playwright": "playwright test --grep-invert '@screenshots'", "playwright-screenshots": "playwright test --grep '@screenshots'", - "playwright-headed": "playwright test --headed", - "preplaywright": "npm run bundle-entry-points", - "preplaywright-headed": "npm run bundle-entry-points", "playwright-e2e": "playwright test -c playwright-e2e.config.js --project duckplayer-e2e", - "playwright-e2e-headed": "npm run playwright-e2e -- --headed", - "preplaywright-e2e": "npm run bundle-entry-points" + "playwright-e2e-headed": "npm run playwright-e2e -- --headed" }, "type": "module", "dependencies": { diff --git a/injected/playwright.config.js b/injected/playwright.config.js index fe6cde2fb..3d077bcd8 100644 --- a/injected/playwright.config.js +++ b/injected/playwright.config.js @@ -93,7 +93,7 @@ export default defineConfig({ webServer: { reuseExistingServer: true, ignoreHTTPSErrors: true, - command: 'npm run serve', + command: 'npm run bundle-entry-points && npm run serve', port: 3220, }, use: { From e8bb502e5fc95b06147ec95aad1813c761ce36d3 Mon Sep 17 00:00:00 2001 From: Shane Osbourne Date: Thu, 27 Feb 2025 10:18:33 +0000 Subject: [PATCH 07/11] comments --- injected/entry-points/chrome.js | 7 ++----- injected/scripts/utils/build.js | 6 ++++++ 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/injected/entry-points/chrome.js b/injected/entry-points/chrome.js index 424d03ab2..1bc543453 100644 --- a/injected/entry-points/chrome.js +++ b/injected/entry-points/chrome.js @@ -49,11 +49,8 @@ function init() { const reusableMethodName = '_rm' + randomString(); const reusableSecret = '_r' + randomString(); const siteObject = computeLimitedSiteObject(); - const initialScript = - contentScopeFeatures + - ` - /* global contentScopeFeatures */ - contentScopeFeatures.load({ + const initialScript = contentScopeFeatures + + `;contentScopeFeatures.load({ platform: { name: 'extension' }, diff --git a/injected/scripts/utils/build.js b/injected/scripts/utils/build.js index fa41023e3..fe989ce5e 100644 --- a/injected/scripts/utils/build.js +++ b/injected/scripts/utils/build.js @@ -125,6 +125,12 @@ function loadFeatures(platform, featureNames = platformSupport[platform]) { }; } +/** + * Create a bundle and allow it to be imported as a string via + * `import bundle from 'ddg:contentScopeFeatures'` + * + * @param {string} platform + */ function contentFeaturesAsString(platform) { const pluginId = 'ddg:contentScopeFeatures'; return { From 25f492e93ea2115c9f924e348587637b62628e8b Mon Sep 17 00:00:00 2001 From: Shane Osbourne Date: Thu, 27 Feb 2025 10:29:00 +0000 Subject: [PATCH 08/11] prettier --- injected/entry-points/chrome.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/injected/entry-points/chrome.js b/injected/entry-points/chrome.js index 1bc543453..61def457f 100644 --- a/injected/entry-points/chrome.js +++ b/injected/entry-points/chrome.js @@ -49,6 +49,8 @@ function init() { const reusableMethodName = '_rm' + randomString(); const reusableSecret = '_r' + randomString(); const siteObject = computeLimitedSiteObject(); + + // prettier-ignore const initialScript = contentScopeFeatures + `;contentScopeFeatures.load({ platform: { From a6a71471baf36a35ad0ae91b5fa0d3ab9c8d1652 Mon Sep 17 00:00:00 2001 From: Shane Osbourne Date: Thu, 27 Feb 2025 14:07:12 +0000 Subject: [PATCH 09/11] use same target as previous --- injected/scripts/utils/build.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/injected/scripts/utils/build.js b/injected/scripts/utils/build.js index fe989ce5e..10d5c57af 100644 --- a/injected/scripts/utils/build.js +++ b/injected/scripts/utils/build.js @@ -38,7 +38,7 @@ export async function bundle(params) { entryPoints: [scriptPath], write: false, outdir: 'build', - target: 'safari15', + target: 'es2021', format: 'iife', supported: { 'class-private-field': false, From 5a5b87cc5a4c7ef5578c4e09da2866cc6b65ab74 Mon Sep 17 00:00:00 2001 From: Shane Osbourne Date: Thu, 27 Feb 2025 14:58:40 +0000 Subject: [PATCH 10/11] legacy command to keep the extension building --- injected/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/injected/package.json b/injected/package.json index 7da635c6e..c10f89fb7 100644 --- a/injected/package.json +++ b/injected/package.json @@ -6,6 +6,7 @@ "build": "npm run build-types && npm run build-locales && npm run bundle-trackers && npm run bundle-entry-points", "bundle-config": "node scripts/bundleConfig.mjs", "bundle-entry-points": "node scripts/entry-points.js", + "build-chrome-mv3": "node scripts/entry-points.js", "build-locales": "node scripts/buildLocales.js", "build-types": "node scripts/types.mjs", "bundle-trackers": "node scripts/bundleTrackers.mjs --output ../build/tracker-lookup.json", From 8d84d5b785de1535e8cfa457763c39ef24b154b8 Mon Sep 17 00:00:00 2001 From: Shane Osbourne Date: Thu, 27 Feb 2025 15:03:56 +0000 Subject: [PATCH 11/11] legacy command to keep the extension building --- injected/scripts/utils/build.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/injected/scripts/utils/build.js b/injected/scripts/utils/build.js index 10d5c57af..a69680f13 100644 --- a/injected/scripts/utils/build.js +++ b/injected/scripts/utils/build.js @@ -40,9 +40,6 @@ export async function bundle(params) { outdir: 'build', target: 'es2021', format: 'iife', - supported: { - 'class-private-field': false, - }, bundle: true, metafile: true, globalName: name,