Javascript array : why is this not valid? - javascript

I have the following working code :
var routes = [];
Eclipse validator for javascript prints the following warning :
Type mismatch: cannot convert from any[] to any
What is wrong with my empty array ?
Edit : the warning disappeared later. Apparently Eclipse was wrong and the question needs to be closed. Sorry about that.

Your JavaScript is valid, the problem is with JSDT plugin for Eclipse. In the latest version they introduced a type verification which is problematic in many situations - not only for empty arrays (like in your case). Another typical case may look like this: a = b || c;
The plugin will complain when b and c are of different types (which is absolutely valid code for JavaScript). There is several bugs already reported to JSDT developers about this problem, but the issues are not fixed yet.
Unfortunately currently it is not possible to switch off the type verification using JSDT configuration screen in Eclipse. I switched it off directly from the JSDT source code. To do this, please follow these steps:
Download the JSDT source code from Eclipse WebTools Project
Open the org.eclipse.wst.jsdt.debug.core project with Eclipse. Make sure you have Eclipse SDK installed. It might also be required to adjust some dependencies in the plugin.xml file.
The type verification is located in computeSeverity method of ProblemReporter class.
To switch off type verification replace the line: case IProblem.TypeMismatch: return ProblemSeverities.Warning; with case IProblem.TypeMismatch: return ProblemSeverities.Ignore;
Build the project and close Eclipse.
In Eclipse folder find the file named org.eclipse.wst.jsdt.core<version>.jar - make a safe copy of it, then open the jar file and replace the ProblemReporter.class file with the one you compiled in the step 5 (the file is in bin folder of your project).
Start Eclipse and clean your JavaScript project. All type checking will be ignored by JSDT.
Important! Make sure you've downloaded the same version of JSDT that you are using in Eclipse. Eventually instead of replacing a single file you can replace the entire plugin.
If you don't want to download and compile the plugin by yourself you can try with my fixed version. I've placed it on my FunctionSack webpage. I am using Eclipse 3.7 (Indigo) with JSDT 1.3.0, so make sure you have similar configuration if you want to use my file.

The eclipse's web tools platform plugin (wtp) includes a JavaScript validator that is somewhat allergic to the object literal "{}" and array literal "[]" notations, it also shows up some other annoying 'problems' such as 'missing semicolon' etc.
I have found the best solution for me and for my nerves is to disable the wtp's-embedded JavaScript validation completely and use a third-party plug-in.
Surprisingly it's not that easy to disable JavaScript validator. Every eclipse versions requires a different approach, so try the following guide:
In Eclipse prior to version 3.6 it was possible to disable javascript
validation via
'Window->Preferences->JavaScript->Validator->Errors/Warnings->[ ]
Enable JavaScript Semantic validation" - but this doesn't seem to
work in 3.7 Indigo see the eclipse bug
In 3.7 Indigo try Project -> Properties -> Builders - > [ ] JavaScript Validator
If doesn't help, try Project -> Properties -> JavaScript -> Include Path -> Source -> Excluded -> Edit -> Exclusion Patterns -> Edit -> */
If nothing above helps, open .project file and delete/comment out "<nature>org.eclipse.wst.jsdt.core.jsNature</nature>" line
After disabling the wtp validator you can try using a third party tool such as jsLint/jsHint

As what I observed in my testing so far, the problem occurs when you define a local variable in a function which body following a return keyword. This scenario can be shown in the following example (assuming the code is in a top level JavaScript file, means not inside any module/function so the first a is defined in global scope):
var a=[]; //Global variable assignment, no warnings
function f1(){ //global function
var a=[]; //level 1 local variable, no warnings
return a;
}
function f2(){ //local functions and member functions
var f = function(){
var a=[]; // no warinings
return a;
};
this.f = function(){
var a=[]; //no warnings
return a;
};
return f; //returning a defined funciton is OK
}
function f3(){ //returning a function
return function(){
var a=[]; //warning: Type mismatch: cannot convert from any[] to any
return a;
};
}
So the workaround is simple: change f3 to
function f3(){ //returning a defined function
var f = function(){
var a=[]; //warning is gone!
return a;
};
return f;
}

It's valid Javascript (assuming you're not writing it in some wierd context like the middle of an expression :P) so either the "Eclipse validator for javascript" is broken, or you're not using the "Eclipse validator for javascript" after all.

