Can't call a global function - javascript

Writing a unit test for Apigee JS policy.
I am trying to call context.getVariable("env") from send Msg ()
but context is not recognized as a global and hence I cant callcontext.getVariable().
edit: I cant add global.context.getVariable("env") as it is an Object of Apigee's platform
global.context={}
global.context.getVariable=function(){}
function logger(){
function log(msg){
this.sendMsg(msg)
}
var sendMsg = function (){
context.getVariable("env")
}
return {
log:log,
sendMsg:sendMsg
}
}
logger().sendMsg()//TypeError: context.getVariable is not a function
Why is it happening? and what should I do?
I have tried calling
logger().sendMsg.apply(global) is that ok?

Related

Calling a JavaScript function from shiny server

I want to call a javascript function, display in my case, from server.R with one parameter. The print statement below the call is getting executed, but the javascript function is not getting executed. Is this the right way of calling js function?
observe ({
if (is.null(input$location))
return()
tags$script(type="text/javascript", src = "datadisplay.js")
tags$script(JS('display(today_trends))'))
print(today_trends[1])
})
}
My js file:
function disp(params) {
var myWindow = window.open("");
myWindow.document.write("New window");
}
I've also tried js$display(today_trends) this way, but I get an error: Attempt to apply non-function.
Modified js file:
shinyjs.display = function(params) {
var myWindow = window.open("");
myWindow.document.write("New window");
};

Best way to detect when a function is called from the console

I would like to know the best way to detect when a method or function is directly called through the console. As far as I currently understand, it's not possible to directly detect it on identical function calls, but using the .call() and .apply() methods of a function I can pass additional data through the this object.
Given the following code structure:
(function(){
var Player = {money: 0};
window.giveMoney = function(amount){
if (this.legit !== true)
throw new Error("Don't try to cheat!");
Player.money += amount;
}
})();
I could call the function using
window.giveMoney.call({legit: true}, 300);
in my actual code to tell a direct call from the console and my own code apart, but this is obviously not fool-proof, since the same code can also be executed from the console to achieve the desired effect.
I would want a way to be able to call the function from both places and then tell the locations of the call apart. If there's no way to do that, what's the best way to try and prevent the execution anyway? Is it best to just not expose any methods at all, and keep everything inside a single closed-off anonymous function?
To prevent global access make sure your code is in a closure. If you want to expose an API you can do so using the module pattern.
Closure
(function() {
var Game = {};
Game.giveMoney = function(money) {
console.log('Gave money (' + money + ')');
};
})();
Wrap all your private code in an IIFE (Immediately Invoked Function Expression) which will lock it up into a closure.
Module
Then expose only custom functions back out of the closure so you can use them on the console (with supervision of course).
window.Game = (function() {
var player = {
money: 500;
};
player.giveMoney = function(money) {
console.log('Gave money (' + money + ')');
player.money += money;
};
player.takeMoney = function(money) {
console.log('Took money (' + money + ')');
player.money -= money;
};
return {
giveMoney: function(money) {
console.error('Don\'t Cheat! A fine was charged.');
player.takeMoney(Math.floor(player.money / 0.05));
}
};
})();
window.Game.giveMoney(200);
You can spool all function calls through a central access point with a boolean variable, that can serve as a indicator whether the call is from a console or not....
var maths = {
add: function(p1,p2)
{
console.log(p1,p2);
}
}
var invoker = {
invoke: function(fu,isconsole)
{
if(isconsole)
{
console.log("Called from console");
}
//invokes the function with all parameters intact
fu;
}
}
//Call without console
invoker.invoke(maths.add(2,3));
//Call with console
invoker.invoke(maths.add(2,3),true);
Hope it helps!!!
You can use the monitor() command in the console to monitor when a function is called. https://developer.chrome.com/devtools/docs/commandline-api#monitorfunction
Just run monitor(functionName); and whenever the function is called it will output a message in the console.

Socket.io + node : TypeError: Object #<Namespace> has no method

I have a simple JavaScript class like that :
function MySIOClass(io)
{
this.io = io
this.ns = this.io.of('/notif')
this.init()
}
MySIOClass.prototype.init = function (){
this.ns.on('connection', this.newClient)
}
MySIOClass.prototype.newClient = function (socket)
{
socket.on('msg', function (data){ this.handle_msg(data)})
 }
MySIOClass.prototype.handle_msg = function (data)
{
// handle my message
}
I get stuck on the function newClient, each time a socket.io client send an event 'msg', the console triggers
TypeError: Object #<Socket> has no method 'handle_msg'
I tried to keep a reference of the operator this inside the function newClient like that :
MySIOClass.prototype.newClient = function (socket)
{
var c = this;
socket.on('msg', function (data){ c.handle_msg(data)})
 }
