Invoke marshalled COM interface multiple times - javascript

I am writing a COM object for JavaScript consumption. JavaScript code is turn runs in an hosted WebBrowserControl. I need to fire some events from COM object to JavaScript, the excellent guide to which at Dr. Dobbs
e.g.
I have following in my *.idl
IJSCallback
{
void Listen(IDispatch* pJSMethod);
}
JavaScript methods are received as IDispatch* in C++ code, which is to be stored for calling it later, from another thread.
No matter what method for marshaling is used (CoMarshalInterThreadInterfaceInStream or IGlobalInterfaceTable) the event firing thread is able to call JavaScript function only once. After that IDispatch::Invoke() returns E_ACCESSDENIED!
sample JavaScript code
var server = new ActiveXObject("prog_id")
var.Listen(function(ip_add) {
// ip_add from COM object
});
the C++ thread is pretty straight forward.
// called from JavaScript
CMyObject::Listen(IDispatch* pJSMethod)
{
// IStream* m_pStream;
CoMarshalInterThreadInterfaceInStream(pJSMethod, IID_IDispatch, &m_pStream);
}
// called from internal C++ thread.
CMyObject::FireEvent()
{
// IStream* m_pStream;
// IDispatch* m_pJSMethod;
CoGetInterfaceAndReleaseStream(m_pStream, IID_IDispatch, (LPVOID*)&m_pJSMethod);
HSREULT hr = m_pJSMethod->Invoke(...); // hr = S_OK, call is received in JavaScript
hr = m_pJSMethod->Invoke(...); // hr = E_ACCESSDENIED, call is not received in JavaScript
}
is this expected behavior? or something wrong in code?

Fixed. As mentioned in comments alert() works but document.writeln() doesn't. That is because document.writeln() resets the current document including scripts elements, use document.createElement(), document.createTextNode() and friends to modify current loaded elements.
This could be common knowledge for those familiar with HTML/JavaScript, for rest of us it can be a real deal.

Related

Running client side javascript without loading a new (blank) view on Odoo 8

I need to run some client-side javascript from a button in a form view in Odoo 8. This button runs a python method which returns this dictionary:
{"type": "ir.actions.client",
"tag": "my_module.do_something",}
do_something is defined in a .js file as follows:
openerp.my_module = function (instance) {
instance.web.client_actions.add("my_module.do_something", "instance.my_module.Action");
instance.my_module.Action = instance.web.Widget.extend({
init: function() {
// Do a lot of nice things here
}
});
};
Now, the javascript is loaded and executed properly, but even before launching the init function, Odoo loads a brand new, blank view, and once the javascript is over I can't get browse any other menu entry. In fact, wherever I click I get this error:
Uncaught TypeError: Cannot read property 'callbackList' of undefined
What I need instead is to run the javascript from the form view where the button belongs, without loading a new view, so both getting the javascript stuff done and leaving all callbacks and the whole environment in a good state. My gut feeling is that I shouldn't override the init funcion (or maybe the whole thing is broken, I'm quite new to Odoo client-side js) , but I couldn't find docs neither a good example to call js the way I want. Any idea to get that?
Sorry, I don't work on v8 since a lot of time and I don't remember how to add that, but this might help you: https://github.com/odoo/odoo/blob/8.0/doc/howtos/web.rst
Plus, if you search into v8 code base you can find some occurence of client actions in web module docs https://github.com/odoo/odoo/search?utf8=%E2%9C%93&q=instance.web.client_actions.add
Thanks to the pointers simahawk posted in another answer, I have been able to fix my js, which is now doing exactly what I needed. For your reference, the code is as follows:
openerp.my_module = function (instance) {
instance.web.client_actions.add("my_module.do_something", "instance.my_module.action");
instance.my_module.action = function (parent, action) {
// Do a lot of nice things here
}
};

Qt function runJavaScript() does not execute JavaScript code

I am trying to implement the displaying of a web page in Qt. I chose to use the Qt WebEngine to achieve my task. Here's what I did :
Wrote a sample web page consisting of a empty form.
Wrote a JS file with just an API to create a radio button inside the form.
In my code, it looks like this :
View = new QWebEngineView(this);
// read the js file using qfile
file.open("path to jsFile");
myJsApi = file.Readall();
View->page()->runjavascript (myjsapi);
View->page()->runjavascript ("createRadioButton(\"button1\");");
I find that the runJavaScript() function has no effect on the web page. I can see the web page in the output window, but the radio button I expected is not present. What am I doing wrong?
I think you will have to connect the signal loadFinished(bool) of your page() to a slot, then execute runJavaScript() in this slot.
void yourClass::mainFunction()
{
View = new QWebEngineView(this);
connect( View->page(), SIGNAL(loadFinished(bool)), this, SLOT(slotForRunJS(bool)));
}
void yourClass::slotForRunJS(bool ok)
{
// read the js file using qfile
file.open("path to jsFile");
myJsApi = file.Readall();
View->page()->runJavaScript(myjsapi);
View->page()->runJavaScript("createRadioButton(\"button1\");");
}
I had this problem, runJavascript didn't have any effect. I had to put some html content into the view (with page().setHtml("") before running it.
Check the application output, it might contain JavaScript errors. Even if your JS code is valid, you might encounter the situation where the script is run before DOMContentLoaded event, that is document.readyState == 'loading'. Therefore, the DOM might not be available yet, as well as variables or functions provided by other scripts. If you depend on them for your code to run, when you detect this readyState, either wait for the event or try calling the function later, after a timeout. The second approach with timeout might be needed if you need to get the result of the code execution, as this can be done only synchronously.

How can I attach an event handler to the process's exit in a native Node.js module?

