Skip to content

Integrate @ohm-js/wasm for faster parsing#1116

Draft
charlespwd wants to merge 2 commits intomainfrom
cp-ohm-wasm-v2
Draft

Integrate @ohm-js/wasm for faster parsing#1116
charlespwd wants to merge 2 commits intomainfrom
cp-ohm-wasm-v2

Conversation

@charlespwd
Copy link
Contributor

@charlespwd charlespwd commented Feb 3, 2026

Summary

Faster Liquid parsing via WebAssembly by integrating @ohm-js/wasm (v0.6.17) in place of ohm-js package.

Key Changes

  • ohm-wasm integration: Replaced ohm-js with @ohm-js/wasm for better perforamnce
  • Test expectation updates: Updated CST snapshots to reflect ohm-wasm output format

Technical Notes

This implementation uses v0.6.17 API patterns:

  • Closure-based toAst: Captures Ohm reference via closure instead of global access
  • ifPresent for OptNode: Handles optional nodes cleanly (e.g., node.ifPresent(n => n.toAst(Ohm)))
  • Deferred children pattern: Uses () => children.map(...) for lazy AST construction

Performance

before after
before faster

About 3s faster on theme-check vs dawn.

Note

This builds on top of the browser test infrastructure added in PR #1112 and #1113 and @pdubroy in #1070

@charlespwd charlespwd changed the base branch from main to graphite-base/1116 February 3, 2026 19:49
@charlespwd charlespwd changed the base branch from graphite-base/1116 to cp-prettier-v3 February 3, 2026 19:49
Copy link
Contributor Author

charlespwd commented Feb 3, 2026

This stack of pull requests is managed by Graphite. Learn more about stacking.

@charlespwd charlespwd mentioned this pull request Feb 3, 2026
1 task
@charlespwd charlespwd force-pushed the cp-prettier-v3 branch 2 times, most recently from a2058e7 to 8c981ca Compare February 3, 2026 20:03
@charlespwd charlespwd force-pushed the cp-ohm-wasm-v2 branch 3 times, most recently from c5a9f07 to 3245c58 Compare February 3, 2026 20:10
Base automatically changed from cp-prettier-v3 to main February 4, 2026 14:00
charlespwd and others added 2 commits February 4, 2026 09:00
Key changes:
- Add @ohm-js/wasm dependency
- Update imports to use @ohm-js/wasm and @ohm-js/wasm/compat

Co-Authored-By: Patrick Dubroy <pdubroy@gmail.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@ohm-js/wasm v0.6.17 FailedMatchResult returns generic "Match failed at pos N"
messages instead of detailed syntax error information. getExpectedText() is
not yet implemented in the WASM version.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
matrix:
os: [windows-latest, ubuntu-latest]
node-version: [18, 20]
node-version: [20]
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Had to drop node 18 support (dead) because of ESM support in 20+.

expect(offenses).to.have.length(1);
expect(offenses[0].message).to.equal(`SyntaxError: expected ">", not """`);
// Note: @ohm-js/wasm returns generic error messages; getExpectedText() is not implemented
expect(offenses[0].message).to.equal(`Match failed at pos 21`);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That diff is probably the only reason we can't merge this right now. Match failed at pos 21 won't make any sense to an end user.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has been resolved in the latest published version (0.7.5).

@charlespwd charlespwd changed the title Integrate @ohm-js/wasm for browser-compatible parsing Integrate @ohm-js/wasm for faster parsing Feb 4, 2026
Copy link

@pdubroy pdubroy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, this helped me recognize a number of issues that I still had. They're mostly fixed now.

Error messages

Error messages are now consistent with the JS version, although the order may differ: e.g., the Wasm version can say "c", "b", or "a" where the JS version says "a", "b", or "c". Let me know if you think that will be a problem.

I tried reverting your commit that changed the expectations for error messages — they all pass now, except for two. One is just an ordering issue. For the other one, it looks like you have some code which reformats the original Ohm error, and the regex isn't correctly parsing the Ohm message, so some information gets dropped. (Ohm's original error message in the Wasm version is equal to the JS version, modulo ordering.)

using

Even though I intended to support the using keyword (in addition to the use() method for environments that don't yet support using), there was an issue with my implementation. It looks like Claude tried to work around that with the whole "deferred children" mechanism. I've fixed the issue, so we shouldn't need any of that anymore.

process

Fixed up the usage so Webpack should no longer complain.

"type-check": "tsc --noEmit"
},
"dependencies": {
"@ohm-js/wasm": "^0.6.17",
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"@ohm-js/wasm": "^0.6.17",
"@ohm-js/wasm": "^0.7.5",

expect(offenses).to.have.length(1);
expect(offenses[0].message).to.equal(`SyntaxError: expected ">", not """`);
// Note: @ohm-js/wasm returns generic error messages; getExpectedText() is not implemented
expect(offenses[0].message).to.equal(`Match failed at pos 21`);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has been resolved in the latest published version (0.7.5).

Comment on lines +74 to +75
// @ohm-js/wasm checks this at runtime; define it to avoid "process is not defined" errors
'process.env.OHM_DEBUG': JSON.stringify(false),
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// @ohm-js/wasm checks this at runtime; define it to avoid "process is not defined" errors
'process.env.OHM_DEBUG': JSON.stringify(false),

Should be fixed in 0.7.5.

Comment on lines +132 to +133
// @ohm-js/wasm checks this at runtime; define it to avoid "process is not defined" errors
'process.env.OHM_DEBUG': JSON.stringify(false),
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// @ohm-js/wasm checks this at runtime; define it to avoid "process is not defined" errors
'process.env.OHM_DEBUG': JSON.stringify(false),

Comment on lines +169 to +170
// @ohm-js/wasm checks this at runtime; define it to avoid "process is not defined" errors
'process.env.OHM_DEBUG': JSON.stringify(false),
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// @ohm-js/wasm checks this at runtime; define it to avoid "process is not defined" errors
'process.env.OHM_DEBUG': JSON.stringify(false),

Comment on lines +73 to +74
// @ohm-js/wasm checks this at runtime; define it to avoid "process is not defined" errors
'process.env.OHM_DEBUG': JSON.stringify(false),
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// @ohm-js/wasm checks this at runtime; define it to avoid "process is not defined" errors
'process.env.OHM_DEBUG': JSON.stringify(false),

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants