Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: improve source code location metadata accuracy #8362

Closed
wants to merge 25 commits into from

Conversation

dominikg
Copy link
Member

@dominikg dominikg commented Mar 8, 2023

by accounting for preprocessor sourcemap and one based counting

fixes #8360

Before submitting the PR, please make sure you do the following

  • It's really useful if your PR references an issue where it is discussed ahead of time. In many cases, features are absent for a reason. For large changes, please create an RFC: https://github.com/sveltejs/rfcs
  • Prefix your PR title with feat:, fix:, chore:, or docs:.
  • This message body should clearly illustrate what problems it solves.
  • Ideally, include a test that fails without this PR but passes with it.

Tests

  • Run the tests with npm test and lint the project with npm run lint

… preprocessor sourcemap and one based counting
if (tracer) {
location = originalPositionFor(tracer, location);
}
location.line += 1; // make line one based
Copy link
Member Author

Choose a reason for hiding this comment

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

is this really just zero based vs one based or another cause?

Copy link
Member

Choose a reason for hiding this comment

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

I'm wondering why this all still works the same, since you're always adding +1 to the line, regardless of a source map existing or not.

Copy link
Member

Choose a reason for hiding this comment

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

you're already adding 1 above: https://github.com/sveltejs/svelte/pull/8362/files#r1135771594

so I think this is really adding 2 which seems wrong to me

Copy link
Member Author

Choose a reason for hiding this comment

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

in a locally linked vite project with sveltekit-ts it produces correct positions in __svelte_meta.

I agree that this looks off and so far havn't been able to understand why it produces the correct result.

@@ -11,14 +11,14 @@ export default {

assert.deepEqual(h1.__svelte_meta.loc, {
file: path.relative(process.cwd(), path.resolve(__dirname, 'main.svelte')),
line: 4,
line: 5,
Copy link
Member Author

Choose a reason for hiding this comment

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

looking at main.svelte, the h1 sits at line 5, not line 4

Copy link
Member

Choose a reason for hiding this comment

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

I've reverted these changes since it seems like there's some other bug that was present previously. Perhaps something like Rich-Harris/magic-string#248 which was causing some of our other source map tests to assert unexpected behavior

column: 0,
char: 53
});

assert.deepEqual(p.__svelte_meta.loc, {
file: path.relative(process.cwd(), path.resolve(__dirname, 'Foo.svelte')),
line: 1,
line: 2,
Copy link
Member Author

@dominikg dominikg Mar 8, 2023

Choose a reason for hiding this comment

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

same for the p, the previous combination of line 1, col 1 and char 7 would require cramming 6 chars at col 0.

@vercel
Copy link

vercel bot commented Mar 8, 2023

@dominikg is attempting to deploy a commit to the Svelte Team on Vercel.

A member of the Team first needs to authorize it.

@dominikg
Copy link
Member Author

dominikg commented Mar 9, 2023

The type error happening in CI is caused by trace-mapping not having a valid "types" reference in package.json and the typescript version svelte uses doesn't understand exports map yet.

src/compiler/compile/Component.ts:1:47 - error TS2307: Cannot find module '@jridgewell/trace-mapping' or its corresponding type declarations.

1 import { TraceMap, originalPositionFor } from '@jridgewell/trace-mapping';

given this and the fact that changing line output to be one based could be considered a breaking change i'd suggest to only add this with svelte 4, where we can update typescript and make it a breaking change, even if only relevant for some tooling during dev.

@dummdidumm
Copy link
Member

That's strange, that packages does have type definitions both through top level typings as well as in exports through types. Is this the Rollup plugin somehow messing up?

@dominikg
Copy link
Member Author

dominikg commented Mar 9, 2023

see my PR i sent them, it should be "types" in top level package.json, not "typings"

@dominikg
Copy link
Member Author

looks like typescript doesn't ignore missing types with @ts-expect-error, tried @ts-ignore locally too.
If we wanted to merge this in svelte3, i guess we'd have to add fake type locally.

@dummdidumm dummdidumm added this to the 4.x milestone Apr 3, 2023
@benmccann benmccann changed the base branch from master to version-4 April 11, 2023 20:50
benmccann and others added 10 commits April 12, 2023 09:01
- upgrade to TypeScript 5
- upgrade @ampproject/remapping
- remove obsolete workarounds

---------

Co-authored-by: Simon Holthausen <[email protected]>
bump to rollup 3. Includes reworking the "treat those imports as external" a bit so that Rollup builds correctly but doesn't bundle some of the (now relative) imports

---------

Co-authored-by: Simon Holthausen <[email protected]>
@benmccann
Copy link
Member

I've gotten this down to a single failing test:

  1) sourcemaps
       sourcemap-basename:

      AssertionError [ERR_ASSERTION]: js.map.sources is wrong
      + expected - actual

       [
      -  "external_code.css"
      +  "input.svelte"
       ]

I'm not sure why that's failing, but it does seem wrong to me that it's returning a .css file for js.map.sources

@naturalethic
Copy link

This should also properly calculate the character position ({ loc: { char } }). In my testing, it is not.

@benmccann benmccann removed this from the 4.x milestone Jun 19, 2023
@benmccann benmccann deleted the branch sveltejs:master June 20, 2023 20:45
@benmccann benmccann closed this Jun 20, 2023
@benmccann benmccann reopened this Jun 20, 2023
@benmccann benmccann changed the base branch from version-4 to master June 20, 2023 20:54
Copy link
Member

@dummdidumm dummdidumm left a comment

Choose a reason for hiding this comment

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

The test failure comes from some sources not showing up when they should, I think this has to do with how remapping handles mapping. I'm not sure if this is related to this issue or if we're doing something wrong or if the tests need adjustment.

Edit: After more digging I'm somewhat sure this may be a bug in our implementation. It happens when combining two source maps. The first one is the JS map which points to the original Svelte positions already, the second one is from the Svelte map after preprocessing pointing to the original Svelte positions. Now remapping traces from the JS map the what's supposed to be original Svelte position to a CSS position because that's what it finds in the Svelte map at that position. So either the JS map needs to skip the preprocess map, or the JS map needs to point to the preprocessed Svelte version.

Edit 2: Ok I think I found the problem - due to this code change, locator now directly points to the original Svelte version, which is good for the meta thing. But it's bad for the source map combination since that's now unnecessary. So one has to change.

line: 4,
column: 0,
char: 53
});

