Performance userscript injecting code - greasemonkey

I have a question about userscripts. Is it faster to have this in before or after of the main function initiateFlasher?
if (typeof unsafeWindow !== 'undefined' && unsafeWindow.jQuery) {
initiateFlasher(unsafeWindow.jQuery);
} else {
function addScript(callback) {
var script = document.createElement('script');
script.text = '(' + callback.toString() + ')();';
document.body.appendChild(script);
}
addScript(initiateFlasher);
}
function initiateFlasher(arg) {}

The speed difference will be negligible.
But it's better form to define initiateFlasher() first. (When in doubt, use jslint.com.)
This is a good habit to get into because, even though a function declaration will work on most browsers before or after, function expressions or function constructors will not.

Related

Predefine callback parameters within class

I have a Command class defined like so
class Command {
constructor(name, permission, callback)
{
this.name = name;
this.permission = permission;
this.callback = callback;
}
}
module.exports.command = Command;
Is there a way I can predefine the structure of callback, so it needs the exact same parameters every time, so you can only define it one way?
For example, if I wanted the callback function to always have the arguments client and args then the constructor would only accept a callback with the arguments client and args
It's possible to assert function arity:
if (callback.length !== 2)
throw new Error('Callback should have 2 parameters');
It's acceptable to rely on function arity in some cases. But this is potential antipattern that may be harmful in different ways, especially since ES6.
Default values or rest operator can make a function appear as parameterless, while it isn't:
(function (foo = 1) {}).length === 0;
(function (...args) {}).length === 0;

Blockly while loop argument