But no luck too, i got the following error about namespace :
TypeError: Object #<Namespace> has no method 'handle_msg'
My class is exported via a module, everything works except when i try to add a listener with the on method of socket.io inside a class. I have correctly used the "new" operator when i instantiated my class.
Could you help me figure out what's happening ? i tried several things, but none of them worked.
Thanks for your time.
When you pass this.newClient to .on('connection', ...), you are passing just the function itself and losing the (this) context. You need to either create a wrapper function that can access the correct context to call newClient() properly or create a bound version of newClient.
First option:
MySIOClass.prototype.init = function (){
var self = this;
this.ns.on('connection', function(socket) {
self.newClient(socket);
});
}
Second option:
MySIOClass.prototype.init = function (){
this.ns.on('connection', this.newClient.bind(this));
}
Regarding the error inside newClient() itself, you are correct in that you have to use a "self"/"that" variable that you can use to access the correct context to call handle_msg().

TypeError: Value does not implement interface EventListener

This works find in IE and Chrome, however, in Firefox, I get the error:
"TypeError: Value does not implement interface EventListener."
This code is posted by a php script, so I had to add the if statement determining if the id exists, first, to avoid errors in Chrome.
Here's the code:
HTML
<a id="Logout">Logout</a>
JavaScript
if (document.getElementById("Logout") != null) {
var Logout_Link = document.getElementById("Logout");
Logout_Link.addEventListener('click', Logout, true);
function Logout() {
var just_logged_out = 1;
window.location.href = "logout-redirect.php";
}
}
if (…) {
function …() {
…
}
}
is invalid. Function declarations must be on the top level of function or program bodies, inside of blocks their behaviour is implementation-dependent. Move it outside the if-statement:
function Logout() {
var just_logged_out = 1;
window.location.href = "logout-redirect.php";
}
if (document.getElementById("Logout") != null) {
var Logout_Link = document.getElementById("Logout");
Logout_Link.addEventListener('click', Logout, true);
}
So if the function was not declared [correctly], what's that odd error message? You might've expected something like WRONG ARGUMENTS ERROR: handler is 'undefined'. But actually it's not, Logout does refer to your link element. And that does indeed not implement the EventListener interface (JavaScript functions do).

javascript function modification

I am trying to write a logger object which logs messages to screen. here is my code.
http://github.com/huseyinyilmaz/javascript-logger
in every function that needs to log something, I am writing loggerstart and loggerEnd functions at start and end of my functions. But I want to run thos codes automaticalls for every function. is there a way to modify Function prototype so every function call can run automatically.
(I am not using any javascript framework.)
EDIT: Rewritten the function to make it more modular
Well, this is a creepy way to do it, but I use this way sometimes when I need overriding some functions. It works well, allows any kind of customization and easy to understand (still creepy).
However, you will need to have all your functions stored in some kind of global object. See the example for details.
function dynamic_call_params(func, fp) {
return func(fp[0],fp[1],fp[2],fp[3],fp[4],fp[5],fp[6],fp[7],fp[8],fp[9],fp[10],fp[11],fp[12],fp[13],fp[14],fp[15],fp[16],fp[17],fp[18],fp[19]);
}
function attachWrapperToFunc(object, funcName, wrapperFunction) {
object["_original_function_"+funcName] = object[funcName];
object[funcName] = function() {
return wrapperFunction(object, object["_original_function_"+funcName], funcName, arguments);
}
}
function attachWrapperToObject(object, wrapperFunction) {
for (varname in object) {
if (typeof(object[varname]) == "function") {
attachWrapperToFunc(object, varname, wrapperFunction);
}
}
}
And some usage example:
var myProgram = new Object();
myProgram.function_one = function(a,b,c,d) {
alert(a+b+c+d);
}
myProgram.function_two = function(a,b) {
alert(a*b);
}
myProgram.function_three = function(a) {
alert(a);
}
function loggerWrapperFunction(functionObject, origFunction, origFunctionName, origParams) {
alert("start: "+origFunctionName);
var result = dynamic_call_params(origFunction, origParams);
alert("end: "+origFunctionName);
return result;
}
attachWrapperToObject(myProgram,loggerWrapperFunction);
myProgram.function_one(1,2,3,4);
myProgram.function_two(2,3);
myProgram.function_three(5);
Output will be:
start,10,end,start,6,end,start,5,end
So generally it allows you to wrap each function in some object automatically with a custom written wrapper function.
You could call every function with a wrapper function.
function wrapper(callback) {
loggerstart();
callback();
loggerend();
}
And call it with wrapper(yourfunction);

Categories

Resources