From b978b804da1e9a20c6b11907b1ac7174b83c91ab Mon Sep 17 00:00:00 2001 From: Dmitry Vasilev Date: Sat, 26 Nov 2022 02:56:32 +0800 Subject: [PATCH] WIP --- docs/examples/globalThis/global.js | 3 ++ docs/examples/globalThis/global2.js | 3 ++ docs/examples/globalThis/index.js | 5 ++ index.html | 1 + src/cmd.js | 3 +- src/index.js | 73 ++++++++++++++++++++++++++--- test/self_hosted_test.js | 2 +- test/test.js | 4 +- test/utils.js | 4 +- 9 files changed, 85 insertions(+), 13 deletions(-) create mode 100644 docs/examples/globalThis/global.js create mode 100644 docs/examples/globalThis/global2.js create mode 100644 docs/examples/globalThis/index.js diff --git a/docs/examples/globalThis/global.js b/docs/examples/globalThis/global.js new file mode 100644 index 0000000..f466c37 --- /dev/null +++ b/docs/examples/globalThis/global.js @@ -0,0 +1,3 @@ +export const test = () => { + return globalThis.mark +} \ No newline at end of file diff --git a/docs/examples/globalThis/global2.js b/docs/examples/globalThis/global2.js new file mode 100644 index 0000000..f466c37 --- /dev/null +++ b/docs/examples/globalThis/global2.js @@ -0,0 +1,3 @@ +export const test = () => { + return globalThis.mark +} \ No newline at end of file diff --git a/docs/examples/globalThis/index.js b/docs/examples/globalThis/index.js new file mode 100644 index 0000000..9bd8323 --- /dev/null +++ b/docs/examples/globalThis/index.js @@ -0,0 +1,5 @@ +// external +import {test} from './global.js' +console.log(globalThis.main) +test() + diff --git a/index.html b/index.html index 8120c4e..676980a 100644 --- a/index.html +++ b/index.html @@ -381,6 +381,7 @@ if(new URLSearchParams(window.location.search).get('leporello') == null) { await import('./src/launch.js'); + // TODO remove? /* const {init} = await import('./src/index.js'); ( diff --git a/src/cmd.js b/src/cmd.js index 3bef6b7..1ccf219 100644 --- a/src/cmd.js +++ b/src/cmd.js @@ -783,7 +783,7 @@ const open_run_window = state => { }) } -export const get_initial_state = state => { +const get_initial_state = state => { const with_files = state.project_dir == null ? state : load_dir(state, state.project_dir) @@ -807,6 +807,7 @@ export const get_initial_state = state => { } export const COMMANDS = { + get_initial_state, input, open_run_window, load_dir, diff --git a/src/index.js b/src/index.js index 021c137..4db5226 100644 --- a/src/index.js +++ b/src/index.js @@ -1,4 +1,3 @@ -import {get_initial_state} from './cmd.js' import {UI} from './editor/ui.js' import {EFFECTS, render_initial_state, render_common_side_effects} from './effects.js' import {load_dir} from './filesystem.js' @@ -23,19 +22,79 @@ const set_error_handler = w => { // window globalThis.run_window = (() => { const iframe = document.createElement('iframe') - iframe.src = 'about:blank' + //iframe.src = 'about:blank' + iframe.src = '/index.html?leporello' iframe.setAttribute('hidden', '') document.body.appendChild(iframe) set_error_handler(iframe.contentWindow) return iframe.contentWindow })() +// Open another browser window so user can interact with application +// TODO test in another browsers export const open_run_window = () => { - if(globalThis.run_window != null) { - globalThis.run_window.close() + globalThis.run_window.close() + + //const next_window = open('about:blank') + const next_window = globalThis.run_window = open('/index.html?leporello') + + const is_loaded = () => { + const nav = next_window.performance.getEntriesByType("navigation")[0] + return nav != null && nav.loadEventEnd > 0 } - globalThis.run_window = open('about:blank') - exec('rerun_code') + + // Wait until `load` event before executing code, because service worker that + // is responsible for loading external modules seems not working until `load` + // event fired. TODO: better register SW explicitly and don't rely on + // already registered SW? + const onload = () => { + exec('open_run_window') + } + + const add_load_handler = () => { + /* + Wait until 'load event', then set unload handler. The page after + window.open seems to go through these steps: + + - about:blank gets opened + - Real URL get opened + - 'unload' event for about:blank page + - 'load event for real URL + + if we set unload handler right now, then it will be fired for unload + event for about:blank page + */ + if(is_loaded()) { + // Already loaded + add_unload_handler() + onload() + } else { + next_window.addEventListener('load', () => { + add_unload_handler() + onload() + }) + } + } + + const add_unload_handler = () => { + next_window.addEventListener('unload', (e) => { + // Set timeout to 100ms because it takes some time for page to get closed + // after triggering 'unload' event + setTimeout(() => { + if(next_window.closed) { + // If by that time next_window.closed was set to true, then page was + // closed + // TODO get back to iframe? + console.log("CLOSED") + } else { + console.log("REFRESHED") + add_load_handler() + } + }, 100) + }) + } + + add_load_handler() } const read_modules = async () => { @@ -71,7 +130,7 @@ export const init = (container, _COMMANDS) => { set_error_handler(window) read_modules().then(initial_state => { - state = get_initial_state({ + state = COMMANDS.get_initial_state({ ...initial_state, on_async_call: (...args) => exec('on_async_call', ...args) }) diff --git a/test/self_hosted_test.js b/test/self_hosted_test.js index e6a4de9..340dac7 100644 --- a/test/self_hosted_test.js +++ b/test/self_hosted_test.js @@ -13,7 +13,7 @@ import { const entry = ` import {parse, load_modules} from './src/parse_js.js'; - import {get_initial_state} from './src/cmd.js'; + import {COMMANDS} from './src/cmd.js'; //console.time('p'); //const parsed = parse(globalThis.module_cache['./src/parse_js.js']); //console.timeEnd('p'); diff --git a/test/test.js b/test/test.js index 9fa1f52..35e3e5d 100644 --- a/test/test.js +++ b/test/test.js @@ -1,7 +1,7 @@ import {find_leaf, ancestry, find_node} from '../src/ast_utils.js' import {parse, print_debug_node} from '../src/parse_js.js' import {eval_tree, eval_frame, eval_modules} from '../src/eval.js' -import {COMMANDS, get_initial_state} from '../src/cmd.js' +import {COMMANDS} from '../src/cmd.js' import {root_calltree_node, active_frame, pp_calltree, get_async_calls} from '../src/calltree.js' import {color_file} from '../src/color.js' @@ -2241,7 +2241,7 @@ const y = x()` }), test('get_initial_state toplevel not entrypoint', () => { - const s = get_initial_state({ + const s = COMMANDS.get_initial_state({ files: { '' : `import {x} from 'x'; x()`, 'x' : `export const x = () => 1; x()`, diff --git a/test/utils.js b/test/utils.js index 1378dd0..e70252d 100644 --- a/test/utils.js +++ b/test/utils.js @@ -1,6 +1,6 @@ import {parse, print_debug_node, load_modules} from '../src/parse_js.js' import {eval_tree, eval_frame} from '../src/eval.js' -import {get_initial_state} from '../src/cmd.js' +import {COMMANDS} from '../src/cmd.js' Object.assign(globalThis, {log: console.log}) @@ -28,7 +28,7 @@ export const assert_code_error = (codestring, error) => { } export const test_initial_state = (code, state) => { - return get_initial_state( + return COMMANDS.get_initial_state( { ...state, files: typeof(code) == 'object' ? code : { '' : code},