I have created a little maze with a robot and I use Blockly to generate code to try to solve it. I can move the robot using Javascript commands which are Blockly blocks. So far so good.
I am currently breaking my head over arguments of if-statements and while loops. Mainly, I have tried two things:
Blockly maze
create a variable, 'not_goal_reached' which says whether or not the robot has reached the goal position (cross). Code:
function not_done() {
var goal_location = get_goal_position()
var goal_x = goal_location[0];
var goal_y = goal_location[1];
console.log('in not done');
//console.log(player.x!= goal_x || player.y != goal_y)
return (player.x!= goal_x || player.y != goal_y);
};
Blockly.Blocks['not_goal_reached'] = {
init: function() {
this.appendDummyInput()
.appendField("not at goal")
this.setOutput(true, "Boolean");
this.setColour(230);
this.setTooltip('');
this.setHelpUrl('');
}
};
Blockly.JavaScript['not_goal_reached'] = function(block) {
var code = 'not_done()';
// TODO: Change ORDER_NONE to the correct strength.
//console.log(code)
return [code, Blockly.JavaScript.ORDER_ATOMIC];
};
However, when using this block in an If or While statement. I always get a Javascript error that does not help me to find the solution:
TypeError: Cannot read property 'toBoolean' of undefined
at Interpreter.stepConditionalExpression (acorn_interpreter.js:148)
at Interpreter.step (acorn_interpreter.js:45)
at nextStep (index.html:79)
I use the Acorn js interpreter:
window.LoopTrap = 2000;
//Blockly.JavaScript.INFINITE_LOOP_TRAP = 'if(--window.LoopTrap == 0) throw "Infinite loop.";\n';
var code = Blockly.JavaScript.workspaceToCode(workspace);
console.log(code);
var myInterpreter = new Interpreter(code, initInterpreter);
//Blockly.JavaScript.INFINITE_LOOP_TRAP = null
var counter = 0;
function nextStep() {
try {
if (myInterpreter.step()) {
counter+=1;
console.log(counter);
if (counter < window.LoopTrap) {
window.setTimeout(nextStep, 30);
}
else {
throw "Infinite Loop!"
}
}
}
catch (e) {
//alert(e);
console.log(e)
}
}
nextStep();
Problem: javascript error I can not solve :(
I created my own While block that does not require input. This While block checks internally whether or not the robot has reached the goal and then processes the DO statements:
Blockly.Blocks['repeat_forever'] = {
init: function() {
this.appendDummyInput()
.appendField("While not at goal");
this.appendStatementInput("DO")
.appendField("Do");
this.setPreviousStatement(true);
this.setColour(230);
this.setTooltip('');
this.setHelpUrl('');
}
};
Blockly.JavaScript['repeat_forever'] = function(block) {
var branch = Blockly.JavaScript.statementToCode(block, 'DO');
// TODO: Assemble JavaScript into code variable.
//if (Blockly.JavaScript.INFINITE_LOOP_TRAP) {
// branch = Blockly.JavaScript.INFINITE_LOOP_TRAP.replace(/%1/g,
// '\'block_id_' + block.id + '\'') + branch;
// console.log(branch);
//}
var code = 'while (' + not_done() + ') {' + branch + '}';
console.log(code)
return [code, Blockly.JavaScript.ORDER_ATOMIC];
};
This works, BUT, here I have the problem that my internal function 'not_done' is only evaluated once (at code generation) to while(true) (since the first time the robot is of course not at the goal location yet). This block correctly applies the DO codes but does not halt (since while (true)). If I add quotes around 'not_done()' the function is evaluated once apparently, but then I receive the same Javascript error as above (Cannot read property 'toBoolean' of undefined)
Am I missing something here? Thanks a lot for your time!
Greetings
K
It seems that you setTimeout which cannot be reached while the while loop runs.

How does the Levenshtein module interact with NodeJS module system?

I am looking here:
https://github.com/gf3/Levenshtein/blob/master/lib/levenshtein.js
I see that the code begins like this:
(function(root, factory){
if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
define(function(){
return factory(root);
});
} else if (typeof module == 'object' && module && module.exports) {
module.exports = factory(root);
} else {
root.Levenshtein = factory(root);
}
}(this, function(root){
I've never seen this before. What does it mean? What does "root" mean?
If I add this to the package.json file of my NodeJS app, then how do I use this inner function:
// Levenshtein distance
function Levenshtein( str_m, str_n )
All the examples use this inner function, but I don't know how to reach it.
TL;DR
What does "root" mean?
root is the first argument passed to this IIFE, which (as you see on line 11) is this. At the "top level" of a JavaScript file in Node.js, this points to the global namespace object. In the browser it points to window.
All the examples use this inner function, but I don't know how to reach it.
That's not a question, but this is how you use it in Node.js:
const Levenshtein = require('levenshtein');
const lev = new Levenshtein('bar', 'baz');
console.log(lev.distance); // => 1
What does it mean?
The purpose of all of this is to make this code work whether you use require in Node.js, an AMD module loader, or a <script> tag in the browser.
If you break it down, the code isn't too hard to understand. Let's start with the anonymous function on line 11, which is a "factory" function that just returns the Levenshtein constructor, like so:
function factory(root) {
// ...
function Levenshtein( str_m, str_n ) {
// ...
}
// ...
return Levenshtein
}
(In the case of the Levenshtein module, the root argument is never actually used in the "factory" function. Go figure.)
Now let's back up to the first line. Here an anonymous function is declared, which basically works like this:
function iife(root, factory) {
const Levenshtein = factory(root);
if (anAMDLoaderIsLoadingMe()) {
// AMD loaders supply a `define` function
define(function() { return Levenshtein; });
} else if (nodeJsIsLoadingMe()) {
// Node.js supplies the `module.exports` object
module.exports = Levenshtein;
} else {
// In a browser, so `root` is `window`
root.Levenshtein = Levenshtein;
}
}
Finally, these two functions are used like this:
iife(this, factory);
That's it! The reason these functions are used anonymously instead of giving them sensible names like iife and factory is so that they don't clash with other functions that you might define (or that other, less well-behaved modules define). This isn't a possibility in Node.js, but it is in the browser.

NodeJS setTimeout/setInterval callback as a string

as far as I know, NodeJS does not support callbacks passed by strings in setTimeout/setInterval functions. (e.g setTimeout("myfunc()", 100);)
Is there any implementation or any other solution to make this work? (e.g instead of calling callback, just eval it, etc..)
I'm just trying to load raw webpage which does exactly same thing so NodeJS just throws exceptions on that.
One way I can suggest is:
setTimeout(function(){
eval("myfunc()")
}, 100);
Edit (to handle evalString passed as an argument)
function callMe(evalString){
return function(){eval(evalString);}
}
setTimeout(callMe('myFunc()'), 100);
Just replace native setTimeout with your one:
setTimeout = timeoutWrapper(setTimeout);
function timeoutWrapper(origSetTimeout) {
var win = typeof global !== 'undefined' ? global : window;
function _setTimeout(fn) {
var code;
if(typeof fn === 'string') {
code = fn
fn = function wrapEval() {
eval(code);
};
}
arguments[0] = fn;
origSetTimeout.apply(win, arguments);
}
return _setTimeout;
}
Test it:
setTimeout('console.log(123)', 100);
setTimeout(function(a,b,c) {
console.log(a, b, c);
}, 100, 'aaa', 'bbb', 'ccc');

how to replace setInterval by requestAnimationFrame

Here is my situation, I need to speed up the function running time, so setInterval is not a wise choose, right? Since it will cost at least 4ms for each time.
So, may I change setInterval function to requestAnimationFrame, but I don't quite understand how the requestAnimationFrame works.
For example
// some code here
var interval = setInterval(doSomething, 10)
var progress = 0
function doSomething(){
if (progress != 100){
// do some thing here
}else{
clearInterval(interval)
}
}
and how can I apply requestAnimationFrame?
I think the key to understand requestAnimationFrame lies in paul Irish's explanation:
Any rAFs queued in a rAF will be executed in the next frame​
from requestAnimationFrame Scheduling For Nerds
var rafReference;
var progress = 0;
function doSomething(){
// only run 100 times
if (progress < 100){
/* do what you wanna do here */
progress++;
//recursively calls it self as requestAnimationFrame's callback
rafReference = requestAnimationFrame(doSomething) // passed as reference
}else{
cancelAnimationFrame(rafReference)
}
}
//starting the recursion
requestAnimationFrame(doSomething)
Looks better in a fiddle-->just the code,no animation
Every thing is commented inside the code for simplification.No need of using setInterval.
Just use cancelAnimationFrame when we are suppose to clear interval.
// This makes sure that there is a method to request a callback to update the graphics for next frame
var requestAnimationFrame =
window.requestAnimationFrame || // According to the standard
window.mozRequestAnimationFrame || // For mozilla
window.webkitRequestAnimationFrame || // For webkit
window.msRequestAnimationFrame || // For ie
function (f) { window.setTimeout(function () { f(Date.now()); }, 1000/60); }; // If everthing else fails
var cancelAnimationFrame =
window.cancelAnimationFrame ||
window.mozCancelAnimationFrame ||
window.webkitCancelAnimationFrame ||
window.msCancelAnimationFrame;
// your code here
var progress = 0;
function doSomething() {
if (progress != 100) {
// do something here
var myAnimation = requestAnimationFrame(doSomething);
} else {
// don't use clearInterval(interval) instead when you know that animation is completed use cancelAnimationFrame()
cancelAnimationFrame(myAnimation);
}
}
Some Links worth a read-->
CreativeJs---the best explanation any one could give,Every begineer must read
CancelAnimationFrame
link 3-->in context of your question
I found this fiddle on google,quite the same that you want.
Other things that you should know:
RAF is still in the development stage.
Why doesn't jQuery use requestAnimationFrame?

Resources