Skip to content

Commit dee0132

Browse files
authored
Merge pull request #151 from CodinGame/run-ext-host-in-worker
WebWorker extension host
2 parents 36e6379 + 572d107 commit dee0132

File tree

88 files changed

+7187
-3788
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

88 files changed

+7187
-3788
lines changed

.eslintrc

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
},
99
"globals": {
1010
"Thenable": "readonly",
11-
"VSCODE_VERSION": "readonly"
11+
"VSCODE_VERSION": "readonly",
12+
"VSCODE_REF": "readonly"
1213
},
1314
"extends": [
1415
"@codingame"
@@ -27,7 +28,9 @@
2728
"net": "always", // Hack for vscode .net.js files
2829
"impl": "always", // Hack for vscode .impl.js files
2930
"worker": "always",
30-
"ts": "always"
31+
"ts": "always",
32+
"services": "always",
33+
"api": "always"
3134
}
3235
],
3336
"@typescript-eslint/no-unused-vars": [

README.md

Lines changed: 72 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,18 +26,77 @@ npm install -D @types/vscode
2626
}
2727
```
2828

29-
If you use Vite, add in your vite.config.js:
30-
```js
31-
assetsInclude: ['node_modules/vscode-oniguruma/**/*.wasm']
32-
```
33-
3429
### Why?
3530

3631
Monaco-editor is a library that is constructed using code from vscode and goes through an intense treeshaking process.
3732

3833
However, due to the inclusion of additional code from VSCode in this library that utilizes internal modules bundled in monaco, this treeshaking is a problem here.
3934

40-
To **tree-mend** (to **un**treeshake it) monaco-editor, this library provide a script that will apply a patch on the local installation of monaco-editor, restoring all the code that was treeshaken during the monaco-editor build process
35+
To **tree-mend** (to **un**treeshake it) monaco-editor, this library provides a script that will apply a patch on the local installation of monaco-editor, restoring all the code that was treeshaken during the monaco-editor build process
36+
37+
## Troubleshooting
38+
39+
### If you use Vite
40+
41+
This library uses a lot the `new URL('asset.extension', import.meta.url)` syntax which [is supported by vite](https://vitejs.dev/guide/assets.html#new-url-url-import-meta-url)
42+
43+
While it works great in `build` mode (because rollup is used), there is some issues in `watch`` mode:
44+
- import.meta.url is not replaced while creating bundles, it is an issue when the syntax is used inside a dependency
45+
- vite is still trying to inject/transform javascript assets files, breaking the code by injecting ESM imports in commonjs files
46+
47+
There are workarounds for both:
48+
49+
- We can help vite by replacing `import.meta.url` by the original module path (you need the --experimental-import-meta-resolve note option):
50+
```typescript
51+
{
52+
...
53+
optimizeDeps: {
54+
esbuildOptions: {
55+
plugins: [{
56+
name: 'import.meta.url',
57+
setup ({ onLoad }) {
58+
// Help vite that bundles/move files in dev mode without touching `import.meta.url` which breaks asset urls
59+
onLoad({ filter: /.*\.js/, namespace: 'file' }, async args => {
60+
const code = fs.readFileSync(args.path, 'utf8')
61+
62+
const assetImportMetaUrlRE = /\bnew\s+URL\s*\(\s*('[^']+'|"[^"]+"|`[^`]+`)\s*,\s*import\.meta\.url\s*(?:,\s*)?\)/g
63+
let i = 0
64+
let newCode = ''
65+
for (let match = assetImportMetaUrlRE.exec(code); match != null; match = assetImportMetaUrlRE.exec(code)) {
66+
newCode += code.slice(i, match.index)
67+
68+
const path = match[1].slice(1, -1)
69+
const resolved = await import.meta.resolve!(path, url.pathToFileURL(args.path))
70+
71+
newCode += `new URL(${JSON.stringify(url.fileURLToPath(resolved))}, import.meta.url)`
72+
73+
i = assetImportMetaUrlRE.lastIndex
74+
}
75+
newCode += code.slice(i)
76+
77+
return { contents: newCode }
78+
})
79+
}
80+
}]
81+
}
82+
}
83+
}
84+
```
85+
- we can serialize and eval the code to prevent vite from touching it:
86+
```typescript
87+
{
88+
plugins: [{
89+
// prevent vite from trying to inject code into an extension file du to an `import()` in that file
90+
name: 'hack-prevent-transform-javascript',
91+
apply: 'serve',
92+
load (source) {
93+
if (source.includes('tsserver.web.js')) {
94+
return `eval(${JSON.stringify(fs.readFileSync(source).toString('utf-8'))})`
95+
}
96+
}
97+
}]
98+
}
99+
```
41100

42101
# Usage
43102

@@ -61,8 +120,9 @@ await initialize({
61120
})
62121
```
63122

64-
Additionally, this library exposes 20 modules that include the vscode version of some services (with some glue to make it work with monaco):
123+
Additionally, this library exposes 21 modules that include the vscode version of some services (with some glue to make it work with monaco):
65124

125+
- Extensions (included by default): `vscode/service-override/extensions`
66126
- Notifications: `vscode/service-override/notifications`
67127
- Dialogs: `vscode/service-override/dialogs`
68128
- Model: `vscode/service-override/model`
@@ -176,14 +236,16 @@ The api will use the manifest of a default vscode extension, which can be overri
176236

177237
You can also register a new extension from its manifest:
178238
```typescript
179-
import { registerExtension, initialize as initializeVscodeExtensions } from 'vscode/extensions'
239+
import { registerExtension, initialize } from 'vscode/extensions'
180240

181241
await initialize()
182242

183-
const { registerFile: registerExtensionFile, api: vscodeApi } = registerExtension(defaultThemesExtensions)
243+
const { registerFile: registerExtensionFile, getApi } = registerExtension(defaultThemesExtensions)
184244

185245
registerExtensionFile('/file.json', async () => fileContent)
186-
vscodeApi.languages.registerCompletionItemProvider(...)
246+
247+
getApi().then(vscodeApi => vscodeApi.languages.registerCompletionItemProvider(...))
248+
187249
```
188250

189251
### Default vscode extensions

0 commit comments

Comments
 (0)