Are "V8 of node.exe" and "V8 of libcef of appjs" are different ?

74 views
Skip to first unread message

ashish negi

unread,
Sep 4, 2013, 5:51:13 AM9/4/13
to appj...@googlegroups.com
Although i am still struggling with building appjs, i am thinking that the structure of appjs is like it executes node.exe with its own bindings_of_js that links with libcef for html and css rendering. But since CEF also uses V8 internally, would not they both be present at the run time ?
Is there any documentation for the same for the newbies ?

Simon Horton

unread,
Sep 4, 2013, 2:04:25 PM9/4/13
to appj...@googlegroups.com

V8 of nodejs and V8 of chronium (libcef) must be exactly the same this is because the reason appjs can directly access objects in the browser window is that the two v8 are merged and share the same thread and event loop. If they have different versions then build will fail.

I am not sure exactly where the architecture is described but I believe I started by reading the first messages on the dev mailing list. If you search for "bridge" and read the discussion around that. You are very welcome to create a wiki page on github and add what you find as more people would be interested in the answer. I did not build the bridge code so dont want to answer with inaccurate information.

On 4 Sep 2013 11:51, "ashish negi" <thisismy...@gmail.com> wrote:
Although i am still struggling with building appjs, i am thinking that the structure of appjs is like it executes node.exe with its own bindings_of_js that links with libcef for html and css rendering. But since CEF also uses V8 internally, would not they both be present at the run time ?
Is there any documentation for the same for the newbies ?

--
You received this message because you are subscribed to the Google Groups "appjs-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to appjs-dev+...@googlegroups.com.
To post to this group, send email to appj...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

ashish negi

unread,
Sep 5, 2013, 12:01:17 AM9/5/13
to appj...@googlegroups.com, siho...@gmail.com
Thanks, as i would gain knowledge i would add data here and then after moderations we could shift it to wiki page.

ashish negi

unread,
Sep 5, 2013, 12:05:15 AM9/5/13
to appj...@googlegroups.com, siho...@gmail.com
One question about : the libcef binaries that we have got : Are these binaries from the pure version of CEF or we have done some patching for making this bridge or any_other_things ?


On Wednesday, September 4, 2013 11:34:25 PM UTC+5:30, sihorton wrote:

Simon Horton

unread,
Sep 5, 2013, 1:48:11 AM9/5/13
to ashish negi, appj...@googlegroups.com

The general philosophy for appjs is to try to do as much as possible without forking chromium or nodejs. Therefore my understanding is that the cef binaries are pure, but someone else with knowledge needs to answer this question.

If you poke around a little in the source code you will notice that a lot of it is in pure javascript. I found that out when writing a new handler for appjs. You can even find a bridge file in javascript - I dont know the split between javascript and C++ but a lot is accomplished with javascript hence reducing need to fork and maintain special code base.

ashish negi

unread,
Sep 5, 2013, 2:00:26 AM9/5/13
to appj...@googlegroups.com, ashish negi, siho...@gmail.com
I also could not find reference of any fork of chromium code for our appjs purpose. 

ashish negi

unread,
Sep 9, 2013, 8:12:04 AM9/9/13
to appj...@googlegroups.com, ashish negi, siho...@gmail.com
After looking into the c++ code and playing here and there, [ js is not my first hand language ], I found some things :
bindings.js -> gets the appjs.node / dll  which deals with native window code.
app.js        -> load app.node so you call to make a app.createWindow which get native_window by calling NativeWindow() in c++ using/by app.node.
                 -> create window in js  by passing  native_window to Window() in js. Then you attach node.process and other things to the window object.
                 -> node's process and others would be available.

But i could not find where V8 of node and that of libcef are being merged ? I am actually doubting it. Because we never touched node.exe it would definately have its own V8. I am not sure about libcef but i guess we do not touch it either. 

Since being a non-javascript person if somebody can tell the basics behind bridge.js and handle.js, it would be appreciated.

Here are some more things that i learned:
How the calls are made: 
a. appjs::Init()
b. Cef::Init()
c. CefLoop::Init()
d. CefLoop::Run()
e. ClientHandler::OnContentsSizeChange
f.ClientHandler::OnAfterCreated
g.ClientHandler::OnContentsSizeChange
 Appjs Window pops up.
