refactor(linter/plugins): ensure debug assertions always shaken out of release build#15946
Conversation
How to use the Graphite Merge QueueAdd either label to this PR to merge it via the merge queue:
You must have a Graphite account in order to use the merge queue. Sign up using this link. An organization admin has enabled the Graphite Merge Queue in this repository. Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue. This stack of pull requests is managed by Graphite. Learn more about stacking. |
6c71108 to
e0f471f
Compare
Pure refactor. Split up `plugins/utils.ts` into 3 files in `utils` directory. Most importantly, assertion functions are by themselves in an `asserts.ts` file. This paves the way for the next PR (#15946).
e0f471f to
df631d3
Compare
df631d3 to
13bc9e2
Compare
|
@overlookmotel do you have a repro for why this is needed? I tried the following, on the $ git diff
diff --git a/apps/oxlint/src-js/plugins/lint.ts b/apps/oxlint/src-js/plugins/lint.ts
index 70cd9f15e5..517fa4d3c7 100644
--- a/apps/oxlint/src-js/plugins/lint.ts
+++ b/apps/oxlint/src-js/plugins/lint.ts
@@ -79,6 +79,7 @@ function lintFileImpl(
ruleIds: number[],
settingsJSON: string,
) {
+ assertIsNonNull("");
// If new buffer, add it to `buffers` array. Otherwise, get existing buffer from array.
// Do this before checks below, to make sure buffer doesn't get garbage collected when not expected
// if there's an error.This yields: Only in the If we're worred about this regressing, I think it'd be better to write a plugin that executes after everythings done that checks that Edit: oh nevermind, i see if you import it in cli.ts, it still gets brought in. I think we should try speaking with the rolldown team to get this working. I think i've heard of solutions to this or other people running into the same issue |
Merge activity
|
…f release build (#15946) The `assert*` functions are no-ops in release builds, and minifier removes them as dead code. However, there's an annoyance - we have to ensure that they're only used in files which end up in the `plugins.js` chunk. If we use those assertions elsewhere (e.g. in `cli.ts`), TSDown creates a shared chunk containing them, and then minifier can't see that they can be removed, and leaves all the assertions in the output. Fix this problem by adding a plugin to TSDown for the release build which replaces `import`s from `asserts.ts` with inlined empty functions. ```ts // Original code import { assertIs, assertIsNonNull } from '../utils/asserts.ts'; ``` ```ts // After transform function assertIs() {} function assertIsNonNull() {} ``` This allows us to use the assertion functions anywhere, and minifier can always remove them as dead code.
13bc9e2 to
4ad085c
Compare
After #15946, we're now free to use `assertIsNonNull` in `cli.ts` without breaking dead code removal. So use it instead of unchecked `!` assertions. In debug build it becomes a real runtime assertion.
…f release build (#15946) The `assert*` functions are no-ops in release builds, and minifier removes them as dead code. However, there's an annoyance - we have to ensure that they're only used in files which end up in the `plugins.js` chunk. If we use those assertions elsewhere (e.g. in `cli.ts`), TSDown creates a shared chunk containing them, and then minifier can't see that they can be removed, and leaves all the assertions in the output. Fix this problem by adding a plugin to TSDown for the release build which replaces `import`s from `asserts.ts` with inlined empty functions. ```ts // Original code import { assertIs, assertIsNonNull } from '../utils/asserts.ts'; ``` ```ts // After transform function assertIs() {} function assertIsNonNull() {} ``` This allows us to use the assertion functions anywhere, and minifier can always remove them as dead code.
4ad085c to
152e5de
Compare
After #15946, we're now free to use `assertIsNonNull` in `cli.ts` without breaking dead code removal. So use it instead of unchecked `!` assertions. In debug build it becomes a real runtime assertion.
Pure refactor. Split up `plugins/utils.ts` into 3 files in `utils` directory. Most importantly, assertion functions are by themselves in an `asserts.ts` file. This paves the way for the next PR (#15946).
…f release build (#15946) The `assert*` functions are no-ops in release builds, and minifier removes them as dead code. However, there's an annoyance - we have to ensure that they're only used in files which end up in the `plugins.js` chunk. If we use those assertions elsewhere (e.g. in `cli.ts`), TSDown creates a shared chunk containing them, and then minifier can't see that they can be removed, and leaves all the assertions in the output. Fix this problem by adding a plugin to TSDown for the release build which replaces `import`s from `asserts.ts` with inlined empty functions. ```ts // Original code import { assertIs, assertIsNonNull } from '../utils/asserts.ts'; ``` ```ts // After transform function assertIs() {} function assertIsNonNull() {} ``` This allows us to use the assertion functions anywhere, and minifier can always remove them as dead code.
After #15946, we're now free to use `assertIsNonNull` in `cli.ts` without breaking dead code removal. So use it instead of unchecked `!` assertions. In debug build it becomes a real runtime assertion.
Yes, that's the idea. But in release build it's removed entirely.
I tried a few things to prevent TSDown producing a shared chunks (manual chunking options etc). But nothing worked. Looks like it's already tracked here: rolldown/rolldown#4437 |
#15946 means we can now simplify the TSDown build config. Previously we had to have 2 separate builds for `index.ts` and `cli.ts`, to avoid `assert*` functions ending up in a shared chunk, and not getting removed by minifier. Now that problem is solved, so we can switch to a single build with 2 entry points. TSDown does create a small extra chunk for its `__toESM` and `__commonJSMin` functions, but I think that's fine. Annoyingly it doesn't seem to be possible to tell TSDown to generate `.d.ts` files only for the `index.js` chunk, so have to delete this pointless files in build script. The point of all this is that `RuleTester` needs to use a ton of code from `plugins.ts`, and we wouldn't want all that code duplicated in both `index` and `plugins` chunks (especially once we're bundling TS-ESlint's parser #15861). Now that code will be shared between the two entry points in a shared chunk, not duplicated.
…15945) Pure refactor. Split up `plugins/utils.ts` into 3 files in `utils` directory. Most importantly, assertion functions are by themselves in an `asserts.ts` file. This paves the way for the next PR (oxc-project#15946).
…f release build (oxc-project#15946) The `assert*` functions are no-ops in release builds, and minifier removes them as dead code. However, there's an annoyance - we have to ensure that they're only used in files which end up in the `plugins.js` chunk. If we use those assertions elsewhere (e.g. in `cli.ts`), TSDown creates a shared chunk containing them, and then minifier can't see that they can be removed, and leaves all the assertions in the output. Fix this problem by adding a plugin to TSDown for the release build which replaces `import`s from `asserts.ts` with inlined empty functions. ```ts // Original code import { assertIs, assertIsNonNull } from '../utils/asserts.ts'; ``` ```ts // After transform function assertIs() {} function assertIsNonNull() {} ``` This allows us to use the assertion functions anywhere, and minifier can always remove them as dead code.
…ject#15947) After oxc-project#15946, we're now free to use `assertIsNonNull` in `cli.ts` without breaking dead code removal. So use it instead of unchecked `!` assertions. In debug build it becomes a real runtime assertion.
oxc-project#15946 means we can now simplify the TSDown build config. Previously we had to have 2 separate builds for `index.ts` and `cli.ts`, to avoid `assert*` functions ending up in a shared chunk, and not getting removed by minifier. Now that problem is solved, so we can switch to a single build with 2 entry points. TSDown does create a small extra chunk for its `__toESM` and `__commonJSMin` functions, but I think that's fine. Annoyingly it doesn't seem to be possible to tell TSDown to generate `.d.ts` files only for the `index.js` chunk, so have to delete this pointless files in build script. The point of all this is that `RuleTester` needs to use a ton of code from `plugins.ts`, and we wouldn't want all that code duplicated in both `index` and `plugins` chunks (especially once we're bundling TS-ESlint's parser oxc-project#15861). Now that code will be shared between the two entry points in a shared chunk, not duplicated.

The
assert*functions are no-ops in release builds, and minifier removes them as dead code.However, there's an annoyance - we have to ensure that they're only used in files which end up in the
plugins.jschunk. If we use those assertions elsewhere (e.g. incli.ts), TSDown creates a shared chunk containing them, and then minifier can't see that they can be removed, and leaves all the assertions in the output.Fix this problem by adding a plugin to TSDown for the release build which replaces
imports fromasserts.tswith inlined empty functions.This allows us to use the assertion functions anywhere, and minifier can always remove them as dead code.