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

Option to remove "use strict"; #128

Closed
dcourtois opened this issue Feb 18, 2013 · 16 comments · May be fixed by eth-sri/UnuglifyJS#4
Closed

Option to remove "use strict"; #128

dcourtois opened this issue Feb 18, 2013 · 16 comments · May be fixed by eth-sri/UnuglifyJS#4

Comments

@dcourtois
Copy link

Hi,
As the title suggest, it would be really nice to have an option switch to enable removing all the "use strict"; of the output.
For instance in my project, I go from 36k to 35k. It's not much, but it's still a few bytes :) (and shouldn't be too complicated to add I guess. I haven't looked at the Uglify code yet, but I find the time, I'll try to add that)

@rvanvelzen
Copy link
Collaborator

The problem is that "use strict" introduces certain semantics, which actually makes it harder in some cases to remove it.

@dcourtois
Copy link
Author

Could you give me an example ? (I'm still quite new to Javascript ^^)
yuicompressor removes it (I was using this tool before finding uglifyjs) so I assumed it could be safe, and also if it's avaiable through a command line option, the user might be free to use it or not, at his/her own risk ?

Anyway for the moment I'm removing the "use strict"; statement as a step of my build process, before using uglifyjs. I just thought that it might be an option not too hard to add and that a few people might like to have.

@ForbesLindesay
Copy link
Contributor

Safety

It's not trivial to check for cases like the following, where it's not safe to remove "use strict";

"use strict";
function Foo() {
  if (typeof this === 'undefined') return new Foo();
  this.val = 1;
}
Foo.prototype.getVal = function () {
  return this.val;
};

// the following then works in strict mode
// but leaks a global variable `val` in non-strict
// mode
Foo().getVal();

Performance

The other reason not to do this is performance. "use strict" serves two purposes. The first is to prevent bad practices and fix some obvious mistakes. The second is to aid performance optimizations. Strict mode allows optimisers to assume certain techniques won't be used (Such as arguments.caller etc.).

As such, removing "use strict" may actually hurt performance.

@mishoo
Copy link
Owner

mishoo commented Feb 20, 2013

@ForbesLindesay thanks for taking the time to explain.

We could have this as an option but I've no interest to do it; will take a patch if someone bothers to write it.

@mishoo mishoo closed this as completed Feb 20, 2013
@dcourtois
Copy link
Author

Thanks a lot for the explanation, I'll need to grab a good javascript book one day to learn those things :)

@estahn
Copy link

estahn commented Apr 10, 2013

Would it make sense to remove multiple "use strict" expressions?

@ForbesLindesay
Copy link
Contributor

After the initial "use strict" for any given scope, it should be pretty safe to just remove all string literals, numeric literals, boolean literals and regular expression literals, that aren't ever used.

@michaelficarra
Copy link
Contributor

It's safe to remove duplicate directives, but not different ones like @ForbesLindesay suggests.

@ForbesLindesay
Copy link
Contributor

There are no other valid directives:

function foo() {
  "foo bar";
  return 5;
}

is exactly equivalent to:

function foo() {
  return 5;
}

The only string literal (that I'm aware of) which has special meaning is "use strict"

@dcourtois
Copy link
Author

@ForbesLindesay There is also "use asm" (see http://asmjs.org/spec/latest/)

@michaelficarra
Copy link
Contributor

@ForbesLindesay: any string in directive position may be meaningful and must be preserved.

@ForbesLindesay
Copy link
Contributor

@Intyuh thanks, I wasn't aware of that directive. We could add exceptions for any that are potentially meaningful.

http://ecma-international.org/ecma-262/5.1/#sec-14.1 States:

A Directive Prologue is the longest sequence of ExpressionStatement productions occurring as the initial SourceElement productions of a Program or FunctionBody and where each ExpressionStatement in the sequence consists entirely of a StringLiteral token followed a semicolon.

Which means only string literals at the beginning of a function body suffer the problem of potentially being directives.

It also does indeed goes on to state:

Implementations may define implementation specific meanings for ExpressionStatement productions which are not a Use Strict Directive and which occur in a Directive Prologue.

so implementations can define implementation specific meanings as @michaelficarra suggests.

It's worth noting that only implementations can define such meaning, not users. Essentially, providing you consider the list of known directives (and keep that up to date), it's no less safe than mangling variable names, since someone is always able to call foo.toString() when foo is a function.

As a final point, pretty much no code actually relies on these directives. For example, code may actually run faster if the "use asm" directive is removed in production, since all it does is enforce strict type checking. Code that relies on "use strict" would also fail pretty frequently at the moment if running in browser environments (the main target for UglifyJS).

@chpio
Copy link

chpio commented Mar 10, 2015

"use asm" also enables the static compiler in Firefox, so no, it runs faster with "use asm"

@ilearnio
Copy link

ilearnio commented Feb 3, 2017

So is there any option to prevent UglifyJS from adding "use strict"; in the beginning of the file? I just don't feel safe knowing that my script will enable strict mode globally for anyone who will use it. i have placed "use strict"; manually to the place where it belongs in my code, but it gets ripped of and placed in the beginning, which is not good

@avdg
Copy link
Contributor

avdg commented Feb 6, 2017

No, there is no option to prevent directives from printing

See https://github.com/mishoo/UglifyJS2/blob/master/lib/output.js#L690 or lookup AST_Directive

@avdg
Copy link
Contributor

avdg commented Feb 6, 2017

(a bit of creative code, automation or manual removal could do the trick anyway)

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 a pull request may close this issue.

9 participants