lookup_char_* can fail on certain type of Typescript node types (enum, etcs)
Current bahavior
To allow optimizing binary size, SWC invokes custom transforms (for custom binary) and plugins after applying resolver, decorators, typescript::strip.
This had great impact on reducing binary size, but because of this plugin or custom transforms may accept BytePos(0), which is reserved for compiler-generated nodes, for spans of those AST nodes.
Currently, changing it to pass AST to plugin before applying decorators is considered. But if we do so the plugins which use noop_visit_mut_type!() for size optimization will be broken.
@kdy1 Thoughts on how to resolve this? it blocks coverage instrumentation for some typescript files.
Maybe we can pass the whole AST with typescript types to the plugin but then plugins using noop_visit_mut for optimization will be broken.
Maybe plugin would silently ignore these, in most cases lookup source would be needed for the real codes only. In that case the issue is lookup_char traps if it fails to lookup - which plugin does not have way to gracefully handle this at all.
this plugin or custom transforms may accept BytePos(0)
In what cases will this happen? Can plugins rely on the spans correctly mapping back to the source?
In what cases will this happen?
If plugin receives already transformed AST from prior transform / or core transforms which have dummy spans.
If plugin receives already transformed AST from prior transform
Not precisely sure what you mean by this. Below is my configuration - I only have my plugin configured, but I'm transforming typescript to JS using the built-in SWC transform. Will the spans my plugin sees map correctly back to the source that created them? It's not clear to me if the ts->js transform runs before or after my plugin - I assume before.
{
"jsc": {
"parser": {
"syntax": "typescript",
"dynamicImport": false,
"decorators": false,
"hidden": {
"jest": true
}
},
"transform": null,
"target": "es2021",
"loose": false,
"externalHelpers": false,
"experimental": {
"plugins": [
[
"<my-plugin>",
{}
]
]
}
},
"minify": true,
"sourceMaps": "inline",
"module": {
"type": "commonjs"
}
}
That is the case issue's main body describes as core transform strips out ts codes.
Thanks for the quick responses!
Ok, so just to be clear. A plugin can rely on mapping a Span to the LineCol when the Span is not at BytePos(0). In this case, the LineCol will point to the code within the original TypeScript code. This would be the expected behavior and I can't imagine it being useful any other way.
A plugin can rely on mapping a Span to the LineCol when the Span is not at BytePos(0)
Yes, that's my understanding as well.
This would be the expected behavior and I can't imagine it being useful any other way.
I'd say yes for the expected behavior, not sure being useful any other way exactly means.
Thank you - that clears things up for me.
not sure being useful any other way exactly means
Oh - I just meant that it wouldn't make sense if a non-zero Span didn't point back to source that created that node.