ImaginativeThinking.ca


A developers blog

What the Heck is Node modules strict by default?

By: Brad

Hey Brad I’m working on a Node.js project and my team is using ESLint to statically analyze our code. I noticed that we are using the strict rule to ensure that we are not putting the use strict pragma in our code files. I asked my team about it and they said that its because Node modules are strict by default now in Node v6 but I can’t find anything online confirming that. What the heck is Node modules strict by default or not?

I ran into the same rule when working with Node and did a bit of surfing around the information super highway to try and figure it out. I ran into this in the ECMAScript 2015 Standard

10.2.1 Strict Mode Code

An ECMAScript Script syntactic unit may be processed using either unrestricted or strict mode syntax and semantics. Code is interpreted as strict mode code in the following situations:

  • Global code is strict mode code if it begins with a Directive Prologue that contains a Use Strict Directive (see 14.1.1).
  • Module code is always strict mode code.
  • All parts of a ClassDeclaration or a ClassExpression are strict mode code.
  • Eval code is strict mode code if it begins with a Directive Prologue that contains a Use Strict Directive or if the call to eval is a direct eval (see 12.3.4.1) that is contained in strict mode code.
  • Function code is strict mode code if the associated FunctionDeclaration, FunctionExpression, GeneratorDeclaration, GeneratorExpression, MethodDefinition, or ArrowFunction is contained in strict mode code or if the code that produces the value of the function’s [[ECMAScriptCode]] internal slot begins with a Directive Prologue that contains a Use Strict Directive.
  • Function code that is supplied as the arguments to the built-in Function and Generator constructors is strict mode code if the last argument is a String that when processed is a FunctionBody that begins with a Directive Prologue that contains a Use Strict Directive.

ECMAScript code that is not strict mode code is called non-strict code.

It states that ES modules are strict by default but I was unclear as to if they were talking about CommonJS or ECMAScript nor what module system was used in Node v6 and if it was strict by default.

Rooting around I could not for the life of me find a straight answer to that question. There is lots of back and forth on forms but they all seemed to be about versions of Node before v4 and talked about using the --use-strict flag to force all code into strict mode or just saying that ESLint was wrong and you should set the rule to require a global use strict pragma in all your Node modules.

What I ended up doing was what any good developer does, I experimented.

I looked up what strict mode does and found that one of the things that it does is make the arguments variable a local copy within the function vs. a reference.

Experiment Theory

In non-strict mode the arguments variable which is accessible within any function and is an array like object containing all parameters passed into said function the parameters held within will be references to the same values stored in any named parameters in your function definition.

My meaning is that if we define a function which takes one parameter called myArg I can reference it via myArg but also by arguments[0]. Therefore the act of changing the value of the parameter via the arguments reference will change the value referenced by the named parameter myArg.

function test(myArg) {
  console.log(`${myArg} -- ${arguments[0]}`);
  arguments[0] = 20;
  console.log(`${myArg} -- ${arguments[0]}`);
}

test(10);

If you execute the above in Node and we’re in non-strict mode it should print out:


10 -- 10
20 -- 20

If we were to run the code in strict mode however the arguments array like object will contain a local copy of the values; thus modifying the value via the arguments reference won’t effect the named parameter.

'use strict';
function test(myArg) {
  console.log(`${myArg} -- ${arguments[0]}`);
  arguments[0] = 20;
  console.log(`${myArg} -- ${arguments[0]}`);
}

test(10);

If you execute the above in Node and thanks to the pragma we are running in strict mode it should print out:


10 -- 10
10 -- 20

Experiment

myModule.js
module.exports = {
  func: function(arg) {
    console.log('Mod')
    console.log(`${arg} -- ${arguments[0]}`);
    arguments[0] = 20;
    console.log(`${arg} -- ${arguments[0]}`);
  }
}
test.js
'use strict';
const mod = require('./myModule');

function local(arg) {
  console.log('Local');
  console.log(`${arg} -- ${arguments[0]}`);
  arguments[0] = 20;
  console.log(`${arg} -- ${arguments[0]}`);
}

local(10);
mod.func(10);

To test if the Node module was being loaded in strict mode by default I ran this: $ node test.js

What I ended seeing printed out in my terminal was:


Local
10 -- 10
10 -- 20
Mod
10 -- 10
20 -- 20

Conclusion

Noticing that under Mod the second line was changed to 20 meaning that when I changed arguments[0] to 20 I modified my function’s named parameter thus arguments is not a local copy and therefore my module is not in strict mode.

Node Modules are NOT strict by default.

I did re-run the experiment with --use-strict and saw that both test.js and myModule.js were then in strict mode but you might not want to use the flag as it might break older npm packages that your project is depending on which rely on non-strict mode behaviour. That of course is a concern that I’m sure is dated and soon might not be an issue any more.

So what is with the standard saying modules are strict now?

Well the standard is talking about the new native modules in ECMAScript, ES Modules. These modules are imported and exported using the import and export keywords. Node is not using ES Modules yet; Node uses modules based on CommonJS, which are not strict by default. Its worth noting that you might be using the new import/export keywords today but its likely your using babel to transpile them back to Node Modules (i.e. require()) so they are not actually ES Modules thus also not strict by default.

There you have it the answer to the question what the heck is Node modules strict by default. No, no they are not. At least not yet maybe one day Node will update to use ES modules but as of Node v6 and Node 8 Node modules are not strict by default.

Until next time think imaginatively and design creatively

Brad

My interest in computer programming started back in high school and Software Development has remained a hobby of mine ever since. I graduated as a Computer Engineering Technologist and have been working as a Software Developer for many years. I believe that software is crafted; understanding that how it is done is as important as getting it done. I enjoy the aesthetics in crafting elegant solutions to complex problems and revel in the knowledge that my code is maintainable and thus, will have longevity. I hold the designation Certified Technician (C.Tech.) with the Ontario Association of Computer Engineering Technicians and Technologists (OACETT), have been certified as a Professional Scrum Master level 1 (PSM I) and as a Professional Scrum Developer level 1 (PSD I) by Scrum.org as well as designated as an Officially Certified Qt Developer by the Qt Company. For more on my story check out the about page here

Feel free to write a reply or comment.

  • Thx for the post, was using eslint ‘airbnb’ rules for a while and they told that modules are using ‘use strict’ by default and you do not need them, pulled the source code, and did not find any trace of ‘use strict injection there’

    • >but its likely your using babel to transpile them back to Node Modules (i.e. require()) so they are not actually ES Modules thus also not strict by default.

      Actually Babel is pretty much aware about ES6 modules strict mode, moreover it assumes all files passed through it are ES6 modules by default and adds ‘use strict’ globally