Skip to content

feat: nyc is being refactored to become the official Istanbul 1.0 bin - #286

Merged
bcoe merged 10 commits into
masterfrom
nyc-7
Jul 4, 2016
Merged

feat: nyc is being refactored to become the official Istanbul 1.0 bin#286
bcoe merged 10 commits into
masterfrom
nyc-7

Conversation

@bcoe

@bcoe bcoe commented Jun 26, 2016

Copy link
Copy Markdown
Member

This refactoring work moves nyc towards using Istanbul's more modular v1.0 API.

Features of Note

  • I've changed the messaging somewhat, announcing nyc as the official Istanbul bin.
  • We no longer call out to the istanbul bin for the feature check-coverage (calculating this is now our responsibility).
  • we no longer load .istanbul.yml, we will extend nyc's configuration gradually to support any configuration options that we're missing.
  • we now point folks towards babel-plugin-istanbul for ES6/ES7 support.
  • we no longer use the preamble function for --all functionality, using an approach closer to what istanbul's original bin used:

Breaking Changes

  • .istanbul.yaml is no longer supported.
  • removed instrumenter configuration option for the time being (I think we get pretty far with the new istanbul-lib-instrument, and a noop instrumenter, and can avoid abstracting this part of the API for the time being).
  • completely new underlying instrumentation engine.

Todo

  • test with a few libraries on Windows (windows testing went very smoothly \o/)
  • add unit tests for native ES6 code (excited to exercise the new instrumentation library).
  • create tickets for further work: porting more istanbul configuration options, switching to the istanbuljs org's source-map library, source-maps for errors?
  • get babel-plugin-istanbul@1.0.0 published.
    - [ ] get --all working with babel-plugin-istanbul. we can address this separately._
  • consolidate source-map support.

CC: @novemberborn, @jamestalmage, @dtinth, @gotwarlost

@bcoe

bcoe commented Jun 27, 2016

Copy link
Copy Markdown
Member Author

one thing I've noted, is that the final bundled nyc balloons from 3MB to 7MB. On the plus side, since it's bundled it comes down as a single .tgz file, on the other hand, it would definitely be good to try to shrink the module a little bit.

As we discussed, a good chunk of this size is in istanbul-lib-instrument:

16K append-transform
 16K    arrify
164K    caching-transform
 72K    convert-source-map
 52K    default-require-extensions
 56K    find-cache-dir
 68K    find-up
560K    foreground-child
308K    glob
108K    istanbul-lib-coverage
 57M    istanbul-lib-instrument
384K    istanbul-lib-report
5.4M    istanbul-reports
 52K    md5-hex
672K    micromatch
156K    mkdirp
 16K    pkg-up
 16K    resolve-from
 24K    rimraf
 24K    signal-exit
784K    source-map
304K    spawn-wrap
1.0M    test-exclude
1.9M    yargs

Specifically the babel tool-chain:

 12M    ./babel-generator
 12M    ./babel-template
 13M    ./babel-traverse
 12M    ./babel-types
7.8M    ./babylon

Currently we bundle nyc with an npm@2.x bin, to avoid some weird historical bugs related to singletons -- I'll try publishing a version using deduping, and see where it gets us to; perhaps we'd do better to address these long-standing singleton bugs, rather than increasing the size of the module.

@bcoe

bcoe commented Jun 27, 2016

Copy link
Copy Markdown
Member Author

package size update

If I bundle using an npm@3.x bin, the tarball size is only 2.7MB, and deduping gets the total size on disk down to about 25MB (post untar) not too shabby!

testing update

I've published the new nyc@7.x bin to the next tag, I would love help testing. If folks could run it against a few of their modules.

npm cache clear; npm i nyc@next

CC: @JaKXz, @rmg, @addaleax.

@bcoe

bcoe commented Jun 27, 2016

Copy link
Copy Markdown
Member Author

I'm seeing some issues with the ava test suite, using the new instrumentation approach:

