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

avoid to change original options (.acorn) object #3051

Merged
merged 29 commits into from Aug 14, 2019
Merged

avoid to change original options (.acorn) object #3051

merged 29 commits into from Aug 14, 2019

Conversation

LongTengDao
Copy link
Contributor

@LongTengDao LongTengDao commented Aug 12, 2019

This PR contains:

  • bugfix
  • feature
  • refactor
  • documentation
  • other

Are tests included?

  • yes (bugfixes and features will not be merged without tests)
  • no

Breaking Changes?

  • yes (breaking changes will not be merged unless absolutely necessary)
  • no

List any relevant issue numbers: #3050

Description

I'm not sure how to test the side effects between multi bundling:

const acorn = {};

rollup({
  input: 'main.js',
  acorn,
  experimentalTopLevelAwait: true,
}).then(()=>{
  console.log(acorn.allowAwaitOutsideFunction);// true, then rollup below will work incorrectly
  rollup({
    input: 'main.js',
    acorn,
    experimentalTopLevelAwait: false,
  });
});

@codecov
Copy link

codecov bot commented Aug 12, 2019

Codecov Report

Merging #3051 into master will not change coverage.
The diff coverage is 100%.

Impacted file tree graph

@@           Coverage Diff           @@
##           master    #3051   +/-   ##
=======================================
  Coverage   88.73%   88.73%           
=======================================
  Files         165      165           
  Lines        5733     5733           
  Branches     1748     1748           
=======================================
  Hits         5087     5087           
  Misses        388      388           
  Partials      258      258
Impacted Files Coverage Δ
src/Graph.ts 92.98% <100%> (ø) ⬆️

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 2593b04...3e13819. Read the comment docs.

Copy link
Contributor

@shellscape shellscape left a comment

Choose a reason for hiding this comment

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

Thanks much for the extra info in #3050.

@LongTengDao LongTengDao changed the title avoid to change input option object avoid to change original input option object Aug 13, 2019
@LongTengDao LongTengDao changed the title avoid to change original input option object avoid to change original options.acorn object Aug 13, 2019
Copy link
Member

@lukastaegert lukastaegert left a comment

Choose a reason for hiding this comment

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

I think it would be cool to have a general test that makes sure we do not mutate options. I would recommend to add a test to the misc/misc.js test file as the other sample based tests to some magic that may pollute the results.

If you look at the other tests in this file, you'll see it is rather straightforward. Maybe you could store the options in a variable and after the test do a deep equal with the options (and make sure the test is red without your modification). If you have more questions, just ask.

@LongTengDao
Copy link
Contributor Author

LongTengDao commented Aug 13, 2019

@lukastaegert I added a simple test. I tried to do a general test, but I actually detected several changes of options in rollup, and I don't understand rollup enough to accomplish this huge task in this PR.


delete rawInputOptions.cache;

(Directly remove this line will cause checks fail, I can't figure why.)


plugin.name = `${ANONYMOUS_PLUGIN_PREFIX}${pluginIndex + 1}`;

(Maybe replace all plugin.name in the source to plugin.name || weakMap.get(plugin)?)

experimentalTopLevelAwait: true,
});
});

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 making this test a little deeper by doing it like this:

	it('throw modification of options.acorn', () => {
		const plugins = [ loader({ input: `export default 0;` }) ];
		const options = {
				input: 'input',
				plugins,
				acorn: {},
				experimentalTopLevelAwait: true,
			};
		return rollup
			.rollup(options).then(() => assert.deepStrictEqual(options, {
				input: 'input',
				plugins,
				acorn: {},
				experimentalTopLevelAwait: true,
			});
	});

Or does this actually fail? That way, we would also check that other options are protected and we can easily extend the test to check more stuff.

Copy link
Member

Choose a reason for hiding this comment

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

Ok, this might have issues with the plugins, but I think it is worth a try.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The plugin returned by loader has no name field, and rollup will set a name for it. I can't remove all plugin.name modification in this PR, that's a big project. The easy way is add name in loader utils directly. Of cause, the easiest way is ignore plugin related modification.

But what I wonder is, since rollup is run in strict mode, just freeze the options, then if there is any modification to the options, an error will be thrown. Do you think there is any defect in this way?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

And assert.deepStrictEqual also can't promise no modification, if rollup set options' property value to another object (same structure), but not same object any more. Then if user had an refference to the original value object, and want to modify it, unexpected things will happen.

const acorn = { ecmaVersion: 6 };
const options = { acorn };
await rollup(options);// suppose rollup set options.acorn = Object.assign({}, options.acorn);
acorn.ecmaVersion = 7;
await rollup(options);// works unexpected

Copy link
Member

Choose a reason for hiding this comment

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

just freeze the options, then if there is any modification to the options

You a re right, the thing with Object.freeze is that it only does a shallow freeze but not a "deep" freeze. Which is ok for this specific issue but would not work for checking the whole options object. But as you said since we are mutating plugins anyway, let's stick with what we have.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hi, you maybe miss my second message ;)

And assert.deepStrictEqual also can't promise no modification, if rollup set options' property value to another object (same structure), but not same object any more. Then if user had an refference to the original value object, and want to modify it, unexpected things will happen.

const acorn = { ecmaVersion: 6 };
const options = { acorn };
await rollup(options);// suppose rollup set options.acorn = Object.assign({}, options.acorn);
acorn.ecmaVersion = 7;
await rollup(options);// works unexpected

assert.deepStrictEqual won't be perfect in modification checking.

And I already add Object.freeze to all non-primitive value to achieve the purpose that checking the whole options object in the latest changes.

And, rollup do modification to the options currenctly infact (add plugin.name and delete options.cache), we can't check them before we adapt all of them. I added two comments in the test too, so as to check the in the future.

Copy link
Member

Choose a reason for hiding this comment

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

I read it and agreed, sorry, there is a lot going on here.

Copy link
Member

@lukastaegert lukastaegert left a comment

Choose a reason for hiding this comment

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

I think this is good to be merged

@LongTengDao LongTengDao changed the title avoid to change original options.acorn object avoid to change original options (.acorn) object Aug 14, 2019
@lukastaegert lukastaegert merged commit 4f1d004 into rollup:master Aug 14, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants