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

Cannot read property 'substr' of undefined #247

Closed
kaiza opened this issue Oct 18, 2016 · 26 comments
Closed

Cannot read property 'substr' of undefined #247

kaiza opened this issue Oct 18, 2016 · 26 comments
Assignees

Comments

@kaiza
Copy link

kaiza commented Oct 18, 2016

TypeError: Cannot read property 'substr' of undefined
at Function. (...\node_modules\webpack-sources\node_modules\source-map\lib\source-node.js:115:26)

Version: 0.5.6

This problem seems to be related to trying to parse a js file containing a long //# sourceMappingURL at the end. For example, by trying to use the typemoq library in an Angular 2 application, as per this SO issue:

http://stackoverflow.com/questions/40002699/typemoq-and-angular-cli-dont-work-together#comment67466029_40002699

If I delete the //# sourceMappingURL line from typemoq.js the source node loads fine.

@morrisonbrett
Copy link

I'm seeing this same error here: https://github.com/mozilla/source-map/blob/master/lib/source-node.js#L95

For me, I can reproduce in an Angular 2 TypeScript file:

THIS breaks:

@Component({
  selector: 'tab-bar',
  templateUrl: 'tabs.html'
})

THIS works:

@Component({selector: 'tab-bar',templateUrl: 'tabs.html'})

@jackytse
Copy link

jackytse commented Mar 1, 2017

Don't write two or more classes in the same ts file. I think it's a bug of 'source-map'.

@ScallyGames
Copy link

Manually applying this patch resolves this issue.
http://stackoverflow.com/a/41923610/4068027

@edmondtm
Copy link

edmondtm commented Jun 4, 2017

Not only in Ionic-app. I also have the error on my Angular 4 app. When I run ng serve.

