Rework Function (capital F) - javascript

I am trying to get a Javascript speex library to run within a CSP protected environment. It runs great without CSP and I already fixed most "eval" problems. However - this one is giving me a headache:
this.interpolate = Function("buffer", toCompile);
See: https://github.com/grantgalitz/XAudioJS/blob/master/resampler.js
I tried something like
this.interpolate = function buffer () { return toCompile };
but that didn't work. Though I understand the .. well, basics of "Function" versus "function", I can't find working fix.
Any help is appreciated.
Michaela

Related

Bind class instance function to v8::FunctionTemplate

I'm fairly new to C++ and v8 in general, and I wanted to build a native node.js addon, but now I'm stuck on something quite simple IMO, but I can't figure out what the issue is, the error message
C:\Path\To\Project\File.cpp(50): error C2664: 'v8::Local<v8::FunctionTemplate> v8::FunctionTemplate::New(v8::Isolate *,v8::FunctionCallback,v8::Local<v8::Value>,v8::Local<v8::Signature>,int,v8::ConstructorBehavior,v8::SideEffectType)': cannot convert argument 2 from 'v8::Local<v8::Value> (__cdecl *)(const v8::FunctionCallbackInfo<v8::Value> &)' to 'v8::FunctionCallback' [C:\Path\To\Project\build\node_gui.vcxproj]
is not that helpful.
I've got the following code,
v8::Local <v8::Object> Window::GetFunctions() {
v8::Local <v8::Object> DrawFunctions = v8::Object::New(isolate);
v8::Local <v8::FunctionTemplate> bgfnc = v8::FunctionTemplate::New(isolate, &Window::BackgroundCB);
DrawFunctions->Set(v8::String::NewFromUtf8(isolate, "background"), bgfnc);
return DrawFunctions;
}
void Window::Background(const v8::FunctionCallbackInfo <v8::Value> &args) {
v8::Isolate *isolate = args.GetIsolate();
renderer->Background(args[0]->NumberValue(), args[1]->NumberValue(), args[2]->NumberValue());
}
v8::Handle <v8::Value> BackgroundCB(const v8::FunctionCallbackInfo <v8::Value> &args) {
return ((Window*)v8::External::Cast(*(args.Data())->Value())->Background());
}
I want to create an object that contains a list of functions, the functions' callbacks would be member functions of the Window class. I know this has been asked before here, which worked once using a non-member function but otherwise not.
Thanks
Sidenote: I've looked far and wide for v8 docs that are suitable for beginners, the nodesource ones don't explain what the parameters mean or rarely give a thorough example of how to use the function / class, if anyone knows some better docs, that would be great, thank you.
Thanks to the gracious and prompt help of the community, I was able to quickly and effortlessly resolve this issue. Turns out, when writing NodeJS addons, it's a good idea to use NodeJS's own N-API, as the documentation is simpler, clearer, and most importantly, existant.

CreateJS - Type not recognized error thrown during sound registration

I am trying to load sounds through the SoundJS sound registration, and getting the following error:
createjs.js:15 Uncaught Error: Type not recognized.
I figure that the soundjs library is having issues either locating my files or having trouble with the file extensions, but I am using .ogg, which is inline with all the examples I've seen.
Here is my code:
createjs.Sound.alternateExtensions = ["mp3", "ogg"];
createjs.Sound.on("fileload", function(event) {
console.log(event);
}, this);
for (var i = 0; i < soundManifest.length; i++) {
soundManifest[i].loaded = false;
console.log("loading " + soundManifest[i].src);
createjs.Sound.registerSound(soundManifest[i].src, soundManifest[i].id)
}
soundManifest is an array of objects with a source item giving the path to the .ogg files, and an id. I've double and triple checked the path names, so pretty sure that's not it. Any ideas? I am developing on Chrome.
Thanks for posting a github link. It was helpful. Fortunately, I have a super simple answer for you.
Rename the "Object" class you made in Main.js, and you should be good to go.
-- The long answer --
I tossed a breakpoint the error that is thrown, and it showed that when SoundJS tries to create a LoadItem, it fails. This is because it should be treating the LoadItem it receives as an Object, but the line below is failing:
} else if (value instanceof Object && value.src) {
// This code should be executed
}
At first I thought there was a bug in SoundJS that we had somehow missed in the last 2 years, but closer inspection showed that object prototypes in your application are messed up. If you open any browser window, and hit the console, this will return true:
({}) instanceof Object
// true
However while running your app, it returns false.
The issue became clear when I removed all your other classes other than CreateJS and main, and then tried this:
new Object();
// Throws an error that includes info about "Victor"
In main.js, you are defining an "Object" class, which extends a CreateJS Shape. It is global because there is no method closure around the code, so it overwrites the global Object class/prototype.
The reason I included this explanation, is because I couldn't figure out what was going on until I had my steps to show that prototypes were broken in the app mostly written out before the reason dawned on me. I thought it might be of some interest :)

