swc: parseFileSync span bug
Describe the bug
same file parse twice, different output
Input code
//test.jsx
const a = 1
import { parseFileSync } from ‘@swc/core’;
const ast = parseFileSync(‘./test.jsx’, { jsx: true, syntax: ‘ecmascript’, comments: true, dynamicImport: true, decorators: true, decoratorsBeforeExport: true, script: true }) const ast1 = parseFileSync(‘./test.jsx’, { jsx: true, syntax: ‘ecmascript’, comments: true, dynamicImport: true, decorators: true, decoratorsBeforeExport: true, script: true })
console.log(JSON.stringify(ast)) console.log(‘====’) console.log(JSON.stringify(ast1))
{"type":"Module","span":{"start":0,"end":11,"ctxt":0},"body":[{"type":"VariableDeclaration","span":{"start":0,"end":11,"ctxt":0},"kind":"const","declare":false,"declarations":[{"type":"VariableDeclarator","span":{"start":6,"end":11,"ctxt":0},"id":{"type":"Identifier","span":{"start":6,"end":7,"ctxt":0},"value":"a","typeAnnotation":null,"optional":false},"init":{"type":"NumericLiteral","span":{"start":10,"end":11,"ctxt":0},"value":1},"definite":false}]}],"interpreter":null}
====
{"type":"Module","span":{"start":12,"end":23,"ctxt":0},"body":[{"type":"VariableDeclaration","span":{"start":12,"end":23,"ctxt":0},"kind":"const","declare":false,"declarations":[{"type":"VariableDeclarator","span":{"start":18,"end":23,"ctxt":0},"id":{"type":"Identifier","span":{"start":18,"end":19,"ctxt":0},"value":"a","typeAnnotation":null,"optional":false},"init":{"type":"NumericLiteral","span":{"start":22,"end":23,"ctxt":0},"value":1},"definite":false}]}],"interpreter":null}
first ast span start at 0, second start at 12
Config
{
// Please copy and paste your .swcrc file here
}
Expected behavior A clear and concise description of what you expected to happen.
Version The version of @swc/core:
“@swc/core”: “^1.2.46”,
Additional context Add any other context about the problem here.
About this issue
- Original URL
- State: open
- Created 3 years ago
- Reactions: 13
- Comments: 27 (10 by maintainers)
Commits related to this issue
- fix(swc-plugin-power-assert): store span as offset at the start of Program/Module node due to SWC issue https://github.com/swc-project/swc/issues/1366 — committed to twada/power-assert-monorepo by twada 6 months ago
- perf: better color cache with binary search - add move away from swc to roadmap because of accumalating offsets (https://github.com/swc-project/swc/issues/1366) - strict requirements for doc color in ... — committed to Yash-Singh1/stylex-vscode by Yash-Singh1 6 months ago
Here is the location of the issue.
Every time
transform_syncis called,SourceMap#new_source_fileis called and thestart_posis set.If you are using
transformSyncand transforming one file at at time, there seems to be no way to reset the start pos. Andspans use the SourceMap start pos.Can we get a config option to not set the start_pos from the end of the previous one? It should probably be the default for the public js api.
NOTE: If
let start_pos = self.next_start_pos(src.len());is set to zero on each compile, source maps actually break…theoriginalLinein the source map is always 1, and the filename is something likejsx-config-pragmaFrag.js.We’ve also at first had problems with using spans (in node/typescript). Apart from taking into account the offset as mentioned in other comments above its also important to keep in mind that the span’s
start/endrefer to byte positions and not char positions. So this was helpful in our context to get the right substrings from SWC’s spans:Hope this is helpful.
By design,just change the file name passed into the
parseFileSyncyou’ll get the same result.It’s not a bug. If you want span to start with 0, you can create new instance of Compiler, which have same apis.
I think it’s a bug
This bug is kind of deal breaker for switching to swc, In our product we need to invoke parser multiple times in the same process. Increasing span.start with each invocation will make swc stopped working at some point – especially when parsing huge file.