cesanta / v7

Embedded JavaScript engine for C/C++
Other
1.43k stars 177 forks source link

Object access from API #568

Closed ScriptBasic closed 8 years ago

ScriptBasic commented 8 years ago

v7_get() only retrieves the properties. I need a way to access the object 'handle' that was created in JavaScript code from my 'C' program.

ScriptBasic commented 8 years ago

Is it possible that v7_get_global() is the way to retrieve an object 'handle' from a V7 instance? If yes, that means that you can't use the same property name in multiple objects.

mkmik commented 8 years ago

I don't understand, what do you mean? Can you provide an example? We don't have handles. The C values v7_val_t are exactly the same as JS values.

ScriptBasic commented 8 years ago

If I create an object in JS code and wish to add a property to it from C, I need a way to get a reference to it so I can pass it as an object argument in a v7_set() call.

mkmik commented 8 years ago

Ok, so I understand that you're creating an object in JS code and you also have some C code that wants to add a property having some name foo and some value. That's clear.

My question is: how does the JS code that creates that object look like ? Where does that object go? How do you execute that JS code? Do you save that object in a global variable? Or do you return it from v7_exec?

For example, here I create an object from JS code (by running the {a: 1} JS expression), save the result of that expression in a C variable obj (this is not technically a handle, but I have the feeling you might mean that), and then use that C variable to add a property to that object:

v7_val_t obj;
v7_exec(v7, "{a: 1}", &obj);
v7_set(v7, obj, "foo", ~0, v7_mk_number(v7, 42));
ScriptBasic commented 8 years ago

In your example you are creating the object in C. One could use the v7_mk_object() to do it as well. What I'm trying to do is get the object reference from the object created in v7_exce() generated JavaScript native code.

mkmik commented 8 years ago

Where does this object get stored? In a global variable? As a property of another object? Please show me how you create the object in JS code.

ScriptBasic commented 8 years ago

// set up object to be serialized var foo = {}; Object.defineProperty(foo, 'bar', { value: 'bar', writable: false, enumerable: true });

Would a v7_exec(v7, "foo", &fooptr) do the trick?

mkmik commented 8 years ago

it would work, but it's calling the interpreter unnecessarily. Here's what you have to do in order to a access a global variable foo:

v7_val_t foo = v7_get(v7, v7_get_global(v7), "foo", ~0);

then you can add new properties to the foo C variable with v7_set or v7_def (if you need to control the property attributes)

ScriptBasic commented 8 years ago

Thanks for clearing that up for me. I think I'm getting a better understanding of the interface.

Is there a way to 'dump' what you have done from the C side? (new objects, properties, ...)

mkmik commented 8 years ago

what do you mean by "dump"? Could you please elaborate on what is the end result you expect?

ScriptBasic commented 8 years ago

I guess I could use Object.getOwnPropertyDescriptor(() and traverse the object tree.

Thanks again for your help and code examples.

mkmik commented 8 years ago

ah I see; well if json serialization is not good enough, you have to traverse the object graph manually; you can do that in C or in JS

ScriptBasic commented 8 years ago

Here is an example of the functionality I was trying to achieve.

IMPORT js.bas

jsobj = JS::CREATE()
JS::EXEC(jsobj, "var myobj = {};", rtncode)
myobj = JS::GET(jsobj, JS::GET_GLOBAL(jsobj), "myobj", 5) 
JS::DEF(jsobj, myobj, "test", 4, JS::WRITABLE(TRUE), JS::MK_NUMBER(jsobj, 64))
jscode = """
var descriptors = {};

Object.keys(myobj).forEach(function(key) {
    descriptors[key] = Object.getOwnPropertyDescriptor(myobj, key);
});

var objdesc = JSON.stringify(descriptors);
"""
JS::EXEC(jsobj, jscode, rtncode)
PRINT JS::GET_STRING(jsobj,JS::GET(jsobj, JS::GET_GLOBAL(jsobj), "objdesc", 7)),"\n"
JS::DESTROY(jsobj)
jrs@laptop:~/sb/sb22/js$ time scriba js_mixed.sb
{"test":{"configurable":true,"enumerable":true,"writable":true,"value":64}}

real    0m0.010s
user    0m0.005s
sys 0m0.005s
jrs@laptop:~/sb/sb22/js$