Calling Method Wrapped for JS on v8 ObjectWrap from C++ - node.js

I'm using a node module and would like to call some of its methods on subclasses of ObjectWrap from C++. It's not entirely clear to me how to correctly construct the Arguments object in the function definitions.
For instance, I'd like to call the following method (Context2d extends ObjectWrap):
Handle<Value>
Context2d::LineTo(const Arguments &args) {
HandleScope scope;
if (!args[0]->IsNumber())
return ThrowException(Exception::TypeError(String::New("lineTo() x must be a number")));
if (!args[1]->IsNumber())
return ThrowException(Exception::TypeError(String::New("lineTo() y must be a number")));
Context2d *context = ObjectWrap::Unwrap<Context2d>(args.This());
cairo_line_to(context->context(), args[0]->NumberValue(), args[1]->NumberValue());
return Undefined();
}
So, concisely: having an unwrapped Context2D, how do I call the static LineTo such that the same instance is returned from the args.This call? I realize of course that I can figure this out by digging through v8, but I was hoping someone knowledgable on the topic could point me in the right direction.

You should be able to call it with something like this. I'm assuming that the function is toLine on the object. You haven't shown your object prototype construction so you'll have to adjust this to match.
int x = 10;
int y = 20;
Context2D *context = ...;
// Get a reference to the function from the object.
Local<Value> toLineVal = context->handle_->Get(String::NewSymbol("toLine"));
if (!toLineVal->IsFunction()) return; // Error, toLine was replaced somehow.
// Cast the generic reference to a function.
Local<Function> toLine = Local<Function>::Cast(toLineVal);
// Call the function with two integer arguments.
Local<Value> args[2] = {
Integer::New(x),
Integer::New(y)
};
toLine->Call(context->handle_, 2, args);
This should be equivalent to this JS:
var toLineVal = context.toLine;
if (typeof toLineVal !== 'function') return; // Error
toLineVal(10, 20);

Related

Javascript. What is the functional equivalent for class constructors?

Class constructor initializes and create objects/functions in a class. If I'm using functions, how would I initialize a function within the function?
This is the simple class
export default class MainProcess{
constructor() {
this.isReady = false
this.init()
}
init() {
this.setupApplicationMenu()
this.initWindowManager()
this.getIcons()
}
}
how can I initiate a MainPRocess Function?
While I'm not entirely sure I understand the question, I think you're asking "How can I create a function in a way that's similar to how I'm used to writing classes, but without using the class keyword?" Here's an example of that:
function Example () {
this.value = 10;
// instance method
this.print = function () {
console.log(this.value);
}
}
// static method
Example.printHello = function () {
console.log('hello world');
}
const example1 = new Example();
example1.print(); // 10
example1.value = 20;
example1.print(); //20
console.log(Object.getPrototypeOf(example1).constructor.name); // "Example"
const example2 = new Example();
example2. print(); //10
Example.printHello(); // "hello world"
Functions are part of the class. Classes are a grouping of functions(methods) and data(as properties). These functions are used to modify properties.
In the above example, you created a class MainProcess with some functions. However, functions defined in the init method is not present. The compiler will throw an error.
constructor is a special method used to create an object with that class.
If I'm using functions, how would I initialize a function within the
function?
It seems you are mixing two concepts function constructors in JS and Classes which are introduced later. Class is nothing, but a syntactic sugar on function constructor. JS is a prototype-based language.
difference b/w function and function constructor?
Functions created with the Function constructor do not create closures to their creation contexts; they always are created in the global scope. When running them, they will only be able to access their own local variables and global ones, not the ones from the scope in which the Function constructor was created. This is different from using Global_Objects/eval with code for a function expression.
var x = 10;
function createFunction1() {
var x = 20;
return new Function('return x;'); // this |x| refers global |x|
}
function createFunction2() {
var x = 20;
function f() {
return x; // this |x| refers local |x| above
}
return f;
}
var f1 = createFunction1();
console.log(f1()); // 10
var f2 = createFunction2();
console.log(f2()); // 20
I highly recommend you first understand the how JS has implemented class in it.

Passing a std::unique_ptr as a void* parameter to a function (CPtrArray::Add)