h.AppjsSchemeHandlerFactory::Create
i. AppjsSchemeHandler::Execute -> REQUIRE_UI_THREAD -> gets node's or some_body's process. calls "node::MakeCallback"
     -> AppjsSchemeHandler::NodeCallback -> Connection keep alive from Server: Appjs0.0.20
     -> AppjsSchemeHandler::GetResponseHeaders
     -> AppjsSchemeHandler::ReadResponse() -> we got index.html file.
     
j. ClientHandler::OnTitleChange
k. ClientHandler::OnContextCreated -> Is it created because of script tag in the index.html ?
     -> It creates an appjs object and adds send function to it. 
     -> It sets send function to point to AppjsSyncHandler.
     
l. AppjsSchemeHandlerFactory::Create
     -> AppjsSchemeHandler::ProcessRequest
     -> AppjsSchemeHandler::NodeCallback -> Connection keep alive from Server: Appjs0.0.20
     -> AppjsSchemeHandler::GetResponseHeaders
     -> AppjsSchemeHandler::ReadResponse() -> we got .css file.
l. AppjsSchemeHandlerFactory::Create
     -> AppjsSchemeHandler::ProcessRequest
     -> AppjsSchemeHandler::NodeCallback -> Connection keep alive from Server: Appjs0.0.20
     -> AppjsSchemeHandler::GetResponseHeaders
     -> AppjsSchemeHandler::ReadResponse() -> something big is read : 119272 bytes  -> This must be .png or photo.

Also, Since i could not debug Javascript, i had to put console messages everywhere and found this trace :

 js: in app.js
js: lib/index.js
js: in lib/router/index.js
In bindings.js file
cpp: in Appjs.cpp Init()
App() in App.js
serveFilesFrom() in App.js
createMenu() in App.js
init() in App.js
cpp: appjs_app.cpp Appjs new instance()
cpp: appjs_app.cpp Appjs new()
createMenu() in App.js
createStatusIcon() in App.js
createWindow() in App.js
cpp: appjs_window.cpp Appjs new()
Window Created

cpp: AppjsSchemeHandlerFactory::Create()
cpp: AppjsSchemeHandler::ProcessRequest()
cpp: AppjsSchemeHandler::Execute()
cpp: AppjsSchemeHandler::GetResponseHeaders()
cpp: AppjsSchemeHandler::ReadResponse()
cpp: cef_handler.cpp OnContextCreated() C
ontext created

cpp: AppjsSchemeHandlerFactory::Create()
cpp: AppjsSchemeHandler::ProcessRequest()
cpp: AppjsSchemeHandler::Execute()
cpp: AppjsSchemeHandler::GetResponseHeaders()
cpp: AppjsSchemeHandler::ReadResponse()
cpp: AppjsSchemeHandlerFactory::Create()
cpp: AppjsSchemeHandler::ProcessRequest()
cpp: AppjsSchemeHandler::Execute()
cpp: AppjsSchemeHandler::GetResponseHeaders()
cpp: AppjsSchemeHandler::ReadResponse()
In bridge.js bridge()
cpp: AppjsSyncHandler() cef_sunc_handler: 036291E0
cpp: AppjsSyncHandler() cef_sunc_handler: 036291E0
cpp: AppjsSyncHandler() cef_sunc_handler: 036291E0

Kevin Ingwersen

unread,
Sep 9, 2013, 8:17:21 AM9/9/13
to appj...@googlegroups.com
Its sort of Magic here. But, did you remember the fact that this all happens in the same process? That is basically what blocks the other context. The both v8's are the exact same, which is why they will, without furthery do, work together...well i think the native code of the -.node does a little magic as well. Whatsoever, I never read the source :).
What I belive though, is that appJS is using the trick of just saying "hey v8, here is v8, have fun!"...and that possibly just does it, basicaly. :p

ashish negi

