I'm trying to port my application (a VoiceXML interpreter) from
Mozilla SpiderMonkey to v8. For ones not familiar with VoiceXML, the
application allows to run JS scripts in one of the several nested
scopes, which are represented as objects. The scopes are session,
application, document and dialog, in order from outer to inner scopes.
Now, if a script is run in document scope, it can access variables and
functions from outer scopes unqualified, and all variables and
functions it defines are created as subobjects of the document scope.
When the scope is left, all its subobjects are deleted.
In SpiderMonkey, I can specify parent objects on their creation, so I
can create scope objects hierarchy with the API calls. Also, I can
specify an object, on which to execute the script, which allows to
execute it in the given scope. How can I achieve similar functionality
in v8?
A few words on what I have tried so far. I managed to construct the
scopes hierarchy by creating properties in the Object interface.
However, I could not figure out the way to specify these objects for
Script to execute on. I tried to wrap scripts in a "with" construct,
but although it solves the scopes visibility problem, it doesn't allow
to create variables in the current scope. For example, if I run this
script:
var a = new Object();
function foo() { return "hello"; }
in the document scope, I want document.a and document.foo objects to
be created. Wrapping it in a "with (document)" block doesn't give
that.
I'm sorry if I'm missing something obvious, I'm relatively new to v8
and JavaScript in general. Any suggestions would be welcome.
to wrap the document object, you must implement the named, indexed
property and call as function handler, and create the object with
ObjectTemplate
v8::HandleScope handle_scope;
v8::Handle<v8::ObjectTemplate> clazz = v8::ObjectTemplate::New();
clazz->SetNamedPropertyHandler(NamedGetter, NamedSetter, NamedQuery,
NamedDeleter, NamedEnumerator);
clazz->SetIndexedPropertyHandler(IndexedGetter, IndexedSetter,
IndexedQuery, IndexedDeleter, IndexedEnumerator);
clazz->SetCallAsFunctionHandler(Caller);
return v8::Persistent<v8::ObjectTemplate>::New(clazz);
if you could use python, it will like following code in pyv8 <http://
code.google.com/p/pyv8/>
from PyV8 import *
class Document(JSClass):
name = "flier"
def hello(self, s):
print "hello " + s
class Global(JSClass):
document = Document()
with JSContext(Global()) as ctxt:
ctxt.eval("document.hello(document.name)")
That's right. I added the root scope in my hierarchy (which is
session) to this object. So I have this:
[global object] =
{
session :
{
application :
{
document :
{
dialog : {}
}
}
}
};
The problem is, I can't find any methods in the context to make
another object global (such as document in my example).
> to wrap the document object, you must implement the named, indexed
> property and call as function handler, and create the object with
> ObjectTemplate
>
> v8::HandleScope handle_scope;
>
> v8::Handle<v8::ObjectTemplate> clazz = v8::ObjectTemplate::New();
>
> clazz->SetNamedPropertyHandler(NamedGetter, NamedSetter, NamedQuery,
> NamedDeleter, NamedEnumerator);
> clazz->SetIndexedPropertyHandler(IndexedGetter, IndexedSetter,
> IndexedQuery, IndexedDeleter, IndexedEnumerator);
> clazz->SetCallAsFunctionHandler(Caller);
>
> return v8::Persistent<v8::ObjectTemplate>::New(clazz);
I don't understand. All scope objects are pure JS objects, they are
not native. Why do I need an ObjectTemplate? Or do you mean that I
have to create an artifical native object that would reroute all its
property access calls to the appropriate scope object of my hierarchy?
http://code.google.com/p/pyv8/source/browse/trunk/src/Context.cpp#79
m_context->Global()->Set(v8::String::NewSymbol("__proto__"),
CPythonObject::Wrap(global));
you could check __proto__ for more detail <https://
developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/
Object/Proto>
The ObjectTemplate and other things are all for the C or python
side :)
On 1月22日, 下午9时56分, Andrey Semashev <andrey.semas...@gmail.com> wrote:
var Session = new Function();
var Application = new Function();
var Document = new Function();
var Dialog = new Function();
var session = new Session();
Application.prototype = session;
session.application = new Application();
Document.prototype = session.application;
session.application.document = new Document();
Dialog.prototype = session.application.document;
session.application.document.dialog = new Dialog();
var x = 10;
and I want to execute it in the document scope. So the sequence should
be like this:
[set the current scope to session.application.document]
v8::Script::Run(); // run the script
[restore scope to the root object]
so that then I have "typeof(session.application.document.x) ==
number", and "typeof(x) == undefined".
I suggest you could create the context with a customized global_object
that point to a stub object, which will redirect any getter/setter/
call to your document object later. Because any v8 javascript object
must belongs to a context, so, you could create a stub object from C
side, and create document object ASAP after create context, and set
the stub object redirect the remaining call.
class V8EXPORT Context {
/** Creates a new context. */
static Persistent<Context> New(
ExtensionConfiguration* extensions = 0,
Handle<ObjectTemplate> global_template = Handle<ObjectTemplate>
(),
Handle<Value> global_object = Handle<Value>());
The __proto__ doesn't work because for your scene.
Andrey How did you achieve scoping in spidermonkey in first place, knowing that I'm using spidermonkey 45. |