92% chunk asset optimization pathtofile/node_modules/source-map/lib/source-node.js:95
          var code = nextLine.substr(0, mapping.generatedColumn -
                             `^`

TypeError: Cannot read property 'substr' of undefined
    at Function.<anonymous> (pathtofile/node_modules/source-map/lib/source-node.js:95:30)
    at Array.forEach (native)
    at BasicSourceMapConsumer.SourceMapConsumer_eachMapping [as eachMapping] (/pathtofile/node_modules/source-map/lib/source-map-consumer.js:155:14)
    at Function.SourceNode_fromStringWithSourceMap [as fromStringWithSourceMap] (/pathtofile/node_modules/source-map/lib/source-node.js:80:24)

@tromey
Copy link
Contributor

tromey commented Jun 5, 2017

There's a patch you can try - see #257. Before merging it, though, I'd like a regression test, and I still don't know how to write one. If you have a recipe for reproducing (the simpler the better, and for best results really walk me through the setup), that would be super helpful.

@david-hollifield
Copy link

I can reproduce using the project angular-cache. If I try import "angular-cache" with devtool: "source-map" you'll get this error every time.

image

@sxcooler
Copy link

Got same error with Preact-based project.

@lahdekorpi
Copy link

Isn't two or more classes in one ts-file valid?

@ivanfretes
Copy link

The fit of the issue is very simple, create other file exclusively your class! (e.g modal-item.ts)

@ganemone
Copy link

The issue is not limited to typescript definitions. You can reproduce not using typescript with [email protected] and webpack.

@tromey
Copy link
Contributor

tromey commented Jul 20, 2017

What would help move this along is a way for me to reproduce it. The more canned the instructions, the better. Then I can try to reduce it to a test case.

@ganemone
Copy link

I created a repo that has a fairly simple reproduction of this issue:

https://github.com/ganemone/source-map-bug-reproduce

@filipesilva
Copy link

filipesilva commented Aug 4, 2017

Heya,

I've been digging into the error a bit more and I'm not sure that it's as easy as just applying #257 to fix it. Applying that fix can hide broken sourcemaps.

In my case it came up when chaining sourcemaps, and having the error was a sign the sourcemap I was creating was incorrect.

An easy way to check this is to incorrectly chain maps. If you have original.ts->transpile-1.js->transpile-2.js, you want to chain transpile-2.js.map into transpile-1.js.map to get the source back to original.ts.

But you can just as easily chain transpile-1.js.map into transpile-2.js.map and that will get a sourcemap that only errors out later with the substr error.

I've prepared a simple reproduction of this. It doesn't include webpack or anything of the sort, just using the source-map package APIs.

git clone https://github.com/filipesilva/sourcemap-debug
cd sourcemap-debug
npm i
npm test

Read through test.js to see what's happening and instructions on how to visualize the sourcemaps.

This repro also includes a version of http://sokra.github.io/source-map-visualization/ that was patched with #257 so you can visualize how the generated map doesn't look right.

/cc @hansl

@jasonLaster
Copy link

Thanks @filipesilva

@tromey tromey self-assigned this Aug 4, 2017
@tromey
Copy link
Contributor

tromey commented Aug 4, 2017

Yes, thanks very much.

@tromey
Copy link
Contributor

tromey commented Aug 7, 2017

@filipesilva IIUC this test case is creating an invalid chaining. My inclination is to say that in this situation, it's fine to yield a bad result. I suppose it would be better (if possible -- I have no idea) to throw an exception when creating the bad map rather than when reading it.

@ganemone I looked at your example. Thank you. I'm still digging into this; but a simple test case loading preact's preact.esm.js.map shows the failure. So the next question is whether this map file is actually incorrect and, if so, what is creating it.

@tromey
Copy link
Contributor

tromey commented Aug 7, 2017

preact.esm.js.map claims there is a mapping:

{ source: '../src/preact.js',
  generatedLine: 965,
  generatedColumn: 21,
  originalLine: 8,
  originalColumn: 15,
  name: undefined }

... but preact.esm.js only has 964 lines. So, that definitely seems invalid to me.

@hansl
Copy link

hansl commented Aug 7, 2017

@tromey throwing a meaningful exception here would be fine with us. Alternatively, allowing a flag that silence the error would also be great. We could surround the sourcemaps handling into a try block, but that just means that we have to drop sourcemaps entirely. I'd say partial sourcemaps are better than no sourcemaps? This can be argued both ways.

We have had people publishing invalid sourcemaps to npm that cannot be chained properly, so it's not just our code.

@tromey
Copy link
Contributor

tromey commented Aug 7, 2017

Applying the propose || "" patch shows that there are several more invalid mappings after that one.

@tromey
Copy link
Contributor

tromey commented Aug 7, 2017

Changing preact to use a newer version of rollup fixed the preact source map.

@tromey
Copy link
Contributor

tromey commented Aug 7, 2017

@hansl I'm curious to know when you'd want to silently accept an invalid source map.

I'm working on source map support in the Firefox DevTools. My first reaction is to just change the error message to be better. My reasoning is that, for DevTools users, showing an error message is somewhat actionable, whereas using an invalid source map is likely to yield weird behavior (sometimes, maybe not always -- but that seems worse) without any explanation. I wish there was a way to make the checking even more strict, like having some kind of hash that so that source/map mismatches could be immediately seen.

@hansl
Copy link

hansl commented Aug 7, 2017

If the user can derive information from it, even a partial sourcemap can be useful for, e.g. sourcemap visualization tools. Let's say you have 3 sources, A, B and C, created by 2 transformations. Assuming the A => B transform outputted an invalid sourcemap, with some symbols outside the length of B. Should the tool doing the transform B => C; (a) not output a sourcemap, (b) output a sourcemap from B to C without, or (c) ignore the out-of-scope symbols and multiply its B => C sourcemap with only the valid parts of A => B? (c) can be surprising for a user but can still have partial information which is useful, but (a) and (b) are entirely useless. Am I missing something?

BTW, I'm in favor of a "validation" function that can tell us in advance if a sourcemap is valid or not without applying it. I understand this is not necessarily complicated to code, but if it was part of this library would at least make it authoritative.

I'm not arguing for ignoring the invalid symbols. I feel the issue here is that working with sourcemaps is complicated and there should be better tooling in place to help those libraries release proper working sourcemaps in the first place. But that's outside of this particular issue (and may just be a question of better documentation/educating developers instead of a technical solution).

@tromey
Copy link
Contributor

tromey commented Aug 8, 2017

Am I missing something?

I wouldn't say that; just that if the source map is in valid, there's no reason to believe any of it is any good. So instead of helping the user, maybe what's happening is just utter confusion and wasted time. That's why I tend to think tools should give users error messages instead of just carrying on.

But I get what you're saying. The situation isn't always that dire. And sometimes tools are broken. So maybe I will add a bypass.

@hansl
Copy link

hansl commented Aug 8, 2017

It's up to you really. We'll communicate to the user that some maps are missing (there'll be empty sourcemaps, basically :/ )

@filipesilva
Copy link

I second @hansl's suggestion of a validation function. It would be great to have a validator that we could add to our unit/e2e tests.

I tried searching for such a thing and couldn't find anything besides https://github.com/ben-ng/sourcemap-validator which didn't seem to work. Perhaps I searched in the wrong places?

It's important to define what a valid sourcemap is though. Some sourcemaps might be missing things (like @hansl's example) but others are just completely broken (like in the invalid chaining). I don't think these are the same from a usage point of view.

With that in mind I think partial sourcemaps still have an use, while completely broken ones serve no purpose.

No idea if it's possible to actually make this distinction though.

@tromey
Copy link
Contributor

tromey commented Sep 27, 2017

I'm going to relent on this and check in a patch. I'd merge one of the PRs but while I like the approach of #257, it has a conflict; but I'd prefer that style rather than #268.

tromey added a commit to tromey/source-map that referenced this issue Sep 27, 2017
Avoid calling substr on `undefined` in `fromStringWithSourceMap`.
This can happen when passing in a source map that refers to lines past
the end of the passed-in string -- caller error, but let's not die.
Fixes mozilla#247
tromey added a commit to tromey/source-map that referenced this issue Sep 27, 2017
Avoid calling substr on `undefined` in `fromStringWithSourceMap`.
This can happen when passing in a source map that refers to lines past
the end of the passed-in string -- caller error, but let's not die.
Fixes mozilla#247
tromey added a commit to tromey/source-map that referenced this issue Sep 27, 2017
Avoid calling substr on `undefined` in `fromStringWithSourceMap`.
This can happen when passing in a source map that refers to lines past
the end of the passed-in string -- caller error, but let's not die.
Fixes mozilla#247
mattdsteele added a commit to mattdsteele/webpack-sources that referenced this issue Oct 2, 2017
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

No branches or pull requests