Is ES6 imported code strict? - javascript

Say that I have a library that relies on non-strict semantics, like coercing a top-level this to the global object:
this.library = { foo: function () {} };
Say that I try to import this library using import:
import './library';
library.foo();
Since I used import, does that mean the library code implicitly runs in strict mode (and breaks, since this is undefined in strict code)? The ECMAScript spec says,
Module code is always strict mode code.
and for the definition of "module code,"
Module code is source text that is code that is provided as a ModuleBody.
And a ModuleBody consists of a ModuleItemList, which consists of ModuleItem's, which could include ImportDeclaration, ExportDeclaration and StatementListItem, and a StatementListItem could be a Statement or Declaration. Which implies that any code could be "module code" depending on the context it is loaded, even without the prescence of an import or export declaration.
Also, the definition of [[RequestedModules]] field from 15.2.1.16 implies that the ModuleSpecifier used in ImportDeclaration indeed specifies the name of a "module:"
A List of all the ModuleSpecifier strings used by the module represented by this record to request the importation of a module.
It would appear that the module system is backwards-incompatible with non-strict code. Is this true?

From this conversation:
A module is not a JavaScript program that includes import/export
statements. Just because they MAY contain import/export statements
does not mean that they MUST have them. You cannot always look at a
program and determine whether or not it is a module. . . .
Since ModuleBody is optional, the empty program is a Module.
The empty program does not contain an export statement.
So, yes, the module system is backwards-incompatible with non-strict code. I suppose code not using the module system is not really fit for participation in the system, because it's likely exporting global variables, which defeats the purpose of it.
Therefore, in order to interoperate, old code will have to be updated either to provide an export declaration or to use strict mode (and/or "guaranteed" non-strict techniques like Function('return this')(), instead of a supposedly non-strict top-level this).

Related

What C++ [[attributes]] are implemented by cheerp?

The C++11 specification defined [[attributes]] which can be used to specify/influence implementation-defined behavior. Cheerp supports this for specifying whether you're writing C++ code meant to be compiled into [[cheerp::genericjs]] or [[cheerp::wasm]] code. This results in your C++ code being compiled into the .js or .wasm output of the compiler respectively. (Right?)
My question: What attributes does Cheerp know and what do they all do?
So far, I've seen the following attributes:
[[cheerp::genericjs]]
[[cheerp::wasm]]
[[cheerp::asmjs]]
[[cheerp::client_layout]]
[[cheerp::static]]
[[cheerp::jsexport]]
The ones that are meant to be used by users are:
cheerp::genericjs: compile the associated item (class/struct definition, global, or function) to JavaScript, using the object memory model
cheerp::wasm: compile the associated item (class/struct definition, global, or function) to WebAssembli OR asm.js, using the linear memory model.
cheerp::asmjs is an alias of cheerp::wasm and considered obsoleted (but kept for backward compatibility). The actual output (wasm or asm.js) depends on command line flags
client::jsexport: export the associated item (function or class/struct) so that it can be used from external JavaScript code
The other attributes you mention do exist, but you should almost never use them yourself. Their meaning is this:
cheerp::static: tell the compiler that the associated method of a client class is static (example: Date.now()). Used in the implementation of various browser apis
cheerp::client_layout: tell the compiler that this class/struct has an external layout defined in external JavaScript. You never need to use this if you inherit your client classes from client::Object (which you should), because derived classes inherit this attribute

What does a sub-path mean in the context of import statements?