unread,
Sep 9, 2013, 9:00:24 AM9/9/13
to appj...@googlegroups.com, ingwi...@googlemail.com
One of the hypothesis i am thinking is that never use Libcef V8. could we not just feed node's V8 everything magically too ? Or are we doing it ? The filesystem call and data is passing through the bridge.js and browser-require.js is being used for window.require.

ashish negi

unread,
Sep 9, 2013, 9:05:27 AM9/9/13
to appj...@googlegroups.com, ingwi...@googlemail.com
What are  var foreignObjects = new WeakMap,
      foreignIDs = new WeakMap,
      localObjects = new WeakMap,
      localIDs = new WeakMap,
      localCanonicals = [],
      foreignCanonicals = Object.create(null);

Any short idea about what they really are ?

Simon Horton

unread,
Sep 9, 2013, 10:00:39 AM9/9/13
to appj...@googlegroups.com, Ingwie Phoenix
Hi,

These are excellent questions. I have never been given a detailed explanation of how the code is written or the design for it. I have played around a little in order to implement a packaging format so then I noticed that a lot was actually written in javascript.

What I understand is that nodejs has the appjs module and this includes the cef stuff, when you open a window that tells cef to basically open a browser window. That window is returned or wrapped somehow as an object and then nodejs code can access that window. If from nodejs you add a property or a function to the window object then javascript code can read that same property and function that has been added to the object. That is the bridge.

Sorry that is only a high level explanation, that is what I know about how it is built but I don't know how that translates into the C++ / v8 level. 

/Simon

Morteza Milani

unread,
Sep 11, 2013, 12:43:28 AM9/11/13
to appj...@googlegroups.com
Hi,

Current version of appjs has two separate v8 engines inside it. First we build a CEF shared library which contains a v8 object for itself, then we compile a nodejs module which uses nodejs' v8 engine. These two instances use a bridge ( node v8 <-> bridge <-> CEF v8 ) to communicate. The bridge uses proxies: when you access DOM in nodejs, it is a reflection of the DOM object in CEF's v8.

I don't know if I answered the question. Let me know if I should explain more.

ashish negi

unread,
Sep 11, 2013, 4:27:35 AM9/11/13
to appj...@googlegroups.com, mrtz....@googlemail.com
Thanks for the response. For some days i looked into bridge.js and found that [ actually i think that the following is what is happening, so if you find that something is wrong, please clarify ]

1. bridge.js runs in both the browser [libcef] and in node. It sends browser-require.js to browser.  Q. Are their any other file that is also available to browser ?
2. bridge.js adds nativeWindow.onmessage and in LibCef it adds appjs.onmessage.
3. The flow of data is like this:
                                   Mirror                                  pipe.send                          cpp                         in Window::oncontextcreateed      bridge.js
From node side -> whoever calls pipe.send -> nativeWindow.send -> LibCEf Window::sendSync -> every context had appjs -> get its onmessage() and make a call to it and sends the data.
   => onmessag() of appjs browser side invokes the "mirror" operation for that msg.key which wraps something based on that key and onmessage then encode or stringify it and returns back. to nativeWindow.send where it is decoded or JSON.parsed.

From browser side -> appjs.send() calls AppjsSyncHandler::Execute() and that takes the window handle and calls the onmessage() on it. => nativeWindow.onmessage() and hence data is passed to node.

4. Localids are those which other side has asked for and i am sending it information about it. These are my things. Similarly, foreignIds are what i have asked from the other side.
5. There is no WebSocket communication heppening.
6. when i do var fs = window.require('fs'); fs.readFile( window.__dirname + "/content/hello.txt", function(data){ alert(data); } );
    This could call the browser-require.js's window.require.
    The readFile function is loaded at node side and stored in proxy. Then parameters are passed. Communication happens between both sides about the kind of parameters like object or function or literal etc.
    The result is send back.  
Message has been deleted

ashish negi

unread,
Sep 12, 2013, 8:48:07 AM9/12/13
to appj...@googlegroups.com, mrtz....@googlemail.com
Are we not storing the handles of V8 on both sides and calling the "onmessage" function on them ?

In the AppjsSyncHandler::Execute, can not we dispatch the call on a thread and from that thread do a CefPostTask to the main UI thread ? That would make it async.
Reply all
Reply to author
Forward
0 new messages