"use strict"; prepended blindly to scripts in the wild

# Brendan Eich (15 years ago)

See, e.g., bugzilla.mozilla.org/show_bug.cgi?id=593963 -- but this is not the first instance. Previously: bugzilla.mozilla.org/show_bug.cgi?id=579119.

Anyone know of bad advice somewhere, or a code generator doing the prepending, or anything else we should evangelize aggressively either to stop pasting "use strict"; blindly, or do do the testing to make sure the code passes in a conforming ES5 implementation (when ready; Firefox 4 betas have strict mode nearing completion).

# Boris Zbarsky (15 years ago)

On 9/7/10 1:21 PM, Brendan Eich wrote:

See, e.g., bugzilla.mozilla.org/show_bug.cgi?id=593963 -- but this is not the first instance. Previously: bugzilla.mozilla.org/show_bug.cgi?id=579119.

The latter wasn't blind. It was just a site concatenating a bunch of third-party scripts together, and one of the third-party scripts (correctly) using strict.... So that one is totally Amazon's flub, imo.

# Brendan Eich (15 years ago)

On Sep 7, 2010, at 10:28 AM, Boris Zbarsky wrote:

On 9/7/10 1:21 PM, Brendan Eich wrote:

See, e.g., bugzilla.mozilla.org/show_bug.cgi?id=593963 -- but this is not the first instance. Previously: bugzilla.mozilla.org/show_bug.cgi?id=579119.

The latter wasn't blind. It was just a site concatenating a bunch of third-party scripts together, and one of the third-party scripts (correctly) using strict.... So that one is totally Amazon's flub, imo.

Thanks -- this clarifies things, and makes me worry about more of the same.

"Blind concatenation" is a feature as much as a bug in the history of JS. Combined with script inline content moving out to src= URL-named convent, it is how we end up with Unicode BOMs and <!-- pseudo-comments in the middle of files.

# Marek Stępień (15 years ago)

On Tue, Sep 7, 2010 at 7:21 PM, Brendan Eich <brendan at mozilla.com> wrote:

Anyone know of bad advice somewhere, or a code generator doing the prepending, or anything else we should evangelize aggressively either to stop pasting "use strict"; blindly, or do do the testing to make sure the code passes in a conforming ES5 implementation

JSLint.com (which is an awesome tool that I use pretty much every day) tells you to add "use strict" if you choose the "Good Parts" option. Its documentation says to "use it wisely", but people don't usually read the docs.

Maybe JSLint should be fixed to disallow non-strict code with "use strict;". The following code is said to be OK by JSLint with "Good Parts" at the moment:

/*global window */ "use strict";

function someFun() { window.alert(arguments.callee); }

someFun();

I'm not sure whether people often run concatenated scripts through tools like JSLint, though. So maybe it should also warn you not to concatenate scripts blindly...

PS. I already wrote most of the above in the Intel bug in Mozilla's Bugzilla, but now I think posting it here makes more sense.

# Oliver Hunt (15 years ago)

The other problem with JSLint is that it can't run all of the code so JSLint won't pick up the runtime error in

function f() { "use strict"; return this.foo; }

f();

I've seen a couple of sites that would break due to this.

# felix (15 years ago)

in the Names strawman, "private foo" at the top level has the same problem as "use strict" at the top level. maybe there should be a general way of delimiting a top-level lexical scope, so that pasting js together is still relatively easy?

# Dean Landolt (15 years ago)

On Wed, Sep 8, 2010 at 6:25 PM, felix <felix8a at gmail.com> wrote:

in the Names strawman, "private foo" at the top level has the same problem as "use strict" at the top level. maybe there should be a general way of delimiting a top-level lexical scope, so that pasting js together is still relatively easy?

{ "use strict"; /* strict code */ }

Not sure if this is legit -- I seem to recall something about "use strict"; being scoped at the block level (or at least that you can scope a specific if block). If so, wouldn't this suffice?

# Mike Samuel (15 years ago)

2010/9/8 Dean Landolt <dean at deanlandolt.com>:

