Skip to content

Commit 825b5e9

Browse files
committed
Move lua transpilation to Monaco's TypeScript worker
1 parent 17edcf1 commit 825b5e9

File tree

7 files changed

+104
-115
lines changed

7 files changed

+104
-115
lines changed

package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@
2424
"gh-pages": "^2.2.0",
2525
"html-loader": "^0.5.5",
2626
"html-webpack-plugin": "^3.2.0",
27-
"monaco-editor-webpack-plugin": "^1.8.2",
28-
"node-libs-browser": "^2.2.1",
2927
"pnp-webpack-plugin": "^1.5.0",
3028
"prettier": "^1.19.1",
3129
"raw-loader": "^4.0.0",
@@ -46,6 +44,7 @@
4644
"fengari-web": "^0.1.4",
4745
"highlight.js": "^9.18.0",
4846
"monaco-editor": "^0.19.3",
47+
"node-libs-browser": "^2.2.1",
4948
"renderjson": "^1.4.0",
5049
"typescript-to-lua": "^0.31.0"
5150
}

src/playground/index.ts

Lines changed: 48 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,29 @@
1-
import { editor } from "monaco-editor/esm/vs/editor/editor.api";
1+
import * as monaco from "monaco-editor/esm/vs/editor/editor.api";
2+
import "monaco-editor/esm/vs/basic-languages/lua/lua.contribution";
3+
import "monaco-editor/esm/vs/basic-languages/typescript/typescript.contribution";
4+
import "monaco-editor/esm/vs/editor/edcore.main";
5+
import "monaco-editor/esm/vs/language/typescript/monaco.contribution";
26
import renderjson from "renderjson";
37
import * as lua from "typescript-to-lua/dist/LuaAST";
48
import { version as tstlVersion } from "typescript-to-lua/package.json";
5-
import FengariWorker from "worker-loader?name=fengari.worker.js!./fengariWorker";
6-
import TSTLWorker from "worker-loader?name=tstl.worker.js!./tstlWorker";
9+
import EditorWorker from "worker-loader?name=editor.worker.js!monaco-editor/esm/vs/editor/editor.worker.js";
10+
import FengariWorker from "worker-loader?name=fengari.worker.js!./fengari.worker";
11+
import TsWorker from "worker-loader?name=ts.worker.js!./ts.worker";
712
import "../../assets/styles/play.scss";
813

14+
// TODO: Use TypeScript 3.8 type imports
15+
type CustomTypeScriptWorker = import("./ts.worker").CustomTypeScriptWorker;
16+
17+
(globalThis as any).MonacoEnvironment = {
18+
getWorker(_workerId: any, label: string) {
19+
if (label === "typescript") {
20+
return new TsWorker();
21+
}
22+
23+
return new EditorWorker();
24+
},
25+
};
26+
927
const container = document.getElementById("editor-ts");
1028
const outputTerminalHeader = document.getElementById("editor-output-terminal-header");
1129
const outputTerminalContent = document.getElementById("editor-output-terminal-content");
@@ -67,14 +85,35 @@ if (queryStringSrcStart == 0) {
6785
}
6886

