Set "use strict" for plugins - javascript

I'm writing a JavaScript-Software that is able to load and work with plugins.
These plugins can also be written by other users.
Now I want to modify my plugin-manager, that it sets the "use strict"-option for all the modules - is this possible?
This is how the plugins are currently written:
"use strict"; //I want to add this command automatically by the plugin-manager
window.pluginName = {
"version": "0.1",
"attribute": function(){},
...
}
How Plugins are being loaded:
I make an ajax-Request to the js-File (which contains exacly one plugin). When the file is ready, I access it via "var newPlugin = window[pluginName];"
Is is possible to automatically use strict-mode, or do I have to rely that the plugin-writer uses this flag for debugging?

Strict mode is defined in variable scope, so the only way to set "use strict" for each plugin is to put the declarative in the functions at the top, or in some function that encompasses all the plugin definitions.
The only other way to affect all plugins would be to define it globally, and that wouldn't be a good idea unless you're absolutely certain that all JavaScript that will run will work properly in strict mode.

Related

Rhino w. Closure compiler generating already existing functions

I'm using closure compiler to optimize a require.js project.
I'm using an "app.build.js" file like this method suggests:
http://requirejs.org/docs/optimization.html#wholeproject
the optimize option is set to "closure" and I run it in Java through Rhino like this:
java -classpath ./tools/lib/rhino/js.jar;./tools/lib/closure/compiler.jar org.mozilla.javascript.tools.shell.Main ./tools/require/r.js -o app.build.js dir=./temp optimize=closure
I'm using this config for closure compiler in app.build.js:
closure: {
CompilerOptions: {},
CompilationLevel: 'SIMPLE_OPTIMIZATIONS',
loggingLevel: 'WARNING'
}
After fixing some ERRORS due to the "use strict" rules, everything works fine and my project gets minified in one file.
This is when running the build on Window 10.
But if I run it on another machine (under Ubuntu 16.04), some methods are name "on" by closure compiler. Thus at runtime, when I try to register a listener using "this.on("EVENT"..."
It calls a random method and crash everything.
Note that "this.on" was defined in the parent class (using require extends mechanism). I've try to define it in the current class instead: closure compiler create another "on" method anyway, right next to it, which overrides the first one at runtime :'(
I'v tried to optimize only the corresponding file alone: The issue is still present, except another method is named "on", the other are named "o0" "oa" etc...
Has anyone ever exprience such a problem and do you know how to avoid it ?
Maybe some compiler options I'm not aware of?
I'm using closure-compiler v20180204 (current last one)
Edit:
Seems like closure compiler is not responsible here. Indeed, using closure comp in SIMPLE mode doesn't rename anything. and using closure compiler in ADVANCED mode by itself (java -jar closure.jar ...) is working just fine.
So the question is: do Rhino apply some renaming rules when using the optimization="closure" mode?
If it's the case, can we edit those rules in any mean?

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

Loading jQuery inside an ES5 strict mode function

I'd like to import jQuery inside an IIFE scope like this:
(function (window, document) {
"use strict";
/* Content of jquery.min.js goes here */
/* Code that uses $ goes here */
}(window, document));
Now, I'm running into a strict mode violation as soon as this code runs, possibly because jQuery itself doesn't conform:
In strict mode code, functions may be declared only at top level or
immediately within another function.
Is there a way to load jQuery just inside a single function scope, while still retaining strict mode for the rest of the code that relies on it?
Answered here: https://github.com/jquery/jquery/issues/1779
jQuery isn't meant to be run with "use strict" in effect. See the comment at the top of the unminified file for the reason, or look at http://bugs.jquery.com/ticket/13335 for more information. You are not gaining anything by attempting to force jQuery into strict mode against its will, doing so prevents interoperability with any third-party libraries that are not use-strict compatible.

Exposing almond module to window object fails due to asynchronicity

I am working on a JavaScript project where we use requirejs to manage our code. The product we create is to be used on 3rd party web sites, and therefore we cannot assume that an AMD compatible library is present. To solve this, we include almond in our target file and expose our main module on window. The file created by our build looks like this:
(function() {
//Almond lib
//Our code
define('window-exposer', ['main-module'], function(mainModule) {
window.mainModule = mainModule;
});
require('window-exposer');
}());
When building a site that want to use mainModule an error is thrown because when the site specific code tries to access window.mainModule it has not been set yet. There are also cases where the module has indeed been initialized and the code works.
Is there any way to guarantee that the window-exposer is run before other JavascriptCode is?
I solved it by using the solution provided here https://github.com/jrburke/almond#exporting-a-public-api

assets pipeline control coffee script's closures

I have 2 simple coffee scripts and assets pipeline. I obtained:
(function() {
window.App.Test_widget = {...}
}).call(this);
(function() {
$.widget("ui.Test_widget", window.App.Test_widget);
$(document).ready(function() {...});
}).call(this);
but I want 1) merge closures 2) add closure parameter
(function($) {
var App;
App.Test_widget = {...}
$.widget("ui.Test_widget", App.Test_widget);
$(document).ready(function() {...});
})(jQuery);
I cant google a way of implementing this
UPD:
1) I dont want to place each file in different closures. I want to control this
2) I dont want to put anything in window if it is possible
ANSWER is simply: "use bare option. for sprockets see commit"
If you want that level of fine-grained control over output, you'll have to write your JavaScript yourself rather than allowing CoffeeScript to do it for you. I say that as an advocate of CoffeeScript: If you use it, you have to accept certain conventions that go along with it, such as the wrapper that gives each file its own scope. You lose the freedom to concatenate files however you want in order to share variables across files.
It's worth mentioning, however, that
In CoffeeScript 1.2.0+, the wrapper is added only when necessary. At least in your first file, that's not the case. (Edit: I was mistaken about this; this feature existed in 1.1.3 but disappeared before 1.2.0)
Writing $ = jQuery at the top of a function is semantically equivalent to having an argument named $ and passing in jQuery as the value of that argument. So you need only put $ = jQuery at the top of each of your CoffeeScript files in order to use jQuery in noConflict mode.
I think what you're describing is a deferred...you want to do something after your two closures finish? If so then look into jQuery 1.5 deferred infrastructure.

Categories

Resources