I'm working on implementing correct memory management for a native Node.js module. I've ran into the problem described in this question:
node.js native addon - destructor of wrapped class doesn't run
The suggested solution is to bind the destructors of native objects to process.on('exit'), however the answer does not contain how to do that in a native module.
I've taken a brief look at the libuv docs as well, but they didn't contain anything useful in this regard, either.
NOTE: I'm not particularly interested in getting the process object, but I tried it that way:
auto globalObj = NanGetCurrentContext()->Global();
auto processObj = ::v8::Handle<::v8::Object>::Cast(globalObj->Get(NanNew<String>("process")));
auto processOnFunc = ::v8::Handle<::v8::Function>::Cast(processObj->Get(NanNew<String>("on")));
Handle<Value> processOnExitArgv[2] = { NanNew<String>("exit"), NanNew<FunctionTemplate>(onProcessExit)->GetFunction() };
processOnFunc->Call(processObj, 2, processOnExitArgv);
The problem then is that I get this message when trying to delete my object:
Assertion `persistent().IsNearDeath()' failed.
I also tried to use std::atexit and got the same assertion error.
So far, the best I could do is collecting stray ObjectWrap instances in an std::set and cleaning up the wrapped objects, but because of the above error, I was unable to clean up the wrappers themselves.
So, how can I do this properly?
I was also getting the "Assertion persistent().IsNearDeath()' failed" message.
There is a node::AtExit() function that runs just before Node.js shuts down - the equivalent of process.on('exit').
Pass a callback function to node::AtExit from within your add-on's init function (or where ever is appropriate).
The function is documented here:
https://nodejs.org/api/addons.html#addons_atexit_hooks
For example:
NAN_MODULE_INIT(my_exports)
{
// other exported stuff here
node::AtExit(my_cleanup);
}
NODE_MODULE(my_module, my_exports) //add-on exports
//call C++ dtors:
void my_cleanup()
{
delete my_object_ptr; //call object dtor, or other stuff that needs to be cleaned up here
}

This object constructor is preventing my script from running

I'm working on a project (creating a browser based check list). One of my goals has been to write every piece by hand without a library like jquery or a mysql database.
Currently I'm trying to create on object for managing tasks. I'm not finished the primary function, but everything is closed, and I don't detect any errors. Furthermore, I'm haven't iterated it or called it's functions yet, so there's nothing to reference it yet. When I comment it out, the script runs normally.
I've included the xml request links up above and tested them successfully in a separate portion of the script.
I'm testing in firefox.
I'm writing this in SciTE
Here's the code:
function Task(name,node,childNode,divClass,content,onclick)
{
function retrieveTask(node,childNode)
{
var taskArray = [];
taskArray.push(xmlDoc.getElementsByTagName(name)[node].childNodes[childNode].nodeValue;)
taskArray.push(xmlDoc.getElementsByTagName(description)[node].childNodes[childNode].nodeValue;)
taskArray.push(xmlDoc.getElementsByTagName(complete)[node].childNodes[childNode].nodeValue;)
return taskArray;
}
function displayTask(name,content)
{
var task = retrieveTask(node,childNode);
var clickDiv = "";
formatDiv(name,"task",task[1],clickDiv);
task[2] === true ? formatDiv(name+1,"incompleteBox"," ",clickDiv) : formatDiv(name+1,"completeBox","O",clickDiv);
}
}
If anyone could give me some insight or tips that would be awesome. This isn't homework, it's a hobby, so it's a self teaching process.
...childNodes[childNode].nodeValue;)
should be );

Is there a way to log the JavaScript stack trace without putting breakpoints?

I would like to be able to perform manipulations on a given JS app, and then simply get a large log of all the functions that have been called. This is possible in Chrome, but only if one puts a breakpoint somewhere. My problem is when I am reverse-engineering a given website (only for self-teaching purposes, of course) it often takes me a whole lot of time to figure out where to even start from. Something like that will help me tremendously because I will no longer have to search within the code, rather, I will just do a user action, and grab the stack log afterwards.
I suppose that there should be a way to intercept (or wrap) every function call, so that it is dumped to the log before the function is called.
Try this article:
http://eriwen.com/javascript/stacktrace-update/
or this post:
http://ivan-ghandhi.livejournal.com/942493.html
and, probably, this: How can I get a Javascript stack trace when I throw an exception?
In Firebug, you can use the profiler to log every function called. Use console.profile() and console.profileEnd() to trigger it programatically.
However, this will not give you proper stack traces. (Are you sure that's what you want?)
To log methods of specific objects, you can overwrite them like so:
for (var key in obj) {
if (typeof obj[key] == 'function') {
(function(){
var origFun = obj[key];
obj[key] = function () {
var result = origFun.apply(this, arguments);
console.log('call to method', key, 'with arguments', arguments,' - Result:', result);
// console.trace(); // for a trace with every call
return result;
};
})();
}
}
Maybe aspect oriented programming (AOP) can provide an answer. I just found out about aspectJS which could help intercept and log function calls
You can use dynatrace. Dynatrace is a profiling tool for IE and FF. Dynatrace can monitor your application while it is running, and then serves you a timeline of all what happened. In the timeline, there is blocks representing the javascript activity. You can right-click on it (purepath), and then walk through the whole call stack. You can export that to excel or other If you want.
You can add markers in your code, those markers will appear on the timeline and in the purepath:
if(typeof(_dt_addMark)!="undefined") _dt_addMark('MyCustomTimerName');
alternatively, if you only want to find "a way to intercept (or wrap) every function call",
there is a low-tech solution, if you are using a real webbapp (single-load javascript app):
bookmarklets
With bookmarklets, once you have loaded your page, you can execute some custom javascript. So what you can do there, is to override the functions methods that you want to observe with the same function containing logging (so just copy and paste the function, and add some console.log in there). This actually works even with native js functions.

Categories

Resources