not ok should match pattern provided
    found: >
      /Users/benjamincoe/bcoe/coverage/ava/node_modules/nyc/node_modules/babylon/lib/parser/location.js:25
        throw err;
        ^

      SyntaxError: 'return' outside of function (14:1)
          at Parser.pp.raise (/Users/benjamincoe/bcoe/coverage/ava/node_modules/nyc/node_modules/babylon/lib/parser/location.js:22:13)
          at Parser.pp.parseReturnStatement (/Users/benjamincoe/bcoe/coverage/ava/node_modules/nyc/node_modules/babylon/lib/parser/statement.js:321:10)
          at Parser.pp.parseStatement (/Users/benjamincoe/bcoe/coverage/ava/node_modules/nyc/node_modules/babylon/lib/parser/statement.js:107:19)
          at Parser.pp.parseBlockBody (/Users/benjamincoe/bcoe/coverage/ava/node_modules/nyc/node_modules/babylon/lib/parser/statement.js:529:21)
          at Parser.pp.parseBlock (/Users/benjamincoe/bcoe/coverage/ava/node_modules/nyc/node_modules/babylon/lib/parser/statement.js:510:8)
          at Parser.pp.parseStatement (/Users/benjamincoe/bcoe/coverage/ava/node_modules/nyc/node_modules/babylon/lib/parser/statement.js:127:19)
          at Parser.pp.parseIfStatement (/Users/benjamincoe/bcoe/coverage/ava/node_modules/nyc/node_modules/babylon/lib/parser/statement.js:314:26)
          at Parser.pp.parseStatement (/Users/benjamincoe/bcoe/coverage/ava/node_modules/nyc/node_modules/babylon/lib/parser/statement.js:105:19)
          at Parser.pp.parseBlockBody (/Users/benjamincoe/bcoe/coverage/ava/node_modules/nyc/node_modules/babylon/lib/parser/statement.js:529:21)
          at Parser.pp.parseTopLevel (/Users/benjamincoe/bcoe/coverage/ava/node_modules/nyc/node_modules/babylon/lib/parser/statement.js:36:8)

@jamestalmage @novemberborn any thoughts?

@jamestalmage

Copy link
Copy Markdown
Member

It looks like you probably need to enable the allowReturnOutsideFunction in babylon.

@bcoe

bcoe commented Jun 27, 2016

Copy link
Copy Markdown
Member Author

@jamestalmage just came to that conclusion myself, got tests running by removing returns in the top-level cli module, I'll go ahead and set that configuration option. great find!