On Wed, Sep 8, 2010 at 6:25 PM, felix <felix8a at gmail.com> wrote:

in the Names strawman, "private foo" at the top level has the same problem as "use strict" at the top level.  maybe there should be a general way of delimiting a top-level lexical scope, so that pasting js together is still relatively easy?

{ "use strict"; /* strict code */ }

Not sure if this is legit -- I seem to recall something about "use strict"; being scoped at the block level (or at least that you can scope a specific if block). If so, wouldn't this suffice?

It is legit, but the "use strict" there is a string literal not a prologue directive since those can only appear at the start of a program or a function body.

# Brendan Eich (15 years ago)

On Sep 8, 2010, at 3:25 PM, felix wrote:

in the Names strawman, "private foo" at the top level has the same problem as "use strict" at the top level. maybe there should be a general way of delimiting a top-level lexical scope, so that pasting js together is still relatively easy?

Today, module pattern:

(function () { // "use strict" or private x; here without fear... })();

Tomorrow, with strawman:simple_modules, something like

module { // "use strict" or private x; here without fear... }

# Brendan Eich (15 years ago)

Until JSLint actually enforces ES5 strict mode, its docs should not be promoting "use strict".

In the SVG past, the dark ages so to speak, some popular tools generated invalid SVG-in-XML, and so did hand-coding authors. This begat missing xmlns= declaration error correction. Same story as HTML quirks mode, which goes back to when NCSA Mosaic had to keep content on ~80 web servers working even if it was not well-formed (from personal communication with Marc Andreessen).

Are there > 80 servers worth of content that has "use strict" but does not conform to ES5 strict mode? Can we evangelize them? See the Mozilla bugs cited in this thread, which are "Technology Evangelism" bugs, and kudos to Intel for its rapid response.

But JSLint shouldn't be writing checks it can't back that its users will want to cash in ES5-conformant browsers.

# felix (15 years ago)

On 9/8/10 17:25, Brendan Eich wrote:

On Sep 8, 2010, at 3:25 PM, felix wrote:

in the Names strawman, "private foo" at the top level has the same problem as "use strict" at the top level. maybe there should be a general way of delimiting a top-level lexical scope, so that pasting js together is still relatively easy?

Today, module pattern:

(function () { // "use strict" or private x; here without fear... })();

that's not quite the same thing since the innards can't introduce new top-level bindings. you can't just wrap an arbitrary js file in the module wrapper and still have it work. you have to rewrite it.

I guess the transformation could be automated, though it's a bit more complex than just concatenation.

# Brendan Eich (15 years ago)

On Sep 8, 2010, at 6:34 PM, felix wrote:

On 9/8/10 17:25, Brendan Eich wrote:

On Sep 8, 2010, at 3:25 PM, felix wrote:

in the Names strawman, "private foo" at the top level has the same problem as "use strict" at the top level. maybe there should be a general way of delimiting a top-level lexical scope, so that pasting js together is still relatively easy?

Today, module pattern:

(function () { // "use strict" or private x; here without fear... })();

that's not quite the same thing since the innards can't introduce new top-level bindings. you can't just wrap an arbitrary js file in the module wrapper and still have it work. you have to rewrite it.

That's true, and there's no way around it. But you can't create global variables by assignment in ES5 strict mode. If your code section really needs to create global bindings, even if properly via var and function (never by assignment), then it's likely you don't want "use strict"; at the top of it.

You could "use strict" in each top-level function, but what if you have 930 functions in your code section? Better to use a module pattern and export object for now (more below), and simple modules later.

I guess the transformation could be automated, though it's a bit more complex than just concatenation.

There's no easy way to support concatenation and "use strict" (or private x). But the "ease" of concatenative programming in JS is an illusion already. Accumulating properties in the global object is a constant source of bugs and confusion. Modern JS libraries minimize their global binding sets.

One nice way to minimize (sorry if this is old hat):

var exports = (function () { // everything else here return {...}; };

This enables "use strict" coverage of all the code in the module pattern that returns the exports object. Of course you'd want to prefix "exports", or do something that avoids binding even one global var.

# felix (15 years ago)

On 9/8/10 18:52, Brendan Eich wrote:

There's no easy way to support concatenation and "use strict" (or private x). But the "ease" of concatenative programming in JS is an illusion already. Accumulating properties in the global object is a constant source of bugs and confusion. Modern JS libraries minimize their global binding sets.

right. but it's common for sites to develop with separate js scripts as "modules" and then combine them into a single script for speed when deployed to end-users. global conflicts can be found and solved when the js scripts are included separately, and naive concatenation does not change how the scripts behave.

except file-level directives like "use script" change that. now I need to either

  • test the concatenation.
  • use a smarter rewriting-concatenator, which is probably complex enough that the result will need testing anyway.
  • validate the individual js files as naive-concatenation-safe before doing the concatenation.

this probably should happen even if I use the module-with-exports pattern in my code, since who knows if some other js lib I use has file-level directives or not, and it's no fun to inspect it manually on every update.

# felix (15 years ago)

On 9/8/10 19:08, felix wrote:

On 9/8/10 18:52, Brendan Eich wrote:

There's no easy way to support concatenation and "use strict" (or private x). But the "ease" of concatenative programming in JS is an illusion already. Accumulating properties in the global object is a constant source of bugs and confusion. Modern JS libraries minimize their global binding sets.

right. but it's common for sites to develop with separate js scripts as "modules" and then combine them into a single script for speed when deployed to end-users. global conflicts can be found and solved when the js scripts are included separately, and naive concatenation does not change how the scripts behave.

except file-level directives like "use script" change that. now I need to either

  • test the concatenation.
  • use a smarter rewriting-concatenator, which is probably complex enough that the result will need testing anyway.
  • validate the individual js files as naive-concatenation-safe before doing the concatenation.
  • or js could barf/warn on file-level directives, basically making the previous option built-in.
  • or js could invent some way for me to say "this is the end of the scope of a file-level directive" within a single file.
# Mark S. Miller (15 years ago)

I recently asked Kris Kowal what he recommends as the simplest way to write simple JS "modules" today that can be used either as browser-side scripts or as CommonJS modules. Adapting the elegant pattern he showed me, I suggest the following variation:

foo.js

(function(require, exports) { "use strict"; // ... exports.x = 21;

}).call({}, typeof require === 'function' ? require : function(id) { return this[id]; }, typeof exports !== 'undefined' ? exports : (this.foo = {}));

bar.js

(function(require, exports) { "use strict"; var foo = require("foo"); // ... exports.y = foo.x * 2;

}).call({}, typeof require === 'function' ? require : function(id) { return this[id]; }, typeof exports !== 'undefined' ? exports : (this.bar = {}));

In a CommonJS environment, "require" and "exports" would be defined and "require" would be a function, so the first branches of the ?:s above would be taken. In a browser-side environment, they wouldn't be defined, so the second branches would be taken. In a CommonJS environment, loading bar.js would cause the loading of foo.js. In a browser-side environment, the page would still have to manually include these scripts in bottom-up order as usual -- first foo and then bar. This works whether foo.js and bar.js are included as separate scripts or whether they are appended together. Fancier adapters like requirejs.org do more but need more setup. When the

simple pattern above is adequate, it works without any prelude or infrastructure.

Everything above should work on old ES3 browsers. On ES5 browsers, each individual module is strict, without the strictness leaking when module sources are appended.

The main limitation for browser-side use is that the module names become global variable names, and so potentially conflict with other global variable names.

# Dmitry Soshnikov (15 years ago)

On Tue, Sep 7, 2010 at 9:35 PM, Brendan Eich <brendan at mozilla.com> wrote:

On Sep 7, 2010, at 10:28 AM, Boris Zbarsky wrote:

On 9/7/10 1:21 PM, Brendan Eich wrote:

See, e.g., bugzilla.mozilla.org/show_bug.cgi?id=593963 -- but this is not the first instance. Previously: bugzilla.mozilla.org/show_bug.cgi?id=579119.

The latter wasn't blind. It was just a site concatenating a bunch of third-party scripts together, and one of the third-party scripts (correctly) using strict.... So that one is totally Amazon's flub, imo.

Thanks -- this clarifies things, and makes me worry about more of the same.

"Blind concatenation" is a feature as much as a bug in the history of JS. Combined with script inline content moving out to src= URL-named convent, it is how we end up with Unicode BOMs and <!-- pseudo-comments in the middle of files.

Currently, a site may normally concatenate 3rd-party libs with "use strict" at the global level. The technique is the same as with forgotten semicolon -- just to put an empty statement at the beginning of the end file.

Thus the site's combined file won't be globally strict, however since a lib is tested before a production release (at least I hope so ;), then the lib's code should pass the strictness, and therefore, a "use strict" may be even removed from the lib's file. However, if not to remove, then an empty statement is enough.

;/1st lib/"use strict";eval = 10;/2st lib/"use strict";arguments=20;/our code/

Dmitry.

# Brendan Eich (15 years ago)

On Sep 9, 2010, at 1:09 AM, Dmitry Soshnikov wrote:

Thus the site's combined file won't be globally strict, however since a lib is tested before a production release (at least I hope so ;), then the lib's code should pass the strictness, and therefore, a "use strict" may be even removed from the lib's file. However, if not to remove, then an empty statement is enough.

That does not disable strict mode. The problem at real sites including an intel.com property is that subsequent parts of the concatenation have had strict mode errors.

;/1st lib/"use strict";eval = 10;/2st lib/"use strict";arguments=20;/our code/

An example showing the problem would need a "use nonstrict"; directive after the first part of the concatenation, but there is no such directive.

# Dean Landolt (15 years ago)

On Thu, Sep 9, 2010 at 10:32 AM, Brendan Eich <brendan at mozilla.com> wrote:

On Sep 9, 2010, at 1:09 AM, Dmitry Soshnikov wrote:

Thus the site's combined file won't be globally strict, however since a lib is tested before a production release (at least I hope so ;), then the lib's code should pass the strictness, and therefore, a "use strict" may be even removed from the lib's file. However, if not to remove, then an empty statement is enough.

That does not disable strict mode. The problem at real sites including an intel.com property is that subsequent parts of the concatenation have had strict mode errors.

;/1st lib/"use strict";eval = 10;/2st lib/"use strict";arguments=20;/our code/

An example showing the problem would need a "use nonstrict"; directive after the first part of the concatenation, but there is no such directive.

I recall reading that the "use strict"; directive was block-scoped. Is this true? If so, there's no need for function wrappers -- putting each script in its own block is easy and should have no ill effects on concatenation, right?

# Brendan Eich (15 years ago)

On Sep 9, 2010, at 8:46 AM, Dean Landolt wrote:

On Thu, Sep 9, 2010 at 10:32 AM, Brendan Eich <brendan at mozilla.com> wrote: On Sep 9, 2010, at 1:09 AM, Dmitry Soshnikov wrote:

Thus the site's combined file won't be globally strict, however since a lib is tested before a production release (at least I hope so ;), then the lib's code should pass the strictness, and therefore, a "use strict" may be even removed from the lib's file. However, if not to remove, then an empty statement is enough.

That does not disable strict mode. The problem at real sites including an intel.com property is that subsequent parts of the concatenation have had strict mode errors.

;/1st lib/"use strict";eval = 10;/2st lib/"use strict";arguments=20;/our code/

An example showing the problem would need a "use nonstrict"; directive after the first part of the concatenation, but there is no such directive.

I recall reading that the "use strict"; directive was block-scoped. Is this true? If so, there's no need for function wrappers -- putting each script in its own block is easy and should have no ill effects on concatenation, right?

No, the "use strict"; directive is meaningful only at top of program and function bodies. See ES5 14.1:

14.1 Directive Prologues and the Use Strict Directive

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. The semicolon may appear explicitly or may be inserted by automatic semicolon insertion. A Directive Prologue may be an empty sequence.

You may be thinking of ES4-era unquoted use strict; pragma syntax, which was block scoped. In Harmony, use ...; should be a block-scoped pragma -- real syntax, no quotes.

# Mike Shaver (15 years ago)

On Thu, Sep 9, 2010 at 1:09 AM, Dmitry Soshnikov <dmitry.soshnikov at gmail.com> wrote:

Currently, a site may normally concatenate 3rd-party libs with "use strict" at the global level. The technique is the same as with forgotten semicolon -- just to put an empty statement at the beginning of the end file.

Thus the site's combined file won't be globally strict, however since a lib is tested before a production release (at least I hope so ;), then the lib's code should pass the strictness, and therefore, a "use strict" may be even removed from the lib's file. However, if not to remove, then an empty statement is enough.

Unfortunately for this eminently reasonable (IMO) assumption, removing "use strict" can change the behaviour of a program, even beyond cases that would have thrown an error. For example, the type and value of |this| can be different, for cases where methods are called on primitives.

I don't know if other languages with optional strictures share this property, but I suspect that a lot of people are going to stub their toe on ES5's use of "use strict" as cover for incompatible changes rather than strictly subsetting legal programs and behaviours. :-/

Mike

# Mike Samuel (15 years ago)

2010/9/9 Dmitry Soshnikov <dmitry.soshnikov at gmail.com>:

On Tue, Sep 7, 2010 at 9:35 PM, Brendan Eich <brendan at mozilla.com> wrote:

On Sep 7, 2010, at 10:28 AM, Boris Zbarsky wrote:

On 9/7/10 1:21 PM, Brendan Eich wrote:

See, e.g., bugzilla.mozilla.org/show_bug.cgi?id=593963 -- but this is not the first instance. Previously: bugzilla.mozilla.org/show_bug.cgi?id=579119.

The latter wasn't blind.  It was just a site concatenating a bunch of third-party scripts together, and one of the third-party scripts (correctly) using strict....  So that one is totally Amazon's flub, imo.

Thanks -- this clarifies things, and makes me worry about more of the same.

"Blind concatenation" is a feature as much as a bug in the history of JS. Combined with script inline content moving out to src= URL-named convent, it is how we end up with Unicode BOMs and <!-- pseudo-comments in the middle of files.

Currently, a site may normally concatenate 3rd-party libs with "use strict" at the global level. The technique is the same as with forgotten semicolon -- just to put an empty statement at the beginning of the end file.

A forgotten semicolon at the end of the first concatenated file can be a problem though.

Consider the concatenation of (function () { foo(); })() and (function () { bar() })()

Independently loaded, you get a call to foo and a call to bar. Concatenated, you get a call to foo and a TypeError complaining that undefined is not a function.

So in both cases naive concatenation introduces subtle bugs by changing the meaning of the first or lass statement in a compilation unit.

# Dmitry Soshnikov (15 years ago)

On Thu, Sep 9, 2010 at 6:32 PM, Brendan Eich <brendan at mozilla.com> wrote:

On Sep 9, 2010, at 1:09 AM, Dmitry Soshnikov wrote:

Thus the site's combined file won't be globally strict, however since a lib is tested before a production release (at least I hope so ;), then the lib's code should pass the strictness, and therefore, a "use strict" may be even removed from the lib's file. However, if not to remove, then an empty statement is enough.

That does not disable strict mode.

Actually it does (since a strict mode, and the directive prologue is an initial statement):

"use strict";eval=10 // strict, error

but

;"use strict";eval = 10; // non-strict, OK

The problem at real sites including an intel.com property is that subsequent parts of the concatenation have had strict mode errors.

The second part of the (combined) file is also evaluated in non-strict, because again, "use strict" is placed not at the initial position. So, the whole file is in non-strict.

However, as mentioned Mike Shaver, there can be issues with vice-versa, turning to non-strict, e.g. non-object or even non-undefined /this/ value.

So, the suggestion is just a workaround.

Dmitry.

# Brendan Eich (15 years ago)

On Sep 9, 2010, at 10:33 AM, Dmitry Soshnikov wrote:

On Thu, Sep 9, 2010 at 6:32 PM, Brendan Eich <brendan at mozilla.com> wrote: On Sep 9, 2010, at 1:09 AM, Dmitry Soshnikov wrote:

Thus the site's combined file won't be globally strict, however since a lib is tested before a production release (at least I hope so ;), then the lib's code should pass the strictness, and therefore, a "use strict" may be even removed from the lib's file. However, if not to remove, then an empty statement is enough.

That does not disable strict mode.

Actually it does (since a strict mode, and the directive prologue is an initial statement):

"use strict";eval=10 // strict, error

but

;"use strict";eval = 10; // non-strict, OK

Oh, I see -- that solves the problem of strict mode in the second or later parts of the concatenation.

But the problem that's already come up on the web has strict mode enabled in the first part, which complies with strict mode, but later parts do not -- and there's no way to disable for them.

# Dmitry Soshnikov (15 years ago)

On Thu, Sep 9, 2010 at 9:35 PM, Brendan Eich <brendan at mozilla.com> wrote:

On Sep 9, 2010, at 10:33 AM, Dmitry Soshnikov wrote:

On Thu, Sep 9, 2010 at 6:32 PM, Brendan Eich <brendan at mozilla.com> wrote:

On Sep 9, 2010, at 1:09 AM, Dmitry Soshnikov wrote:

Thus the site's combined file won't be globally strict, however since a lib is tested before a production release (at least I hope so ;), then the lib's code should pass the strictness, and therefore, a "use strict" may be even removed from the lib's file. However, if not to remove, then an empty statement is enough.

That does not disable strict mode.

Actually it does (since a strict mode, and the directive prologue is an initial statement):

"use strict";eval=10 // strict, error

but

;"use strict";eval = 10; // non-strict, OK

Oh, I see -- that solves the problem of strict mode in the second or later parts of the concatenation.

But the problem that's already come up on the web has strict mode enabled in the first part, which complies with strict mode, but later parts do not -- and there's no way to disable for them.

OK, seems I didn't catch the goal then. I though, that there is some single "js-holy-file", which is a combination of some 3rd-party js-files (libs). And one (the first one) of the libs uses strict mode, and other -- do not (that causes issues in the code of later parts, 'cause the whole file becomes strict). But that exactly I proposed -- to insert into the combined file an /empty statement/ before the first part. Thus, the whole single (combined) file will be non-strict. Even if there are several strict directives later (from every part) -- all of them (including the first one) will be canceled because of this inserted empty statement at the beginning of the file.

But repeat, there may be issues with different semantics of /this/ value in strict and non-strict modes. So, as noted, it's just a quick workaround.

Also it won't help if a user uses dynamically loaded js-files from external sources. So, this issue may really be the issue for users of such external files.

Dmitry.

# Brendan Eich (15 years ago)

On Sep 9, 2010, at 11:57 AM, Dmitry Soshnikov wrote:

But that exactly I proposed -- to insert into the combined file an /empty statement/ before the first part.

Right. There's a rule, Dojo follows it IIRC, to prepend ; to all files, always. That will do the trick.

But of course people don't all folllow that rule and nothing enforces it.

Concatenation is never safe when done blindly, but "use strict" ups the ante. The particular problem is that browsers aren't yet checking "use strict", so erroneous content is getting out into the wild.

# Allen Wirfs-Brock (15 years ago)

The note in section 14.1 advises: "If an appropriate notification mechanism exists, an implementation should issue a warning if it encounters in a Directive Prologue an ExpressionStatement that is not a Use Strict Directive or which does not have a meaning defined by the implementation."

It sounds like it would also be a good idea for implementations to issue such a warning if an "use string" expression statement appears anywhere at the global level that is outside of the Directive Prologue.

From: es-discuss-bounces at mozilla.org [mailto:es-discuss-bounces at mozilla.org] On Behalf Of Dmitry Soshnikov Sent: Thursday, September 09, 2010 11:57 AM To: Brendan Eich Cc: es-discuss at mozilla.org Subject: Re: "use strict"; prepended blindly to scripts in the wild

On Thu, Sep 9, 2010 at 9:35 PM, Brendan Eich <brendan at mozilla.com<mailto:brendan at mozilla.com>> wrote:

On Sep 9, 2010, at 10:33 AM, Dmitry Soshnikov wrote:

On Thu, Sep 9, 2010 at 6:32 PM, Brendan Eich <brendan at mozilla.com<mailto:brendan at mozilla.com>> wrote:

On Sep 9, 2010, at 1:09 AM, Dmitry Soshnikov wrote:

Thus the site's combined file won't be globally strict, however since a lib is tested before a production release (at least I hope so ;), then the lib's code should pass the strictness, and therefore, a "use strict" may be even removed from the lib's file. However, if not to remove, then an empty statement is enough.

That does not disable strict mode.

Actually it does (since a strict mode, and the directive prologue is an initial statement):

"use strict";eval=10 // strict, error

but

;"use strict";eval = 10; // non-strict, OK

Oh, I see -- that solves the problem of strict mode in the second or later parts of the concatenation.

But the problem that's already come up on the web has strict mode enabled in the first part, which complies with strict mode, but later parts do not -- and there's no way to disable for them.

OK, seems I didn't catch the goal then. I though, that there is some single "js-holy-file", which is a combination of some 3rd-party js-files (libs). And one (the first one) of the libs uses strict mode, and other -- do not (that causes issues in the code of later parts, 'cause the whole file becomes strict). But that exactly I proposed -- to insert into the combined file an /empty statement/ before the first part. Thus, the whole single (combined) file will be non-strict. Even if there are several strict directives later (from every part) -- all of them (including the first one) will be canceled because of this inserted empty statement at the beginning of the file.

But repeat, there may be issues with different semantics of /this/ value in strict and non-strict modes. So, as noted, it's just a quick workaround.

Also it won't help if a user uses dynamically loaded js-files from external sources. So, this issue may really be the issue for users of such external files.

Dmitry.

# Dmitry A. Soshnikov (15 years ago)

On 15.09.2010 2:24, Allen Wirfs-Brock wrote:

The note in section 14.1 advises: "If an appropriate notification mechanism exists, an implementation should issue a warning if it encounters in a Directive Prologue an ExpressionStatement that is not a Use Strict Directive or which does not have a meaning defined by the implementation."

It sounds like it would also be a good idea for implementations to issue such a warning if an "use string" expression statement appears anywhere at the global level that is outside of the Directive Prologue.

If these consequences are acceptable:

  1. It may bring such warnings for old scripts (any "string"; appeared in the source will be treated as a potential issue for the notifier);
  2. It won't be possible (without a warning) also to combine two scripts with "use strict" at the global level;
  3. and it won't be possible (without a warning) to use the mentioned workaround with inserting an empty statement at the beginning,

then it's possibly OK. The most important, though, is the first point (regarding again backward compats).

Dmitry.

# Andrea Giammarchi (15 years ago)

sorry I could not find a way to inject myself in the original thread.

Dmitry has very valid points there and I have not seen a concrete solution to this problem so here I am with a couple of proposals.

.#1 First Script Rule I do believe, since there is no "use quirks" directive, that once we put a "use strict" in the global scope and in the very first script, we would like to be sure the whole thingy uses strict. In few words, if I am the author of the application/webpage/whatever I should be the one responsible for strictness. Moreover, if strict is messed up with non strict we may have horrible side effects so ... "all strict" when global strict is set sounds reasonable while if we do not want "all strict" we should use our own closure and most of the libraries out there do already.

.#2 Strict Label JS labels have been there since ages so I wonder if something like this would make sense:

// optionally with a var statement // for all variables used in this // strict context strict:for(;;){

var i = 123;
// etc etc ...

break strict}

// optionally made semantic // via const and a while // const could be a var as well const valid = true; strict:while(valid){

var j = 123;

break strict}

// but we don't need const or var strict:if(true){

// your stuff here

break strict}

Labels would be compatible and the concatenation of scripts won't be a problem, we always have a proper block when we wont to do stuff in a strict way where "strict" should be the reserved label name for "use strict" activation.

What do you think?

Best , Andrea Giammarchi