mirror of
https://github.com/enso-org/enso.git
synced 2024-11-24 00:27:16 +03:00
Correctly interpret string arguments as booleans in electron arguments. (https://github.com/enso-org/ide/pull/1539)
Original commit: f0e712e45c
This commit is contained in:
parent
6fd49b26c8
commit
b7baae57ff
@ -1,6 +1,6 @@
|
||||
overrides:
|
||||
|
||||
- files: "*.js"
|
||||
- files: "*.[j|t]s"
|
||||
options:
|
||||
printWidth: 100
|
||||
tabWidth: 4
|
||||
|
@ -44,6 +44,10 @@ you can find their release notes
|
||||
|
||||
<br/>![Bug Fixes](/docs/assets/tags/bug_fixes.svg)
|
||||
|
||||
- [Fix some internal settings not being applied correctly in the IDE][1539].
|
||||
Some arguments were not passed correctly to the IDE leading to erroneous
|
||||
behaviour in the electron app. This is now fixed.
|
||||
|
||||
#### Visual Environment
|
||||
|
||||
- [Some command line arguments were not applied correctly in the IDE][1536].
|
||||
@ -59,6 +63,7 @@ you can find their release notes
|
||||
[1511]: https://github.com/enso-org/ide/pull/1511
|
||||
[1536]: https://github.com/enso-org/ide/pull/1536
|
||||
[1531]: https://github.com/enso-org/ide/pull/1531
|
||||
[1531]: https://github.com/enso-org/ide/pull/1539
|
||||
|
||||
<br/>
|
||||
|
||||
|
@ -14,6 +14,10 @@ let config = {
|
||||
"compression-webpack-plugin": "^3.1.0",
|
||||
"copy-webpack-plugin": "^5.1.1",
|
||||
"yaml-loader": "^0.6.0",
|
||||
"ts-loader": "^8.0.3",
|
||||
"typescript": "^4.0.2",
|
||||
"webpack": "^4.44.1",
|
||||
"webpack-cli": "^3.3.12"
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,14 +2,16 @@
|
||||
/// user with a visual representation of this process (welcome screen). It also implements a view
|
||||
/// allowing to choose a debug rendering test from.
|
||||
|
||||
// @ts-ignore
|
||||
import * as loader_module from 'enso-studio-common/src/loader'
|
||||
import * as html_utils from 'enso-studio-common/src/html_utils'
|
||||
import * as animation from 'enso-studio-common/src/animation'
|
||||
import * as globalConfig from '../../../../config.yaml'
|
||||
import cfg from '../../../config'
|
||||
import assert from "assert";
|
||||
|
||||
|
||||
// @ts-ignore
|
||||
import * as html_utils from 'enso-studio-common/src/html_utils'
|
||||
// @ts-ignore
|
||||
import * as globalConfig from '../../../../config.yaml'
|
||||
// @ts-ignore
|
||||
import cfg from '../../../config'
|
||||
// @ts-ignore
|
||||
import assert from 'assert'
|
||||
|
||||
// =================
|
||||
// === Constants ===
|
||||
@ -17,17 +19,32 @@ import assert from "assert";
|
||||
|
||||
const ALIVE_LOG_INTERVAL = 1000 * 60
|
||||
|
||||
|
||||
|
||||
// ==================
|
||||
// === Global API ===
|
||||
// ==================
|
||||
|
||||
let API = {}
|
||||
class ContentApi {
|
||||
main: (inputConfig: any) => Promise<void>
|
||||
private logger: MixpanelLogger
|
||||
|
||||
initLogging(config: Config) {
|
||||
assert(typeof config.no_data_gathering == 'boolean')
|
||||
if (!config.no_data_gathering) {
|
||||
this.logger = new MixpanelLogger()
|
||||
}
|
||||
}
|
||||
remoteLog(event: string, data?: any) {
|
||||
if (this.logger) {
|
||||
this.logger.log(event, data)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const API = new ContentApi()
|
||||
|
||||
// @ts-ignore
|
||||
window[globalConfig.windowAppScopeName] = API
|
||||
|
||||
|
||||
|
||||
// ========================
|
||||
// === Content Download ===
|
||||
// ========================
|
||||
@ -37,27 +54,29 @@ let incorrect_mime_type_warning = `
|
||||
'application/wasm' MIME type. Falling back to 'WebAssembly.instantiate' which is slower.
|
||||
`
|
||||
|
||||
function wasm_instantiate_streaming(resource,imports) {
|
||||
return WebAssembly.instantiateStreaming(resource,imports).catch(e => {
|
||||
return wasm_fetch.then(r => {
|
||||
if (r.headers.get('Content-Type') != 'application/wasm') {
|
||||
console.warn(`${incorrect_mime_type_warning} Original error:\n`, e)
|
||||
return r.arrayBuffer()
|
||||
} else {
|
||||
throw("Server not configured to serve WASM with 'application/wasm' mime type.")
|
||||
}
|
||||
}).then(bytes => WebAssembly.instantiate(bytes,imports))
|
||||
})
|
||||
async function wasm_instantiate_streaming(
|
||||
resource: Response,
|
||||
imports: WebAssembly.Imports
|
||||
): Promise<ArrayBuffer | WebAssembly.WebAssemblyInstantiatedSource> {
|
||||
try {
|
||||
return WebAssembly.instantiateStreaming(resource, imports)
|
||||
} catch (e) {
|
||||
const r = await resource
|
||||
if (r.headers.get('Content-Type') != 'application/wasm') {
|
||||
console.warn(`${incorrect_mime_type_warning} Original error:\n`, e)
|
||||
return r.arrayBuffer()
|
||||
} else {
|
||||
throw "Server not configured to serve WASM with 'application/wasm' mime type."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Downloads the WASM binary and its dependencies. Displays loading progress bar unless provided
|
||||
/// with `{use_loader:false}` option.
|
||||
async function download_content(config) {
|
||||
async function download_content(config: { wasm_glue_url: RequestInfo; wasm_url: RequestInfo }) {
|
||||
let wasm_glue_fetch = await fetch(config.wasm_glue_url)
|
||||
let wasm_fetch = await fetch(config.wasm_url)
|
||||
let loader =
|
||||
new loader_module.Loader([wasm_glue_fetch,wasm_fetch], config)
|
||||
let wasm_fetch = await fetch(config.wasm_url)
|
||||
let loader = new loader_module.Loader([wasm_glue_fetch, wasm_fetch], config)
|
||||
|
||||
// TODO [mwu]
|
||||
// Progress indication for WASM loading is hereby capped at 30%.
|
||||
@ -69,35 +88,35 @@ async function download_content(config) {
|
||||
|
||||
loader.done.then(() => {
|
||||
console.groupEnd()
|
||||
console.log("Download finished. Finishing WASM compilation.")
|
||||
console.log('Download finished. Finishing WASM compilation.')
|
||||
})
|
||||
|
||||
let download_size = loader.show_total_bytes()
|
||||
let download_info = `Downloading WASM binary and its dependencies (${download_size}).`
|
||||
let wasm_loader = html_utils.log_group_collapsed(download_info, async () => {
|
||||
let wasm_loader = html_utils.log_group_collapsed(download_info, async () => {
|
||||
let wasm_glue_js = await wasm_glue_fetch.text()
|
||||
let wasm_glue = Function("let exports = {};" + wasm_glue_js + "; return exports")()
|
||||
let imports = wasm_glue.wasm_imports()
|
||||
console.log("WASM dependencies loaded.")
|
||||
console.log("Starting online WASM compilation.")
|
||||
let wasm_loader = await wasm_instantiate_streaming(wasm_fetch,imports)
|
||||
let wasm_glue = Function('let exports = {};' + wasm_glue_js + '; return exports')()
|
||||
let imports = wasm_glue.wasm_imports()
|
||||
console.log('WASM dependencies loaded.')
|
||||
console.log('Starting online WASM compilation.')
|
||||
let wasm_loader = await wasm_instantiate_streaming(wasm_fetch, imports)
|
||||
// @ts-ignore
|
||||
wasm_loader.wasm_glue = wasm_glue
|
||||
return wasm_loader
|
||||
})
|
||||
|
||||
let wasm = await wasm_loader.then(({instance,module,wasm_glue}) => {
|
||||
// @ts-ignore
|
||||
let wasm = await wasm_loader.then(({ instance, module, wasm_glue }) => {
|
||||
let wasm = instance.exports
|
||||
wasm_glue.after_load(wasm,module)
|
||||
wasm_glue.after_load(wasm, module)
|
||||
return wasm
|
||||
})
|
||||
console.log("WASM Compiled.")
|
||||
console.log('WASM Compiled.')
|
||||
|
||||
await loader.initialized
|
||||
return {wasm,loader}
|
||||
return { wasm, loader }
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ====================
|
||||
// === Debug Screen ===
|
||||
// ====================
|
||||
@ -106,46 +125,44 @@ async function download_content(config) {
|
||||
let main_entry_point = 'ide'
|
||||
|
||||
/// Prefix name of each scene defined in the WASM binary.
|
||||
let wasm_entry_point_pfx = "entry_point_"
|
||||
|
||||
let wasm_entry_point_pfx = 'entry_point_'
|
||||
|
||||
/// Displays a debug screen which allows the user to run one of predefined debug examples.
|
||||
function show_debug_screen(wasm,msg) {
|
||||
API.remoteLog("show_debug_screen")
|
||||
function show_debug_screen(wasm: any, msg: string) {
|
||||
API.remoteLog('show_debug_screen')
|
||||
let names = []
|
||||
for (let fn of Object.getOwnPropertyNames(wasm)) {
|
||||
if (fn.startsWith(wasm_entry_point_pfx)) {
|
||||
let name = fn.replace(wasm_entry_point_pfx,"")
|
||||
let name = fn.replace(wasm_entry_point_pfx, '')
|
||||
names.push(name)
|
||||
}
|
||||
}
|
||||
|
||||
if(msg==="" || msg===null || msg===undefined) { msg = "" }
|
||||
if (msg === '' || msg === null || msg === undefined) {
|
||||
msg = ''
|
||||
}
|
||||
let debug_screen_div = html_utils.new_top_level_div()
|
||||
let newDiv = document.createElement("div")
|
||||
let newContent = document.createTextNode(msg + "Available entry points:")
|
||||
let currentDiv = document.getElementById("app")
|
||||
let ul = document.createElement('ul')
|
||||
let newDiv = document.createElement('div')
|
||||
let newContent = document.createTextNode(msg + 'Available entry points:')
|
||||
let ul = document.createElement('ul')
|
||||
debug_screen_div.style.position = 'absolute'
|
||||
debug_screen_div.style.zIndex = 1
|
||||
debug_screen_div.style.zIndex = 1
|
||||
newDiv.appendChild(newContent)
|
||||
debug_screen_div.appendChild(newDiv)
|
||||
newDiv.appendChild(ul)
|
||||
|
||||
for (let name of names) {
|
||||
let li = document.createElement('li')
|
||||
let a = document.createElement('a')
|
||||
let li = document.createElement('li')
|
||||
let a = document.createElement('a')
|
||||
let linkText = document.createTextNode(name)
|
||||
ul.appendChild(li)
|
||||
a.appendChild(linkText)
|
||||
a.title = name
|
||||
a.href = "?entry="+name
|
||||
a.title = name
|
||||
a.href = '?entry=' + name
|
||||
li.appendChild(a)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ====================
|
||||
// === Scam Warning ===
|
||||
// ====================
|
||||
@ -159,52 +176,58 @@ function printScamWarning() {
|
||||
font-weight : bold;
|
||||
padding: 10px 20px 10px 20px;
|
||||
`
|
||||
let headerCSS1 = headerCSS + "font-size : 46px;"
|
||||
let headerCSS2 = headerCSS + "font-size : 20px;"
|
||||
let msgCSS = "font-size:16px;"
|
||||
let headerCSS1 = headerCSS + 'font-size : 46px;'
|
||||
let headerCSS2 = headerCSS + 'font-size : 20px;'
|
||||
let msgCSS = 'font-size:16px;'
|
||||
|
||||
let msg1 = "This is a browser feature intended for developers. If someone told you to " +
|
||||
"copy-paste something here, it is a scam and will give them access to your " +
|
||||
"account and data."
|
||||
let msg2 = "See https://github.com/enso-org/ide/blob/main/docs/security/selfxss.md for more " +
|
||||
"information."
|
||||
console.log("%cStop!",headerCSS1)
|
||||
console.log("%cYou may be victim of a scam!",headerCSS2)
|
||||
console.log("%c"+msg1,msgCSS)
|
||||
console.log("%c"+msg2,msgCSS)
|
||||
let msg1 =
|
||||
'This is a browser feature intended for developers. If someone told you to ' +
|
||||
'copy-paste something here, it is a scam and will give them access to your ' +
|
||||
'account and data.'
|
||||
let msg2 =
|
||||
'See https://github.com/enso-org/ide/blob/main/docs/security/selfxss.md for more ' +
|
||||
'information.'
|
||||
console.log('%cStop!', headerCSS1)
|
||||
console.log('%cYou may be victim of a scam!', headerCSS2)
|
||||
console.log('%c' + msg1, msgCSS)
|
||||
console.log('%c' + msg2, msgCSS)
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ======================
|
||||
// === Remote Logging ===
|
||||
// ======================
|
||||
|
||||
class MixpanelLogger {
|
||||
private readonly mixpanel: any
|
||||
|
||||
constructor() {
|
||||
this.mixpanel = require('mixpanel-browser');
|
||||
this.mixpanel.init("5b541aeab5e08f313cdc1d1bbebc12ac", { "api_host": "https://api-eu.mixpanel.com" }, "");
|
||||
this.mixpanel = require('mixpanel-browser')
|
||||
this.mixpanel.init(
|
||||
'5b541aeab5e08f313cdc1d1bbebc12ac',
|
||||
{ api_host: 'https://api-eu.mixpanel.com' },
|
||||
''
|
||||
)
|
||||
}
|
||||
|
||||
log(event,data) {
|
||||
log(event: string, data: any) {
|
||||
if (this.mixpanel) {
|
||||
event = MixpanelLogger.trim_message(event)
|
||||
if (data !== undefined && data !== null) {
|
||||
data = MixpanelLogger.trim_message(JSON.stringify(data))
|
||||
this.mixpanel.track(event,{data});
|
||||
this.mixpanel.track(event, { data })
|
||||
} else {
|
||||
this.mixpanel.track(event);
|
||||
this.mixpanel.track(event)
|
||||
}
|
||||
} else {
|
||||
console.warn(`Failed to log the event '${event}'.`)
|
||||
}
|
||||
}
|
||||
|
||||
static trim_message(message) {
|
||||
const MAX_MESSAGE_LENGTH = 500;
|
||||
let trimmed = message.substr(0,MAX_MESSAGE_LENGTH)
|
||||
static trim_message(message: string) {
|
||||
const MAX_MESSAGE_LENGTH = 500
|
||||
let trimmed = message.substr(0, MAX_MESSAGE_LENGTH)
|
||||
if (trimmed.length < message.length) {
|
||||
trimmed += "..."
|
||||
trimmed += '...'
|
||||
}
|
||||
return trimmed
|
||||
}
|
||||
@ -214,36 +237,46 @@ class MixpanelLogger {
|
||||
// === Logs Buffering ===
|
||||
// ======================
|
||||
|
||||
const logsFns = ['log','info','debug','warn','error','group','groupCollapsed','groupEnd']
|
||||
const logsFns = ['log', 'info', 'debug', 'warn', 'error', 'group', 'groupCollapsed', 'groupEnd']
|
||||
|
||||
class LogRouter {
|
||||
private buffer: any[]
|
||||
private readonly raw: {}
|
||||
autoFlush: boolean
|
||||
|
||||
constructor() {
|
||||
this.buffer = []
|
||||
this.raw = {}
|
||||
this.buffer = []
|
||||
this.raw = {}
|
||||
this.autoFlush = true
|
||||
// @ts-ignore
|
||||
console.autoFlush = true
|
||||
for (let name of logsFns) {
|
||||
// @ts-ignore
|
||||
this.raw[name] = console[name]
|
||||
// @ts-ignore
|
||||
console[name] = (...args) => {
|
||||
this.handle(name,args)
|
||||
this.handle(name, args)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto_flush_on() {
|
||||
this.autoFlush = true
|
||||
// @ts-ignore
|
||||
console.autoFlush = true
|
||||
for (let {name,args} of this.buffer) {
|
||||
for (let { name, args } of this.buffer) {
|
||||
// @ts-ignore
|
||||
this.raw[name](...args)
|
||||
}
|
||||
this.buffer = []
|
||||
}
|
||||
|
||||
handle(name,args) {
|
||||
handle(name: string, args: any[]) {
|
||||
if (this.autoFlush) {
|
||||
// @ts-ignore
|
||||
this.raw[name](...args)
|
||||
} else {
|
||||
this.buffer.push({name,args})
|
||||
this.buffer.push({ name, args })
|
||||
}
|
||||
|
||||
// The following code is just a hack to discover if the logs start with `[E]` which
|
||||
@ -271,8 +304,8 @@ class LogRouter {
|
||||
}
|
||||
}
|
||||
|
||||
handleError(...args) {
|
||||
API.remoteLog("error", args)
|
||||
handleError(...args: any[]) {
|
||||
API.remoteLog('error', args)
|
||||
}
|
||||
}
|
||||
|
||||
@ -281,6 +314,7 @@ let logRouter = new LogRouter()
|
||||
function hideLogs() {
|
||||
console.log('All subsequent logs will be hidden. Eval `showLogs()` to reveal them.')
|
||||
logRouter.autoFlush = false
|
||||
// @ts-ignore
|
||||
console.autoFlush = false
|
||||
}
|
||||
|
||||
@ -288,10 +322,9 @@ function showLogs() {
|
||||
logRouter.auto_flush_on()
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
window.showLogs = showLogs
|
||||
|
||||
|
||||
|
||||
// ======================
|
||||
// === Crash Handling ===
|
||||
// ======================
|
||||
@ -304,7 +337,7 @@ function initCrashHandling() {
|
||||
}
|
||||
}
|
||||
|
||||
const crashMessageStorageKey = "crash-message"
|
||||
const crashMessageStorageKey = 'crash-message'
|
||||
|
||||
function previousCrashMessageExists() {
|
||||
return sessionStorage.getItem(crashMessageStorageKey) !== null
|
||||
@ -314,7 +347,7 @@ function getPreviousCrashMessage() {
|
||||
return sessionStorage.getItem(crashMessageStorageKey)
|
||||
}
|
||||
|
||||
function storeLastCrashMessage(message) {
|
||||
function storeLastCrashMessage(message: string) {
|
||||
sessionStorage.setItem(crashMessageStorageKey, message)
|
||||
}
|
||||
|
||||
@ -322,7 +355,6 @@ function clearPreviousCrashMessage() {
|
||||
sessionStorage.removeItem(crashMessageStorageKey)
|
||||
}
|
||||
|
||||
|
||||
// === Crash detection ===
|
||||
|
||||
function setupCrashDetection() {
|
||||
@ -341,38 +373,42 @@ function setupCrashDetection() {
|
||||
window.addEventListener('unhandledrejection', function (event) {
|
||||
// As above, we prefer stack traces.
|
||||
// But here, `event.reason` is not even guaranteed to be an `Error`.
|
||||
handleCrash(event.reason.stack || event.reason.message || "Unhandled rejection")
|
||||
handleCrash(event.reason.stack || event.reason.message || 'Unhandled rejection')
|
||||
})
|
||||
}
|
||||
|
||||
function handleCrash(message) {
|
||||
API.remoteLog("crash", message)
|
||||
function handleCrash(message: string) {
|
||||
API.remoteLog('crash', message)
|
||||
if (document.getElementById(crashBannerId) === null) {
|
||||
storeLastCrashMessage(message)
|
||||
location.reload()
|
||||
} else {
|
||||
for (let element of [... document.body.childNodes]) {
|
||||
// @ts-ignore
|
||||
for (let element of [...document.body.childNodes]) {
|
||||
// @ts-ignore
|
||||
if (element.id !== crashBannerId) {
|
||||
element.remove()
|
||||
}
|
||||
}
|
||||
document.getElementById(crashBannerContentId).insertAdjacentHTML("beforeend",
|
||||
document.getElementById(crashBannerContentId).insertAdjacentHTML(
|
||||
'beforeend',
|
||||
`<hr>
|
||||
<div>A second error occurred. This time, the IDE will not automatically restart.</div>`)
|
||||
<div>A second error occurred. This time, the IDE will not automatically restart.</div>`
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// === Crash recovery ===
|
||||
|
||||
// Those IDs should be the same that are used in index.html.
|
||||
const crashBannerId = "crash-banner"
|
||||
const crashBannerContentId = "crash-banner-content"
|
||||
const crashReportButtonId = "crash-report-button"
|
||||
const crashBannerCloseButtonId = "crash-banner-close-button"
|
||||
const crashBannerId = 'crash-banner'
|
||||
const crashBannerContentId = 'crash-banner-content'
|
||||
const crashReportButtonId = 'crash-report-button'
|
||||
const crashBannerCloseButtonId = 'crash-banner-close-button'
|
||||
|
||||
function showCrashBanner(message) {
|
||||
document.body.insertAdjacentHTML('afterbegin',
|
||||
function showCrashBanner(message: string) {
|
||||
document.body.insertAdjacentHTML(
|
||||
'afterbegin',
|
||||
`<div id="${crashBannerId}">
|
||||
<button id="${crashBannerCloseButtonId}" class="icon-button">✖</button>
|
||||
<div id="${crashBannerContentId}">
|
||||
@ -390,9 +426,9 @@ function showCrashBanner(message) {
|
||||
report_button.onclick = async _event => {
|
||||
try {
|
||||
await reportCrash(message)
|
||||
content.textContent = "Thank you, the crash was reported."
|
||||
content.textContent = 'Thank you, the crash was reported.'
|
||||
} catch (e) {
|
||||
content.textContent = "The crash could not be reported."
|
||||
content.textContent = 'The crash could not be reported.'
|
||||
}
|
||||
}
|
||||
close_button.onclick = () => {
|
||||
@ -400,20 +436,19 @@ function showCrashBanner(message) {
|
||||
}
|
||||
}
|
||||
|
||||
async function reportCrash(message) {
|
||||
async function reportCrash(message: string) {
|
||||
// @ts-ignore
|
||||
const crashReportHost = API[globalConfig.windowAppScopeConfigName].crash_report_host
|
||||
await fetch(`http://${crashReportHost}/`, {
|
||||
method: 'POST',
|
||||
mode: 'no-cors',
|
||||
headers: {
|
||||
'Content-Type': 'text/plain'
|
||||
'Content-Type': 'text/plain',
|
||||
},
|
||||
body: message
|
||||
})
|
||||
body: message,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ========================
|
||||
// === Main Entry Point ===
|
||||
// ========================
|
||||
@ -426,6 +461,7 @@ function style_root() {
|
||||
/// Waits for the window to finish its show animation. It is used when the website is run in
|
||||
/// Electron. Please note that it returns immediately in the web browser.
|
||||
async function windowShowAnimation() {
|
||||
// @ts-ignore
|
||||
await window.showAnimation
|
||||
}
|
||||
|
||||
@ -435,63 +471,104 @@ function disableContextMenu() {
|
||||
})
|
||||
}
|
||||
|
||||
function ok(value) {
|
||||
function ok(value: any) {
|
||||
return value !== null && value !== undefined
|
||||
}
|
||||
|
||||
class Config {
|
||||
public use_loader: boolean
|
||||
public wasm_url: string
|
||||
public wasm_glue_url: string
|
||||
public crash_report_host: string
|
||||
public no_data_gathering: boolean
|
||||
public is_in_cloud: boolean
|
||||
public entry: string
|
||||
|
||||
static default() {
|
||||
let config = new Config()
|
||||
config.use_loader = true
|
||||
config.wasm_url = '/assets/ide.wasm'
|
||||
config.wasm_glue_url = '/assets/wasm_imports.js'
|
||||
config.crash_report_host = cfg.defaultLogServerHost
|
||||
config.no_data_gathering = false
|
||||
config.is_in_cloud = false
|
||||
config.entry = null
|
||||
return config
|
||||
}
|
||||
|
||||
updateFromObject(other: any) {
|
||||
if (!ok(other)) {
|
||||
return
|
||||
}
|
||||
this.use_loader = ok(other.use_loader) ? tryAsBoolean(other.use_loader) : this.use_loader
|
||||
this.no_data_gathering = ok(other.no_data_gathering)
|
||||
? tryAsBoolean(other.no_data_gathering)
|
||||
: this.no_data_gathering
|
||||
this.is_in_cloud = ok(other.is_in_cloud)
|
||||
? tryAsBoolean(other.is_in_cloud)
|
||||
: this.is_in_cloud
|
||||
this.wasm_url = ok(other.wasm_url) ? tryAsString(other.wasm_url) : this.wasm_url
|
||||
this.wasm_glue_url = ok(other.wasm_glue_url)
|
||||
? tryAsString(other.wasm_glue_url)
|
||||
: this.wasm_glue_url
|
||||
this.crash_report_host = ok(other.crash_report_host)
|
||||
? tryAsString(other.crash_report_host)
|
||||
: this.crash_report_host
|
||||
this.entry = ok(other.entry) ? tryAsString(other.entry) : this.entry
|
||||
}
|
||||
}
|
||||
|
||||
/// Check whether the value is a string with value `"true"`/`"false"`, if so, return the
|
||||
// appropriate boolean instead. Otherwise, return the original value.
|
||||
function parseBooleanOrLeaveAsIs(value) {
|
||||
if (value === "true"){
|
||||
function parseBooleanOrLeaveAsIs(value: any): any {
|
||||
if (value === 'true') {
|
||||
return true
|
||||
}
|
||||
if (value === "false"){
|
||||
if (value === 'false') {
|
||||
return false
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
/// Turn all values that have a boolean in string representation (`"true"`/`"false"`) into actual
|
||||
/// booleans (`true/`false``).
|
||||
function parseAllBooleans(config) {
|
||||
for (const key in config) {
|
||||
config[key] = parseBooleanOrLeaveAsIs(config[key])
|
||||
}
|
||||
function tryAsBoolean(value: any): boolean {
|
||||
value = parseBooleanOrLeaveAsIs(value)
|
||||
assert(typeof value == 'boolean')
|
||||
return value
|
||||
}
|
||||
|
||||
function initLogging(config) {
|
||||
assert(typeof config.no_data_gathering == "boolean")
|
||||
if (config.no_data_gathering ) {
|
||||
API.remoteLog = function (_event, _data) {}
|
||||
} else {
|
||||
let logger = new MixpanelLogger
|
||||
API.remoteLog = function (event,data) {logger.log(event,data)}
|
||||
}
|
||||
function tryAsString(value: any): string {
|
||||
return value.toString()
|
||||
}
|
||||
|
||||
/// Main entry point. Loads WASM, initializes it, chooses the scene to run.
|
||||
API.main = async function (inputConfig) {
|
||||
let defaultConfig = {
|
||||
use_loader : true,
|
||||
wasm_url : '/assets/ide.wasm',
|
||||
wasm_glue_url : '/assets/wasm_imports.js',
|
||||
crash_report_host : cfg.defaultLogServerHost,
|
||||
no_data_gathering : false,
|
||||
is_in_cloud : false,
|
||||
}
|
||||
let urlParams = new URLSearchParams(window.location.search);
|
||||
let urlConfig = Object.fromEntries(urlParams.entries())
|
||||
let config = Object.assign(defaultConfig,inputConfig,urlConfig)
|
||||
parseAllBooleans(config)
|
||||
API.main = async function (inputConfig: any) {
|
||||
const urlParams = new URLSearchParams(window.location.search)
|
||||
// @ts-ignore
|
||||
const urlConfig = Object.fromEntries(urlParams.entries())
|
||||
|
||||
const config = Config.default()
|
||||
config.updateFromObject(inputConfig)
|
||||
config.updateFromObject(urlConfig)
|
||||
|
||||
// @ts-ignore
|
||||
API[globalConfig.windowAppScopeConfigName] = config
|
||||
|
||||
initLogging(config)
|
||||
API.initLogging(config)
|
||||
|
||||
window.setInterval(() =>{API.remoteLog("alive");}, ALIVE_LOG_INTERVAL)
|
||||
//Build data injected during the build process. See `webpack.config.js` for the source.
|
||||
API.remoteLog("git_hash", {hash: GIT_HASH})
|
||||
API.remoteLog("build_information", BUILD_INFO)
|
||||
API.remoteLog("git_status", {satus: GIT_STATUS})
|
||||
window.setInterval(() => {
|
||||
API.remoteLog('alive')
|
||||
}, ALIVE_LOG_INTERVAL)
|
||||
|
||||
// Build data injected during the build process. See `webpack.config.js` for the source.
|
||||
// @ts-ignore
|
||||
const hash = GIT_HASH
|
||||
API.remoteLog('git_hash', { hash })
|
||||
// @ts-ignore
|
||||
const buildInfo = BUILD_INFO
|
||||
API.remoteLog('build_information', buildInfo)
|
||||
// @ts-ignore
|
||||
const status = GIT_STATUS
|
||||
API.remoteLog('git_status', { status })
|
||||
|
||||
//initCrashHandling()
|
||||
style_root()
|
||||
@ -500,21 +577,23 @@ API.main = async function (inputConfig) {
|
||||
disableContextMenu()
|
||||
|
||||
let entryTarget = ok(config.entry) ? config.entry : main_entry_point
|
||||
config.use_loader = config.use_loader && (entryTarget === main_entry_point)
|
||||
config.use_loader = config.use_loader && entryTarget === main_entry_point
|
||||
|
||||
API.remoteLog("window_show_animation")
|
||||
API.remoteLog('window_show_animation')
|
||||
await windowShowAnimation()
|
||||
API.remoteLog("download_content")
|
||||
let {wasm,loader} = await download_content(config)
|
||||
API.remoteLog("wasm_loaded")
|
||||
API.remoteLog('download_content')
|
||||
let { wasm, loader } = await download_content(config)
|
||||
API.remoteLog('wasm_loaded')
|
||||
if (entryTarget) {
|
||||
let fn_name = wasm_entry_point_pfx + entryTarget
|
||||
let fn = wasm[fn_name]
|
||||
if (fn) { fn() } else {
|
||||
let fn = wasm[fn_name]
|
||||
if (fn) {
|
||||
fn()
|
||||
} else {
|
||||
loader.destroy()
|
||||
show_debug_screen(wasm,"Unknown entry point '" + entryTarget + "'. ")
|
||||
show_debug_screen(wasm, "Unknown entry point '" + entryTarget + "'. ")
|
||||
}
|
||||
} else {
|
||||
show_debug_screen(wasm)
|
||||
show_debug_screen(wasm, '')
|
||||
}
|
||||
}
|
7
gui/src/js/lib/content/tsconfig.json
Normal file
7
gui/src/js/lib/content/tsconfig.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"noImplicitAny": true,
|
||||
"target": "ES5",
|
||||
"module": "ES2015"
|
||||
}
|
||||
}
|
@ -18,7 +18,7 @@ const BUILD_INFO = JSON.parse(require('fs').readFileSync(buildPath, 'utf8'));
|
||||
|
||||
module.exports = {
|
||||
entry: {
|
||||
index: path.resolve(thisPath,'src','index.js'),
|
||||
index: path.resolve(thisPath,'src','index.ts'),
|
||||
wasm_imports: './src/wasm_imports.js',
|
||||
},
|
||||
output: {
|
||||
@ -51,8 +51,9 @@ module.exports = {
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
wasm_rust_glue$: path.resolve(wasmPath,'ide.js')
|
||||
}
|
||||
wasm_rust_glue$: path.resolve(wasmPath,'ide.js'),
|
||||
},
|
||||
extensions: [ '.ts', '.js' ],
|
||||
},
|
||||
performance: {
|
||||
hints: false,
|
||||
@ -65,6 +66,11 @@ module.exports = {
|
||||
test: /\.ya?ml$/,
|
||||
type: 'json',
|
||||
use: 'yaml-loader'
|
||||
},
|
||||
{
|
||||
test: /\.tsx?/,
|
||||
use: 'ts-loader',
|
||||
exclude: /node_modules/,
|
||||
}
|
||||
]
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user