My code:
void CAssignSelectedColumnDlg::AddColumnData(CString strHeading, CStringArray* pAryStrNames, int iColumnIndex, int iCustomIndex /*-1*/, BOOL bFixedCustomType /*FALSE*/)
{
//COLUMN_DATA_S *psData = nullptr;
//psData = new COLUMN_DATA_S;
auto psData = std::make_unique<COLUMN_DATA_S>();
if (psData != nullptr)
{
// Note: we don't "own" pAryStrNames
psData->strHeading = strHeading;
psData->pAryStrNames = pAryStrNames;
psData->sActionListInfo.byColumnIndex = iColumnIndex;
psData->sActionListInfo.byCustomIndex = iCustomIndex;
psData->sActionListInfo.bFixedCustomType = bFixedCustomType ? true : false;
m_aryPtrColumnData.Add(psData);
}
}
Code analysis was suggesting I use std::make_unique instead of new. So I adjusted teh code but now get a compile error. I tried to find a suitable approach:
No suitable conversion function from std::unique_ptr<COLUMN_DATA_S>, std::default_delete<COLUMN_DATA_S>> to void * exists.
The function in question is CPtrArray::Add. I am still trying to gras the smart pointers and their usage in a context like this.
Note that we should not be deleting the pointer when the function ends. The deletion of the collection is done in a dialog event handler.

duktape how to parse argument of type String Object (similarly Number object) in duktape c function

How to type check the String object/Number object argument types in duktape c function and parse the value from String object/Number object. There is generic api like duk_is_object() but I need the correct object type to parse the value .
ex:
ecmascript code
var str1 = new String("duktape");
var version = new Number(2.2);
dukFunPrintArgs(str1,str2);
duktape c function :
dukFunPrintArgs(ctx)
{
// code to know whether the args is of type String Object / Number Object
}
Where did you find the information how to register a C function in duktape? That place certainly also has details on how to access the parameters passed to it. Already on the homepage of duktape.org you can find a Getting Started example:
3 Add C function bindings
To call a C function from Ecmascript code, first declare your C functions:
/* Being an embeddable engine, Duktape doesn't provide I/O
* bindings by default. Here's a simple one argument print()
* function.
*/
static duk_ret_t native_print(duk_context *ctx) {
printf("%s\n", duk_to_string(ctx, 0));
return 0; /* no return value (= undefined) */
}
/* Adder: add argument values. */
static duk_ret_t native_adder(duk_context *ctx) {
int i;
int n = duk_get_top(ctx); /* #args */
double res = 0.0;
for (i = 0; i < n; i++) {
res += duk_to_number(ctx, i);
}
duk_push_number(ctx, res);
return 1; /* one return value */
}
Register your functions e.g. into the global object:
duk_push_c_function(ctx, native_print, 1 /*nargs*/);
duk_put_global_string(ctx, "print");
duk_push_c_function(ctx, native_adder, DUK_VARARGS);
duk_put_global_string(ctx, "adder");
You can then call your function from Ecmascript code:
duk_eval_string_noresult(ctx, "print('2+3=' + adder(2, 3));");
One of the core concepts in duktape are stacks. The value stack is where parameters are stored. Read more on the Getting Started page.

Define a literal Javascript object so a property referenced directly calls a function and not its sub-ordinates [duplicate]

