Inject new instances of native objects into every JS context

This prevents concurrent access to the same state from different
worker threads. We needed to treat windowState specially because we
explicitly want it to last beyond the life-span of a single context.
So we store it as a static variable in `native.mm` and synchronize
access with a static `NSLock`. Good enough for now.
This commit is contained in:
Nathan Sobo
2013-01-23 17:15:09 -07:00
committed by Kevin Sawicki
parent 9bff6f63df
commit f22fedebcf
13 changed files with 32 additions and 71 deletions

View File

@@ -15,12 +15,13 @@ void AtomCefRenderProcessHandler::OnWebKitInitialized() {
void AtomCefRenderProcessHandler::OnContextCreated(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefV8Context> context) {
v8_extensions::Atom::CreateContextBinding(context);
v8_extensions::Native::CreateContextBinding(context);
v8_extensions::Git::CreateContextBinding(context);
v8_extensions::OnigRegExp::CreateContextBinding(context);
v8_extensions::OnigScanner::CreateContextBinding(context);
v8_extensions::Tags::CreateContextBinding(context);
// these objects are deleted when the context removes all references to them
(new v8_extensions::Atom())->CreateContextBinding(context);
(new v8_extensions::Native())->CreateContextBinding(context);
(new v8_extensions::Git())->CreateContextBinding(context);
(new v8_extensions::OnigRegExp())->CreateContextBinding(context);
(new v8_extensions::OnigScanner())->CreateContextBinding(context);
(new v8_extensions::Tags())->CreateContextBinding(context);
}
void AtomCefRenderProcessHandler::OnContextReleased(CefRefPtr<CefBrowser> browser,
@@ -32,7 +33,6 @@ void AtomCefRenderProcessHandler::OnContextReleased(CefRefPtr<CefBrowser> browse
void AtomCefRenderProcessHandler::OnWorkerContextCreated(int worker_id,
const CefString& url,
CefRefPtr<CefV8Context> context) {
v8_extensions::Native::CreateContextBinding(context);
}
void AtomCefRenderProcessHandler::OnWorkerContextReleased(int worker_id,

View File

@@ -4,7 +4,8 @@
namespace v8_extensions {
class Atom : public CefV8Handler {
public:
static void CreateContextBinding(CefRefPtr<CefV8Context> context);
Atom();
void CreateContextBinding(CefRefPtr<CefV8Context> context);
virtual bool Execute(const CefString& name,
CefRefPtr<CefV8Value> object,
const CefV8ValueList& arguments,
@@ -15,8 +16,6 @@ namespace v8_extensions {
IMPLEMENT_REFCOUNTING(Atom);
private:
static CefRefPtr<CefV8Handler> GetInstance();
Atom();
Atom(Atom const&);
void operator=(Atom const&);
};

View File

@@ -10,19 +10,13 @@ namespace v8_extensions {
}
void Atom::CreateContextBinding(CefRefPtr<CefV8Context> context) {
CefRefPtr<CefV8Value> function = CefV8Value::CreateFunction("sendMessageToBrowserProcess", GetInstance());
CefRefPtr<CefV8Value> function = CefV8Value::CreateFunction("sendMessageToBrowserProcess", this);
CefRefPtr<CefV8Value> atomObject = CefV8Value::CreateObject(NULL);
atomObject->SetValue("sendMessageToBrowserProcess", function, V8_PROPERTY_ATTRIBUTE_NONE);
CefRefPtr<CefV8Value> global = context->GetGlobal();
global->SetValue("atom", atomObject, V8_PROPERTY_ATTRIBUTE_NONE);
}
CefRefPtr<CefV8Handler> Atom::GetInstance() {
static Atom instance;
static CefRefPtr<CefV8Handler> instancePtr = CefRefPtr<CefV8Handler>(&instance);
return instancePtr;
}
bool Atom::Execute(const CefString& name,
CefRefPtr<CefV8Value> object,
const CefV8ValueList& arguments,

View File

@@ -4,7 +4,8 @@
namespace v8_extensions {
class Git : public CefV8Handler {
public:
static void CreateContextBinding(CefRefPtr<CefV8Context> context);
Git();
void CreateContextBinding(CefRefPtr<CefV8Context> context);
virtual bool Execute(const CefString& name,
CefRefPtr<CefV8Value> object,
const CefV8ValueList& arguments,
@@ -15,8 +16,6 @@ namespace v8_extensions {
IMPLEMENT_REFCOUNTING(Git);
private:
static CefRefPtr<CefV8Handler> GetInstance();
Git();
Git(Git const&);
void operator=(Git const&);
};

View File

@@ -197,7 +197,7 @@ namespace v8_extensions {
int arrayLength = sizeof(methodNames) / sizeof(const char *);
for (int i = 0; i < arrayLength; i++) {
const char *functionName = methodNames[i];
CefRefPtr<CefV8Value> function = CefV8Value::CreateFunction(functionName, GetInstance());
CefRefPtr<CefV8Value> function = CefV8Value::CreateFunction(functionName, this);
nativeObject->SetValue(functionName, function, V8_PROPERTY_ATTRIBUTE_NONE);
}
@@ -205,12 +205,6 @@ namespace v8_extensions {
global->SetValue("$git", nativeObject, V8_PROPERTY_ATTRIBUTE_NONE);
}
CefRefPtr<CefV8Handler> Git::GetInstance() {
static Git instance;
static CefRefPtr<CefV8Handler> instancePtr = CefRefPtr<CefV8Handler>(&instance);
return instancePtr;
}
bool Git::Execute(const CefString& name,
CefRefPtr<CefV8Value> object,
const CefV8ValueList& arguments,

View File

@@ -5,7 +5,8 @@ namespace v8_extensions {
class Native : public CefV8Handler {
public:
static void CreateContextBinding(CefRefPtr<CefV8Context> context);
Native();
void CreateContextBinding(CefRefPtr<CefV8Context> context);
virtual bool Execute(const CefString& name,
CefRefPtr<CefV8Value> object,
const CefV8ValueList& arguments,
@@ -16,11 +17,7 @@ namespace v8_extensions {
IMPLEMENT_REFCOUNTING(Native);
private:
static CefRefPtr<CefV8Handler> GetInstance();
Native();
Native(Native const&);
void operator=(Native const&);
std::string windowState;
};
}

View File

@@ -8,9 +8,11 @@
#import "path_watcher.h"
#import <iostream>
#include <fts.h>
static std::string windowState = "{}";
static NSLock *windowStateLock = [[NSLock alloc] init];
namespace v8_extensions {
using namespace std;
@@ -18,7 +20,6 @@ namespace v8_extensions {
void throwException(const CefRefPtr<CefV8Value>& global, CefRefPtr<CefV8Exception> exception, NSString *message);
Native::Native() : CefV8Handler() {
windowState = "{}";
}
void Native::CreateContextBinding(CefRefPtr<CefV8Context> context) {
@@ -33,7 +34,7 @@ namespace v8_extensions {
int arrayLength = sizeof(methodNames) / sizeof(const char *);
for (int i = 0; i < arrayLength; i++) {
const char *functionName = methodNames[i];
CefRefPtr<CefV8Value> function = CefV8Value::CreateFunction(functionName, GetInstance());
CefRefPtr<CefV8Value> function = CefV8Value::CreateFunction(functionName, this);
nativeObject->SetValue(functionName, function, V8_PROPERTY_ATTRIBUTE_NONE);
}
@@ -41,12 +42,6 @@ namespace v8_extensions {
global->SetValue("$native", nativeObject, V8_PROPERTY_ATTRIBUTE_NONE);
}
CefRefPtr<CefV8Handler> Native::GetInstance() {
static Native instance;
static CefRefPtr<CefV8Handler> instancePtr = CefRefPtr<CefV8Handler>(&instance);
return instancePtr;
}
bool Native::Execute(const CefString& name,
CefRefPtr<CefV8Value> object,
const CefV8ValueList& arguments,
@@ -500,12 +495,16 @@ namespace v8_extensions {
}
else if (name == "setWindowState") {
[windowStateLock lock];
windowState = arguments[0]->GetStringValue().ToString();
[windowStateLock unlock];
return true;
}
else if (name == "getWindowState") {
[windowStateLock lock];
retval = CefV8Value::CreateString(windowState);
[windowStateLock unlock];
return true;
}

View File

@@ -5,7 +5,8 @@ namespace v8_extensions {
class OnigRegExp : public CefV8Handler {
public:
static void CreateContextBinding(CefRefPtr<CefV8Context> context);
OnigRegExp();
void CreateContextBinding(CefRefPtr<CefV8Context> context);
virtual bool Execute(const CefString& name,
CefRefPtr<CefV8Value> object,
const CefV8ValueList& arguments,
@@ -16,8 +17,6 @@ namespace v8_extensions {
IMPLEMENT_REFCOUNTING(OnigRegExp);
private:
static CefRefPtr<CefV8Handler> GetInstance();
OnigRegExp();
OnigRegExp(OnigRegExp const&);
void operator=(OnigRegExp const&);
};

View File

@@ -59,7 +59,7 @@ void OnigRegExp::CreateContextBinding(CefRefPtr<CefV8Context> context) {
int arrayLength = sizeof(methodNames) / sizeof(const char *);
for (int i = 0; i < arrayLength; i++) {
const char *functionName = methodNames[i];
CefRefPtr<CefV8Value> function = CefV8Value::CreateFunction(functionName, GetInstance());
CefRefPtr<CefV8Value> function = CefV8Value::CreateFunction(functionName, this);
nativeObject->SetValue(functionName, function, V8_PROPERTY_ATTRIBUTE_NONE);
}
@@ -67,12 +67,6 @@ void OnigRegExp::CreateContextBinding(CefRefPtr<CefV8Context> context) {
global->SetValue("$onigRegExp", nativeObject, V8_PROPERTY_ATTRIBUTE_NONE);
}
CefRefPtr<CefV8Handler> OnigRegExp::GetInstance() {
static OnigRegExp instance;
static CefRefPtr<CefV8Handler> instancePtr = CefRefPtr<CefV8Handler>(&instance);
return instancePtr;
}
bool OnigRegExp::Execute(const CefString& name,
CefRefPtr<CefV8Value> object,
const CefV8ValueList& arguments,

View File

@@ -5,7 +5,8 @@ namespace v8_extensions {
class OnigScanner : public CefV8Handler {
public:
static void CreateContextBinding(CefRefPtr<CefV8Context> context);
OnigScanner();
void CreateContextBinding(CefRefPtr<CefV8Context> context);
virtual bool Execute(const CefString& name,
CefRefPtr<CefV8Value> object,
const CefV8ValueList& arguments,
@@ -16,8 +17,6 @@ namespace v8_extensions {
IMPLEMENT_REFCOUNTING(OnigRegExp);
private:
static CefRefPtr<CefV8Handler> GetInstance();
OnigScanner();
OnigScanner(OnigScanner const&);
void operator=(OnigScanner const&);
};

View File

@@ -139,7 +139,7 @@ void OnigScanner::CreateContextBinding(CefRefPtr<CefV8Context> context) {
int arrayLength = sizeof(methodNames) / sizeof(const char *);
for (int i = 0; i < arrayLength; i++) {
const char *functionName = methodNames[i];
CefRefPtr<CefV8Value> function = CefV8Value::CreateFunction(functionName, GetInstance());
CefRefPtr<CefV8Value> function = CefV8Value::CreateFunction(functionName, this);
nativeObject->SetValue(functionName, function, V8_PROPERTY_ATTRIBUTE_NONE);
}
@@ -147,12 +147,6 @@ void OnigScanner::CreateContextBinding(CefRefPtr<CefV8Context> context) {
global->SetValue("$onigScanner", nativeObject, V8_PROPERTY_ATTRIBUTE_NONE);
}
CefRefPtr<CefV8Handler> OnigScanner::GetInstance() {
static OnigScanner instance;
static CefRefPtr<CefV8Handler> instancePtr = CefRefPtr<CefV8Handler>(&instance);
return instancePtr;
}
bool OnigScanner::Execute(const CefString& name,
CefRefPtr<CefV8Value> object,
const CefV8ValueList& arguments,

View File

@@ -6,7 +6,8 @@ namespace v8_extensions {
class Tags : public CefV8Handler {
public:
static void CreateContextBinding(CefRefPtr<CefV8Context> context);
Tags();
void CreateContextBinding(CefRefPtr<CefV8Context> context);
virtual bool Execute(const CefString& name,
CefRefPtr<CefV8Value> object,
const CefV8ValueList& arguments,
@@ -17,8 +18,6 @@ namespace v8_extensions {
IMPLEMENT_REFCOUNTING(Tags);
private:
static CefRefPtr<CefV8Handler> GetInstance();
Tags();
Tags(Tags const&);
void operator=(Tags const&);
CefRefPtr<CefV8Value> ParseEntry(tagEntry entry);

View File

@@ -13,7 +13,7 @@ namespace v8_extensions {
int arrayLength = sizeof(methodNames) / sizeof(const char *);
for (int i = 0; i < arrayLength; i++) {
const char *functionName = methodNames[i];
CefRefPtr<CefV8Value> function = CefV8Value::CreateFunction(functionName, GetInstance());
CefRefPtr<CefV8Value> function = CefV8Value::CreateFunction(functionName, this);
nativeObject->SetValue(functionName, function, V8_PROPERTY_ATTRIBUTE_NONE);
}
@@ -21,12 +21,6 @@ namespace v8_extensions {
global->SetValue("$tags", nativeObject, V8_PROPERTY_ATTRIBUTE_NONE);
}
CefRefPtr<CefV8Handler> Tags::GetInstance() {
static Tags instance;
static CefRefPtr<CefV8Handler> instancePtr = CefRefPtr<CefV8Handler>(&instance);
return instancePtr;
}
CefRefPtr<CefV8Value> Tags::ParseEntry(tagEntry entry) {
CefRefPtr<CefV8Value> tagEntry = CefV8Value::CreateObject(NULL);
tagEntry->SetValue("name", CefV8Value::CreateString(entry.name), V8_PROPERTY_ATTRIBUTE_NONE);