Skip to content

Commit

Permalink
fix: Ignore non-manifest fields when merging content script entries (w…
Browse files Browse the repository at this point in the history
  • Loading branch information
aklinker1 authored Oct 13, 2023
1 parent 95442dd commit 739b738
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 47 deletions.
50 changes: 25 additions & 25 deletions e2e/tests/manifest-content.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,15 +194,15 @@ describe('Manifest Content', () => {
});

describe('content_scripts', () => {
it('should group content scripts and styles together based on their matches and run_at', async () => {
it('should group content scripts and styles together based on their manifest properties', async () => {
const project = new TestProject();
project.addFile(
'entrypoints/one.content/index.ts',
`import "./style.css";
export default defineContentScript({
matches: ["*://google.com/*"],
main: () => {},
})`,
export default defineContentScript({
matches: ["*://google.com/*"],
main: () => {},
})`,
);
project.addFile(
'entrypoints/one.content/style.css',
Expand All @@ -211,11 +211,11 @@ describe('Manifest Content', () => {
project.addFile(
'entrypoints/two.content/index.ts',
`import "./style.css";
export default defineContentScript({
matches: ["*://google.com/*"],
runAt: "document_end",
main: () => {},
})`,
export default defineContentScript({
matches: ["*://google.com/*"],
runAt: "document_end",
main: () => {},
})`,
);
project.addFile(
'entrypoints/two.content/style.css',
Expand All @@ -224,11 +224,11 @@ describe('Manifest Content', () => {
project.addFile(
'entrypoints/three.content/index.ts',
`import "./style.css";
export default defineContentScript({
matches: ["*://google.com/*"],
runAt: "document_end",
main: () => {},
})`,
export default defineContentScript({
matches: ["*://google.com/*"],
runAt: "document_end",
main: () => {},
})`,
);
project.addFile(
'entrypoints/three.content/style.css',
Expand All @@ -237,11 +237,11 @@ describe('Manifest Content', () => {
project.addFile(
'entrypoints/four.content/index.ts',
`import "./style.css";
export default defineContentScript({
matches: ["*://duckduckgo.com/*"],
runAt: "document_end",
main: () => {},
})`,
export default defineContentScript({
matches: ["*://duckduckgo.com/*"],
runAt: "document_end",
main: () => {},
})`,
);
project.addFile(
'entrypoints/four.content/style.css',
Expand Down Expand Up @@ -276,15 +276,15 @@ describe('Manifest Content', () => {
project.addFile(
'entrypoints/one.content/index.ts',
`export default defineContentScript({
matches: ["*://google.com/*"],
main: () => {},
})`,
matches: ["*://google.com/*"],
main: () => {},
})`,
);
project.addFile(
'entrypoints/two.content/style.css',
`body {
background-color: red;
}`,
background-color: red;
}`,
);
project.setConfigFileConfig({
manifest: {
Expand Down
2 changes: 2 additions & 0 deletions src/core/types/external.ts
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,8 @@ export interface ContentScriptDefinition extends ExcludableEntrypoint {
* - `"manual"` - Exclude the CSS from the manifest. You are responsible for manually loading it
* onto the page. Use `browser.runtime.getURL("content-scripts/<name>.css")` to get the file's
* URL
* - `"ui"` - Exclude the CSS from the manifest. CSS will be automatically added to your UI when
* calling `createContentScriptUi`
*
* @default "manifest"
*/
Expand Down
32 changes: 21 additions & 11 deletions src/core/utils/__tests__/content-scripts.test.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,36 @@
import { describe, expect, it } from 'vitest';
import { hashContentScriptOptions } from '../content-scripts';
import { fakeInternalConfig } from '../../../testing/fake-objects';

describe('Content Script Utils', () => {
describe('hashContentScriptOptions', () => {
it('should return a string containing all the options with defaults applied', () => {
const hash = hashContentScriptOptions({ matches: [] });
const hash = hashContentScriptOptions(
{ matches: [] },
fakeInternalConfig(),
);

expect(hash).toMatchInlineSnapshot(
'"[[\\"allFrames\\",false],[\\"excludeGlobs\\",[]],[\\"excludeMatches\\",[]],[\\"includeGlobs\\",[]],[\\"matchAboutBlank\\",false],[\\"matches\\",[]],[\\"matchOriginAsFallback\\",false],[\\"runAt\\",\\"document_idle\\"],[\\"world\\",\\"ISOLATED\\"]]"',
'"[[\\"all_frames\\",false],[\\"exclude_globs\\",[]],[\\"exclude_matches\\",[]],[\\"include_globs\\",[]],[\\"match_about_blank\\",false],[\\"match_origin_as_fallback\\",false],[\\"matches\\",[]],[\\"run_at\\",\\"document_idle\\"],[\\"world\\",\\"ISOLATED\\"]]"',
);
});

it('should be consistent regardless of the object ordering and default values', () => {
const hash1 = hashContentScriptOptions({
allFrames: true,
matches: ['*://google.com/*', '*://duckduckgo.com/*'],
matchAboutBlank: false,
});
const hash2 = hashContentScriptOptions({
matches: ['*://duckduckgo.com/*', '*://google.com/*'],
allFrames: true,
});
const hash1 = hashContentScriptOptions(
{
allFrames: true,
matches: ['*://google.com/*', '*://duckduckgo.com/*'],
matchAboutBlank: false,
},
fakeInternalConfig(),
);
const hash2 = hashContentScriptOptions(
{
matches: ['*://duckduckgo.com/*', '*://google.com/*'],
allFrames: true,
},
fakeInternalConfig(),
);

expect(hash1).toBe(hash2);
});
Expand Down
29 changes: 19 additions & 10 deletions src/core/utils/content-scripts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,27 @@ import { resolvePerBrowserOption } from './entrypoints';
*/
export function hashContentScriptOptions(
options: ContentScriptEntrypoint['options'],
config: InternalConfig,
): string {
const withDefaults: ContentScriptEntrypoint['options'] = {
excludeGlobs: [],
excludeMatches: [],
includeGlobs: [],
matchAboutBlank: false,
matchOriginAsFallback: false,
runAt: 'document_idle',
allFrames: false,
const simplifiedOptions = mapWxtOptionsToContentScript(options, config);

// Remove undefined fields and use defaults to generate hash
Object.keys(simplifiedOptions).forEach((key) => {
// @ts-expect-error: key not typed as keyof ...
if (simplifiedOptions[key] == null) delete simplifiedOptions[key];
});

const withDefaults: Manifest.ContentScript = {
exclude_globs: [],
exclude_matches: [],
include_globs: [],
match_about_blank: false,
run_at: 'document_idle',
all_frames: false,
// @ts-expect-error - not in type
match_origin_as_fallback: false,
world: 'ISOLATED',
// TODO: strip undefined fields from options object to improve content script grouping.
...options,
...simplifiedOptions,
};
return JSON.stringify(
Object.entries(withDefaults)
Expand Down
2 changes: 1 addition & 1 deletion src/core/utils/manifest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ function addEntrypoints(
);
} else {
const hashToEntrypointsMap = contentScripts.reduce((map, script) => {
const hash = hashContentScriptOptions(script.options);
const hash = hashContentScriptOptions(script.options, config);
if (map.has(hash)) map.get(hash)?.push(script);
else map.set(hash, [script]);
return map;
Expand Down

0 comments on commit 739b738

Please sign in to comment.