Invoking functions with `out` arguments, passing arguments by reference in JScript - javascript

I'm using following code in JScript (WSH) to connect to local registry using WMI: var registry = GetObject('winmgmts:{impersonationLevel=impersonate}!\\\\.\\root\\default:StdRegProv'); and that works.
Then I have to determine if I'm allowed to delete key without really trying to delete it (e.g. perform a non-destructive check). I looked over docs and found that I need StdRegProv.CheckAccess() method. Problem is that CheckAccess returns result as out argument and I could not find VBScript's ByRef equivalent in JScript.
Somewhere in the Internet I've found that using SWbemServices.ExecMethod would help somehow, but I hadn't figured out how can I use that yet.
Could anyone provide me with code sample in JScript performing function call with argument passed by reference?

Heh, got it working.
For anyone who will need it, CheckAccess invokation in JScript looks something like this:
function CheckAccess(defKey, subkeyName, required) {
var providerName = "StdRegProv";
var funcName = "CheckAccess";
// connect to WMI
var services = GetObject("winmgmts:{impersonationLevel=impersonate}!\\\\.\\root\\default");
// get provider
var registry = services.Get(providerName);
var in_params = registry.Methods_(funcName).InParameters.SpawnInstance_();
in_params.hDefKey = defKey;
in_params.sSubKeyName = subkeyName;
in_params.uRequired = required;
var outParams = services.ExecMethod(providerName, funcName, inParams);
return Boolean(outParams.bGranted);
};

Related

How to verify if a method in a JavaScript object follows a particular interface?

I'm relatively new to JS and i have come across this scenario, where i need to identify if a method defined in a JS object follows a particular interface.
Let me explain with the help of an example:
let logger1 = {
log: function(message, meta){
//logging functionality
}
};
let logger2 = {
log: function(level, message, meta){
//logging functionality
}
}
There are 2 logger objects (logger1 or logger2), which has its own logging functionalities. They can get passed from the client to a library, that the client consumes. Library expects the log method to be of a particular interface, which is already mentioned in the library documentation. Inside the library, how would we verify if the logger object passed in has the 'log' method that matches the interface, the library is expecting ?
let Library = function(logger){
//Here I can verify if the 'log' function is defined. But how do i make sure the log
//function matches the interface that the library is expecting ?
//Let's say the interface that the library is expecting is function(level,message,meta),
//which is satisfied only by logger2.
if(logger && typeof(logger.log) === 'function'){
this.logger = logger;
}
else{
this.logger = console;
}
}
let lib1 = new Library(logger1);
let lib2 = new Library(logger2);
You cannot really. A Javascript function can omit parameters that it doesn't use, so the function may have fewer parameters and still be compatible. The function may define more parameters which will become undefined if not passed, and hence still be compatible. It may internally use arguments and hence not define any parameters, and still be compatible. It may name any of its parameters any way it wants, and still be compatible, so even inspecting the parameter names won't help you at all.
The only thing you can do it use something like Typescript and add compile-time checks.
Hmm, tricky one.
We would just determine the interface first and then the implementation. In this case we would code logger1 to have the signature: ( message, meta ) and logger2 ( message, meta, level ) .
That way we can call either function with eg. ( 'test', 'extra', 1 ) and logger1 will just ignore the level argument.
If you work with a system that has to juggle alot of different argumented versions, it might be better to just use an object as the only argument every time: function( config ) and just add extra properties when needed.
That way you can also force the interface to stay the same while also being extendable in some way.
There is a property length property for function which gives number of arguments it holds
Example:
let logger1 = {
log: function(message, meta){
//logging functionality
}
};
console.log(logger1.log.length); // 2
let logger2 = {
log: function(level, message, meta){
//logging functionality
}
}
console.log(logger2.log.length); // 3

Why can a MongoDb cursor be indexed as if it was an array?

