I'm tring to create a javascript object to pass it to a function-callback like following:
void MyClass::ThreadTaskOnSuccess(CefRefPtr<CefV8Value> callback, CefRefPtr<CefV8Context> callbackCtxt)
{
if (!CefCurrentlyOn(TID_UI))
{
// switch to UI thread
CefPostTask(TID_UI, NewCefRunnableMethod(this, &NewDownloadObject::CreateTempDownloadOnSuccess, callback, callbackCtxt));
return;
}
// String creation works perfect!
// CefRefPtr<CefV8Value> executionResult = CefV8Value::CreateString("test");
// "Access violation" will be thrown
CefRefPtr<CefV8Value> executionResult = CefV8Value::CreateObject(NULL);
executionResult->SetValue("size", CefV8Value::CreateInt(123), V8_PROPERTY_ATTRIBUTE_NONE);
executionResult->SetValue("fileName", CefV8Value::CreateString("some name of file"), V8_PROPERTY_ATTRIBUTE_NONE);
CefV8ValueList args;
args.push_back(executionResult);
CefRefPtr<CefV8Value> retval;
CefRefPtr<CefV8Exception> exception;
if (callback->ExecuteFunctionWithContext(callbackCtxt, callbackCtxt->GetGlobal(), args, retval, exception, false))
{
if (exception.get())
{
throw CFdmException(exception->GetMessage().c_str());
}
else
{
// Execution succeeded.
}
}
}
But CefV8Value::CreateObject(NULL) always returns null result. I guess that happens because the code is run in a custom thread, for some tasks have to be performed in a special thread.
Am I right? And how to switch to cef thread to work with V8 engine and syncronise with it?
Am I wrong? And why V8 creates a null object?
Updated
I have added UI thread switching. After that I always have "Access violation reading location" exception in cef_v8value_create_object like in the Hzmy's quiestion.
The chromiumembedded documentation contains following:
So you should switch on the right contect before your actions with javascript model. If V8 is not currently inside a context, or if you need to retrieve and store a reference to a context, you can use one of two available CefV8Context static methods. GetCurrentContext() returns the context for the frame that is currently executing JS. GetEnteredContext() returns the context for the frame where JS execution began. For example, if a function in frame1 calls a function in frame2 then the current context will be frame2 and the entered context will be frame1.
Arrays, objects and functions may only be created, modified and, in the case of functions, executed, if V8 is inside a context. If V8 is not inside a context then the application needs to enter a context by calling Enter() and exit the context by calling Exit(). The Enter() and Exit() methods should only be used:
When creating a V8 object, function or array outside of an existing context. For example, when creating a JS object in response to a native menu callback.
When creating a V8 object, function or array in a context other than the current context. For example, if a call originating from frame1 needs to modify the context of frame2.
So that's why I couldn't create an object but was able to create js strings. Also you could see the general usage example.
And the following code solves the problem:
if (callbackCtxt.get() && callbackCtxt->Enter())
{
CefRefPtr<CefV8Value> object = CefV8Value::CreateObject(NULL);
// call ExecuteFunctionWithContext and perform other actions
callbackCtxt->Exit();
}