Featureful (#31)
* Fix loading within the CLI * Remove app * Remove promise handle * Add initial travis file * Add libxkbfile dependency * Add libxkbfile-dev * Add build script * Fix malformed bash statement * Remove yarn from script * Improve build script * Extract upx before usage * Only run upx if on linux * Ensure resource directory exists * Pack runnable binary * Export binary with platform * Improve build process * Install upx before running install script * Update typescript version before running nexe * Add os.release() function for multi-platform support * Update travis.yml to improve deployment * Add on CI * Update to v1.31.0 * Add libsecret * Update build target * Skip cleanup * Fix built-in extensions * Add basics for apps * Create custom DNS server * Fix forking within CLI. Fixes TS language features * Fix filename resolve * Fix default extensions path * Add custom dialog * Store workspace path * Remove outfiles * Cleanup * Always authed outside of CLI * Use location.host for client * Remove useless app interface * Remove debug file for building wordlist * Use chromes tcp host * Update patch * Build browser app before packaging * Replace all css containing file:// URLs, fix webviews * Fix save * Fix mkdir
This commit is contained in:
@ -32,6 +32,13 @@ export abstract class IdeClient {
|
||||
logger.info("Loading IDE");
|
||||
this.loadTime = time(2500);
|
||||
|
||||
let appWindow: Window | undefined;
|
||||
window.addEventListener("message", (event) => {
|
||||
if (event.data === "app") {
|
||||
appWindow = event.source as Window;
|
||||
}
|
||||
});
|
||||
|
||||
this.sharedProcessData = new Promise((resolve): void => {
|
||||
client.onSharedProcessActive(resolve);
|
||||
});
|
||||
@ -48,6 +55,9 @@ export abstract class IdeClient {
|
||||
|
||||
this.initialize().then(() => {
|
||||
logger.info("Load completed", field("duration", this.loadTime));
|
||||
if (appWindow) {
|
||||
appWindow.postMessage("loaded", "*");
|
||||
}
|
||||
}).catch((error) => {
|
||||
logger.error(error.message);
|
||||
logger.warn("Load completed with errors", field("duration", this.loadTime));
|
||||
|
@ -92,7 +92,7 @@ class WebsocketConnection implements ReadWriteConnection {
|
||||
private async openSocket(): Promise<WebSocket> {
|
||||
this.dispose();
|
||||
const socket = new WebSocket(
|
||||
`${location.protocol === "https" ? "wss" : "ws"}://${location.host}`,
|
||||
`${location.protocol === "https:" ? "wss" : "ws"}://${location.host}`,
|
||||
);
|
||||
socket.binaryType = "arraybuffer";
|
||||
this.activeSocket = socket;
|
||||
|
@ -19,15 +19,59 @@ if (typeof document === "undefined") {
|
||||
(global as any).document = {} as any;
|
||||
}
|
||||
|
||||
const oldCreateElement: <K extends keyof HTMLElementTagNameMap>(
|
||||
tagName: K, options?: ElementCreationOptions,
|
||||
) => HTMLElementTagNameMap[K] = document.createElement;
|
||||
|
||||
const oldCreateElement = document.createElement;
|
||||
const newCreateElement = <K extends keyof HTMLElementTagNameMap>(tagName: K): HTMLElementTagNameMap[K] => {
|
||||
const createElement = <K extends keyof HTMLElementTagNameMap>(tagName: K): HTMLElementTagNameMap[K] => {
|
||||
return oldCreateElement.call(document, tagName);
|
||||
// tslint:disable-next-line:no-any
|
||||
return oldCreateElement.call(document, tagName as any);
|
||||
};
|
||||
|
||||
if (tagName === "style") {
|
||||
const style = createElement("style");
|
||||
// tslint:disable-next-line:no-any
|
||||
const getPropertyDescriptor = (object: any, id: string): PropertyDescriptor | undefined => {
|
||||
let op = Object.getPrototypeOf(object);
|
||||
while (!Object.getOwnPropertyDescriptor(op, id)) {
|
||||
op = Object.getPrototypeOf(op);
|
||||
}
|
||||
|
||||
return Object.getOwnPropertyDescriptor(op, id);
|
||||
};
|
||||
const oldInnerHtml = getPropertyDescriptor(style, "innerHTML");
|
||||
if (!oldInnerHtml) {
|
||||
throw new Error("Failed to find innerHTML property");
|
||||
}
|
||||
Object.defineProperty(style, "innerHTML", {
|
||||
get: (): string => {
|
||||
return oldInnerHtml!.get!.call(style);
|
||||
},
|
||||
set: (value: string): void => {
|
||||
value = value.replace(/file:\/\//g, "/resource");
|
||||
oldInnerHtml!.set!.call(style, value);
|
||||
},
|
||||
});
|
||||
let overridden = false;
|
||||
const oldSheet = getPropertyDescriptor(style, "sheet");
|
||||
Object.defineProperty(style, "sheet", {
|
||||
// tslint:disable-next-line:no-any
|
||||
get: (): any => {
|
||||
const sheet = oldSheet!.get!.call(style);
|
||||
if (sheet && !overridden) {
|
||||
const oldInsertRule = sheet.insertRule;
|
||||
sheet.insertRule = (rule: string, index?: number): void => {
|
||||
rule = rule.replace(/file:\/\//g, "/resource");
|
||||
oldInsertRule.call(sheet, rule, index);
|
||||
};
|
||||
overridden = true;
|
||||
}
|
||||
|
||||
return sheet;
|
||||
},
|
||||
});
|
||||
|
||||
return style;
|
||||
}
|
||||
|
||||
if (tagName === "webview") {
|
||||
const view = createElement("iframe") as HTMLIFrameElement;
|
||||
view.style.border = "0px";
|
||||
@ -56,8 +100,19 @@ const newCreateElement = <K extends keyof HTMLElementTagNameMap>(tagName: K): HT
|
||||
view.contentDocument.body.parentElement!.style.overflow = "hidden";
|
||||
const script = createElement("script");
|
||||
script.src = url;
|
||||
script.addEventListener("load", () => {
|
||||
view.contentDocument!.dispatchEvent(new Event("DOMContentLoaded", {
|
||||
bubbles: true,
|
||||
cancelable: true,
|
||||
}));
|
||||
// const e = new CustomEvent("ipc-message");
|
||||
// (e as any).channel = "webview-ready"; // tslint:disable-line no-any
|
||||
// (e as any).args = [frameID]; // tslint:disable-line no-any
|
||||
// view.dispatchEvent(e);
|
||||
});
|
||||
view.contentDocument.head.appendChild(script);
|
||||
}
|
||||
|
||||
};
|
||||
},
|
||||
});
|
||||
@ -65,8 +120,8 @@ const newCreateElement = <K extends keyof HTMLElementTagNameMap>(tagName: K): HT
|
||||
(view as any).send = (channel: string, ...args: any[]): void => { // tslint:disable-line no-any
|
||||
if (args[0] && typeof args[0] === "object" && args[0].contents) {
|
||||
// TODO
|
||||
// args[0].contents = (args[0].contents as string).replace(/"(file:\/\/[^"]*)"/g, (m) => `"${getFetchUrl(m)}"`);
|
||||
// args[0].contents = (args[0].contents as string).replace(/"vscode-resource:([^"]*)"/g, (m) => `"${getFetchUrl(m)}"`);
|
||||
args[0].contents = (args[0].contents as string).replace(/"(file:\/\/[^"]*)"/g, (m1) => `"/resource${m1}"`);
|
||||
args[0].contents = (args[0].contents as string).replace(/"vscode-resource:([^"]*)"/g, (m, m1) => `"/resource${m1}"`);
|
||||
}
|
||||
if (view.contentWindow) {
|
||||
view.contentWindow.postMessage({
|
||||
|
@ -118,6 +118,7 @@ class FS {
|
||||
const str = fs.createWriteStream(path, options);
|
||||
ae.on("write", (d: string) => str.write(_Buffer.from(d, "utf8")));
|
||||
ae.on("close", () => str.close());
|
||||
ae.on("destroy", () => str.destroy());
|
||||
str.on("close", () => ae.emit("close"));
|
||||
str.on("open", (fd) => ae.emit("open", fd));
|
||||
str.on("error", (err) => ae.emit(err));
|
||||
@ -157,6 +158,10 @@ class FS {
|
||||
ae.emit("close");
|
||||
}
|
||||
|
||||
public destroy(): void {
|
||||
ae.emit("destroy");
|
||||
}
|
||||
|
||||
}) as fs.WriteStream;
|
||||
}
|
||||
|
||||
|
@ -32,6 +32,10 @@ class OS {
|
||||
this._tmpdir = data.tmpDirectory;
|
||||
}
|
||||
|
||||
public release(): string {
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
public platform(): NodeJS.Platform {
|
||||
if (navigator.appVersion.indexOf("Win") != -1) {
|
||||
return "win32";
|
||||
|
Reference in New Issue
Block a user