I noticed that if I execute a JavaScript script using the mongo command, the script can treat a cursor object as if it was an array.
var conn = new Mongo('localhost:27017');
var db = conn.getDB('learn');
db.test.remove({});
db.test.insert({foo: 'bar'});
var cur = db.test.find();
print(cur[0].foo); //prints: bar
print(cur[1]); // prints: undefined
This seems like it should be beyond the capabilities of the JavaScript language, since there is no way to "overload the subscript operator". So how does this actually work?
As documentation says, it is special ability of driver. It automagicly converts cursor[0] to cursor.toArray()[0]. You can prove it by overriding toArray() with print function or new Error().stack to get callstack back. Here it is:
at DBQuery.a.toArray ((shell):1:32)
at DBQuery.arrayAccess (src/mongo/shell/query.js:290:17)
at (shell):1:2
As you can see, indexing calls arrayAccess. How? Here we have a dbQueryIndexAccess function, which calls arrayAccess.
v8::Handle<v8::Value> arrayAccess = info.This()->GetPrototype()->ToObject()->Get(
v8::String::New("arrayAccess"));
...
v8::Handle<v8::Function> f = arrayAccess.As<v8::Function>();
...
return f->Call(info.This(), 1, argv);
And here we have a code, which sets indexed property handler to this function. WOW, v8 API gives us ability to add this handler!
DBQueryFT()->InstanceTemplate()->SetIndexedPropertyHandler(dbQueryIndexAccess);
... and injects it into JS cursor class, which is defined originaly in JS.
injectV8Function("DBQuery", DBQueryFT(), _global);
Tl;dr: It is hacked in C++ source code of mongo shell.

Override javascript function while preserving the original context

I just want to confirm that I'm not missing something with regards to managing context and overriding methods. I'm using the http-proxy module in a node.js app and I need to override the function HttpProxy.prototype.proxyRequest. I'd like to do it without modifying the original module code directly but haven't been able to find a way to do it.
If I do this:
var httpProxy = require('http-proxy'),
httpProxyOverride = require('./http-proxy-override.js');
httpProxy.HttpProxy.prototype.proxyRequest = httpProxyOverride.proxyRequestOverride;
Then I lose the original context and errors are thrown. If I use apply(), I can provide a new context, but it doesn't appear I can persist the original context.
Based off of this SO thread:
Is it possible to call function.apply without changing the context?
It doesn't appear that there is a way to achieve what I'm trying to do and I'm hoping that someone can confirm this or correct me if I'm wrong.
What about saving the old function and then overwriting it like:
var old = httpProxy.HttpProxy.prototype.proxyRequest;
httpProxy.HttpProxy.prototype.proxyRequest = function () {
old.apply(this, arguments);
//do more stuff
}
taken from Javascript: Extend a Function

ExecJS - Javascript object instances in Ruby?

If I have a javascript object, I would normally interact with the object and its methods like this:
var obj = someObject.getInstance();
var result = obj.someMethod();
where someMethod is defined like this:
someObject.prototype.someOtherMethod = function() { //do stuff };
someObject.prototype.someMethod = function(foo) { this.someOtherMethod(); };
However, I am getting an error when I want to call someMethod in Ruby via ExecJS:
context = ExecJS.compile(# the javascript file)
context.call('someObject.getInstance().someMethod')
# Gives a TypeError where Object has no method 'someOtherMethod'
On the other hand, functions that are defined in the javascript module are working fine:
someFunction = function() { // do stuff };
# in Ruby
context.call('someFunction') # does stuff
Can ExecJS handle Javascript objects and their methods, or am I only able to call functions with it?
With regards to the specific application, I am looking into https://github.com/joenoon/libphonenumber-execjs, but the parse function in Libphonenumber does not work for the above reason.
Discovered the answer through some experimentation. I managed to get the desired functionality by using context.exec() instead of call.
js = <<JS
var jsObj = someObject.getInstance();
var res = jsObj.someMethod();
return res;
JS
context.exec(js);
However, if your method returns a Javascript object, you have to serialize it first or otherwise parse the results so that it can be returned by ExecJS into a suitable Ruby object.

Windows 8 IndexedDB createObjectStore

Trying to build a Metro app using Javascript and having issues with IndexedDb. I cannot create an object store. My code is shown below. I'm doing this on success of the open() function.
dbReq.onsuccess = function (evt) {
var txn = evt.target.transaction;
var db = evt.target.result;
if (!db.objectStoreNames.contains("test")) {
var store = db.createObjectStore("test");
}
}
Every time, it throws an exception on the 'createObjectStore' call that says
0x800a139e - JavaScript runtime error: [object IDBDatabaseException]
Over here they talk about it and it's a nice example to look at too, but still, did not help me.
Notice that control hits the one line of code inside 'if' statement. So 'db' is not null and is valid. But I saw that the transaction is null - not sure if that is an issue or even if you are supposed to get a valid transaction back at this point.
Not sure why it was not working. Switched to using roaming settings and it is very easy to use.
roamingSettings.values[SETTING_NAME] = SETTING_VALUE;
To read, of course,
var temp = roamingSettings.values[SETTING_NAME];

Categories