disabling "use strict"; everywhere

# Andrea Giammarchi (12 years ago)

I have a blog post about it called

Resurrecting The With Statement

and before I post the link, there the long story short:

putting with(this){ before any build process/inlined library and } at the end of all concatenated files nobody is strict anymore ^_^

webreflection.blogspot.com/2013/01/resurrecting-with-statement.html

I actually like this possibility, but I'd like to know what you think about it

br

# Claude Pache (12 years ago)

Le 30 janv. 2013 à 06:12, Andrea Giammarchi <andrea.giammarchi at gmail.com> a écrit :

I have a blog post about it called

Resurrecting The With Statement

and before I post the link, there the long story short:

putting with(this){ before any build process/inlined library and } at the end of all concatenated files nobody is strict anymore ^_^

For what I understand of ES5, putting some random stuff (other than string literals or comments) before a "use strict" directive at the beginning of a file will disable it. This is a known fact, orthogonal to the "Function + with" dirty/creative hack of your blog post.

# Brandon Benvie (12 years ago)

To enable strict mode, the "use strict" expression must come as the first non-statement of a script or function body. That means function x(){} "use strict";

Will enable strict mode, but

(function x(){});
"use strict";

won't. To make your example strict, you'd have to do

with (ob) {
  (function(){
    "use strict'";
    /* concatenated stuff */
  })();
}
# Brandon Benvie (12 years ago)

Correction, the use strict directive needs to appear as the first statement (ExpressionStatement) that's not an EmptyStatement and not a FunctionDeclaration. Anything else will cause the directive to be ignored.

# Andrea Giammarchi (12 years ago)

let me rephrase ...

putting with(this){ before any build process/inlined library and } at the end of all concatenated files nothing is strict anymore ^_^

function isStrict() {"use strict"; return this; }

isStrict(); // undefined

now, wraping the whole thing inside a with statement

with(this){ function isStrict() {"use strict"; return this; } alert(isStrict()); // global object }

forget the Function hack, there is no library able to ensure itself to be executed in strict mode. Using the width statement around any code makes it not strict.

Thoughts ?

# Andrea Giammarchi (12 years ago)

actually, interesting enough, function expressions do not suffer this problem ... this is getting weirder and weirder ...

with(this){ alert(function isStrict() {"use strict"; return this; }()); // undefined }

br

# Brandon Benvie (12 years ago)

The behavior of a FunctionDeclaration that's not directly in the body of a Program or function is not defined in ES5 and this is likely fallout from that.

# Andrea Giammarchi (12 years ago)

so the directive is about expressions only ? interesting

# Brandon Benvie (12 years ago)

The behavior you showed is very odd indeed, I suspect it's actually a bug. But I would guess the reason the bug exists is because of it being a FunctionDeclaration.

# Andreas Rossberg (12 years ago)

On 30 January 2013 18:00, Andrea Giammarchi <andrea.giammarchi at gmail.com> wrote:

let me rephrase ...

putting with(this){ before any build process/inlined library and } at the end of all concatenated files nothing is strict anymore ^_^

function isStrict() {"use strict"; return this; }

isStrict(); // undefined

now, wraping the whole thing inside a with statement

with(this){ function isStrict() {"use strict"; return this; } alert(isStrict()); // global object }

forget the Function hack, there is no library able to ensure itself to be executed in strict mode. Using the width statement around any code makes it not strict.

That is, er, balls, of course. All that happens here is that inside the 'with', a call to a toplevel function like 'isStrict()' becomes 'this.isStrict()', and so receives the global object. That does not otherwise change strictness, however. Try:

with(this) { function isStrict() { "use strict"; var x; delete x; } alert(isStrict()); }

for example. Moreover, calls to functions not resolving to global definitions are completely unaffected, so are calls using 'call' or 'apply':

with(this) { function isStrict() { "use strict"; return this; }; function call(f) { f() }; alert(call(isStrict)); // undefined alert(isStrict.call()); // undefined }

Both calls would return window in sloppy mode.

# Andreas Rossberg (12 years ago)

On 30 January 2013 17:19, Brandon Benvie <brandon at brandonbenvie.com> wrote:

Correction, the use strict directive needs to appear as the first statement (ExpressionStatement) that's not an EmptyStatement and not a FunctionDeclaration. Anything else will cause the directive to be ignored.

Any statement/declaration before the use directive renders it inoperational, empty, function, or otherwise. Actually, any token before the magic string does.

# Andrea Giammarchi (12 years ago)

thanks, that makes sense. I have tried this too:

with({}){ function isStrict() {"use strict"; return this; } alert(isStrict()); // global object }

still global though, but I believe that a side effect of the with statement.

Weird that expressions behave outside that implicit context.

Libraries wrapped in inline expressions seem to be safe then, hooooray I guess :-)

# Andrea Giammarchi (12 years ago)

last examples, for archive reasons:

function isStrict() {"use strict"; return this; }

with(false){ alert(isStrict()); // global object alert((0, isStrict)()); // undefined }

mystery solved, still something to be aware for library authors. I'll explain in a tiny counter post later on.

br

# Claude Pache (12 years ago)

Le 30 janv. 2013 à 18:00, Andrea Giammarchi <andrea.giammarchi at gmail.com> a écrit :

let me rephrase ...

putting with(this){ before any build process/inlined library and } at the end of all concatenated files nothing is strict anymore ^_^

function isStrict() {"use strict"; return this; }

isStrict(); // undefined

now, wraping the whole thing inside a with statement

with(this){ function isStrict() {"use strict"; return this; } alert(isStrict()); // global object }

Presumably some weirdness between "with" statement mixed with function declaration. You should test specifically the strictness, not the this-binding:

with(this){ function test() { "use strict" return (function() { return this === void 0 })() } alert(test()); // true }

The test function is manifestly in strict mode regardless of its this-binding.

...

!! But wait, I think I understand what's happening:

var obj = { returnThis: function() { "use strict"; return this } , toString: function() { return 'I am "obj"' } } var otherReturnThis = function() { "use strict"; return this }

with(obj){ alert(returnThis()); // 'I am "obj"' alert(otherReturnThis()); // undefined }

Here, "returnThis()" is strictly equivalent to "obj.returnThis()", including the this-binding, while "otherReturnThis()" use "undefined" as target object

In your example, when you say "isStrict()", it is interpreted as "this.isStrict()", since "isStrict" is a property of "this" and "this" is the argument of the "with" statement. (You're still with me?) Nothing to do with strict mode

Ok, you convinced me that the semantic of the "with" statement is really weird, but not that you can disable strict mode.