JScript 'import' syntax for ASP classic - javascript

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.

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.

Is using an ES6 import to load specific names faster than importing a namespace?

I've found at least two ways to import functions in from a module like Ramda for example. There are probably a few more ways to do something very similar like const R = require('ramda');
Option 1 is to import certain functions:
import { cond, T, always, curry, compose } from 'ramda';
Option 2 is to import the whole module like:
import * as R from "ramda";
I would prefer to reference the module from which the function is being called like so:
R.T();
But if the 2nd option is used, does it bring in every Ramda function not just the ones used in a module I'm working in? Are there any impacts on actual memory use, or bandwidth use as far as what gets sent to the browser if option 2 is used?
Is it possible to somehow do this:
// invalid syntax below:
import R { cond, T, always, curry, compose } from 'ramda';
R.T();
My question is kinda related to this one, but it's a bit different
import R (ramda) into typescript .ts file
TL;DR: It does not matter.
import * as … from 'ramda';
import { … } from 'ramda';
will both by default always bring in the complete Ramda module with all its dependencies. All code inside the module would be run, and which syntax was used to reference the exported bindings doesn't matter. Whether you use named or namespaced imports comes down to preference entirely.
What can reduce the file size to download and the used memory is static analysis. After having evaluated the module, the engine can garbage-collect those bindings that are referenced from nowhere. Module namespace objects might make this slightly harder, as anyone with access to the object can access all exports. But still those objects are specified in a way (as immutable) to allow static analysis on their usage and if the only thing you're doing with them is property access with constant names, engines are expected to utilise this fact.
Any size optimisation involves guessing which parts of the module need to be evaluated and which not, and happens in your module bundler (like Rollup or WebPack). This is known as Tree Shaking, dropping parts of the code and entire dependencies when not needed (used by anything that got imported). It should be able to detect which imports you are using regardless of the import style, although it might have to bail out when are doing unusual things with the namespace object (like looping it or using dynamic property access).
To learn about the exact guesses your bundler can make, contact its documentation.
#Bergi is right in his comment, which I think should be the answer. I would also like to point out you can always try things out in Babel to see what it compiles to: click here to see what an example destructuring actually does
So basically even if you destructure just one function from the module, the whole module will be required. In the Babel example I gave, I just extracted Component from the 'react' module, but the compiled code actually just required the whole thing. :)
Adding to #Bergi, Also just for future reference if you want to shed unused functions and import only the desired function, use selective import like below
import isEmpty from 'ramda/src/isEmpty';
This way you can complement it with Webpack and get a better tree shaking. Hope it helps

Is there a `declare` keyword in ES6/7?

Recently I've been studying ES6, and that lead to me using Babel a lot. Being the curious type, I started looking at the Babel Github repository to know how they built this awesome tool, and know if I can somehow contribute.
However, I came across this file, and it has things like declare class BabelNodeSourceLocation {} written all over it, and the file ends with .js.
This got me very confused, and I am now wondering whether there's a declare keyword in JavaScript that I didn't know of, or is this just a Babel-specific syntax? All my Google searches resulted in nothing.
Update: Putting the code in the Babel REPL resulted in nothing. Babel just ignored the code and did not produce any equivalent ES5 output. It also did not throw any error.
and the file ends with .js.
That doesn't mean a lot these days :-)
I am wondering whether there's a declare keyword in JavaScript that I didn't know of
No, there is not.
Or is this just a Babel-specific syntax?
No. It is a type declaration file for the Flow typechecker.
With Flow, you can declare a global class that allows you to reference the class type anywhere in your project. This has no affect on runtime code and won't affect babel output.
An example from the docs:
declare class URL {
constructor(urlStr: string): URL;
toString(): string;
static compare(url1: URL, url2: URL): boolean;
};
And then in your project you can reference URL as a class type.
Similarly, you can declare other global Types, Modules, Functions, Variables. A good way to keep them organized.

Is ES6 imported code strict?

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).

Categories

Resources