Suppose I have a statement like this:
import * as bar from 'foo/bar';
I have a few questions:
What does the /bar bit mean?
Is there a sepcific (google-able) term for this?
Does this provide efficiency gains (reducing module bloat)?
How can I bundle a common-js module (ideally with Rollup) on NPM and support this syntax?
Breaking it down:
Firstly to provide context to your first and second question, let's go a bit further and break down all the parts of that statement:
import * as quux from 'foo/bar';
Note: The first bar instance in your example has been intentionally changed to quux to disambiguate the following points.
Collectively it is referred to as an Import Statement, or more specifically; an Import Declaration as defined in the ECMA-262 Imports Syntax Specification.
The import part is referred to as the Import Keyword.
The * as quux part is referred to as a NameSpace Import.
The asterisk * indicates that all exported bindings in bar will be imported to a newly created namespace object called quux. The resultant effect is that the quux object will hold all the exported members from bar.
The quux part of that is referred to as the Imported Binding and, as previously mentioned, it's used as the name for the newly created namespace object.
The from 'foo/bar' part is referred to as the From Clause.
The foo/bar part is a String Literal and is referred to as the Module Specifier... it's simply a filepath.
Answers to your specific questions:
What does the /bar bit mean?
It's part of the Module Specifier which is part of the From Clause. It is simply a reference to the name of the file whose exported member(s) will be imported from. In this example its exported member(s) will be imported into a new namespace object called quux.
With regards to what is that actual "part" called; ECMA-262 doesn't provide a specific reference/name for it, however, I refer to that part as the filename; (i.e. the filename in the filepath of the module to import).
As far as I know, /bar may or may not need to include a file extension (i.e. /bar.js). Again there's nothing in the ECMA-262 Imports Syntax that enforces this. ECMAScript only defines the syntax for modules and not the specific mechanism(s) for loading them. So the requirement for with or without a .js suffix may vary per implementation. For example:
In Apple's latest Safari browser built upon WebKit which runs on iOS the inclusion of the .js suffix is necessary.
In Modules docs for Node v8.10.0 they do include the .js file extension for imported files in their examples. Note: As ES6 Modules currently have a Stability Index 2 this could change.
Is there a specific (google-able) term for this?
Not per se, as ECMA hasn't named it specifically. You could try googling some of the terminology/nomenclature that I've previously mentioned.
Does this provide efficiency gains (reducing module bloat)?
I'm not sure I fully understand what you mean by "module bloat". However, If you mean will it result in less modules in application code? I think not, it's more likely result in an increased usage of modules.
Efficiency gains will be had from there being native ES6 Module support. Native support by it's very nature can bring speed/performance increases. Other benefits of ES6 Modules are:
ES6 Modules are statically analyzable which allows dead/unused code elimination via a process named Tree Shaking. More info here and here . So, if that's what you mean by the term "module bloat" - then yes; unused/dead code will be removed by tools that perform Tree Shaking.
Caveat; I'm not 100% certain whether tools that perform Tree Shaking are capable of removing dead code when using the wildcard/asterisk (*) in a NameSpace Import. It MAY be necessary to import specific member(s) that you'll use instead, i.e.
import { foo, bar, quux } from './foo/bar.js';
It's an official ECMAScript standard.
The example that you gave included a NameSpace Import, so there's another benefit - it will help to avoid namespace collisions.
More benefits are mentioned here.
How can I bundle a common-js module (ideally with Rollup) on NPM and support this syntax?
Rollup works with a plugin named #rollup/plugin-commonjs which will convert CommonJS modules to ES6, so they can be included in a Rollup bundle.

Why is 'use strict' usually after an IIFE (rather than at the top of a script)?

