Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ulixee
GitHub Repository: ulixee/secret-agent
Path: blob/main/plugins/default-browser-emulator/lib/DomOverridesBuilder.ts
1029 views
1
import * as fs from 'fs';
2
import INewDocumentInjectedScript from '@secret-agent/interfaces/INewDocumentInjectedScript';
3
import injectedSourceUrl from '@secret-agent/interfaces/injectedSourceUrl';
4
5
const cache: { [name: string]: string } = {};
6
const shouldCache = process.env.NODE_ENV === 'production';
7
8
const utilsScript = [
9
fs.readFileSync(`${__dirname}/../injected-scripts/_proxyUtils.js`, 'utf8'),
10
fs.readFileSync(`${__dirname}/../injected-scripts/_descriptorBuilder.js`, 'utf8'),
11
].join('\n');
12
13
export default class DomOverridesBuilder {
14
private readonly scriptsByName = new Map<string, string>();
15
16
public build(scriptNames?: string[]): INewDocumentInjectedScript[] {
17
const scripts = [];
18
for (const [name, script] of this.scriptsByName) {
19
const shouldIncludeScript = scriptNames ? scriptNames.includes(name) : true;
20
if (shouldIncludeScript) {
21
scripts.push(script);
22
}
23
}
24
return [
25
{
26
// NOTE: don't make this async. It can cause issues if you read a frame right after creation, for instance
27
script: `(function newDocumentScript() {
28
// Worklet has no scope to override, but we can't detect until it loads
29
if (typeof self === 'undefined' && typeof window === 'undefined') return;
30
31
const sourceUrl = '${injectedSourceUrl}';
32
33
${utilsScript}
34
35
${scripts.join('\n\n')}
36
})();
37
//# sourceURL=${injectedSourceUrl}`.replace(/\/\/# sourceMap.+/g, ''),
38
},
39
];
40
}
41
42
public add(name: string, args: any = {}) {
43
let script = cache[name];
44
if (!script) {
45
if (!fs.existsSync(`${__dirname}/../injected-scripts/${name}.js`)) {
46
throw new Error(`Browser-Emulator injected script doesn\`t exist: ${name}`);
47
}
48
script = fs.readFileSync(`${__dirname}/../injected-scripts/${name}.js`, 'utf8');
49
}
50
if (shouldCache) cache[name] = script;
51
52
if (name === 'errors') args.sourceUrl = injectedSourceUrl;
53
54
let wrapper = `(function newDocumentScript_${name.replace(/\./g, '__')}(args) {
55
try {
56
${script};
57
} catch(err) {
58
console.log('Failed to initialize "${name}"', err);
59
}
60
})(${JSON.stringify(args)});`;
61
62
if (name.startsWith('polyfill.')) {
63
wrapper = `// if main frame and HTML element not loaded yet, give it a sec
64
if (!document.documentElement) {
65
new MutationObserver((list, observer) => {
66
observer.disconnect();
67
${wrapper}
68
}).observe(document, {childList: true, subtree: true});
69
} else {
70
${wrapper}
71
}
72
`;
73
}
74
this.scriptsByName.set(name, wrapper);
75
}
76
}
77
78
export function getOverrideScript(name: string, args?: any) {
79
const injected = new DomOverridesBuilder();
80
injected.add(name, args);
81
return injected.build()[0];
82
}
83
84