6987
if (container && exampleLua && astLua) {
70-
let tsEditor = editor.create(container, {
88+
renderjson.set_show_to_level(1);
89+
renderjson.set_replacer((key: string, value: any) => {
90+
if (key === "kind") {
91+
return lua.SyntaxKind[value];
92+
}
93+
94+
return value;
95+
});
96+
97+
async function compileLua() {
98+
const model = tsEditor.getModel()!;
99+
const getWorker = await monaco.languages.typescript.getTypeScriptWorker();
100+
const client = (await getWorker(model.uri)) as CustomTypeScriptWorker;
101+
const { code, ast } = await client.getTranspileOutput();
102+
103+
luaEditor.setValue(code);
104+
astLua!.innerText = "";
105+
astLua!.appendChild(renderjson(ast));
106+
fengariWorker.postMessage({ luaStr: code });
107+
}
108+
109+
let tsEditor = monaco.editor.create(container, {
71110
value: example,
72111
language: "typescript",
73112
minimap: { enabled: false },
74113
theme: "vs-dark",
75114
});
76115

77-
let luaEditor = editor.create(exampleLua, {
116+
let luaEditor = monaco.editor.create(exampleLua, {
78117
value: "",
79118
language: "lua",
80119
minimap: { enabled: false },
@@ -87,20 +126,19 @@ if (container && exampleLua && astLua) {
87126
luaEditor.layout();
88127
};
89128

90-
const tstlWorker = new TSTLWorker();
91-
tstlWorker.postMessage({ tsStr: tsEditor.getValue() });
129+
compileLua();
92130

93131
let timerVar: any;
94132
let ignoreHashChange = false;
95133

96134
tsEditor.onDidChangeModelContent(e => {
97135
clearInterval(timerVar);
98-
// wait one second before submitting work
136+
// Update transpile result only once per 250s
99137
timerVar = setTimeout(() => {
100-
tstlWorker.postMessage({ tsStr: tsEditor.getValue() });
138+
compileLua();
101139
window.location.replace("#src=" + encodeURIComponent(tsEditor.getValue()));
102140
ignoreHashChange = true;
103-
}, 500);
141+
}, 250);
104142
});
105143

106144
window.onhashchange = () => {
@@ -111,26 +149,6 @@ if (container && exampleLua && astLua) {
111149
};
112150

113151
const fengariWorker = new FengariWorker();
114-
115-
tstlWorker.onmessage = (event: MessageEvent) => {
116-
if (event.data.luaStr) {
117-
luaEditor.setValue(event.data.luaStr);
118-
119-
astLua.innerText = "";
120-
astLua.appendChild(
121-
renderjson.set_show_to_level(1).set_replacer((name: string, val: any) => {
122-
if (name === "kind") {
123-
return lua.SyntaxKind[val];
124-
}
125-
return val;
126-
})(event.data.luaAST),
127-
);
128-
fengariWorker.postMessage({ luaStr: event.data.luaStr });
129-
} else {
130-
luaEditor.setValue(event.data.diagnostics);
131-
}
132-
};
133-
134152
fengariWorker.onmessage = (event: MessageEvent) => {
135153
if (outputTerminalContent) {
136154
outputTerminalContent.innerText = event.data.luaPrint;

src/playground/ts.worker.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// @ts-ignore
2+
import * as worker from "monaco-editor/esm/vs/editor/editor.worker";
3+
import { TypeScriptWorker } from "monaco-editor/esm/vs/language/typescript/tsWorker";
4+
import * as ts from "typescript";
5+
import * as tstl from "typescript-to-lua";
6+
7+
const emitHost: tstl.EmitHost = {
8+
getCurrentDirectory: () => ".",
9+
readFile: (fileName: string) => {
10+
let featureName = fileName.replace("/dist/lualib/", "").replace(".lua", "");
11+
return require(`raw-loader!typescript-to-lua/dist/lualib/${featureName}.lua`).default;
12+
},
13+
};
14+
15+
// TODO: In latest monaco-typescript it returns `ts.Diagnostic[]`
16+
const clearDiagnostics = (TypeScriptWorker as any).clearFiles;
17+
18+
export class CustomTypeScriptWorker extends TypeScriptWorker {
19+
public async getTranspileOutput() {
20+
const { transpiledFiles } = this.transpileLua();
21+
const [transpiledFile] = transpiledFiles;
22+
return { code: transpiledFile.lua!, ast: transpiledFile.luaAst! };
23+
}
24+
25+
public async getSemanticDiagnostics(fileName: string) {
26+
const diagnostics = await super.getSemanticDiagnostics(fileName);
27+
const { diagnostics: transpileDiagnostics } = this.transpileLua();
28+
clearDiagnostics(transpileDiagnostics);
29+
return [...diagnostics, ...transpileDiagnostics];
30+
}
31+
32+
private transpileLua() {
33+
const program = ((this as any)._languageService as ts.LanguageService).getProgram()!;
34+
35+
const compilerOptions = program.getCompilerOptions();
36+
compilerOptions.luaLibImport = tstl.LuaLibImportKind.Inline;
37+
compilerOptions.luaTarget = tstl.LuaTarget.Lua53;
38+
39+
const sourceFiles = program.getRootFileNames().map(n => program.getSourceFile(n)!);
40+
return tstl.transpile({ program, emitHost, sourceFiles });
41+
}
42+
}
43+
44+
globalThis.onmessage = () => {
45+
worker.initialize((context: any, createData: any) => new CustomTypeScriptWorker(context, createData));
46+
};

src/playground/tstlWorker.ts

Lines changed: 0 additions & 67 deletions
This file was deleted.

webpack.config.js

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
const webpack = require("webpack");
22
const path = require("path");
3-
const MonacoWebpackPlugin = require("monaco-editor-webpack-plugin");
43
const HtmlWebpackPlugin = require("html-webpack-plugin");
54
const PnpWebpackPlugin = require("pnp-webpack-plugin");
65

@@ -46,7 +45,6 @@ module.exports = {
4645
contentFile: "landing.html",
4746
}),
4847

49-
new MonacoWebpackPlugin({ languages: ["javascript", "typescript", "lua"] }),
5048
new HtmlWebpackPlugin({
5149
title: "TypeScriptToLua - Online Compiler",
5250
chunks: ["play_bundle"],
@@ -58,12 +56,20 @@ module.exports = {
5856
// Ignore pnpapi reference in patched typescript source
5957
new webpack.IgnorePlugin(/pnpapi/),
6058

61-
// Exclude `typescript` from `play_bundle` referenced from `typescript-to-lua/dist/LuaAST`
6259
new webpack.NormalModuleReplacementPlugin(/typescript/, resource => {
60+
// Exclude `typescript` from `play_bundle` referenced from `typescript-to-lua/dist/LuaAST`
6361
const { issuer, compiler } = (resource.resourceResolveData && resource.resourceResolveData.context) || {};
6462
if (issuer === require.resolve("typescript-to-lua/dist/LuaAST") && compiler !== "worker") {
6563
resource.resource = emptyModulePath;
6664
}
65+
66+
// Replace vendored monaco-typescript's services build with full TypeScript API.
67+
if (
68+
resource.resource ===
69+
require.resolve("monaco-editor/esm/vs/language/typescript/lib/typescriptServices.js")
70+
) {
71+
resource.request = require.resolve("typescript");
72+
}
6773
}),
6874
],
6975
};

yarn.lock

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3945,18 +3945,6 @@ fsevents@~2.1.2:
39453945
languageName: node
39463946
linkType: hard
39473947

3948-
"monaco-editor-webpack-plugin@npm:^1.8.2":
3949-
version: 1.8.2
3950-
resolution: "monaco-editor-webpack-plugin@npm:1.8.2"
3951-
dependencies:
3952-
loader-utils: ^1.2.3
3953-
peerDependencies:
3954-
monaco-editor: ^0.19.1
3955-
webpack: ^4.5.0
3956-
checksum: 44bcc76dfe7fae0cf57138435b87deb1b71bd0bcdd5792c97891bc84406305a2a6f96c82f0fc4a0735da34db5d6a1e6bfcea240de7f1f6110849fd3259b4904f
3957-
languageName: node
3958-
linkType: hard
3959-
39603948
"monaco-editor@npm:^0.19.3":
39613949
version: 0.19.3
39623950
resolution: "monaco-editor@npm:0.19.3"
@@ -6352,7 +6340,6 @@ resolve@^1.13.1:
63526340
html-loader: ^0.5.5
63536341
html-webpack-plugin: ^3.2.0
63546342
monaco-editor: ^0.19.3
6355-
monaco-editor-webpack-plugin: ^1.8.2
63566343
node-libs-browser: ^2.2.1
63576344
pnp-webpack-plugin: ^1.5.0
63586345
prettier: ^1.19.1

0 commit comments

Comments
 (0)