Skip to content

Commit

Permalink
Use jiti for sync loading from TS Plugin (#803)
Browse files Browse the repository at this point in the history
  • Loading branch information
machty authored Mar 4, 2025
1 parent 469c15e commit a8cefd1
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 49 deletions.
1 change: 1 addition & 0 deletions packages/typescript-plugin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"prepack": "yarn build"
},
"dependencies": {
"jiti": "~2.4.2",
"@glint/core": "^1.4.0",
"@volar/typescript": "2.4.11"
},
Expand Down
78 changes: 29 additions & 49 deletions packages/typescript-plugin/src/typescript-server-plugin.ts
Original file line number Diff line number Diff line change
@@ -1,57 +1,37 @@
import type ts from 'typescript';
const { createJiti } = require('jiti');
const jiti = createJiti(__filename);

// Top level "imports" need to be CJS `require`s because TS Plugins must be CJS;
// we dynamically import() the ESM modules we need below within the async fn
// to cross the gap between CJS and ESM.
const {
createAsyncLanguageServicePlugin,
} = require('@volar/typescript/lib/quickstart/createAsyncLanguageServicePlugin.js');
createLanguageServicePlugin,
} = require('@volar/typescript/lib/quickstart/createLanguageServicePlugin.js');

/**
* Volar provides two variants of functions for initializing a TS Plugin:
* - createLanguageServicePlugin
* - createAsyncLanguageServicePlugin
*
* The only difference is whether their setup callback is an async function or not.
* The reason we use the async variant is because of our use of `await import`, which
* we need in order to import the ESM glint package into our CJS VSCode extension.
*
* Unfortunately this singular tick of async appears to be causing a few race conditions,
* in particular that when freshly booting VSCode on a .gts file, there might not be
* any diagnostic messages until something "kicks" the TS Plugin to run, e.g.
* by editing the file.
*/
const plugin = createAsyncLanguageServicePlugin(
['.gts', '.gjs', '.hbs'],
(fileName: string) => {
if (fileName.endsWith('.gts')) {
return 3 satisfies ts.ScriptKind.TS;
} else if (fileName.endsWith('.gjs')) {
return 1 satisfies ts.ScriptKind.JS;
}
return 3 satisfies ts.ScriptKind.TS;
},
async (_ts: any, info: any) => {
// The diagnostics race condition mentioned above appears to happen or at least
// be exacerbated by the fact that we use `await import` here.
const glintCore = await import('@glint/core');
const plugin = createLanguageServicePlugin((_ts: typeof import('typescript'), info: any) => {
/**
* we use the jiti (https://github.com/unjs/jiti) runtime to make it possible to
* synchronously load the ESM glint libaries from the current CommonJS context. It is a requirement
* that TypeScript plugins are written in CommonJS, which poses issues with
* having Glint be authored in ESM due to the requirement that typically `await import`
* is required to load ESM modules from CJS. But with jiti we can synchronously load the ESM
* modules from CJS which lets us avoid a ton of hacks and complexity we (or Volar)
* would otherwise have to write to bridge the sync/async APIs.
*/
const glintCore = jiti('@glint/core');

const { findConfig, createEmberLanguagePlugin } = glintCore;
const { findConfig, createEmberLanguagePlugin } = glintCore;

const cwd = info.languageServiceHost.getCurrentDirectory();
const glintConfig = findConfig(cwd);
const cwd = info.languageServiceHost.getCurrentDirectory();
const glintConfig = findConfig(cwd);

if (glintConfig && glintConfig.enableTsPlugin) {
const gtsLanguagePlugin = createEmberLanguagePlugin(glintConfig);
return {
languagePlugins: [gtsLanguagePlugin],
};
} else {
return {
languagePlugins: [],
};
}
},
);
if (glintConfig && glintConfig.enableTsPlugin) {
const gtsLanguagePlugin = createEmberLanguagePlugin(glintConfig);
return {
languagePlugins: [gtsLanguagePlugin],
};
} else {
return {
languagePlugins: [],
};
}
});

export = plugin;
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -9686,6 +9686,11 @@ jest-worker@^27.4.5:
merge-stream "^2.0.0"
supports-color "^8.0.0"

jiti@~2.4.2:
version "2.4.2"
resolved "https://registry.yarnpkg.com/jiti/-/jiti-2.4.2.tgz#d19b7732ebb6116b06e2038da74a55366faef560"
integrity sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==

js-string-escape@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/js-string-escape/-/js-string-escape-1.0.1.tgz#e2625badbc0d67c7533e9edc1068c587ae4137ef"
Expand Down

0 comments on commit a8cefd1

Please sign in to comment.