I've anecdotally noticed that use strict appears to be more common like this:
(function() {
'use strict';
...
Than this:
'use strict';
(function() {
...
The vanilla JS implementation of TodoMVC does this, for example.
Is there a reason for this?
Edit: I'm aware of the whole-file versus function-block distinction. TodoMVC is a good example to demonstrate why this placement is strange to me, because it doesn't rely on any external libraries, so the whole "play nice with non-strict third parties" doesn't apply here.
Declaring it in local scope will enforce function block to be considered under strict-mode by browser.
You can have non-strict observation for other code outside of the IIFE
Inside IIFE:
(function() {
"use strict";
a = 100;
})();
b = 200;
For entire script:
"use strict";
(function() {
try {
a = 100;
} catch (e) {
console.log(e + '');
}
})();
b = 200;
As highlighted in docs,
If you are using strict mode for entire script, it isn't possible to blindly concatenate non-conflicting scripts. Consider concatenating a strict mode script with a non-strict mode script: the entire concatenation looks strict! The inverse is also true: non-strict plus strict looks non-strict. Concatenation of strict mode scripts with each other is fine, and concatenation of non-strict mode scripts is fine. Only concatenating strict and non-strict scripts is problematic. It is thus recommended that you enable strict mode on a function-by-function basis (at least during the transition period).
You can also take the approach of wrapping the entire contents of a script in a function and having that outer function use strict mode. This eliminates the concatenation problem but it means that you have to explicitly export any global variables out of the function scope.
I’m guessing it’s because that placement is sure to enable strict mode even if multiple JS files are concatenated together as a build step (to allow organizing of code without the performance penalty of multiple HTTP requests). With placement of "use strict" at the beginning of the file, there could be a problem with these files:
foo.js
function doThing() {
console.log("done");
}
main.js
"use strict";
(function() {
document.getElementById('thingy').addEventListener("click", doThing);
})();
If the above files were concatenated with foo.js first, the "use strict" inside main.js would have no effect. This possibility could be avoided by putting the "use strict" inside the function.
I don’t know how common concatenation of JS is any more, and I don’t know whether the newer require method or import keyword lets you place "use strict" anywhere you want, but maybe the placement of "use strict" inside the function caught on while simple concatenation was popular, and people saw no reason to change the convention after using it for so long.
If you using:
'use strict';
(function() {
...
It will apply use strict mode to all file.
Opposite, when you using use strict in function like this:
// Non-strict code...
(function(){
"use strict";
...
// Define your library strictly...
})();
// Non-strict code...
That might be helpful if you have to mix old and new code.
Why Strict Mode At All
Strict mode eliminates certain permissive language parsing and execution characteristics deemed less desirable from a language design point of view. These non-strict mode language characteristics were deemed prudent as default behavior for backward compatibility. The synopsis and details appear here.
ECMA-262 7.0 Strict Mode Code
ECMA-262 7.0 Strict Mode in detail
It is not unambiguously defined when and if these older language characteristics from the early Netscape days will be deprecated or whether strict mode will become default behavior across browsers at some point, but the stricter model is likely to produce less ambiguous and risky source. If you wish to improving maintainability, portability, and extensibility in coding practice and code bases, then strict mode is a good option.
Syntax
"use strict";
Scope of Declaration
The scope of is dependent on whether you place the declaration inside or outside a function and applies to all statements following the declaration within the closure's scope.
Use of the declaration inside the function is the wrong way to do it if all of the file or stream is already compatible with the stricter mode or can be made so with ease. The redundancy is unnecessary, so placing the declaration on the top of the file or beginning of the stream is the recommended use.
Sometimes only some of the functions comply with the stricter rules. In such cases the less desirable function scope of the declaration can be used to encourage finer coding practices at least in the functions that already comply.
NOTE For those coming here from "What's the benefit of using "function() 'use strict'” in every file?"
You can place
"use strict";
on the top of the code sequence or inside the function, so it is only one line of code per file or per function.
The other lines of code have other purposes in the code here.
Self-invoking function
Factory invocation

What "use asm" does exactly?

As far as I know, Asm.js is just a strict specification of JavaScript, it uses the JavaScript features and it's not a new language.
For instance, instead of using var a = e;, it offers var a = e|0;.
My question is, if asm.js is just a definition and can be achieved by changing the way one uses and declares variables and dynamic types, what does "use asm"; actually do? Is this necessary to put this string before declaring function's body or not?
Asm.js is a very strict subset of JavaScript, that is optimized for machines rather than humans. If you want your browser to interpret certain code as asm.js code, you need to create a module wherein the following conditions apply :
all code is fully statically typed and limited to the very restrictive asm.js subset of JavaScript
your module starts with the "use asm" pragma
Additionally, an asm.js module allows only up to three optional yet very specific parameters :
a standard library object, providing access to a subset of the JavaScript standard libraries
a foreign function interface (FFI), providing access to custom external JavaScript functions
a heap buffer, providing a single ArrayBuffer to act as the asm.js heap
So, your module should basically look like this :
function MyAsmModule(stdlib, foreign, heap) {
"use asm";
// module body...
return {
export1: f1,
export2: f2,
// ...
};
}
The function parameters of your module allow asm.js to call into external JavaScript and to share its heap buffer with "normal" JavaScript. The exports object returned from the module allows external JavaScript to call into asm.js.
Leave out the "use asm", and your browser will not know that it should interpret your code as an asm.js module. It will treat your code as "ordinary" JavaScript. However, just using "use asm" is not enough for your code to be interpreted as asm.js. Fail to meet any of the other criteria mentioned hereabove, and your code will be also interpreted as "ordinary" JavaScript :
For more info on asm.js, see eg. John Resig's article from 2013 or the official specs.
"use asm" is a pragma that tells the JavaScript engine specifically how to interpret it. Although it's valid JavaScript and can be used without the pragma, FireFox can perform additional optimizations to the Asm.js subset to increase performance. To do this, it must know that it is Asm.js.

JScript 'import' syntax for ASP classic

I'm using an ASP "classic" server, with JavaScript as the language engine, specified by the directive:
<%#LANGUAGE='JAVASCRIPT'%>
I've noticed that `import' seems to be a keyword.
Technical Information (for support personnel)
* Error Type:
Microsoft JScript compilation (0x800A03F2)
Expected identifier
/Default.asp, line 4, column 4
var import = 'whut'
---^
How is the `import' keyword used, if at all?
Like in most programming languages, certain keywords are reserved. Javascript is a bit special since it reserves more keywords than are implemented in the language. Import is one of those words. Other examples are 'private' and 'void', though they are not implemented in the current releases.
From here:
The import statement allows a script
to import properties, functions and
objects exported by a signed script.
The following code imports the 'wine'
and 'beer' properties of the object
'drinks' provided they have been made
available by an exporting script
(compare the export statement):
Code: import drinks.beer, drinks.wine;
NOTE: Any exported script must be
loaded into a window, frame or layer
before it can be imported and used.
import is a reserved word in js, but I think it is only actually used in JScript.NET and ActionScript.
The full list of reserved words for JScript (although many are not used in the language) are:
abstract, boolean, break, byte, case, catch, char, class, const, continue, debugger,
default, delete, do, double, else, enum, export, extends, false, final, finally,
float, for, function, goto, if, implements, import, in, instanceof, int, interface,
long, native, new, null, package, private, protected, public, return, short, static,
super, switch, synchronized, this, throw, throws, transient, true, try, typeof, var,
volatile, void, while, with
Hope this helps.

Categories

Resources