Comment thread index.js
instrumented = instrumenter.instrumentSync(code, filename)
} catch (e) {
// don't fail external tests due to instrumentation bugs.
console.warn('failed to instrument', filename, 'with error:', e.message)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Any way to configure this to prevent it from logging? Could there be a scenario where this happens and cannot be easily prevented? If so, this log would be annoying/distracting noise.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

@kentcdodds my gut was annoy people while we're in the early phases of v7, get bug reports, and fix quickly -- there are a few more knobs and dials it looks like we can turn in babylon.

If you think this strategy might annoy people too much, I could definitely be convinced to drop the log message.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Let's wait until it becomes a problem I think 👍

@bcoe

bcoe commented Jun 27, 2016

Copy link
Copy Markdown
Member Author

added a test for native ES6 support, found a few interesting edge-cases but in general, things seem to be working a lot better:

screen shot 2016-06-26 at 11 16 40 pm

I could not get this to instrument:

let a = 33 || () => {
   console.log('missed')
}

CC: @gotwarlost ^ we should probably put a test around this.

@JaKXz

JaKXz commented Jun 27, 2016

Copy link
Copy Markdown
Collaborator

@bcoe just tried nyc@7.0.0-alpha3 and found some reporting errors with an ES2015 Babel project.

Interestingly, the errors look similar to what I was getting with the current instructions using the --all flag with the __coverage__ plugin. I ignored this before because of the --all flag and it's existing issues.

@gotwarlost

Copy link
Copy Markdown
Collaborator

On the subject of allowReturnsOutsideFunction, this is controlled using the instrumenter option autoWrap (false by default - which is a change from v0)

https://github.com/istanbuljs/istanbul-lib-instrument/blob/master/v0-changes.md

@gotwarlost

Copy link
Copy Markdown
Collaborator

On the es6 edge cases, this is a babylon issue:

$ cat .babelrc 
{
  "presets": ["es2015"]
}

$ ./node_modules/.bin/babel 
let a = 33 || () => {
   console.log('missed')
}
SyntaxError: unknown: Unexpected token (1:15)
> 1 | let a = 33 || () => {
    |                ^
  2 |    console.log('missed')
  3 | }
  4 | 

@gotwarlost

Copy link
Copy Markdown
Collaborator

@bcoe - great progress so far. We need to figure out - if the istanbul-cli is gone - what happens to commands needed for testing on the browser (e.g. istanbul instrument , istanbul report etc.)

@gotwarlost

Copy link
Copy Markdown
Collaborator

I think babylon is correct in its parsing and parens are needed around the second expression (need someone who knows the ES6 spec intimately to chime in). This one works:

let a = 33 || (() => {
   console.log('missed')
})

@bcoe

bcoe commented Jun 27, 2016

Copy link
Copy Markdown
Member Author
  • @JaKXz mind opening a separate issues with a reproduction case for the behavior that you're seeing?
  • @gotwarlost found the allowReturnsOutsideFunction setting and enabled it 👍, I think in nyc's case we want to be pretty loose out of the gate (we'll probably find there are a few other babylon nits we gradually address).
  • @gotwarlost embarrassingly I haven't used Istanbul too much in the browser, mind opening a ticket describing an MVP of some of the features we should consider adding:
    • we have nyc report.
    • we can add nyc instrument, which I assume instruments a file and returns the code.
  • @gotwarlost mind tossing me on babel-plugin-istanbul as an owner:
    • I'd like to mention this plugin on HackerNews, I think it will bring some attention to the Istanbul 1.0 effort.
    • once we land this, and are happy, I'd love to also write a blog post on the merger of Istanbul 1.0 + nyc.

@addaleax

Copy link
Copy Markdown
Member

Ran tests for a couple of my packages with nyc@next, looks great so far! :)

@bcoe

bcoe commented Jun 28, 2016

Copy link
Copy Markdown
Member Author

I'm a little afraid to actually drop the hammer, but:

  • I've tested thoroughly with Windows.
  • I've tested against yargs, ava, npm, and tap (found a few bugs in the process, but for the most part all these large nyc reliant libraries are working well).
  • people's smoke tests seem to be going well so far?

If folks could take one more day to hammer on this (CC: @istanbuljs/nyc) I think we'll land it.

@kentcdodds

Copy link
Copy Markdown
Member

After npm i nyc@next, I'm getting:

/Users/kdodds/Developer/paypal/p2pnodeweb/node_modules/nyc/node_modules/istanbul-reports/lib/lcovonly/index.js:32
        writer.println('FN:' + [meta.decl.start.line, meta.name].join(','));
                                         ^

TypeError: Cannot read property 'start' of undefined
    at /Users/kdodds/Developer/paypal/p2pnodeweb/node_modules/nyc/node_modules/istanbul-reports/lib/lcovonly/index.js:32:42
    at Array.forEach (native)
    at LcovOnlyReport.onDetail (/Users/kdodds/Developer/paypal/p2pnodeweb/node_modules/nyc/node_modules/istanbul-reports/lib/lcovonly/index.js:30:28)
    at LcovReport.(anonymous function) [as onDetail] (/Users/kdodds/Developer/paypal/p2pnodeweb/node_modules/nyc/node_modules/istanbul-reports/lib/lcov/index.js:21:24)
    at Visitor.(anonymous function) [as onDetail] (/Users/kdodds/Developer/paypal/p2pnodeweb/node_modules/nyc/node_modules/istanbul-lib-report/lib/tree.js:34:30)
    at ReportNode.Node.visit (/Users/kdodds/Developer/paypal/p2pnodeweb/node_modules/nyc/node_modules/istanbul-lib-report/lib/tree.js:123:17)
    at /Users/kdodds/Developer/paypal/p2pnodeweb/node_modules/nyc/node_modules/istanbul-lib-report/lib/tree.js:116:23
    at Array.forEach (native)
    at visitChildren (/Users/kdodds/Developer/paypal/p2pnodeweb/node_modules/nyc/node_modules/istanbul-lib-report/lib/tree.js:115:32)
    at ReportNode.Node.visit (/Users/kdodds/Developer/paypal/p2pnodeweb/node_modules/nyc/node_modules/istanbul-lib-report/lib/tree.js:126:5)

