From 1e67e30863b73a091927916a86033f875735912a Mon Sep 17 00:00:00 2001 From: Jan Cajthaml Date: Sun, 15 Sep 2024 10:34:48 +0200 Subject: [PATCH 01/14] experimentation with loading modules without eval --- platform/src/kernel/registry/assets.js | 66 ++++++++++++++++++++++++-- platform/src/register.js | 24 ++++++---- 2 files changed, 77 insertions(+), 13 deletions(-) diff --git a/platform/src/kernel/registry/assets.js b/platform/src/kernel/registry/assets.js index 2011c7ec..169e427b 100644 --- a/platform/src/kernel/registry/assets.js +++ b/platform/src/kernel/registry/assets.js @@ -185,9 +185,69 @@ async function downloadProgram(name, program, controller) { if (!program) { return {}; } - const data = await downloadAsset(program.url, controller); - const content = await data.text(); - return SequentialProgramEvaluator.compile(name, content); + + const sandbox = { + __SANDBOX_SCOPE__: {}, + }; + + const dllFragments = []; + for (const dll in top) { + if (dll.startsWith('rocker_so')) { + dllFragments.push(`self.${dll}=top.${dll}`); + } + } + + const bootstrap = ` + + `; + const iframe = top.document.createElement('iframe'); + //iframe.id = 'module-registration'; + + const script = top.document.createElement('script'); + + script.src = program.url; + //script.async = true; + //script.defer = true; + + iframe.sandbox = 'allow-same-origin allow-scripts'; + iframe.srcdoc = bootstrap+script.outerHTML; + //iframe.contentWindow.__SANDBOX_SCOPE__ = sandbox.__SANDBOX_SCOPE__; + + //iframe.appendChild(script); + + //const check = '' + + console.log('Downloading program', program); + + try { + const promise = new Promise((resolve, reject) => { + script.onload = () => { + console.log('script loaded', program.url) + resolve(); + } + }) + + top.document.head.appendChild(iframe); + await promise; + } finally { + console.log(iframe.contentWindow.__SANDBOX_SCOPE__) + //delete top.__SANDBOX_SCOPE__; + top.document.head.removeChild(iframe); + } + + console.log('Downloaded program', program); + + console.log('Result is', sandbox.__SANDBOX_SCOPE__) + + return sandbox.__SANDBOX_SCOPE__; + + //const data = await downloadAsset(program.url, controller); + //const content = await data.text(); + //return SequentialProgramEvaluator.compile(name, content); } export { downloadAsset, downloadProgram }; diff --git a/platform/src/register.js b/platform/src/register.js index 12b6ee6e..c60cfaf3 100644 --- a/platform/src/register.js +++ b/platform/src/register.js @@ -13,59 +13,63 @@ function isFunction(val) { } export default function (scope) { + // INFO this function is in DLL (in top frame) and not part of module thus execution happens in wrong scope + + console.log('registerModule was called'); + if (!scope) { return; } - if (scope.constructor !== Object) { + if (scope.constructor.toString() !== Object.toString()) { throw new Error(`registerModule accepts only plain object, was called with ${typeof scope}`); } if (scope.BUILD_ID) { if (typeof scope.BUILD_ID !== "string") { warning(`implicit attribute "BUILD_ID" provided in registerModule is not string`); } else { - top.__SANDBOX_SCOPE__.BUILD_ID = scope.BUILD_ID; + self.__SANDBOX_SCOPE__.BUILD_ID = scope.BUILD_ID; } } if (scope.component) { if (!(isFunction(scope.component) || scope.component instanceof React.Component)) { warning(`attribute "component" provided in registerModule is not function or React.Component`); } else { - top.__SANDBOX_SCOPE__.component = scope.component; + self.__SANDBOX_SCOPE__.component = scope.component; } } if (scope.fallback) { if (!(isFunction(scope.fallback) || scope.fallback instanceof React.Component)) { warning(`attribute "fallback" provided in registerModule is not function or React.Component`); } else { - top.__SANDBOX_SCOPE__.fallback = scope.fallback; + self.__SANDBOX_SCOPE__.fallback = scope.fallback; } } if (scope.reducers) { - if (scope.reducers.constructor !== Object) { + if (scope.reducers.constructor.toString() !== Object.toString()) { warning(`attribute "reducers" provided in registerModule is not plain object`); } else { - top.__SANDBOX_SCOPE__.reducers = scope.reducers; + self.__SANDBOX_SCOPE__.reducers = scope.reducers; } } if (scope.middleware) { if (!isFunction(scope.middleware) || isGenerator(scope.middleware)) { warning(`attribute "middleware" provided in registerModule is not function or async function`); } else { - top.__SANDBOX_SCOPE__.middleware = scope.middleware; + self.__SANDBOX_SCOPE__.middleware = scope.middleware; } } if (scope.saga) { if (!isGenerator(scope.saga)) { warning(`attribute "saga" provided in registerModule is not generator function or async generator function`); } else { - top.__SANDBOX_SCOPE__.saga = scope.saga; + self.__SANDBOX_SCOPE__.saga = scope.saga; } } if (scope.props) { - if (scope.props.constructor !== Object) { + if (scope.props.constructor.toString() !== Object.toString()) { warning(`attribute "props" provided in registerModule is not plain object`); } else { - top.__SANDBOX_SCOPE__.props = scope.props; + self.__SANDBOX_SCOPE__.props = scope.props; } } } From f833598158ff51355b6a5fe2a788b9a6b906477b Mon Sep 17 00:00:00 2001 From: Jan Cajthaml Date: Sun, 15 Sep 2024 11:07:12 +0200 Subject: [PATCH 02/14] experimentation with loading modules without eval --- platform/src/kernel/registry/assets.js | 48 ++++++++++++-------------- platform/src/register.js | 26 +++++++------- 2 files changed, 37 insertions(+), 37 deletions(-) diff --git a/platform/src/kernel/registry/assets.js b/platform/src/kernel/registry/assets.js index 169e427b..794ce12b 100644 --- a/platform/src/kernel/registry/assets.js +++ b/platform/src/kernel/registry/assets.js @@ -186,10 +186,6 @@ async function downloadProgram(name, program, controller) { return {}; } - const sandbox = { - __SANDBOX_SCOPE__: {}, - }; - const dllFragments = []; for (const dll in top) { if (dll.startsWith('rocker_so')) { @@ -199,51 +195,53 @@ async function downloadProgram(name, program, controller) { const bootstrap = ` `; const iframe = top.document.createElement('iframe'); - //iframe.id = 'module-registration'; const script = top.document.createElement('script'); script.src = program.url; - //script.async = true; - //script.defer = true; + script.async = true; + script.defer = true; iframe.sandbox = 'allow-same-origin allow-scripts'; - iframe.srcdoc = bootstrap+script.outerHTML; - //iframe.contentWindow.__SANDBOX_SCOPE__ = sandbox.__SANDBOX_SCOPE__; - //iframe.appendChild(script); + const trap = {}; - //const check = '' + try { - console.log('Downloading program', program); + iframe.srcdoc = bootstrap+script.outerHTML; - try { + top.document.head.appendChild(iframe); + const promise = new Promise((resolve, reject) => { - script.onload = () => { - console.log('script loaded', program.url) - resolve(); - } + console.log('waiting on load inner'); + + Object.defineProperty(iframe.contentWindow, "__SANDBOX_SCOPE__", { + set(value) { + console.log('frame called set on __SANDBOX_SCOPE__', value); + Object.assign(trap, value); + resolve(); + }, + get() { + return trap; + } + }); }) - - top.document.head.appendChild(iframe); + await promise; } finally { - console.log(iframe.contentWindow.__SANDBOX_SCOPE__) - //delete top.__SANDBOX_SCOPE__; top.document.head.removeChild(iframe); } console.log('Downloaded program', program); - console.log('Result is', sandbox.__SANDBOX_SCOPE__) + console.log('Result is', trap) - return sandbox.__SANDBOX_SCOPE__; + return trap; //const data = await downloadAsset(program.url, controller); //const content = await data.text(); diff --git a/platform/src/register.js b/platform/src/register.js index c60cfaf3..6e7fc5c3 100644 --- a/platform/src/register.js +++ b/platform/src/register.js @@ -1,7 +1,6 @@ +// TODO remove this dependency import React from "react"; -import { warning } from "./utils"; - /* istanbul ignore next */ function isGenerator(val) { return /\[object Generator|GeneratorFunction\]/.test(Object.prototype.toString.call(val)); @@ -20,54 +19,57 @@ export default function (scope) { if (!scope) { return; } - if (scope.constructor.toString() !== Object.toString()) { + + const objectConstructor = Object.toString(); + + if (scope.constructor.toString() !== objectConstructor) { throw new Error(`registerModule accepts only plain object, was called with ${typeof scope}`); } if (scope.BUILD_ID) { if (typeof scope.BUILD_ID !== "string") { - warning(`implicit attribute "BUILD_ID" provided in registerModule is not string`); + console.error(`implicit attribute "BUILD_ID" provided in registerModule is not string`); } else { self.__SANDBOX_SCOPE__.BUILD_ID = scope.BUILD_ID; } } if (scope.component) { if (!(isFunction(scope.component) || scope.component instanceof React.Component)) { - warning(`attribute "component" provided in registerModule is not function or React.Component`); + console.error(`attribute "component" provided in registerModule is not function or React.Component`); } else { self.__SANDBOX_SCOPE__.component = scope.component; } } if (scope.fallback) { if (!(isFunction(scope.fallback) || scope.fallback instanceof React.Component)) { - warning(`attribute "fallback" provided in registerModule is not function or React.Component`); + console.error(`attribute "fallback" provided in registerModule is not function or React.Component`); } else { self.__SANDBOX_SCOPE__.fallback = scope.fallback; } } if (scope.reducers) { - if (scope.reducers.constructor.toString() !== Object.toString()) { - warning(`attribute "reducers" provided in registerModule is not plain object`); + if (scope.reducers.constructor.toString() !== objectConstructor) { + console.error(`attribute "reducers" provided in registerModule is not plain object`); } else { self.__SANDBOX_SCOPE__.reducers = scope.reducers; } } if (scope.middleware) { if (!isFunction(scope.middleware) || isGenerator(scope.middleware)) { - warning(`attribute "middleware" provided in registerModule is not function or async function`); + console.error(`attribute "middleware" provided in registerModule is not function or async function`); } else { self.__SANDBOX_SCOPE__.middleware = scope.middleware; } } if (scope.saga) { if (!isGenerator(scope.saga)) { - warning(`attribute "saga" provided in registerModule is not generator function or async generator function`); + console.error(`attribute "saga" provided in registerModule is not generator function or async generator function`); } else { self.__SANDBOX_SCOPE__.saga = scope.saga; } } if (scope.props) { - if (scope.props.constructor.toString() !== Object.toString()) { - warning(`attribute "props" provided in registerModule is not plain object`); + if (scope.props.constructor.toString() !== objectConstructor) { + console.error(`attribute "props" provided in registerModule is not plain object`); } else { self.__SANDBOX_SCOPE__.props = scope.props; } From f81d5c0f549188001a0e2d7728348d6ea8051800 Mon Sep 17 00:00:00 2001 From: Jan Cajthaml Date: Sun, 15 Sep 2024 11:13:14 +0200 Subject: [PATCH 03/14] experimentation with loading modules without eval --- platform/src/kernel/registry/assets.js | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/platform/src/kernel/registry/assets.js b/platform/src/kernel/registry/assets.js index 794ce12b..f9ef48d5 100644 --- a/platform/src/kernel/registry/assets.js +++ b/platform/src/kernel/registry/assets.js @@ -205,8 +205,8 @@ async function downloadProgram(name, program, controller) { script.src = program.url; script.async = true; - script.defer = true; + // INFO yields "An iframe which has both allow-scripts and allow-same-origin for its sandbox attribute can escape its sandboxing." iframe.sandbox = 'allow-same-origin allow-scripts'; const trap = {}; @@ -216,23 +216,22 @@ async function downloadProgram(name, program, controller) { iframe.srcdoc = bootstrap+script.outerHTML; top.document.head.appendChild(iframe); - - const promise = new Promise((resolve, reject) => { - console.log('waiting on load inner'); - + + // INFO handling errors plus timeout CLIENT_TIMEOUT + await new Promise((resolve, reject) => { Object.defineProperty(iframe.contentWindow, "__SANDBOX_SCOPE__", { set(value) { console.log('frame called set on __SANDBOX_SCOPE__', value); Object.assign(trap, value); + delete iframe.contentWindow.__SANDBOX_SCOPE__; resolve(); }, get() { return trap; } }); - }) + }); - await promise; } finally { top.document.head.removeChild(iframe); } From b53d5759b1c3e527be1b4c1534e776eeaa55383f Mon Sep 17 00:00:00 2001 From: Jan Cajthaml Date: Sun, 15 Sep 2024 11:19:45 +0200 Subject: [PATCH 04/14] experimentation with loading modules without eval --- platform/src/kernel/registry/assets.js | 29 ++++++++++++++++---------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/platform/src/kernel/registry/assets.js b/platform/src/kernel/registry/assets.js index f9ef48d5..ba95e791 100644 --- a/platform/src/kernel/registry/assets.js +++ b/platform/src/kernel/registry/assets.js @@ -193,45 +193,52 @@ async function downloadProgram(name, program, controller) { } } - const bootstrap = ` - - `; const iframe = top.document.createElement('iframe'); + const bootstrap = top.document.createElement('script'); + bootstrap.innerHTML = `self.lastuiJsonp=top.lastuiJsonp;${dllFragments};`; + const script = top.document.createElement('script'); script.src = program.url; script.async = true; // INFO yields "An iframe which has both allow-scripts and allow-same-origin for its sandbox attribute can escape its sandboxing." - iframe.sandbox = 'allow-same-origin allow-scripts'; + //iframe.sandbox = 'allow-same-origin allow-scripts'; const trap = {}; try { - iframe.srcdoc = bootstrap+script.outerHTML; + iframe.src = "about:blank"; + + //iframe.srcdoc = bootstrap+script.outerHTML; top.document.head.appendChild(iframe); - + + iframe.contentDocument.head.appendChild(bootstrap); + iframe.contentDocument.head.appendChild(script); + // INFO handling errors plus timeout CLIENT_TIMEOUT await new Promise((resolve, reject) => { + let wasSet = false; Object.defineProperty(iframe.contentWindow, "__SANDBOX_SCOPE__", { set(value) { + if (wasSet) { + return false; + } console.log('frame called set on __SANDBOX_SCOPE__', value); Object.assign(trap, value); - delete iframe.contentWindow.__SANDBOX_SCOPE__; resolve(); + return true; }, get() { return trap; } }); }); - + } catch (error) { + console.log('frame error', error); } finally { top.document.head.removeChild(iframe); } From ccbad3b4b7acb45b9cc0e2ed5bf7997a2287b56d Mon Sep 17 00:00:00 2001 From: Jan Cajthaml Date: Sun, 15 Sep 2024 11:25:08 +0200 Subject: [PATCH 05/14] experimentation with loading modules without eval --- platform/src/kernel/registry/assets.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/platform/src/kernel/registry/assets.js b/platform/src/kernel/registry/assets.js index ba95e791..803bd3e6 100644 --- a/platform/src/kernel/registry/assets.js +++ b/platform/src/kernel/registry/assets.js @@ -186,18 +186,18 @@ async function downloadProgram(name, program, controller) { return {}; } - const dllFragments = []; + + const bootstrap = top.document.createElement('script'); + bootstrap.innerHTML = 'self.lastuiJsonp=top.lastuiJsonp;'; + for (const dll in top) { if (dll.startsWith('rocker_so')) { - dllFragments.push(`self.${dll}=top.${dll}`); + bootstrap.innerHTML += `self.${dll}=top.${dll};`; } } const iframe = top.document.createElement('iframe'); - const bootstrap = top.document.createElement('script'); - bootstrap.innerHTML = `self.lastuiJsonp=top.lastuiJsonp;${dllFragments};`; - const script = top.document.createElement('script'); script.src = program.url; From 524e5bdf9926ef6470400bf48b1af28c8a76df01 Mon Sep 17 00:00:00 2001 From: Jan Cajthaml Date: Mon, 16 Sep 2024 02:05:15 +0200 Subject: [PATCH 06/14] experimentation with loading modules without eval --- babel/index.js | 70 ------------------ babel/plugins/RegisterModuleInjectBuildId.js | 30 -------- platform/src/index.js | 4 +- platform/src/kernel/index.js | 3 - platform/src/kernel/registry/assets.js | 31 +++++--- platform/src/register.js | 77 -------------------- webpack/config/module/development.js | 4 +- webpack/config/module/production.js | 4 +- 8 files changed, 27 insertions(+), 196 deletions(-) delete mode 100644 babel/index.js delete mode 100644 babel/plugins/RegisterModuleInjectBuildId.js delete mode 100644 platform/src/register.js diff --git a/babel/index.js b/babel/index.js deleted file mode 100644 index 82d042d7..00000000 --- a/babel/index.js +++ /dev/null @@ -1,70 +0,0 @@ -const plugins = ["@babel/plugin-proposal-export-default-from", "@babel/plugin-proposal-throw-expressions"]; - -const presets = [ - [ - "@babel/preset-typescript", - { - allowNamespaces: true, - }, - ], - [ - "@babel/preset-react", - { - throwIfNamespace: true, - runtime: "automatic", - development: false, - }, - ], -]; - -const assumptions = { - noDocumentAll: true, - setPublicClassFields: false, -}; - -module.exports = { - assumptions, - presets, - plugins, - - env: { - development: { - presets, - plugins, - assumptions, - }, - production: { - presets: [ - ...presets, - [ - "@babel/preset-env", - { - useBuiltIns: false, - targets: { - browsers: ["last 4 versions, not dead, not op_mini all"], - }, - debug: false, - bugfixes: true, - modules: false, - shippedProposals: false, - }, - ], - ], - plugins, - assumptions, - }, - test: { - presets, - plugins: [ - ...plugins, - [ - "@babel/plugin-transform-modules-commonjs", - { - importInterop: "babel", - }, - ], - ], - assumptions, - }, - }, -}; diff --git a/babel/plugins/RegisterModuleInjectBuildId.js b/babel/plugins/RegisterModuleInjectBuildId.js deleted file mode 100644 index f15dfe79..00000000 --- a/babel/plugins/RegisterModuleInjectBuildId.js +++ /dev/null @@ -1,30 +0,0 @@ -const types = require("@babel/types"); - -module.exports = { - name: "register-module-inject-build-id", - visitor: { - CallExpression: { - enter(path) { - if (path.node.callee.name !== "registerModule") { - return; - } - if (path.node.arguments.length === 0) { - return; - } - for (const prop of path.node.arguments[0].properties) { - if (prop.key.name === "BUILD_ID") { - return; - } - } - path.replaceWith( - types.callExpression(types.identifier("registerModule"), [ - types.objectExpression([ - ...path.node.arguments[0].properties, - types.objectProperty(types.identifier("BUILD_ID"), types.identifier("BUILD_ID")), - ]), - ]), - ); - }, - }, - }, -}; diff --git a/platform/src/index.js b/platform/src/index.js index ff9156fd..a85459c6 100644 --- a/platform/src/index.js +++ b/platform/src/index.js @@ -2,7 +2,6 @@ import "regenerator-runtime/runtime"; import Module from "./component/Module"; import { SET_LANGUAGE, REFRESH, SET_SHARED, CLEAR_SHARED } from "./constants"; -import registerModule from "./register"; function setLanguage(language) { return { @@ -42,10 +41,9 @@ const actions = { refresh, }; -export { Module, actions, registerModule }; +export { Module, actions }; export default { Module, actions, - registerModule, }; diff --git a/platform/src/kernel/index.js b/platform/src/kernel/index.js index 2d47c1e8..6eae4762 100644 --- a/platform/src/kernel/index.js +++ b/platform/src/kernel/index.js @@ -3,7 +3,6 @@ import "regenerator-runtime/runtime"; /* istanbul ignore file */ import Module from "../component/Module"; import * as constants from "../constants"; -import registerModule from "../register"; import createDynamicMiddleware from "./middleware/dynamic"; import createLoaderMiddleware from "./middleware/loader"; @@ -24,7 +23,6 @@ export { modulesReducer, createDynamicMiddleware, createSagaMiddleware, - registerModule, getStore, setStore, manualCleanup, @@ -40,7 +38,6 @@ export default { modulesReducer, createDynamicMiddleware, createSagaMiddleware, - registerModule, getStore, setStore, manualCleanup, diff --git a/platform/src/kernel/registry/assets.js b/platform/src/kernel/registry/assets.js index 803bd3e6..59657ae5 100644 --- a/platform/src/kernel/registry/assets.js +++ b/platform/src/kernel/registry/assets.js @@ -186,22 +186,34 @@ async function downloadProgram(name, program, controller) { return {}; } - - const bootstrap = top.document.createElement('script'); - bootstrap.innerHTML = 'self.lastuiJsonp=top.lastuiJsonp;'; + const pre = top.document.createElement('script'); + pre.innerHTML = ` +self.lastuiJsonp = top.lastuiJsonp; +self.onerror = function(_message, _file, _line, _col, error) { + self.__SANDBOX_SCOPE__ = { + component() { + throw error; + }, + }; + return false; +}`; for (const dll in top) { if (dll.startsWith('rocker_so')) { - bootstrap.innerHTML += `self.${dll}=top.${dll};`; + pre.innerHTML += ` +self.${dll} = top.${dll};`; } } - const iframe = top.document.createElement('iframe'); - const script = top.document.createElement('script'); script.src = program.url; - script.async = true; + script.async = false; + + const post = top.document.createElement('script'); + post.innerHTML = 'self.__SANDBOX_SCOPE__ = {};'; + + const iframe = top.document.createElement('iframe'); // INFO yields "An iframe which has both allow-scripts and allow-same-origin for its sandbox attribute can escape its sandboxing." //iframe.sandbox = 'allow-same-origin allow-scripts'; @@ -212,12 +224,13 @@ async function downloadProgram(name, program, controller) { iframe.src = "about:blank"; - //iframe.srcdoc = bootstrap+script.outerHTML; + //iframe.srcdoc = bootstrap.outerHTML + script.outerHTML; top.document.head.appendChild(iframe); - iframe.contentDocument.head.appendChild(bootstrap); + iframe.contentDocument.head.appendChild(pre); iframe.contentDocument.head.appendChild(script); + iframe.contentDocument.head.appendChild(post); // INFO handling errors plus timeout CLIENT_TIMEOUT await new Promise((resolve, reject) => { diff --git a/platform/src/register.js b/platform/src/register.js deleted file mode 100644 index 6e7fc5c3..00000000 --- a/platform/src/register.js +++ /dev/null @@ -1,77 +0,0 @@ -// TODO remove this dependency -import React from "react"; - -/* istanbul ignore next */ -function isGenerator(val) { - return /\[object Generator|GeneratorFunction\]/.test(Object.prototype.toString.call(val)); -} - -/* istanbul ignore next */ -function isFunction(val) { - return /\[object Function|AsyncFunction\]/.test(Object.prototype.toString.call(val)); -} - -export default function (scope) { - // INFO this function is in DLL (in top frame) and not part of module thus execution happens in wrong scope - - console.log('registerModule was called'); - - if (!scope) { - return; - } - - const objectConstructor = Object.toString(); - - if (scope.constructor.toString() !== objectConstructor) { - throw new Error(`registerModule accepts only plain object, was called with ${typeof scope}`); - } - if (scope.BUILD_ID) { - if (typeof scope.BUILD_ID !== "string") { - console.error(`implicit attribute "BUILD_ID" provided in registerModule is not string`); - } else { - self.__SANDBOX_SCOPE__.BUILD_ID = scope.BUILD_ID; - } - } - if (scope.component) { - if (!(isFunction(scope.component) || scope.component instanceof React.Component)) { - console.error(`attribute "component" provided in registerModule is not function or React.Component`); - } else { - self.__SANDBOX_SCOPE__.component = scope.component; - } - } - if (scope.fallback) { - if (!(isFunction(scope.fallback) || scope.fallback instanceof React.Component)) { - console.error(`attribute "fallback" provided in registerModule is not function or React.Component`); - } else { - self.__SANDBOX_SCOPE__.fallback = scope.fallback; - } - } - if (scope.reducers) { - if (scope.reducers.constructor.toString() !== objectConstructor) { - console.error(`attribute "reducers" provided in registerModule is not plain object`); - } else { - self.__SANDBOX_SCOPE__.reducers = scope.reducers; - } - } - if (scope.middleware) { - if (!isFunction(scope.middleware) || isGenerator(scope.middleware)) { - console.error(`attribute "middleware" provided in registerModule is not function or async function`); - } else { - self.__SANDBOX_SCOPE__.middleware = scope.middleware; - } - } - if (scope.saga) { - if (!isGenerator(scope.saga)) { - console.error(`attribute "saga" provided in registerModule is not generator function or async generator function`); - } else { - self.__SANDBOX_SCOPE__.saga = scope.saga; - } - } - if (scope.props) { - if (scope.props.constructor.toString() !== objectConstructor) { - console.error(`attribute "props" provided in registerModule is not plain object`); - } else { - self.__SANDBOX_SCOPE__.props = scope.props; - } - } -} diff --git a/webpack/config/module/development.js b/webpack/config/module/development.js index ce37c88a..bd9d74d2 100644 --- a/webpack/config/module/development.js +++ b/webpack/config/module/development.js @@ -10,7 +10,6 @@ const { merge } = require("webpack-merge"); const dependenciesDlls = require("@lastui/dependencies"); const babel = require("../../../babel"); -const RegisterModuleInjectBuildId = require("../../../babel/plugins/RegisterModuleInjectBuildId"); const ImplicitDLLAssetPlugin = require("../../plugins/ImplicitDLLAssetPlugin"); const ModuleLocalesPlugin = require("../../plugins/ModuleLocalesPlugin"); const settings = require("../../settings"); @@ -26,6 +25,7 @@ module.exports = merge(require("../../internal/base.js"), require("../../interna "react-dom$": "react-dom/profiling", "scheduler/tracing": "scheduler/tracing-profiling", "@lastui/rocker/platform/kernel": "@lastui/rocker/platform", + "@lastui/rocker/register": path.resolve(__dirname, "..", "..", "loaders", "ModuleRegistration", "runtime.js"), }, }, output: { @@ -58,7 +58,7 @@ module.exports = merge(require("../../internal/base.js"), require("../../interna return [preset[0], preset[1], `babel-${preset[0]}`]; } }), - plugins: [RegisterModuleInjectBuildId, ...webpackBabel.plugins].map((plugin) => { + plugins: webpackBabel.plugins.map((plugin) => { if (!Array.isArray(plugin)) { return [plugin, {}, `babel-${plugin.name || plugin}`]; } else { diff --git a/webpack/config/module/production.js b/webpack/config/module/production.js index 241fb4a5..bd17488b 100644 --- a/webpack/config/module/production.js +++ b/webpack/config/module/production.js @@ -5,7 +5,6 @@ const { merge } = require("webpack-merge"); const dependenciesDlls = require("@lastui/dependencies"); const babel = require("../../../babel"); -const RegisterModuleInjectBuildId = require("../../../babel/plugins/RegisterModuleInjectBuildId"); const ModuleLocalesPlugin = require("../../plugins/ModuleLocalesPlugin"); const SoftwareBillOfMaterialsPlugin = require("../../plugins/SoftwareBillOfMaterialsPlugin"); const settings = require("../../settings"); @@ -17,6 +16,7 @@ module.exports = merge(require("../../internal/base.js"), require("../../interna resolve: { alias: { "@lastui/rocker/platform/kernel": "@lastui/rocker/platform", + "@lastui/rocker/register": path.resolve(__dirname, "..", "..", "loaders", "ModuleRegistration", "runtime.js"), }, }, output: { @@ -55,7 +55,7 @@ module.exports = merge(require("../../internal/base.js"), require("../../interna return [preset[0], preset[1], `babel-${preset[0]}`]; } }), - plugins: [RegisterModuleInjectBuildId, ...webpackBabel.plugins].map((plugin) => { + plugins: webpackBabel.plugins.map((plugin) => { if (!Array.isArray(plugin)) { return [plugin, {}, `babel-${plugin.name || plugin}`]; } else { From 05e3293690f14b631e669e87eed7dbf7812066a5 Mon Sep 17 00:00:00 2001 From: Jan Cajthaml Date: Mon, 16 Sep 2024 02:05:46 +0200 Subject: [PATCH 07/14] experimentation with loading modules without eval --- webpack/loaders/ModuleRegistration/runtime.js | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 webpack/loaders/ModuleRegistration/runtime.js diff --git a/webpack/loaders/ModuleRegistration/runtime.js b/webpack/loaders/ModuleRegistration/runtime.js new file mode 100644 index 00000000..1b936684 --- /dev/null +++ b/webpack/loaders/ModuleRegistration/runtime.js @@ -0,0 +1,68 @@ +function isGenerator(val) { + return /\[object Generator|GeneratorFunction\]/.test(Object.prototype.toString.call(val)); +} + +function isFunction(val) { + return /\[object Function|AsyncFunction\]/.test(Object.prototype.toString.call(val)); +} + +module.exports = function (scope) { + const result = {} + + if (!scope) { + return; + } + + const objectConstructor = Object.toString(); + + if (scope.constructor.toString() !== objectConstructor) { + throw new Error(`registerModule accepts only plain object, was called with ${typeof scope}`); + } + + result.BUILD_ID = BUILD_ID; + + if (scope.component) { + if (!isFunction(scope.component)) { + console.error(`attribute "component" provided in registerModule is not function`); + } else { + result.component = scope.component; + } + } + if (scope.fallback) { + if (!isFunction(scope.fallback)) { + console.error(`attribute "fallback" provided in registerModule is not function`); + } else { + result.fallback = scope.fallback; + } + } + if (scope.reducers) { + if (scope.reducers.constructor.toString() !== objectConstructor) { + console.error(`attribute "reducers" provided in registerModule is not plain object`); + } else { + result.reducers = scope.reducers; + } + } + if (scope.middleware) { + if (!isFunction(scope.middleware) || isGenerator(scope.middleware)) { + console.error(`attribute "middleware" provided in registerModule is not function or async function`); + } else { + result.middleware = scope.middleware; + } + } + if (scope.saga) { + if (!isGenerator(scope.saga)) { + console.error(`attribute "saga" provided in registerModule is not generator function or async generator function`); + } else { + result.saga = scope.saga; + } + } + if (scope.props) { + if (scope.props.constructor.toString() !== objectConstructor) { + console.error(`attribute "props" provided in registerModule is not plain object`); + } else { + result.props = scope.props; + } + } + + self.__SANDBOX_SCOPE__ = result; +} From 2c4ab57a01df9cae97cee81d1f3880e72b0b0d87 Mon Sep 17 00:00:00 2001 From: Jan Cajthaml Date: Mon, 16 Sep 2024 02:06:21 +0200 Subject: [PATCH 08/14] experimentation with loading modules without eval --- webpack/loaders/ModuleRegistration/runtime.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/webpack/loaders/ModuleRegistration/runtime.js b/webpack/loaders/ModuleRegistration/runtime.js index 1b936684..05c6a9a1 100644 --- a/webpack/loaders/ModuleRegistration/runtime.js +++ b/webpack/loaders/ModuleRegistration/runtime.js @@ -7,7 +7,7 @@ function isFunction(val) { } module.exports = function (scope) { - const result = {} + const result = { BUILD_ID } if (!scope) { return; @@ -19,8 +19,6 @@ module.exports = function (scope) { throw new Error(`registerModule accepts only plain object, was called with ${typeof scope}`); } - result.BUILD_ID = BUILD_ID; - if (scope.component) { if (!isFunction(scope.component)) { console.error(`attribute "component" provided in registerModule is not function`); From a1e864f597735978469f054541220c20b50d7eb3 Mon Sep 17 00:00:00 2001 From: Jan Cajthaml Date: Mon, 16 Sep 2024 02:07:40 +0200 Subject: [PATCH 09/14] experimentation with loading modules without eval --- babel/index.js | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 babel/index.js diff --git a/babel/index.js b/babel/index.js new file mode 100644 index 00000000..8f7455dc --- /dev/null +++ b/babel/index.js @@ -0,0 +1,70 @@ +const plugins = ["@babel/plugin-proposal-export-default-from", "@babel/plugin-proposal-throw-expressions"]; + +const presets = [ + [ + "@babel/preset-typescript", + { + allowNamespaces: true, + }, + ], + [ + "@babel/preset-react", + { + throwIfNamespace: true, + runtime: "automatic", + development: false, + }, + ], +]; + +const assumptions = { + noDocumentAll: true, + setPublicClassFields: false, +}; + +module.exports = { + assumptions, + presets, + plugins, + + env: { + development: { + presets, + plugins, + assumptions, + }, + production: { + presets: [ + ...presets, + [ + "@babel/preset-env", + { + useBuiltIns: false, + targets: { + browsers: ["last 4 versions, not dead, not op_mini all"], + }, + debug: false, + bugfixes: true, + modules: false, + shippedProposals: false, + }, + ], + ], + plugins, + assumptions, + }, + test: { + presets, + plugins: [ + ...plugins, + [ + "@babel/plugin-transform-modules-commonjs", + { + importInterop: "babel", + }, + ], + ], + assumptions, + }, + }, +}; \ No newline at end of file From 7bcb381b476768b5f36f6795febe4e22f8fe5c9e Mon Sep 17 00:00:00 2001 From: Jan Cajthaml Date: Mon, 16 Sep 2024 02:29:52 +0200 Subject: [PATCH 10/14] experimentation with loading modules without eval --- platform/src/kernel/registry/assets.js | 79 +++++-------------- webpack/config/module/development.js | 3 +- webpack/config/module/production.js | 3 +- webpack/loaders/ModuleRegistration/runtime.js | 9 ++- 4 files changed, 30 insertions(+), 64 deletions(-) diff --git a/platform/src/kernel/registry/assets.js b/platform/src/kernel/registry/assets.js index 59657ae5..1f015636 100644 --- a/platform/src/kernel/registry/assets.js +++ b/platform/src/kernel/registry/assets.js @@ -4,58 +4,6 @@ import { warning } from "../../utils"; const CLIENT_TIMEOUT = 30 * 1000; -export class SequentialProgramEvaluator { - static queue = []; - static compiling = false; - - static compile(name, data) { - return new Promise((resolve) => { - this.queue.push({ - data, - name, - resolve, - }); - this.tick(); - }); - } - - static tick() { - /* istanbul ignore next */ - if (this.compiling) { - return; - } - const item = this.queue.shift(); - if (!item) { - this.compiling = false; - return; - } - this.compiling = true; - const sandbox = { - __SANDBOX_SCOPE__: {}, - }; - try { - top.__SANDBOX_SCOPE__ = sandbox.__SANDBOX_SCOPE__; - - new Function("", item.data)({}); - } catch (error) { - if (!(item.data.startsWith("!") || item.data.startsWith("/*"))) { - warning(`asset for module ${item.name} is not a module`); - } else { - warning(`module ${item.name} failed to adapt`); - } - sandbox.__SANDBOX_SCOPE__.component = () => { - throw error; - }; - } finally { - delete top.__SANDBOX_SCOPE__; - } - item.resolve(sandbox.__SANDBOX_SCOPE__); - this.compiling = false; - this.tick(); - return; - } -} - /* istanbul ignore next */ async function clientCache(name) { try { @@ -186,6 +134,8 @@ async function downloadProgram(name, program, controller) { return {}; } + console.log('Downloading program', program); + const pre = top.document.createElement('script'); pre.innerHTML = ` self.lastuiJsonp = top.lastuiJsonp; @@ -232,15 +182,21 @@ self.${dll} = top.${dll};`; iframe.contentDocument.head.appendChild(script); iframe.contentDocument.head.appendChild(post); - // INFO handling errors plus timeout CLIENT_TIMEOUT - await new Promise((resolve, reject) => { + console.log('Waiting for program', program); + + const callback = function(resolve, _reject) { let wasSet = false; - Object.defineProperty(iframe.contentWindow, "__SANDBOX_SCOPE__", { + + console.log('defining __SANDBOX_SCOPE__ property for program', program, 'in scope', this); + + // INFO for some reason this property is always defined on a firstly inserted iframe + // maybe hoisting? + Object.defineProperty(this, "__SANDBOX_SCOPE__", { set(value) { + console.log('frame called set on __SANDBOX_SCOPE__', value, 'for program', program); if (wasSet) { return false; } - console.log('frame called set on __SANDBOX_SCOPE__', value); Object.assign(trap, value); resolve(); return true; @@ -249,7 +205,12 @@ self.${dll} = top.${dll};`; return trap; } }); - }); + }.bind(iframe.contentWindow); // INFO browser possibly recycles frame window references + + await new Promise(callback); + console.log('Done for program', program); + + // INFO now need to move implicitely injected styles from frame into main frame } catch (error) { console.log('frame error', error); } finally { @@ -261,10 +222,6 @@ self.${dll} = top.${dll};`; console.log('Result is', trap) return trap; - - //const data = await downloadAsset(program.url, controller); - //const content = await data.text(); - //return SequentialProgramEvaluator.compile(name, content); } export { downloadAsset, downloadProgram }; diff --git a/webpack/config/module/development.js b/webpack/config/module/development.js index bd9d74d2..85aec665 100644 --- a/webpack/config/module/development.js +++ b/webpack/config/module/development.js @@ -10,6 +10,7 @@ const { merge } = require("webpack-merge"); const dependenciesDlls = require("@lastui/dependencies"); const babel = require("../../../babel"); +const RegisterModuleInjectBuildId = require("../../../babel/plugins/RegisterModuleInjectBuildId"); const ImplicitDLLAssetPlugin = require("../../plugins/ImplicitDLLAssetPlugin"); const ModuleLocalesPlugin = require("../../plugins/ModuleLocalesPlugin"); const settings = require("../../settings"); @@ -58,7 +59,7 @@ module.exports = merge(require("../../internal/base.js"), require("../../interna return [preset[0], preset[1], `babel-${preset[0]}`]; } }), - plugins: webpackBabel.plugins.map((plugin) => { + plugins: [RegisterModuleInjectBuildId, ...webpackBabel.plugins].map((plugin) => { if (!Array.isArray(plugin)) { return [plugin, {}, `babel-${plugin.name || plugin}`]; } else { diff --git a/webpack/config/module/production.js b/webpack/config/module/production.js index bd17488b..7b0332c9 100644 --- a/webpack/config/module/production.js +++ b/webpack/config/module/production.js @@ -5,6 +5,7 @@ const { merge } = require("webpack-merge"); const dependenciesDlls = require("@lastui/dependencies"); const babel = require("../../../babel"); +const RegisterModuleInjectBuildId = require("../../../babel/plugins/RegisterModuleInjectBuildId"); const ModuleLocalesPlugin = require("../../plugins/ModuleLocalesPlugin"); const SoftwareBillOfMaterialsPlugin = require("../../plugins/SoftwareBillOfMaterialsPlugin"); const settings = require("../../settings"); @@ -55,7 +56,7 @@ module.exports = merge(require("../../internal/base.js"), require("../../interna return [preset[0], preset[1], `babel-${preset[0]}`]; } }), - plugins: webpackBabel.plugins.map((plugin) => { + plugins: [RegisterModuleInjectBuildId, ...webpackBabel.plugins].map((plugin) => { if (!Array.isArray(plugin)) { return [plugin, {}, `babel-${plugin.name || plugin}`]; } else { diff --git a/webpack/loaders/ModuleRegistration/runtime.js b/webpack/loaders/ModuleRegistration/runtime.js index 05c6a9a1..8d8f4270 100644 --- a/webpack/loaders/ModuleRegistration/runtime.js +++ b/webpack/loaders/ModuleRegistration/runtime.js @@ -7,7 +7,7 @@ function isFunction(val) { } module.exports = function (scope) { - const result = { BUILD_ID } + const result = {} if (!scope) { return; @@ -19,6 +19,13 @@ module.exports = function (scope) { throw new Error(`registerModule accepts only plain object, was called with ${typeof scope}`); } + if (scope.BUILD_ID) { + if (typeof scope.BUILD_ID !== "string") { + console.error(`implicit attribute "BUILD_ID" provided in registerModule is not string`); + } else { + result.BUILD_ID = scope.BUILD_ID; + } + } if (scope.component) { if (!isFunction(scope.component)) { console.error(`attribute "component" provided in registerModule is not function`); From 85aefd680f8515fdeedd0b2abdba546068e8af97 Mon Sep 17 00:00:00 2001 From: Jan Cajthaml Date: Mon, 16 Sep 2024 02:30:51 +0200 Subject: [PATCH 11/14] experimentation with loading modules without eval --- platform/src/kernel/registry/assets.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/src/kernel/registry/assets.js b/platform/src/kernel/registry/assets.js index 1f015636..7f0fdd83 100644 --- a/platform/src/kernel/registry/assets.js +++ b/platform/src/kernel/registry/assets.js @@ -193,7 +193,7 @@ self.${dll} = top.${dll};`; // maybe hoisting? Object.defineProperty(this, "__SANDBOX_SCOPE__", { set(value) { - console.log('frame called set on __SANDBOX_SCOPE__', value, 'for program', program); + console.log('frame called set on __SANDBOX_SCOPE__', value, 'for program', program, 'wasSet', wasSet); if (wasSet) { return false; } From 50959423b5d1074cffefcf9c1c6bb3e1cfd784bf Mon Sep 17 00:00:00 2001 From: Jan Cajthaml Date: Mon, 16 Sep 2024 09:01:34 +0200 Subject: [PATCH 12/14] experimentation with loading modules without eval --- babel/plugins/RegisterModuleInjectBuildId.js | 30 ++++++++++++ platform/src/kernel/registry/assets.js | 50 +++++++++++++------- 2 files changed, 64 insertions(+), 16 deletions(-) create mode 100644 babel/plugins/RegisterModuleInjectBuildId.js diff --git a/babel/plugins/RegisterModuleInjectBuildId.js b/babel/plugins/RegisterModuleInjectBuildId.js new file mode 100644 index 00000000..e1ee0bc2 --- /dev/null +++ b/babel/plugins/RegisterModuleInjectBuildId.js @@ -0,0 +1,30 @@ +const types = require("@babel/types"); + +module.exports = { + name: "register-module-inject-build-id", + visitor: { + CallExpression: { + enter(path) { + if (path.node.callee.name !== "registerModule") { + return; + } + if (path.node.arguments.length === 0) { + return; + } + for (const prop of path.node.arguments[0].properties) { + if (prop.key.name === "BUILD_ID") { + return; + } + } + path.replaceWith( + types.callExpression(types.identifier("registerModule"), [ + types.objectExpression([ + ...path.node.arguments[0].properties, + types.objectProperty(types.identifier("BUILD_ID"), types.identifier("BUILD_ID")), + ]), + ]), + ); + }, + }, + }, +}; \ No newline at end of file diff --git a/platform/src/kernel/registry/assets.js b/platform/src/kernel/registry/assets.js index 7f0fdd83..f83b558e 100644 --- a/platform/src/kernel/registry/assets.js +++ b/platform/src/kernel/registry/assets.js @@ -137,9 +137,12 @@ async function downloadProgram(name, program, controller) { console.log('Downloading program', program); const pre = top.document.createElement('script'); + pre.defer = true; pre.innerHTML = ` +self.name = "registration-${name}"; self.lastuiJsonp = top.lastuiJsonp; self.onerror = function(_message, _file, _line, _col, error) { + console.log(self.name, "caught uncaught error", error); self.__SANDBOX_SCOPE__ = { component() { throw error; @@ -157,11 +160,16 @@ self.${dll} = top.${dll};`; const script = top.document.createElement('script'); + // INFO in dev mode the module script tries to connect to webpack's websocket server and overlay, this should not happen script.src = program.url; script.async = false; + script.defer = true; const post = top.document.createElement('script'); - post.innerHTML = 'self.__SANDBOX_SCOPE__ = {};'; + post.defer = true; + post.innerHTML = ` +console.log("Done", self); + `; const iframe = top.document.createElement('iframe'); @@ -177,37 +185,47 @@ self.${dll} = top.${dll};`; //iframe.srcdoc = bootstrap.outerHTML + script.outerHTML; top.document.head.appendChild(iframe); - - iframe.contentDocument.head.appendChild(pre); - iframe.contentDocument.head.appendChild(script); - iframe.contentDocument.head.appendChild(post); console.log('Waiting for program', program); - const callback = function(resolve, _reject) { + //.bind(iframe.contentWindow); // INFO browser possibly recycles frame window references + + // INFO not ideal because its non blocking e.g. POST script executes before SCRIPT script + const registration = await new Promise(function(resolve, _reject) { let wasSet = false; - console.log('defining __SANDBOX_SCOPE__ property for program', program, 'in scope', this); + //const ref = iframe.contentWindow; + + console.log('defining property for program', program, 'in scope', iframe.contentWindow); // INFO for some reason this property is always defined on a firstly inserted iframe // maybe hoisting? - Object.defineProperty(this, "__SANDBOX_SCOPE__", { + Object.defineProperty(iframe.contentWindow, "__SANDBOX_SCOPE__", { set(value) { - console.log('frame called set on __SANDBOX_SCOPE__', value, 'for program', program, 'wasSet', wasSet); - if (wasSet) { - return false; - } - Object.assign(trap, value); - resolve(); + console.log('frame called set on __SANDBOX_SCOPE__ for program', program, value, 'wasSet', wasSet); + //if (wasSet) { + //return false; + //} + //wasSet = true; + //delete iframe.contentWindow.__SANDBOX_SCOPE__; + //resolve(value); return true; }, get() { return trap; } }); - }.bind(iframe.contentWindow); // INFO browser possibly recycles frame window references - await new Promise(callback); + // TODO need a serial execution here + iframe.contentDocument.head.appendChild(pre); + iframe.contentDocument.head.appendChild(script); + iframe.contentDocument.head.appendChild(post); + }); + + console.log('Checking the contents of __SANDBOX_SCOPE__ for', program, 'is', registration); + + Object.assign(trap, registration); + console.log('Done for program', program); // INFO now need to move implicitely injected styles from frame into main frame From 433630e5c7953254e619f5cb278da7b55ffe0675 Mon Sep 17 00:00:00 2001 From: Jan Cajthaml Date: Sat, 21 Sep 2024 09:57:16 +0200 Subject: [PATCH 13/14] experimentation with loading modules without eval --- platform/src/kernel/registry/assets.js | 31 +++++++++++++++++++++----- webpack/internal/development.js | 3 ++- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/platform/src/kernel/registry/assets.js b/platform/src/kernel/registry/assets.js index f83b558e..b9c4c46f 100644 --- a/platform/src/kernel/registry/assets.js +++ b/platform/src/kernel/registry/assets.js @@ -137,10 +137,29 @@ async function downloadProgram(name, program, controller) { console.log('Downloading program', program); const pre = top.document.createElement('script'); - pre.defer = true; + pre.async = false; + pre.defer = false; pre.innerHTML = ` + + function callback(data) { + + console.log('lastuiJsonp.push called', data); + //const volatile = []; + + //for (const item in data[1]) { + //console.log(item); + //} + + //top.lastuiJsonp.push(data); + + data[2](); + + } + self.name = "registration-${name}"; -self.lastuiJsonp = top.lastuiJsonp; +self.lastuiJsonp = []; +self.lastuiJsonp.push = callback.bind(null) + self.onerror = function(_message, _file, _line, _col, error) { console.log(self.name, "caught uncaught error", error); self.__SANDBOX_SCOPE__ = { @@ -163,12 +182,14 @@ self.${dll} = top.${dll};`; // INFO in dev mode the module script tries to connect to webpack's websocket server and overlay, this should not happen script.src = program.url; script.async = false; - script.defer = true; + script.defer = false; const post = top.document.createElement('script'); - post.defer = true; + post.async = false; + post.defer = false; post.innerHTML = ` console.log("Done", self); +self.__SANDBOX_SCOPE__ = {}; `; const iframe = top.document.createElement('iframe'); @@ -196,7 +217,7 @@ console.log("Done", self); //const ref = iframe.contentWindow; - console.log('defining property for program', program, 'in scope', iframe.contentWindow); + console.log('defining property for program', program, 'in scope', iframe.contentWindow); // INFO for some reason this property is always defined on a firstly inserted iframe // maybe hoisting? diff --git a/webpack/internal/development.js b/webpack/internal/development.js index 75208e14..325f6d88 100644 --- a/webpack/internal/development.js +++ b/webpack/internal/development.js @@ -23,7 +23,7 @@ module.exports = { errorDetails: true, errorStack: true, }, - devtool: "eval-cheap-module-source-map", + devtool: "cheap-module-source-map", watch: true, devServer: { hot: false, @@ -43,6 +43,7 @@ module.exports = { host: "0.0.0.0", port: settings.DEV_SERVER_PORT, client: { + reconnect: 2, overlay: { errors: true, runtimeErrors: true, From cb6f4ecb9fd078f6a769d3c2efee524b1658d960 Mon Sep 17 00:00:00 2001 From: Jan Cajthaml Date: Mon, 23 Sep 2024 15:34:26 +0200 Subject: [PATCH 14/14] experimentation with loading modules without eval --- platform/src/kernel/registry/assets.js | 1 + 1 file changed, 1 insertion(+) diff --git a/platform/src/kernel/registry/assets.js b/platform/src/kernel/registry/assets.js index b9c4c46f..ecd30e1a 100644 --- a/platform/src/kernel/registry/assets.js +++ b/platform/src/kernel/registry/assets.js @@ -144,6 +144,7 @@ async function downloadProgram(name, program, controller) { function callback(data) { console.log('lastuiJsonp.push called', data); + //const volatile = []; //for (const item in data[1]) {