JavaScript allows functions to be treated as objects--if you first define a variable as a function, you can subsequently add properties to that function. How do you do the reverse, and add a function to an "object"?
This works:
var foo = function() { return 1; };
foo.baz = "qqqq";
At this point, foo() calls the function, and foo.baz has the value "qqqq".
However, if you do the property assignment part first, how do you subsequently assign a function to the variable?
var bar = { baz: "qqqq" };
What can I do now to arrange for bar.baz to have the value "qqqq" and bar() to call the function?
It's easy to be confused here, but you can't (easily or clearly or as far as I know) do what you want. Hopefully this will help clear things up.
First, every object in Javascript inherits from the Object object.
//these do the same thing
var foo = new Object();
var bar = {};
Second, functions ARE objects in Javascript. Specifically, they're a Function object. The Function object inherits from the Object object. Checkout the Function constructor
var foo = new Function();
var bar = function(){};
function baz(){};
Once you declare a variable to be an "Object" you can't (easily or clearly or as far as I know) convert it to a Function object. You'd need to declare a new Object of type Function (with the function constructor, assigning a variable an anonymous function etc.), and copy over any properties of methods from your old object.
Finally, anticipating a possible question, even once something is declared as a function, you can't (as far as I know) change the functionBody/source.
There doesn't appear to be a standard way to do it, but this works.
WHY however, is the question.
function functionize( obj , func )
{
out = func;
for( i in obj ){ out[i] = obj[i]; } ;
return out;
}
x = { a: 1, b: 2 };
x = functionize( x , function(){ return "hello world"; } );
x() ==> "hello world"
There is simply no other way to acheive this,
doing
x={}
x()
WILL return a "type error". because "x" is an "object" and you can't change it. its about as sensible as trying to do
x = 1
x[50] = 5
print x[50]
it won't work. 1 is an integer. integers don't have array methods. you can't make it.
Object types are functions and an object itself is a function instantiation.
alert([Array, Boolean, Date, Function, Number, Object, RegExp, String].join('\n\n'))
displays (in FireFox):
function Array() {
[native code]
}
function Boolean() {
[native code]
}
function Date() {
[native code]
}
function Function() {
[native code]
}
function Number() {
[native code]
}
function Object() {
[native code]
}
function RegExp() {
[native code]
}
function String() {
[native code]
}
In particular, note a Function object, function Function() { [native code] }, is defined as a recurrence relation (a recursive definition using itself).
Also, note that the answer 124402#124402 is incomplete regarding 1[50]=5. This DOES assign a property to a Number object and IS valid Javascript. Observe,
alert([
[].prop="a",
true.sna="fu",
(new Date()).tar="fu",
function(){}.fu="bar",
123[40]=4,
{}.forty=2,
/(?:)/.forty2="life",
"abc".def="ghi"
].join("\t"))
displays
a fu fu bar 4 2 life ghi
interpreting and executing correctly according to Javascript's "Rules of Engagement".
Of course there is always a wrinkle and manifest by =. An object is often "short-circuited" to its value instead of a full fledged entity when assigned to a variable. This is an issue with Boolean objects and boolean values.
Explicit object identification resolves this issue.
x=new Number(1); x[50]=5; alert(x[50]);
"Overloading" is quite a legitimate Javascript exercise and explicitly endorsed with mechanisms like prototyping though code obfuscation can be a hazard.
Final note:
alert( 123 . x = "not" );
alert( (123). x = "Yes!" ); /* ()'s elevate to full object status */
Use a temporary variable:
var xxx = function()...
then copy all the properties from the original object:
for (var p in bar) { xxx[p] = bar[p]; }
finally reassign the new function with the old properties to the original variable:
bar = xxx;
var A = function(foo) {
var B = function() {
return A.prototype.constructor.apply(B, arguments);
};
B.prototype = A.prototype;
return B;
};
NB: Post written in the style of how I solved the issue. I'm not 100% sure it is usable in the OP's case.
I found this post while looking for a way to convert objects created on the server and delivered to the client by JSON / ajax.
Which effectively left me in the same situation as the OP, an object that I wanted to be convert into a function so as to be able to create instances of it on the client.
In the end I came up with this, which is working (so far at least):
var parentObj = {}
parentObj.createFunc = function (model)
{
// allow it to be instantiated
parentObj[model._type] = function()
{
return (function (model)
{
// jQuery used to clone the model
var that = $.extend(true, null, model);
return that;
})(model);
}
}
Which can then be used like:
var data = { _type: "Example", foo: "bar" };
parentObject.createFunc(data);
var instance = new parentObject.Example();
In my case I actually wanted to have functions associated with the resulting object instances, and also be able to pass in parameters at the time of instantiating it.
So my code was:
var parentObj = {};
// base model contains client only stuff
parentObj.baseModel =
{
parameter1: null,
parameter2: null,
parameterN: null,
func1: function ()
{
return this.parameter2;
},
func2: function (inParams)
{
return this._variable2;
}
}
// create a troop type
parentObj.createModel = function (data)
{
var model = $.extend({}, parentObj.baseModel, data);
// allow it to be instantiated
parentObj[model._type] = function(parameter1, parameter2, parameterN)
{
return (function (model)
{
var that = $.extend(true, null, model);
that.parameter1 = parameter1;
that.parameter2 = parameter2;
that.parameterN = parameterN;
return that;
})(model);
}
}
And was called thus:
// models received from an AJAX call
var models = [
{ _type="Foo", _variable1: "FooVal", _variable2: "FooVal" },
{ _type="Bar", _variable1: "BarVal", _variable2: "BarVal" },
{ _type="FooBar", _variable1: "FooBarVal", _variable2: "FooBarVal" }
];
for(var i = 0; i < models.length; i++)
{
parentObj.createFunc(models[i]);
}
And then they can be used:
var test1 = new parentObj.Foo(1,2,3);
var test2 = new parentObj.Bar("a","b","c");
var test3 = new parentObj.FooBar("x","y","z");
// test1.parameter1 == 1
// test1._variable1 == "FooVal"
// test1.func1() == 2
// test2.parameter2 == "a"
// test2._variable2 == "BarVal"
// test2.func2() == "BarVal"
// etc
Here's easiest way to do this that I've found:
let bar = { baz: "qqqq" };
bar = Object.assign(() => console.log("do something"), bar)
This uses Object.assign to concisely make copies of all the the properties of bar onto a function.
Alternatively you could use some proxy magic.
JavaScript allows functions to be
treated as objects--you can add a
property to a function. How do you do
the reverse, and add a function to an
object?
You appear to be a bit confused. Functions, in JavaScript, are objects. And variables are variable. You wouldn't expect this to work:
var three = 3;
three = 4;
assert(three === 3);
...so why would you expect that assigning a function to your variable would somehow preserve its previous value? Perhaps some annotations will clarify things for you:
// assigns an anonymous function to the variable "foo"
var foo = function() { return 1; };
// assigns a string to the property "baz" on the object
// referenced by "foo" (which, in this case, happens to be a function)
foo.baz = "qqqq";
var bar = {
baz: "qqqq",
runFunc: function() {
return 1;
}
};
alert(bar.baz); // should produce qqqq
alert(bar.runFunc()); // should produce 1
I think you're looking for this.
can also be written like this:
function Bar() {
this.baz = "qqqq";
this.runFunc = function() {
return 1;
}
}
nBar = new Bar();
alert(nBar.baz); // should produce qqqq
alert(nBar.runFunc()); // should produce 1