assert.deepEqual(p.__svelte_meta.loc, {
file: path.relative(process.cwd(), path.resolve(__dirname, 'Foo.svelte')),
// TODO: fix this. the p is on line 2
Copy link
Member

Choose a reason for hiding this comment

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

I think these tests are correct, as source maps are zero line based. There's actually code in Element/index.js where it substracts one from the returned location to account for that. Why do you think these are incorrect?

Copy link
Member

Choose a reason for hiding this comment

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

source maps are 0-based, but locator is 1-based because it gets printed out to the user and users would expect it to be 1-based:

`${warning.message} (${start.line}:${start.column})\n${frame}`

I didn't realize that this loc is different than what's in locator because I missed the -1 here:

b`@add_location(${this.var}, ${renderer.file_var}, ${loc.line - 1}, ${loc.column}, ${

it's pretty confusing to me to keep track of where things are 0-based and where they're 1-based. I wonder if we can use this opportunity to make it 0-based everywhere and just make it 1-based at the very last second when it's printed to a user

location = originalPositionFor(tracer, location);
// originalPositionFor returns 0-based lines?
// https://github.com/jridgewell/trace-mapping/issues/27
location.line += 1;
Copy link
Member

Choose a reason for hiding this comment

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

judging from some other code in language tools and the fact that tracemapping says it is a drop-in replacement for source-map which has line-1-based return values, this should not be done

dummdidumm added a commit that referenced this pull request Jun 21, 2023
We need to use a different method for getting the meta info because `locate` is used to help construct the source map that references the preprocessed Svelte file. If we would now add source maps to that `locate` function it would go the the original source directly which means skipping potentially intermediate source maps which we would need in other situations.

fixes #8360
closes #8362
dummdidumm added a commit that referenced this pull request Jun 22, 2023
We need to use a different method for getting the meta info because `locate` is used to help construct the source map that references the preprocessed Svelte file. If we would now add source maps to that `locate` function it would go the the original source directly which means skipping potentially intermediate source maps which we would need in other situations. Sadly we can't map the character offset because for that we would need to the original source contents which we don't have in this context.

fixes #8360
closes #8362
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
6 participants