Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion babel/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,4 @@ module.exports = {
assumptions,
},
},
};
};
2 changes: 1 addition & 1 deletion babel/plugins/RegisterModuleInjectBuildId.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,4 @@ module.exports = {
},
},
},
};
};
4 changes: 1 addition & 3 deletions platform/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -42,10 +41,9 @@ const actions = {
refresh,
};

export { Module, actions, registerModule };
export { Module, actions };

export default {
Module,
actions,
registerModule,
};
3 changes: 0 additions & 3 deletions platform/src/kernel/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -24,7 +23,6 @@ export {
modulesReducer,
createDynamicMiddleware,
createSagaMiddleware,
registerModule,
getStore,
setStore,
manualCleanup,
Expand All @@ -40,7 +38,6 @@ export default {
modulesReducer,
createDynamicMiddleware,
createSagaMiddleware,
registerModule,
getStore,
setStore,
manualCleanup,
Expand Down
184 changes: 129 additions & 55 deletions platform/src/kernel/registry/assets.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -185,9 +133,135 @@ 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);

console.log('Downloading program', program);

const pre = top.document.createElement('script');
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 = [];
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__ = {
component() {
throw error;
},
};
return false;
}`;

for (const dll in top) {
if (dll.startsWith('rocker_so')) {
pre.innerHTML += `
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 = false;

const post = top.document.createElement('script');
post.async = false;
post.defer = false;
post.innerHTML = `
console.log("Done", self);
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';

const trap = {};

try {

iframe.src = "about:blank";

//iframe.srcdoc = bootstrap.outerHTML + script.outerHTML;

top.document.head.appendChild(iframe);

console.log('Waiting for program', program);

//.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;

//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(iframe.contentWindow, "__SANDBOX_SCOPE__", {
set(value) {
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;
}
});

// 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
} catch (error) {
console.log('frame error', error);
} finally {
top.document.head.removeChild(iframe);
}

console.log('Downloaded program', program);

console.log('Result is', trap)

return trap;
}

export { downloadAsset, downloadProgram };
71 changes: 0 additions & 71 deletions platform/src/register.js

This file was deleted.

1 change: 1 addition & 0 deletions webpack/config/module/development.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,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: {
Expand Down
1 change: 1 addition & 0 deletions webpack/config/module/production.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,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: {
Expand Down
3 changes: 2 additions & 1 deletion webpack/internal/development.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -43,6 +43,7 @@ module.exports = {
host: "0.0.0.0",
port: settings.DEV_SERVER_PORT,
client: {
reconnect: 2,
overlay: {
errors: true,
runtimeErrors: true,
Expand Down
Loading