This is completely valid JS and sounds like Eclipse may be using the incorrect syntax plugin or something is ... well ... wrong.
You can confirm this by trying...
var routes = [];
routes.push({ url: '/' });
console.log(routes.length);

Related

Intellisense Javascript static namespacing

I'm trying to get intellisense in visual studio code. The following code works fine:
var Bar = function(){
}
Bar.prototype.logMsg = function(msg){
console.log(msg);
}
Intellisense working
But I don't recive any intellisense when writing:
var FOO = {};
FOO.Bar = function(){
}
FOO.Bar.prototype.logMsg = function(msg){
console.log(msg);
}
Not working
This might be due to restrictions I'm not aware of, but I can't find any documentation/posts mentioning this. Is there a way to get it working without rewriting big parts?
I work on TypeScript and JavaScript support in VSCode. As of VSCode 1.8.1, this type of dynamic property assignment is not something that our IntelliSense recognizes.
We use TypeScript to power both our TypeScript and JavaScript IntelliSense, and while TypeScript is able to recognize the common prototype pattern shown in your first example, it does not recognize properties added to an object, as in your second example. This means that FOO.Bar will always have an any type.
We're tracking support for this type of IntelliSense in the TypeScript project: https://github.com/Microsoft/TypeScript/issues/13271

Firefox add-on. How to really dowload image/file?

