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

Use separate module system to properly handle errors #111

Merged
merged 5 commits into from Sep 21, 2017

Conversation

zamotany
Copy link
Contributor

@zamotany zamotany commented Sep 15, 2017

Few notes

Related to #81

Things done in this PR

  • Custom module system with separate cache
    • Full control over transpilation, no need for babel-register
    • No babel-register leakage to main module system
  • Proper errors from source maps
    screen shot 2017-09-15 at 10 27 18
  • Moved some tests to __integration-tests__

Things to do

  • mock native module module in module system 😛
  • unit tests for preval-extract modules
  • unit tests for babel/lib modules
  • more options for transpilation exposed in linaria preset (in follow-up PR)
  • integration test optimization (in follow-up PR)
  • calculate column name for styles correctly (in follow-up PR)
  • squash commits

@zamotany zamotany added the status: in progress 🚧 Someone is working on the issue label Sep 15, 2017
@codecov
Copy link

codecov bot commented Sep 15, 2017

Codecov Report

Merging #111 into master will increase coverage by 0.77%.
The diff coverage is 100%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #111      +/-   ##
==========================================
+ Coverage   96.87%   97.65%   +0.77%     
==========================================
  Files          15       18       +3     
  Lines         256      341      +85     
  Branches       49       59      +10     
==========================================
+ Hits          248      333      +85     
  Misses          8        8
Impacted Files Coverage Δ
src/babel/preval-extract/resolveSource.js 100% <100%> (ø) ⬆️
src/babel/preval-extract/getReplacement.js 100% <100%> (ø)
src/babel/preval-extract/prevalStyles.js 100% <100%> (ø)
src/babel/lib/errorUtils.js 100% <100%> (ø)
src/babel/preval-extract/index.js 100% <100%> (ø) ⬆️
src/babel/preval-extract/validators.js 100% <100%> (ø) ⬆️
src/babel/preval-extract/extractStyles.js 100% <100%> (ø) ⬆️
src/babel/lib/moduleSystem.js 100% <100%> (ø)
... and 2 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 08b6425...09dd8f0. Read the comment docs.

> 4 | width: \${document.width};
| ^
5 | \`;
at File.buildCodeFrameError (<<REPLACED>>/node_modules/babel-core/lib/transformation/file/index.js:427:15)
Copy link
Member

Choose a reason for hiding this comment

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

This stacktrace seems confusing

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This stacktrace is negligible here. Could not find a reference to error is thrown even before evaluating, also this error is from previous PR.

pluginOptions: any = { cache: false, extract: false },
babelOptions: any = { filename: 'test.js' }
) {
const PATH_TO_TRANSPILE_BIN = path.join(__dirname, './transpile.js');
Copy link
Member

Choose a reason for hiding this comment

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

nit: don't need the ./

const filenames = [];

fs.writeFileSync = (filename, data, opts) => {
if (/\.css$/.test(filename)) {
Copy link
Member

Choose a reason for hiding this comment

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

A comment will be nice to tell what's going on here

@zamotany zamotany changed the title Use separate module system and properly handle errors Use separate module system to properly handle errors Sep 19, 2017
@callstack callstack deleted a comment from satya164 Sep 19, 2017
@zamotany zamotany removed the status: in progress 🚧 Someone is working on the issue label Sep 20, 2017
Copy link
Member

@thymikee thymikee left a comment

Choose a reason for hiding this comment

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

Left some small comments, but generally looks good. Now it makes sense why we need our own module mock for prevaled stuff, stellar work 👍

expect.addSnapshotSerializer({
test: val => val && val.toString && val.toString().includes(process.cwd()),
serialize,
print: serialize,
Copy link
Member

Choose a reason for hiding this comment

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

you should use either serialize or print, both are not necessary.

font-size: 3em;
\`;
`);
expect(code.includes('font-size: 3em;')).toBeTruthy();
Copy link
Member

Choose a reason for hiding this comment

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

You can use toMatch, also snapshot is usually not needed when you're matching strings (you're already testing the transpiled output in other places).

expect(code).toMatch('font-size: 3em;')

`);
} catch (error) {
expect(stripAnsi(error.toString())).toMatch(/> 10 \| {5}throw new Error/);
expect(error).toMatchSnapshot();
Copy link
Member

Choose a reason for hiding this comment

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

Either snapshot or toMatch.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

why not both?

Copy link
Member

Choose a reason for hiding this comment

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

Because it's just redundant

codeWithSlugFromFilename
);

expect(classnameWithSlugFromContent).not.toBeNull();
Copy link
Member

Choose a reason for hiding this comment

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

RegExp.test is faster than exec and returns a boolean, also global flag is not needed.

expect(/header = '(header__[a-z0-9]+)'/.test(codeWithSlugFromContent)).toBe(true)

But I see you're already using exec everywhere, so I can live with that.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I need to use exec, test is insufficient for the test.

expect(css).toMatchSnapshot();
});

it('should preval const and let without transpilation to var', () => {
Copy link
Member

Choose a reason for hiding this comment

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

Are you actually testing that here?

expect(data).toMatchSnapshot();
});
});
});
Copy link
Member

Choose a reason for hiding this comment

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

Generally in this whole file, when you have toMatch next to toMatchSnapshot – pick one, in most cases I'd pick toMatch because it's simple and clear enough and doesn't force me to jump between files

"Error: Test message
  1 | // comment
> 2 | throw new Error(\\"test\\");
 |  ^
Copy link
Member

Choose a reason for hiding this comment

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

Can we strip these colors? I can live without them being here and it's pretty hard to read in this form.

const filename = resolveMock(moduleId);

// Native Node modules
if (filename === moduleId && !moduleId.startsWith('/')) {
Copy link
Member

Choose a reason for hiding this comment

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

How about windows?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Suggest the solution

expect(ModuleMock('file.js')).toEqual(new Module('file.js'));
const cache = ModuleMock._cache;
expect(ModuleMock._debug()).toBeUndefined();
expect(ModuleMock._preloadModules()).toBeUndefined();
Copy link
Member

@thymikee thymikee Sep 20, 2017

Choose a reason for hiding this comment

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

Things like this should be handled by Flow, just sayin'

* ==============================================
* To avoid leakage from evaled code to module cache in current context,
* for example with `babel-register` we provide our custom module system.
* It designed to mimic the native node one, with the exception being
Copy link
Member

Choose a reason for hiding this comment

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

nit: It's

@thymikee
Copy link
Member

Rebase to master and I think we're good to go. @satya164 ?

const { code } = transpile(dedent`
/* linaria-preval */
const header = css\`
font-size: {2 + 1}em;
Copy link
Member

Choose a reason for hiding this comment

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

did you mean ${2 + 1}? this syntax seems wrong?

}

export function clearModulesCache() {
Object.keys(modulesCache).forEach(moduleId => {
Copy link
Member

Choose a reason for hiding this comment

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

won't it be better just to do modulesCache = {}?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Will break references. Besides it's used only in tests.

@satya164
Copy link
Member

satya164 commented Sep 21, 2017

Is it ready? There seem to be some small comments which need to be addressed

ARE YOU READY?

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.

None yet

3 participants