How to check for correct type when calling ObjectWrap::Unwrap in a Nodejs add-on?

I have 2 C++ classes exposed as javascript classes, VanillaOption and NoomraEngine, both inheriting from ObjectWrap.
In the following method in NoomraEngine, I m supposed to receive a previously "wrapped" VanillaOption:
Handle<Value>
NoomraEngine::Price(const Arguments& args) {
HandleScope scope;
Local<Object> object = args[0]->ToObject(); // VanillaOption expected in args[0]
VanillaOption* equityOption = ObjectWrap::Unwrap<VanillaOption>(object);
Local<Number> x = Number::New(this->price(equityOption));
return scope.Close(x);
}
Everything works fine except that if I pass the wrong type to the method, node crashes in ObjectWrap::Unwrap.
My question is how can I make sure that I've received the correct type in args[0] ?
EDIT: a better method than the bare V8 one below is to use NanHasInstance (https://github.com/rvagg/nan#api_nan_has_instance)
In MyObject::Init:
Local<FunctionTemplate> tpl = NanNew<FunctionTemplate>(New);
tpl->SetClassName(NanNew<String>("MyObject"));
...
NanAssignPersistent(prototype, tpl);
where prototype is a static Persistent<FunctionTemplate> member of MyObject.
Use like this:
if (NanHasInstance(prototype, handle)) {
MyObject* obj = ObjectWrap::Unwrap<MyObject>(handle);
...
}
With the caveat that this is my first go at writing a Node addon, I solved this exact problem by checking the prototype of the object with my own wrapper around UnWrap.
Here's a patch to the addon factory class demo showing the method:
https://github.com/petli/node-addon-examples/commit/d3e92cd060a26da2623690718e78f9005db060a8
It will only support factory-generated objects, and not ones where a constructor is exposed so that users could inherit from the base class. However, that could be generalised by walking the prototype chain.
In summary, it grabs hold of the reference to the expected class prototype in MyObject::Init:
Local<Object> obj = constructor->NewInstance();
prototype = Persistent<Value>::New(obj->GetPrototype());
And then checks that before dereferencing the object:
MyObject* MyObject::CheckedUnWrap(Handle<Object> handle)
{
if (!handle.IsEmpty() && handle->InternalFieldCount() == 1) {
Handle<Value> objproto = handle->GetPrototype();
if (objproto == prototype) {
// OK, this is us
return ObjectWrap::Unwrap<MyObject>(handle);
}
}
ThrowException(Exception::TypeError(String::New("<this> is not a MyObject")));
return NULL;
}
All functions then use CheckedUnWrap instead:
Handle<Value> MyObject::PlusOne(const Arguments& args) {
HandleScope scope;
MyObject* obj = CheckedUnWrap(args.This());
if (obj) {
obj->counter_ += 1;
return scope.Close(Number::New(obj->counter_));
}
else {
// Invalid type, an exception has been thrown so return an empty value
return Handle<Value>();
}
}
I was also considering adding an internal field and set that to some some magic pointer, but then the code would have depended on that node::ObjectWrap wouldn't change how it uses the internal fields.
Update: Since NanHasInstance has been deprecated, the new solution to this answer is to use bool FunctionTemplate::HasInstance(Local<Value> object). This function returns true if the given object is an instance of this function template.
Persistent<Function> Wrapper::constructor;
Persistent<FunctionTemplate> Wrapper::tpl;
Then in your Wrapper::Init() function, set the public Persistent object:
Local<FunctionTemplate> tpl = FunctionTemplate::New(isolate, New);
// ...
Wrapper::tpl.Reset(isolate, tpl);
Now to unwrap:
Local<FunctionTemplate> wrapper_tpl = Wrapper::tpl.Get(isolate);
if (!(wrapper_tpl->HasInstance(args[0]))) {
isolate->ThrowException(Exception::TypeError(
String::NewFromUtf8(isolate, "Argument must be a Wrapper object")));
return;
}
// Now we are safe to call ObjectWrap::Unwrap
node::Buffer::HasInstance(args[0]);
Also see:
http://www.lamedoc.com/node.js/classnode_1_1Buffer.html#a4cc6fa734527df461641c6e93e6d1197

Resources