Skip to content
This repository was archived by the owner on Oct 3, 2024. It is now read-only.

Commit 61550fc

Browse files
Expose the script api version to runner modules and user scripts
1 parent ca8841b commit 61550fc

12 files changed

Lines changed: 145 additions & 29 deletions

File tree

core/lib/background/RunnerScriptParent.js

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ class RunnerScriptParent {
4444
return this[PRIVATE].compileScript(content, stackFileName);
4545
}
4646

47+
get scriptApiVersion() {
48+
return this[PRIVATE].scriptApiVersion;
49+
}
50+
4751
async run() {
4852
return this[PRIVATE].run();
4953
}
@@ -171,6 +175,19 @@ class RunnerScriptParentPrivate {
171175
await this.rpcCall({name: 'ping', timeout: 1001});
172176

173177
const {runTimeoutMs, stackFileName} = this;
178+
await this.rpcCall(
179+
{
180+
name: 'core.compileScript',
181+
timeout: 10002,
182+
},
183+
{
184+
runTimeout: runTimeoutMs,
185+
scriptContent: this.scriptContent,
186+
stackFileName,
187+
scriptApiVersion: this.scriptApiVersion,
188+
}
189+
);
190+
174191
this.scriptTimeoutTimer = setTimeout(() => {
175192
this.scriptTimeoutTimer = 0;
176193
this.stop({
@@ -192,11 +209,7 @@ class RunnerScriptParentPrivate {
192209
// note: if this timeout hits, the result log will be fairly empty, it is only used as a last resort:
193210
timeout: runTimeoutMs + 30000,
194211
},
195-
{
196-
runTimeout: runTimeoutMs,
197-
scriptContent: this.scriptContent,
198-
stackFileName,
199-
}
212+
{}
200213
);
201214
await this.emitRunScriptResult(runScriptResult);
202215
scriptResult.timing.endNow();

core/lib/script-env/RunnerScript.js

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,16 @@ class RunnerScript {
5757
await this[PRIVATE].stop(reason);
5858
}
5959

60-
compileScript(scriptContent, stackFileName) {
61-
this[PRIVATE].compileScript(scriptContent, stackFileName);
60+
compileScript(scriptContent, stackFileName, scriptApiVersion) {
61+
this[PRIVATE].compileScript(scriptContent, stackFileName, scriptApiVersion);
62+
}
63+
64+
get compiled() {
65+
return this[PRIVATE].compiled;
66+
}
67+
68+
get scriptApiVersion() {
69+
return this[PRIVATE].scriptApiVersion;
6270
}
6371

6472
async run() {
@@ -80,8 +88,10 @@ class RunnerScriptPrivate {
8088
});
8189
this.rpcRegisterMethods(coreMethods(this.publicInterface));
8290
this.attached = false;
91+
this.compiled = false;
8392
this.scriptFunction = null;
8493
this.stackFileName = null;
94+
this.scriptApiVersion = null;
8595
this.moduleRegister = new ModuleRegister();
8696
this.stopReason = null;
8797
this.stopPromise = new Promise((resolve, reject) => {
@@ -166,9 +176,11 @@ class RunnerScriptPrivate {
166176
this.stopPromiseReject(err);
167177
}
168178

169-
compileScript(scriptContent, stackFileName) {
179+
compileScript(scriptContent, stackFileName, scriptApiVersion) {
170180
this.scriptFunction = compileRunnerScript(scriptContent);
171181
this.stackFileName = stackFileName;
182+
this.scriptApiVersion = scriptApiVersion;
183+
this.compiled = true;
172184
}
173185

174186
async include(name) {

core/lib/script-env/coreMethods.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,11 @@ module.exports = script => {
66
await script.stop(reason);
77
};
88

9-
const runScript = async ({scriptContent, stackFileName}) => {
10-
script.compileScript(scriptContent, stackFileName);
9+
const compileScript = async ({scriptContent, stackFileName, scriptApiVersion}) => {
10+
script.compileScript(scriptContent, stackFileName, scriptApiVersion);
11+
};
12+
13+
const runScript = async () => {
1114
const {scriptError, scriptValue} = await script.run();
1215
return {scriptError, scriptValue};
1316
};
@@ -35,6 +38,7 @@ module.exports = script => {
3538
};
3639

3740
return new Map([
41+
['core.compileScript', compileScript],
3842
['core.stopScript', stopScript],
3943
['core.runScript', runScript],
4044
['core.importScripts', (...urls) => importScripts(...urls)],

core/lib/script-env/globalFunctions.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@ module.exports = async script => {
44
const include = async name => {
55
return await script.include(name);
66
};
7+
Object.defineProperties(include, {
8+
scriptApiVersion: {
9+
enumerable: true,
10+
get: () => script.scriptApiVersion,
11+
},
12+
});
713

814
const runResult = await include('runResult');
915
const transaction = (...args) => runResult.scriptResult.transaction(...args);

core/lib/script-env/index.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,16 @@ try {
1313
self.openRunnerRegisterRunnerModule = async (moduleName, func) => {
1414
try {
1515
if (!isValidModuleName(moduleName)) {
16-
throw Error('openRunnerRegisterRunnerModule(); Invalid argument `moduleName`');
16+
throw Error('openRunnerRegisterRunnerModule(): Invalid argument `moduleName`');
1717
}
1818
if (typeof func !== 'function') {
1919
throw Error('openRunnerRegisterRunnerModule(): Invalid argument `func`');
2020
}
2121

22+
if (!script.compiled) {
23+
throw Error('openRunnerRegisterRunnerModule(): Called too soon; The RunnerScript has not been compiled yet');
24+
}
25+
2226
const initModule = async () => {
2327
return await func({script});
2428
};

lib/getRunnerScriptMetadata.js

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@ const log = require('./logger')({hostname: 'background', MODULE: 'getRunnerScrip
77
const DEFAULT_RUN_TIMEOUT = 60 * 1000;
88

99
const getRunnerScriptMetadata = (scriptContent) => {
10-
let scriptApiVersion = null;
10+
let versionValue = null;
1111
let runTimeoutMs = DEFAULT_RUN_TIMEOUT;
1212
const metaData = metaDataParser(scriptContent).filter(entry => /^openrunner-/i.test(entry.key));
1313

1414
for (const {key, value} of metaData) {
1515
const lowerKey = key.toLowerCase();
16-
if (!scriptApiVersion && lowerKey === 'openrunner-script') {
17-
scriptApiVersion = value;
16+
if (!versionValue && lowerKey === 'openrunner-script') {
17+
versionValue = value;
1818
}
1919
else if (lowerKey === 'openrunner-script-timeout') {
2020
const valueMatch = /^\s*(\d+(s)?)\s*$/.exec(value);
@@ -35,19 +35,22 @@ const getRunnerScriptMetadata = (scriptContent) => {
3535
}
3636
}
3737

38-
if (!scriptApiVersion) {
38+
if (!versionValue) {
3939
log.warn('"Openrunner-Script" metadata literal is missing');
4040
throw Error(
4141
`The mandatory "Openrunner-Script" metadata literal is missing within the given Openrunner script. ` +
4242
`The line 'Openrunner-Script: v1'; should be added to the top of your script.`
4343
);
4444
}
4545

46-
if (scriptApiVersion !== 'v1') {
47-
log.warn({scriptApiVersion}, 'Invalid API version');
46+
const versionExec = /^v(\d+)$/.exec(versionValue);
47+
const scriptApiVersion = versionExec && parseInt(versionExec[1], 10);
48+
49+
if (scriptApiVersion !== 1) {
50+
log.warn({versionValue}, 'Invalid API version');
4851
throw Error(
4952
`The given Openrunner script specified an API version (e.g. 'Openrunner-Script: v123') which is not supported ` +
50-
`by this script runner. Version given: "${scriptApiVersion}"; Supported: "v1"`
53+
`by this script runner. Version given: "${versionValue}"; Supported: "v1"`
5154
);
5255
}
5356

runner-modules/tabs/lib/background/TabManager.js

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,13 @@ const contentMethods = require('./contentMethods');
1414
const TOP_FRAME_ID = 0;
1515

1616
class TabManager extends EventEmitter {
17-
constructor({runtime: browserRuntime, windows: browserWindows, tabs: browserTabs, webNavigation: browserWebNavigation}) {
17+
constructor({
18+
runtime: browserRuntime,
19+
windows: browserWindows,
20+
tabs: browserTabs,
21+
webNavigation: browserWebNavigation,
22+
scriptApiVersion,
23+
}) {
1824
super();
1925
this._attached = false;
2026
this.browserRuntime = browserRuntime;
@@ -30,6 +36,7 @@ class TabManager extends EventEmitter {
3036
context: 'runner-modules/tabs',
3137
onRpcInitialize: obj => this.handleRpcInitialize(obj),
3238
});
39+
this.scriptApiVersion = scriptApiVersion;
3340
this._navigationCommittedWait = new WaitForEvent(); // key is [browserTabId, browserFrameId]
3441

3542
this.handleTabCreated = this.handleTabCreated.bind(this);
@@ -142,7 +149,7 @@ class TabManager extends EventEmitter {
142149
}
143150
}
144151

145-
handleTabMainContentInitialized(browserTabId, browserFrameId) {
152+
async handleTabMainContentInitialized(browserTabId, browserFrameId) {
146153
const tab = this.myTabs.getByBrowserTabId(browserTabId);
147154
const isMyTab = Boolean(tab);
148155
log.info({browserTabId, browserFrameId, isMyTab}, 'Main tab content script has been initialized');
@@ -157,6 +164,10 @@ class TabManager extends EventEmitter {
157164
this.myTabs.expectInitToken(browserTabId, browserFrameId, 'tabs');
158165
const rpc = this.tabContentRPC.get(browserTabId, browserFrameId);
159166

167+
await rpc.call('tabs.initializedMainTabContent', {
168+
scriptApiVersion: this.scriptApiVersion,
169+
});
170+
160171
const files = [];
161172
const executeContentScript = (initToken, file) => {
162173
log.debug({browserTabId, browserFrameId, initToken, file}, 'Executing content script for runner module');

runner-modules/tabs/lib/background/index.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,13 @@ const tabsMethods = require('./tabsMethods');
66
const scriptEnvUrl = browser.extension.getURL('/build/tabs-script-env.js');
77

88
module.exports = script => {
9-
const tabManager = new TabManager(browser);
9+
const tabManager = new TabManager({
10+
runtime: browser.runtime,
11+
windows: browser.windows,
12+
tabs: browser.tabs,
13+
webNavigation: browser.webNavigation,
14+
scriptApiVersion: script.scriptApiVersion,
15+
});
1016
tabManager.on('windowCreated', data => script.emit('tabs.windowCreated', data));
1117
tabManager.on('windowClosed', data => script.emit('tabs.windowClosed', data));
1218
tabManager.on('tabCreated', data => script.emit('tabs.tabCreated', data));

runner-modules/tabs/lib/content/index.js

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,22 @@ try {
2222
const getModule = name => moduleRegister.waitForModuleRegistration(name);
2323
const eventEmitter = new EventEmitter();
2424
const fireContentUnload = contentUnloadEvent(eventEmitter);
25+
let backgroundScriptInitData = null;
26+
const scriptApiVersion = () => backgroundScriptInitData && backgroundScriptInitData.scriptApiVersion;
27+
const initializedMainTabContent = async (data) => {
28+
// when we send 'tabs.mainContentInit' to the background script, the background script will then in turn send us
29+
// 'tabs.initializedMainTabContent', after which it will begin to load runner modules
30+
// backgroundScriptInitData = {scriptApiVersion}
31+
backgroundScriptInitData = data;
32+
};
2533
const rpc = new ContentRPC({
2634
browserRuntime: browser.runtime,
2735
context: 'runner-modules/tabs',
2836
});
2937
rpc.attach();
30-
rpc.methods(tabsMethods(moduleRegister, eventEmitter));
38+
rpc.methods(tabsMethods(moduleRegister, eventEmitter, scriptApiVersion));
3139
rpc.method('tabs.contentUnload', fireContentUnload);
40+
rpc.method('tabs.initializedMainTabContent', initializedMainTabContent);
3241
window.addEventListener('unload', fireContentUnload);
3342
eventEmitter.on('tabs.contentUnload', () => log.debug('Content is about to unload'));
3443

@@ -47,8 +56,20 @@ try {
4756
throw Error('openRunnerRegisterRunnerModule(): Invalid `func`');
4857
}
4958

59+
if (!backgroundScriptInitData) {
60+
throw Error(
61+
'openRunnerRegisterRunnerModule(): Called too early. Background script has not yet sent ' +
62+
'\'tabs.initializedMainTabContent\' to content script'
63+
);
64+
}
65+
5066
const initModule = async () => {
51-
return await func({eventEmitter, getModule, rpc});
67+
return await func({
68+
eventEmitter,
69+
getModule,
70+
rpc,
71+
scriptApiVersion: scriptApiVersion(),
72+
});
5273
};
5374

5475
const promise = initModule();

runner-modules/tabs/lib/content/tabsMethods.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,15 @@ const getModuleValues = function* (modulesMap, metadata) {
1919
};
2020

2121

22-
module.exports = (moduleRegister, eventEmitter) => {
22+
module.exports = (moduleRegister, eventEmitter, getScriptApiVersion) => {
2323
const getModule = name => moduleRegister.waitForModuleRegistration(name);
2424
const globalFunctionsPromise = constructGlobalFunctions(getModule);
2525

26-
const compileFunction = async (functionCode, globalFunctions, metadata) => {
26+
const compileFunction = async (functionCode, globalFunctions, metadataArg) => {
27+
const metadata = {
28+
...metadataArg,
29+
scriptApiVersion: getScriptApiVersion(),
30+
};
2731
const modules = await moduleRegister.getAllModules();
2832
const argNames = [
2933
'runMetadata',

0 commit comments

Comments
 (0)