What this is
Hexana is a binary inspector for WebAssembly modules and components. It ships as two plugins built from one parser:
- IntelliJ-platform plugin (IDEA, CLion, GoLand, RustRover, WebStorm, etc.) — https://plugins.jetbrains.com/plugin/29090-hexana
- VS Code extension and Open VSX —
marketplace.visualstudio.com/items?itemName=JetBrains.hexana-wasm, open-vsx.org/extension/JetBrains/hexana-wasm
Repo (issue tracker, not source): https://github.com/JetBrains/hexana
License: JetBrains User Agreement (proprietary, free to install)
The same Kotlin parser backs both plugins. It reads core modules and components and feeds an editor that shows section structure, type signatures, function bodies, and disassembled native code where applicable. No execution — Hexana is a viewer/analyzer, not a runtime.
Why I'm asking before sending a PR
The matrix on https://webassembly.github.io/website/features/ shows engines and toolchains, plus a tools column. Before I send a PR, I'd like to know which of these you'd prefer:
- Fit Hexana into the existing
tools column. Binary inspectors aren't quite the same shape as wasm-tools / wabt / binaryen — they observe, they don't transform — but the column is the closest existing home.
- Add a new column for IDE integrations / inspectors. Hexana, and probably any future viewer-style entries, sit between engines and toolchains. If you'd accept a new column, I'd be happy to propose a schema.
- Not a fit for this matrix. Reasonable answer; I'll close this out and won't send the PR.
If (1) or (2): here is what I'd claim per row. I've kept "partial" rows narrow and stated the specific gap in one line.
Proposed feature-support rows (keys from features.json)
| Key |
Status |
Gap, if any |
bulkMemory |
full |
— |
componentModel |
partial |
See note below. |
exceptions (legacy) |
full |
— |
exceptionsFinal |
full |
— |
extendedConst |
full |
— |
extendedNameSection |
full |
All 12 sub-sections read (module, functions, locals, labels, types, tables, memories, globals, elems, data segments, fields, tags). |
gc |
full |
All 0xFB:0x00–0x1E opcodes; rectype groups; sub-typing with final/non-final marker; struct / array / func comptype. |
memory64 |
partial |
64-bit limit flags and memidx-carrying memory ops are decoded; not separately validated against the rest of the proposal scope. |
multiValue |
partial |
Known bug: the empty block-type 0x40 is misdecoded as a reference type instead of "no type". Type-index multi-value blocks work. |
mutableGlobals |
full |
— |
referenceTypes |
full |
ref.null (with heaptype), ref.is_null, ref.func, ref.eq, ref.as_non_null, br_on_null, br_on_non_null, funcref / externref. |
relaxedSimd |
full |
Lane-select for i8/i16/i32/i64, relaxed madd/nmadd/min/max for f32x4 and f64x2, relaxed swizzle, q15-mul, dot products. |
saturatedFloatToInt |
full |
— |
signExtensions |
full |
— |
simd |
full |
Full 0xFD prefix: v128 load/store/const, shuffle, splat, extract/replace_lane, comparison, bitwise, arithmetic, conversions. |
tailCall |
full |
return_call, return_call_indirect, call_ref, return_call_ref. |
threads |
partial |
Full atomic opcode family (0xFE prefix): notify, wait32/64, fence, atomic load/store, and the rmw add/sub/and/or/xor/xchg/cmpxchg families. Shared-memory limit flag 0x03 is parsed; open-shared flag 0x02 is not. |
typedFunctionReferences |
full |
0x63 nullable and 0x64 non-null typed refs; call_ref / return_call_ref. |
compactImportSection |
none |
No dedicated handler. |
customPageSizes |
none |
No dedicated handler. |
wideArithmetic |
none |
No dedicated handler. |
branchHinting |
none |
No dedicated handler. |
stackSwitching |
none |
Opcodes in the reserved range are tolerated but not structurally decoded. |
Note on componentModel
We treat the wasm-tools encoding as ground truth rather than the CG phase number. Against that bar:
- Component preamble (
\0asm 0x0d 0x00 0x01 0x00) detected; 10 of 13 top-level section IDs fully decoded (core-instance, core-type, nested component, instance, alias, type, import, export, plus custom delegated to the core path).
- Component type model covers all 14 primitives including
error-context, plus record / variant / list / array / tuple / flags / enum / option / result / own / borrow / stream / future, sync + async function types, and resource types.
- The
canon section is a stub. Specifically: canon.lift, canon.lower, canon.resource.{new,drop,rep} are not decoded, and the WASI 0.3 async built-ins stream.{new,read,write,cancel-read,cancel-write}, future.{new,read,write,cancel-read,cancel-write}, and error-context.{new,debug-message,drop} are not decoded either.
- The component-level
start section is a stub.
- The
value section has a latent ID issue on our side (the spec uses id 12).
- The
core:module section is recorded by offset/size but the embedded core module is not yet sub-parsed through the same handler.
- The
component-type custom section — the mechanism wasm-tools component embed / cargo-component / componentize-py use to ship a WIT world inside a binary — is not yet extracted.
So partial. I'd rather under-claim and upgrade later than over-claim.
WIT support
Hexana implements the Component Model's WIT grammar as a first-class IDE language, not as plain-text tokenisation. PSI-level features: highlighting, completion, references, find-usages, rename, folding, inspections, documentation-on-hover, breadcrumbs, brace matching, and a formatter. PSI-first constructs: package (with semver), interface, world, type alias, record, variant, enum, flags, resource (opaque and with body, including constructor / static / instance methods), function types (func and async func), handle types (borrow<T> and owned), list<T> / list<T, N>, option<T>, result<T,E>, tuple<...>, future<T>, stream<T>, use, include with rename map, and @since / @unstable / @deprecated feature gates. WASI 0.2 and 0.3 standard interfaces are indexed as built-ins.
Known WIT-side gaps, for honesty: error-context as a first-class type is not in the grammar yet; async func is parsed and highlighted but does not yet have a dedicated PSI subtype or async-specific inspections; named result lists (-> (name: ty, ...)) are not yet supported; flags fields do not have per-field PSI nodes (so per-bit rename and find-usages are not available).
If a dedicated WIT row in the matrix would make sense, I'm happy to discuss what the schema should look like — probably grammar coverage plus binary component-type round-trip status.
One more note
Hexana also parses DWARF debug info embedded as a WASM custom section. It isn't on this matrix and I don't expect it to be — flagging in case it's relevant to a future addition.
Offer
Hexana's source isn't public, so I can't link per-row to file paths the way a wasm-tools PR could. If you green-light a PR (option 1 or option 2 above), I'm happy to elaborate on any row in this thread — including, where useful, building a small reproducer module that demonstrates Hexana decoding the relevant section or opcodes — so the claims are verifiable end-to-end rather than just on my word.
Thanks for maintaining this list — it's the first place I send people who ask what the standard supports today.
What this is
Hexana is a binary inspector for WebAssembly modules and components. It ships as two plugins built from one parser:
marketplace.visualstudio.com/items?itemName=JetBrains.hexana-wasm,open-vsx.org/extension/JetBrains/hexana-wasmRepo (issue tracker, not source): https://github.com/JetBrains/hexana
License: JetBrains User Agreement (proprietary, free to install)
The same Kotlin parser backs both plugins. It reads core modules and components and feeds an editor that shows section structure, type signatures, function bodies, and disassembled native code where applicable. No execution — Hexana is a viewer/analyzer, not a runtime.
Why I'm asking before sending a PR
The matrix on https://webassembly.github.io/website/features/ shows engines and toolchains, plus a
toolscolumn. Before I send a PR, I'd like to know which of these you'd prefer:toolscolumn. Binary inspectors aren't quite the same shape aswasm-tools/wabt/binaryen— they observe, they don't transform — but the column is the closest existing home.If (1) or (2): here is what I'd claim per row. I've kept "partial" rows narrow and stated the specific gap in one line.
Proposed feature-support rows (keys from
features.json)bulkMemorycomponentModelexceptions(legacy)exceptionsFinalextendedConstextendedNameSectiongc0xFB:0x00–0x1Eopcodes;rectypegroups; sub-typing with final/non-final marker; struct / array / funccomptype.memory64memidx-carrying memory ops are decoded; not separately validated against the rest of the proposal scope.multiValue0x40is misdecoded as a reference type instead of "no type". Type-index multi-value blocks work.mutableGlobalsreferenceTypesref.null(withheaptype),ref.is_null,ref.func,ref.eq,ref.as_non_null,br_on_null,br_on_non_null,funcref/externref.relaxedSimdsaturatedFloatToIntsignExtensionssimd0xFDprefix: v128 load/store/const, shuffle, splat, extract/replace_lane, comparison, bitwise, arithmetic, conversions.tailCallreturn_call,return_call_indirect,call_ref,return_call_ref.threads0xFEprefix): notify, wait32/64, fence, atomic load/store, and the rmw add/sub/and/or/xor/xchg/cmpxchg families. Shared-memory limit flag0x03is parsed; open-shared flag0x02is not.typedFunctionReferences0x63nullable and0x64non-null typed refs;call_ref/return_call_ref.compactImportSectioncustomPageSizeswideArithmeticbranchHintingstackSwitchingNote on
componentModelWe treat the wasm-tools encoding as ground truth rather than the CG phase number. Against that bar:
\0asm 0x0d 0x00 0x01 0x00) detected; 10 of 13 top-level section IDs fully decoded (core-instance, core-type, nested component, instance, alias, type, import, export, plus custom delegated to the core path).error-context, plus record / variant / list / array / tuple / flags / enum / option / result / own / borrow / stream / future, sync + async function types, and resource types.canonsection is a stub. Specifically:canon.lift,canon.lower,canon.resource.{new,drop,rep}are not decoded, and the WASI 0.3 async built-insstream.{new,read,write,cancel-read,cancel-write},future.{new,read,write,cancel-read,cancel-write}, anderror-context.{new,debug-message,drop}are not decoded either.startsection is a stub.valuesection has a latent ID issue on our side (the spec uses id12).core:modulesection is recorded by offset/size but the embedded core module is not yet sub-parsed through the same handler.component-typecustom section — the mechanismwasm-tools component embed/cargo-component/componentize-pyuse to ship a WIT world inside a binary — is not yet extracted.So
partial. I'd rather under-claim and upgrade later than over-claim.WIT support
Hexana implements the Component Model's WIT grammar as a first-class IDE language, not as plain-text tokenisation. PSI-level features: highlighting, completion, references, find-usages, rename, folding, inspections, documentation-on-hover, breadcrumbs, brace matching, and a formatter. PSI-first constructs:
package(with semver),interface,world, type alias,record,variant,enum,flags,resource(opaque and with body, including constructor / static / instance methods), function types (funcandasync func), handle types (borrow<T>and owned),list<T>/list<T, N>,option<T>,result<T,E>,tuple<...>,future<T>,stream<T>,use,includewith rename map, and@since/@unstable/@deprecatedfeature gates. WASI 0.2 and 0.3 standard interfaces are indexed as built-ins.Known WIT-side gaps, for honesty:
error-contextas a first-class type is not in the grammar yet;async funcis parsed and highlighted but does not yet have a dedicated PSI subtype or async-specific inspections; named result lists (-> (name: ty, ...)) are not yet supported; flags fields do not have per-field PSI nodes (so per-bit rename and find-usages are not available).If a dedicated WIT row in the matrix would make sense, I'm happy to discuss what the schema should look like — probably grammar coverage plus binary
component-typeround-trip status.One more note
Hexana also parses DWARF debug info embedded as a WASM custom section. It isn't on this matrix and I don't expect it to be — flagging in case it's relevant to a future addition.
Offer
Hexana's source isn't public, so I can't link per-row to file paths the way a wasm-tools PR could. If you green-light a PR (option 1 or option 2 above), I'm happy to elaborate on any row in this thread — including, where useful, building a small reproducer module that demonstrates Hexana decoding the relevant section or opcodes — so the claims are verifiable end-to-end rather than just on my word.
Thanks for maintaining this list — it's the first place I send people who ask what the standard supports today.