diff --git a/extension/background.js b/extension/background.js index 85adbe8..50b5f6d 100644 --- a/extension/background.js +++ b/extension/background.js @@ -247,11 +247,13 @@ router["/tabs/by-id"] = { buf => ({ active: buf.startsWith("true") })); })(); (function() { - let evals = {}; + const evals = {}; router["/tabs/by-id/*/evals"] = { async readdir({path}) { const tabId = parseInt(pathComponent(path, -2)); - return { entries: [".", "..", ...Object.keys(evals[tabId] || [])] }; + return { entries: [".", "..", + ...Object.keys(evals[tabId] || {}), + ...Object.keys(evals[tabId] || {}).map(f => f + '.result')] }; }, getattr() { return { @@ -263,24 +265,75 @@ router["/tabs/by-id"] = { }; router["/tabs/by-id/*/evals/*"] = { // NOTE: eval runs in extension's content script, not in original page JS context - async create({path, mode}) { - const [tabId, expr] = [parseInt(pathComponent(path, -3)), pathComponent(path, -1)]; + async mknod({path, mode}) { + const [tabId, name] = [parseInt(pathComponent(path, -3)), pathComponent(path, -1)]; evals[tabId] = evals[tabId] || {}; - evals[tabId][expr] = async function() { + evals[tabId][name] = { code: '' }; + return {}; + }, + async unlink({path}) { + const [tabId, name] = [parseInt(pathComponent(path, -3)), pathComponent(path, -1)]; + delete evals[tabId][name]; // TODO: also delete evals[tabId] if empty + return {}; + }, + + ...defineFile(async path => { + const [tabId, filename] = [parseInt(pathComponent(path, -3)), pathComponent(path, -1)]; + const name = filename.replace(/\.result$/, ''); + if (!evals[tabId] || !(name in evals[tabId])) { throw new UnixError(unix.ENOENT); } + + if (filename.endsWith('.result')) { + return evals[tabId][name].result || ''; + } else { + return evals[tabId][name].code; + } + }, async (path, buf) => { + const [tabId, name] = [parseInt(pathComponent(path, -3)), pathComponent(path, -1)]; + if (name.endsWith('.result')) { + // FIXME + + } else { + evals[tabId][name].code = buf; + evals[tabId][name].result = JSON.stringify((await browser.tabs.executeScript(tabId, {code: buf}))[0]) + '\n'; + } + }) + }; +})(); +(function() { + const watches = {}; + router["/tabs/by-id/*/watches"] = { + async readdir({path}) { + const tabId = parseInt(pathComponent(path, -2)); + return { entries: [".", "..", ...Object.keys(watches[tabId] || [])] }; + }, + getattr() { + return { + st_mode: unix.S_IFDIR | 0777, // writable so you can create/rm watches + st_nlink: 3, + st_size: 0, + }; + }, + }; + router["/tabs/by-id/*/watches/*"] = { + // NOTE: eval runs in extension's content script, not in original page JS context + async mknod({path, mode}) { + const [tabId, expr] = [parseInt(pathComponent(path, -3)), pathComponent(path, -1)]; + watches[tabId] = watches[tabId] || {}; + watches[tabId][expr] = async function() { return (await browser.tabs.executeScript(tabId, {code: expr}))[0]; }; return {}; }, async unlink({path}) { const [tabId, expr] = [parseInt(pathComponent(path, -3)), pathComponent(path, -1)]; - delete evals[tabId][expr]; // TODO: also delete evals[tabId] if empty + delete watches[tabId][expr]; // TODO: also delete watches[tabId] if empty return {}; }, ...defineFile(async path => { const [tabId, expr] = [parseInt(pathComponent(path, -3)), pathComponent(path, -1)]; - if (!evals[tabId] || !(expr in evals[tabId])) { throw new UnixError(unix.ENOENT); } - return JSON.stringify(await evals[tabId][expr]()) + '\n'; + if (!watches[tabId] || !(expr in watches[tabId])) { throw new UnixError(unix.ENOENT); } + return JSON.stringify(await watches[tabId][expr]()) + '\n'; }, () => { // setData handler -- only providing this so that getattr reports // that the file is writable, so it can be deleted without annoying prompt. diff --git a/test/test.c b/test/test.c index 0e97a04..e18197c 100644 --- a/test/test.c +++ b/test/test.c @@ -70,14 +70,14 @@ int main() { } assert(system("cat ../fs/mnt/tabs/last-focused/debugger/scripts/*test-script.js") == 0); - // FIXME: rewrite to use TAB/evals - /* { */ - /* FILE* console = fopen("../fs/mnt/tabs/last-focused/console", "r"); */ - /* assert(system("echo \"console.log('hi')\" > ../fs/mnt/tabs/last-focused/execute-script") == 0); */ - /* char hi[3] = {0}; fread(hi, 1, 2, console); */ - /* assert(strcmp(hi, "hi") == 0); */ - /* fclose(console); */ - /* } */ + { + assert(system("echo '2 + 2' > ../fs/mnt/tabs/last-focused/evals/twoplustwo.js") == 0); + + FILE* result = fopen("../fs/mnt/tabs/last-focused/evals/twoplustwo.js.result", "r"); + char four[2] = {0}; fread(four, 1, 1, result); + assert(strcmp(four, "4") == 0); + fclose(result); + } // try to shorten the URL (#40) /* assert(system("echo about:blank > ../fs/mnt/tabs/last-focused/url.txt") == 0); */ @@ -88,18 +88,19 @@ int main() { { assert(system("echo file://$(pwd)/test-textarea.html > ../fs/mnt/tabs/create") == 0); - // FIXME: rewrite to use TAB/evals - /* { */ - /* FILE* console = fopen("../fs/mnt/tabs/last-focused/console", "r"); */ - /* assert(system("echo \"console.log(document.getElementById('ta').value)\" > ../fs/mnt/tabs/last-focused/execute-script") == 0); */ + { + assert(system("echo \"document.getElementById('ta').value\" > ../fs/mnt/tabs/last-focused/evals/ta.js") == 0); - /* char ta[100] = {0}; fread(ta, 1, sizeof(ta), console); */ - /* assert(strcmp(ta, "initial text") == 0); */ + FILE* result = fopen("../fs/mnt/tabs/last-focused/evals/ta.js.result", "r"); + char ta[100] = {0}; fread(ta, 1, sizeof(ta), result); + fclose(result); - /* assert(file_contents_equal("../fs/mnt/tabs/last-focused/inputs/ta.txt", ta)); */ + assert(strcmp(ta, "\"initial text\"\n") == 0); - /* fclose(console); */ - /* } */ + // FIXME: check against the inputs file ... + /* assert(file_contents_equal("../fs/mnt/tabs/last-focused/inputs/ta.txt", ta)); */ + + } assert(system("echo remove > ../fs/mnt/tabs/last-focused/control") == 0); }