Cannot wrap my head around Immediately Invoking Anonymous Functions in Javascript

I have been studying framework development for a few weeks, and I ran across what is highly suggested and pressured in the world of lib development, Immediately-invoking Anonymous Functions.
I never can get it to work, and I have failed to find a resource that explains in-detail the use and logic behind it.
Here's what I know so far:
It's immediately invoking - It runs everything anonymously, immediately.
It's anonymous - It does not carry a name therefore the code inside of it is not "reachable" by exterior code.
You can pass global window, object and undefined parameters - That's about all I know on that, but do not understand them completely.
I am looking not only for a detailed resource, but one that explains the logic behind it. Because I find it very illogical.
Here's what I have:
(function( window, document, undefined ) {
window.myThingy = myThingy;
var myThingy = function() {
};
myThingy.prototype = {
constructor: myThingy,
create: function( elementToBeCreated ) {
return document.createElement( elementToBeCreated );
}
};
})( window, document );
Then,
myThingy().create("div");
But it is still saying myThingy() [object] is not a function.
What am I doing wrong? Why should I use immediately-invoking functions and not just create a global myThingy = function() object? Why do I have to use window?
I know there are several resources on the net about this, but I can't understand any of it. Some of them go half-way into detail, some of them try to go into detail, but fail to explain the critical stuff. Why is this so stressed when developing a framework?
Don't worry, I'm not trying to "re-invent the wheel", but I am trying, however, to actually learn JavaScript, not just the pre-packaged stuff.
A good answer should contain:
A good resource where it explains the logic behind immediately invoking anonymous functions
An insight to that link
What I am doing wrong with the code I provided
First off, you have not yet defined your function when you try to assign it to the global object so it is undefined:
window.myThingy = myThingy;
console.log(myThingy);//undefined
You need to do the assignment after myThingy is defined:
(function( window, document, undefined ) {
var myThingy = function() {
};
myThingy.prototype = {
constructor: myThingy,
create: function( elementToBeCreated ) {
return document.createElement( elementToBeCreated );
}
};
window.myThingy = myThingy;
})( window, document );
Okay, next, you cannot use
myThingy.create("div");
because myThingy is a function and not an object. Function objects are created when the new keyword is issued to a function. You can make this change to convert your function into a function object:
window.myThingy = new myThingy();//create a function object
This pattern is not how all frameworks are implemented, but similar. Sometimes there is more abstraction. However, making these changes will allow your approach to work.
Here is a demo of your code: http://jsfiddle.net/ZjRJW/
Links
Here are some of my favorites:
http://ejohn.org/blog/simple-class-instantiation/
http://ejohn.org/apps/learn/
http://ejohn.org/blog/simple-javascript-inheritance/
http://jibbering.com/faq/notes/closures/
https://developer.mozilla.org/en-US/docs/JavaScript/Guide/Details_of_the_Object_Model
http://javascript.crockford.com/prototypal.html
If you want to learn about JS design patterns, I highly recommend Addy Osmani's books/articles. He keeps things very simple and usually supplies quite a bit of example code to help you understand. As far as your code and implementing a design pattern is concerned, it depends on what you want your code to do, and how you want your code/objects to behave. Understanding your requirements/goals are very important before you start coding so you don't get lost in a spaghetti of patterns that really aren't solving a specific problem.
In some cases, implementing a pattern intended for a complex, large application is simply overkill.
Since someone else already correctly pointed out the issues with your code, I'll just leave it there.

How to check if 'debugger;' keyword exists?

Sometimes some developers forgot to remove debugger; in javascript code, and it produce javascript error on IE.
How can you check (like for the console: if(window.console){console.log('foo');}) if a debugger exists?
BTW: I don't want to detect if the browser is IE, I want a generic method if possible
Thanks,
You cannot.
The best solution would be adding a hook to your version control system to prevent code containing debugger; statements from being committed/pushed.
Asking your devs to search for debugger; or at least have a careful look at the diff before committing is also a solution - but not as effective as hard-rejecting in the VCS.
You could attempt to compile a function that declares debugger as a local variable. If debugger is reserved as a keyword, the JS engine will throw an error which you can catch.
var debuggerIsKeyword = false;
try {
new Function("var debugger;");
} catch(e) {
debuggerIsKeyword = true;
}
However I'm not sure that knowing whether a keyword exists or not is actually helpful.
Maybe the safest approach is to have a global include file for all your projects that stubs out the debugger if it doesn't exist:
if (typeof debugger == 'undefined') {
window.debugger = null;
}
That way calls to debugger just become a reference to null. which is harmless. Seems like a better approach than expecting forgetful developers to wrap each debugger call in an if statement.
The same approach works for console.log, etc.
EDIT: As AndrewF points out, debugger is actually a keyword, not a global, so this won't work. The same effect can be achieved using the following without throwing an error:
window['debugger'] = null;
Haven't tried it for lack of an IE, but this should work:
if (typeof console !== 'undefined') {
console.log("logging enabled");
}

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