Works fine with latest.

@bcoe

bcoe commented Jun 29, 2016

Copy link
Copy Markdown
Member Author

@kentcdodds don't suppose you might be able to make a reproduction case, and tack it onto an issue? I'm holding off on merging this until we address a couple similar issues that have cropped up.

@gotwarlost saw some patches landing regarding crashers/performance. Just let me know any code reviews/implementation work you need done.

@kentcdodds

Copy link
Copy Markdown
Member

I believe my issue is the same that @JaKXz reported in #288

@gotwarlost

Copy link
Copy Markdown
Collaborator

istanbul v1 now adds a new location called decl in the fnMap metadata to track the range for function declarations. This is being lost here: https://github.com/istanbuljs/nyc/blob/master/lib/source-map-cache.js#L123-L147

That's the reason the lcov report is failing. Note that this new location info also needs to be mapped when source maps are in play.

@bcoe

bcoe commented Jun 29, 2016

Copy link
Copy Markdown
Member Author

@gotwarlost would retiring nyc's sourcemap handling for istanbul's solve this issue?

@gotwarlost

Copy link
Copy Markdown
Collaborator

possibly. We need to compare if there is any difference in processing between the two.

@bcoe

bcoe commented Jul 2, 2016

Copy link
Copy Markdown
Member Author

@gotwarlost I pulled in istanbul-lib-source-maps and it seems to have solved the problems, there's still the weird highlighting issues (which I think you have an open issue on babel regarding). We have a few remaining things to do:

  • seems like there continues to be some performance questions with babel-plugin-istanbul.
  • I'd like to add the instrument feature to nyc so that we can support front-end better, like you requested. Mind commenting on this issue and letting me know if I'm on the right track.
  • I'd like to switch to using your better --all support (maybe this will make it easier to support --all in babel-pluglin-istanbul too?).
  • it would be nice to dig into merging istanbul-lib-hook, and append-transform's functionality, as it relates to nyc.

Other than that, I think we're pretty on track for landing this?

@gotwarlost

Copy link
Copy Markdown
Collaborator

Re: my "better --all" support, I'm having second thoughts about this. It may not be "better" :)

Problem is the babel cache. If we process a file for side-effects only then only the preamble gets written to the babel cache because we basically nuke the real code, which is going to have all sorts of fun implications when the user goes about exercising that code later and "nothing works".

If the caching were smarter to allow inclusion of the extra parameters in the cache key, it would be fine but previous comments seemed to indicate that the caching in babel is naive.

@jamestalmage

Copy link
Copy Markdown
Member

I have been poking around in the babel code recently. I think the cache only applies to babel-register. You can still parse any code using babel-core without impacting the cache.

@gotwarlost

Copy link
Copy Markdown
Collaborator

@jamestalmage - when the babel plugin is used, it does not control any babel-specific options (the library API will not have issues since we use babylon and babel-generate as libraries). I'm not sure what will happen to the cache when babel-plugin-istanbul is used.

@gotwarlost

gotwarlost commented Jul 10, 2016

Copy link
Copy Markdown
Collaborator

Although if we are disabling the babel cache in nyc this might work. Just not sure how we plan to implement the --all processing when the babel plugin is used.

@alexjeffburke

Copy link
Copy Markdown

Hey, if this has been previously mentioned apologies - I had a project recently where I wanted to use nyc but ended up at the older istanbul bin primary for the ability to run coverage to a JSON file and then run istanbul report after the fact. This was for a node lib that had been packaged for the browser with browserify - I found that command pair immensely useful to get browser coverage over the library. I think I also used the browserify-istanbul transform. Just mentioning in case you needed someone to speak up for the use case. And lastly, hank you ever so much for tools. AJB

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

Successfully merging this pull request may close these issues.

Implement --all without requiring modules

7 participants