I'm getting more and more downhearted. For the last three days, I've been trying to add to my simple Firefox add-on a 'download image' feature.
The following is an add-on that creates a right-click contextual menu with a sub-menu:
var contextMenu = require("sdk/context-menu");
var clipboard = require("sdk/clipboard");
var data = require("sdk/self").data;
var myApp_cm = contextMenu.Menu({
label: "Send to myApp",
context: contextMenu.SelectorContext("body"),
items: [
contextMenu.Item({
label: "Send image to MyApp",
context: contextMenu.SelectorContext("img"),
contentScript: 'self.on("click", function (node, data) { ' +
' var link = node.src; ' +
' self.postMessage(link); ' +
'});',
onMessage: function(link) {
//
// Download image from 'link' and run 'myApp.exe' with
// downloaded image as parameter
//
}
})
]
});
I would like to add to the above code a simple download feature as the "Save as..." option of Firefox that downloads the image from the selected URL and runs an EXE with the downloaded image as a parameter.
I read everything I found about this argument starting from Mozilla MDN to all the questions asked at Stackoverflow. But, I never managed to make a single line of code work. I really don't understand why it's so complicated to download a file when this is the browser's job.
For example, I know that from Firefox 26+ I need to use downloads.jsm. So, I copied the following code from MDN.
Components.utils.import("resource://gre/modules/Downloads.jsm");
Components.utils.import("resource://gre/modules/osfile.jsm")
Components.utils.import("resource://gre/modules/Task.jsm");
Task.spawn(function () {
yield Downloads.fetch("http://www.mozilla.org/",OS.Path.join(OS.Constants.Path.tmpDir,"example-download.html"));
console.log("example-download.html has been downloaded.");
}).then(null, Components.utils.reportError);
But, I keep getting the error below:
So I added the string let {Cu, Ci, CC} = require('chrome') but nothing changes.
I'm 43 years old and I'm still learning JavaScript. I'm aware I don't have the same flexibility I had 2 decades ago. But, I remember that programming was much more straightforward. I still love programming but now I often find it quite frustrating.
I have not actually tried it, but I would not not expect the destructuring assignment
let {Cu, Ci, Cc} = require('chrome');
[Note: your CC should be Cc.]
to provide your Add-on SDK code to have access to the complete Components object through referencing it as Components, but only to have the properties (sub-objects) which you have assigned to "aliases" be available through the objects that you have defined using let:
Object ("alias") now available Object full name normally available
to your SDK add-on to Overlay and Restartless add-ons
Cu = Components.utils
Ci = Components.interfaces
Cc = Components.classes
The destructuring assignment should have extracted just the properties (sub-objects) referred to as Cu, Ci, and Cc within requre('chrome').
The code you copied from MDN would need to change to:
Cu.import("resource://gre/modules/Downloads.jsm");
Cu.import("resource://gre/modules/osfile.jsm")
Cu.import("resource://gre/modules/Task.jsm");
Task.spawn(function () {
yield Downloads.fetch("http://www.mozilla.org/",
OS.Path.join(OS.Constants.Path.tmpDir,"example-download.html"));
console.log("example-download.html has been downloaded.");
}).then(null, Cu.reportError);
If you wanted to use Components without using the Cc, Ci, Cu, Cr, and Cm aliases, you would need to use:
let {components} = require('chrome'); // note the lowercase "components"
let Components = components;
With that you could then use your original code:
Components.utils.import("resource://gre/modules/Downloads.jsm");
Components.utils.import("resource://gre/modules/osfile.jsm")
Components.utils.import("resource://gre/modules/Task.jsm");
Task.spawn(function () {
yield Downloads.fetch("http://www.mozilla.org/",
OS.Path.join(OS.Constants.Path.tmpDir,"example-download.html"));
console.log("example-download.html has been downloaded.");
}).then(null, Components.utils.reportError);
For more information, you can see the Chrome Authority page on MDN.
So, I copied the following code from MDN.
This is a big part of your problem. You're copying code without reasoning about it. Code snippets generally have prerequisites and assumptions that must be fulfilled, i.e. they must be evaluated on specific contexts - npm modules won't run in a browser for example.
Those code snippets too have dependencies, e.g. the Components object. The error message warns you about that, so that might be a good hint to read the documentation on require("chrome") and Components.
The second issue is that you're trying to use JSMs in an SDK addon without looking for equivalent SDK APIs first. Note that the top-level MDN Addon page distinguishes several types of extensions, especially SDK and legacy extensions. You're writing an SDK extension.
So for the purpose of downloading images instead of going through the file download manager (Downloads.jsm) you can simply use the request and IO SDK modules to download the file and then child_process to spawn the exe.
Task.spawn(function () {
yield Downloads.fetch("http://www.mozilla.org/",
That's using yield outside a generator function, which is legacy syntax and should not be used.
For chaining you probably should use ES6 promises instead.

Does Webstorm support autosuggestion for Revealing-Module-Pattern in different Files

When I try to use the autosuggestion in Webstorm(V 10.0.4/ Linux machine)
with the Revealing-Module-Pattern and the definition of the module is in one File like this:
var testModule = testModule || (function(){
function myPrivateTestFunction(){
console.log("test");
}
return{
test: myPrivateTestFunction
}
})();
in another File I try to call the the function by:
testModule.test();
it correctly finds the module-object, defined in the other file but doesn't find the function.
If I look at the settings: File->Settings->Javascript
There is an option called "Weaker type guess for completion".
If I enable this, it indeed shows my desired function testModule.test().
But it also shows all private members of the module and of all other modules, defined somewhere, so this doesn't make sense to me.
Logged as WEB-18186, please vote for it to be notified on updates
The feature was implemented by the Webstorm Team.
I tested it (in the Early Access Program Version 142.5255).
It works perfectly!
Thanks to the Webstorm-Team who implemented the feature that fast and to lena who created the ticket!

How do I use uncompressed files in Dojo 1.7?

I've created a Dojo module which depends on dojox/data/JsonRestStore like this:
define("my/MyRestStore",
["dojo/_base/declare", "dojox/data/JsonRestStore"],
function(declare, JsonRestStore) {
var x = new JsonRestStore({
target: '/items',
identifier: 'id'
});
...
which is fine. But now I want to have the the uncompressed version of the JsonRestStore code loaded so that I can debug it. I can't find any documentation on how to do this, but since there is a file called 'JsonRestStore.js.uncompressed.js' I changed my code to:
define("my/MyRestStore",
["dojo/_base/declare", "dojox/data/JsonRestStore.js.uncompressed"],
function(declare, JsonRestStore) {
...
thinking that might work.
I can see the JsonRestStore.js.uncompressed.js file being loaded in FireBug, but I get an error when trying to do new JsonRestStore:
JsonRestStore is not a constructor
Should this work?
Is there a way of configuring Dojo to use uncompressed versions of all modules? That's what I really want, but will settle for doing it on a per dependency basis if that's the only way.
Update
I've found a way to achieve what I want to do: rename the JsonRestStore.js.uncompressed.js file to JsonRestStore.js.
However, this seems a bit like a hacky workaround so I'd still be keen to know if there is a better way (e.g. via configuration).
You have two options
1) Create a custom build. The custom build will output a single uncompressed file that you can use for debugging. Think the dojo.js.uncompressed.js but it includes all the extra modules that you use.
OR
2) For a development environment, use the dojo source code. This means downloading the Dojo Toolkit SDK and referencing dojo.js from that in the development environment.
For the projects I work on, I do both. I set up the Dojo configuration so that it can be dynamic and I can change which configuration that I want using a query string parameter.
When I am debugging a problem, I will use the first option just to let me step through code and see what is going on. I use the second option when I am writing some significant js and don't want the overhead of the custom build to see my changes.
I describe this a bit more at
http://swingingcode.blogspot.com/2012/03/dojo-configurations.html
I think the reason for this is due to the fact that the loader declares its class-loads (modules), by the file conventions used. The 1.7 loader is not too robust just yet, ive had similar problems until realizing how to separate the '.' and '/' chars.
Its only a qualified guess; but i believe it has to do with the interpretation of '.' character in the class-name which signifies as a sub-namespace and not module name.
The 'define(/ * BLANK * / [ / * DEPENDENCIES * / ], ...)' - where no first string parameter is given - gets loaded by the filename (basename). The returned declare also has a saying though. So, for your example with jsonrest, its split/parsed as such:
toplevel = dojox
mid = data
modulename = JsonRestStore.js.uncompressed
(Fail.. Module renders as dojox.data.JsonRestStore.js.uncompressed, not dojox.data.JsonRestStore as should).
So, three options;
Load uncomressed classes through <script src="{{dataUrl}}/dojox/data/JsonRestStore.js.uncompressed.js"></script> and work them on dojo.ready
I think modifying the define([], function(){}) in uncompressed.js to define("JsonRestStore", [], function() {}) would do the trick (uncomfirmed)
Use the dojo/text loader, see below
Text filler needed :)
define("my/MyRestStore",
["dojo/_base/declare", "dojo/text!dojox/data/JsonRestStore.js.uncompressed.js"],
function(declare, JsonRestStore) {
...
JsonRestStore = eval(JsonRestStore);
// not 100% sure 'define' returns reference to actual class,
// if above renders invalid, try access through global reference, such as
// dojox.dat...

Exclude debug JavaScript code during minification

I'm looking into different ways to minify my JavaScript code including the regular JSMin, Packer, and YUI solutions. I'm really interested in the new Google Closure Compiler, as it looks exceptionally powerful.
I noticed that Dean Edwards packer has a feature to exclude lines of code that start with three semicolons. This is handy to exclude debug code. For instance:
;;; console.log("Starting process");
I'm spending some time cleaning up my codebase and would like to add hints like this to easily exclude debug code. In preparation for this, I'd like to figure out if this is the best solution, or if there are other techniques.
Because I haven't chosen how to minify yet, I'd like to clean the code in a way that is compatible with whatever minifier I end up going with. So my questions are these:
Is using the semicolons a standard technique, or are there other ways to do it?
Is Packer the only solution that provides this feature?
Can the other solutions be adapted to work this way as well, or do they have alternative ways of accomplishing this?
I will probably start using Closure Compiler eventually. Is there anything I should do now that would prepare for it?
here's the (ultimate) answer for closure compiler :
/** #const */
var LOG = false;
...
LOG && log('hello world !'); // compiler will remove this line
...
this will even work with SIMPLE_OPTIMIZATIONS and no --define= is necessary !
Here's what I use with Closure Compiler. First, you need to define a DEBUG variable like this:
/** #define {boolean} */
var DEBUG = true;
It's using the JS annotation for closure, which you can read about in the documentation.
Now, whenever you want some debug-only code, just wrap it in an if statement, like so:
if (DEBUG) {
console.log("Running in DEBUG mode");
}
When compiling your code for release, add the following your compilation command: --define='DEBUG=false' -- any code within the debug statement will be completely left out of the compiled file.
A good solution in this case might be js-build-tools which supports 'conditional compilation'.
In short you can use comments such as
// #ifdef debug
var trace = debug.getTracer("easyXDM.Rpc");
trace("constructor");
// #endif
where you define a pragma such as debug.
Then when building it (it has an ant-task)
//this file will not have the debug code
<preprocess infile="work/easyXDM.combined.js" outfile="work/easyXDM.js"/>
//this file will
<preprocess infile="work/easyXDM.combined.js" outfile="work/easyXDM.debug.js" defines="debug"/>
Adding logic to every place in your code where you are logging to the console makes it harder to debug and maintain.
If you are already going to add a build step for your production code, you could always add another file at the top that turns your console methods into noop's.
Something like:
console.log = console.debug = console.info = function(){};
Ideally, you'd just strip out any console methods, but if you are keeping them in anyway but not using them, this is probably the easiest to work with.
If you use the Closure Compiler in Advanced mode, you can do something like:
if (DEBUG) console.log = function() {}
Then the compiler will remove all your console.log calls. Of course you need to --define the variable DEBUG in the command line.
However, this is only for Advanced mode. If you are using Simple mode, you'll need to run a preprocessor on your source file.
Why not consider the Dojo Toolkit? It has built-in comment-based pragma's to include/exclude sections of code based on a build. Plus, it is compatible with the Closure Compiler in Advanced mode (see link below)!
http://dojo-toolkit.33424.n3.nabble.com/file/n2636749/Using_the_Dojo_Toolkit_with_the_Closure_Compiler.pdf?by-user=t
Even though its an old question. I stumbled upon the same issue today and found that it can be achieved using CompilerOptions.
I followed this thread.
We run the compiler, from Java, on our server before sending the code to the client. This worked for us in Simple mode.
private String compressWithClosureCompiler(final String code) {
final Compiler compiler = new Compiler();
final CompilerOptions options = new CompilerOptions();
Logger.getLogger("com.google.javascript.jscomp").setLevel(Level.OFF);
if (compressRemovesLogging) {
options.stripNamePrefixes = ImmutableSet.of("logger");
options.stripNameSuffixes = ImmutableSet.of("debug", "dev", "info", "error",
"warn", "startClock", "stopClock", "dir");
}
CompilationLevel.SIMPLE_OPTIMIZATIONS.setOptionsForCompilationLevel(options);
final JSSourceFile extern = JSSourceFile.fromCode("externs.js", "");
final JSSourceFile input = JSSourceFile.fromCode("input.js", code);
compiler.compile(extern, input, options);
return compiler.toSource();
}
It will remove all the calls to logger.debug, logger.dev...etc.etc
If you're using UglifyJS2, you can use the drop_console argument to remove console.* functions.
I use this in my React apps:
if (process.env.REACT_APP_STAGE === 'PROD')
console.log = function no_console() {};
In other words, console.log will return nothing on prod enviroment.
I am with #marcel-korpel. Isn't perfect but works. Replace the debug instructions before minification. The regular expression works in many places. Watch out unenclosed lines.
/console\.[^;]*/gm
Works on:
;;; console.log("Starting process");
console.log("Starting process");
console.dir("Starting process");;;;;
console.log("Starting "+(1+2)+" processes"); iamok('good');
console.log('Message ' +
'with new line'
);
console.group("a");
console.groupEnd();
swtich(input){
case 1 : alert('ok'); break;
default: console.warn("Fatal error"); break;
}
Don't works:
console.log("instruction without semicolon")
console.log("semicolon in ; string");
I haven't looked into minification so far, but this behaviour could be accomplished using a simple regular expression:
s/;;;.*//g
This replaces everything in a line after (and including) three semicolons with nothing, so it's discarded before minifying. You can run sed (or a similar tool) before running your minification tool, like this:
sed 's/;;;.*//g' < infile.js > outfile.js
BTW, if you're wondering whether the packed version or the minified version will be 'better', read this comparison of JavaScript compression methods.
I've used following self-made stuf:
// Uncomment to enable debug messages
// var debug = true;
function ShowDebugMessage(message) {
if (debug) {
alert(message);
}
}
So when you've declared variable debug which is set to true - all ShowDebugMessage() calls would call alert() as well. So just use it in a code and forget about in place conditions like ifdef or manual commenting of the debug output lines.
I was searching for a built-in option to do this. I have not found that yet, but my favorite answer also does not require any changes to existing source code. Here's an example with basic usage.
Assume HTML file test.html with:
<html>
<script src="hallo.js"></script>
</html>
And hallo.js with:
sayhi();
function sayhi()
{
console.log("hallo, world!");
}
We'll use a separate file, say noconsole.js, having this from the linked answer:
console.log = console.debug = console.info = function(){};
Then we can compile it as follows, bearing in mind that order matters, noconsole.js must be placed first in the arguments:
google-closure-compiler --js noconsole.js hallo.js --js_output_file hallo.out.js
If you cat hallo.out.js you'd see:
console.log=console.debug=console.info=function(){};sayhi();function sayhi(){console.log("hallo, world!")};
And if I test with mv hallo.out.js hallo.js and reload the page, I can see that the console is now empty.
Hope this clarifies it. Note that I have not yet tested this in the ideal mode of compiling all the source code with ADVANCED optimizations, but I'd expect it to also work.

Categories