Files
atom/native/v8_extensions/onig_reg_exp.mm
Nathan Sobo f22fedebcf 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.
2013-01-24 17:22:50 -08:00

104 lines
3.8 KiB
Plaintext

#import <Cocoa/Cocoa.h>
#import <iostream>
#import "CocoaOniguruma/OnigRegexp.h"
#import "include/cef_base.h"
#import "include/cef_v8.h"
#import "onig_reg_exp.h"
namespace v8_extensions {
extern NSString *stringFromCefV8Value(const CefRefPtr<CefV8Value>& value);
class OnigRegExpUserData : public CefBase {
public:
OnigRegExpUserData(CefRefPtr<CefV8Value> source) {
NSString *sourceString = [NSString stringWithUTF8String:source->GetStringValue().ToString().c_str()];
m_regex = [[OnigRegexp compile:sourceString] retain];
}
~OnigRegExpUserData() {
[m_regex release];
}
CefRefPtr<CefV8Value> Search(CefRefPtr<CefV8Value> string, CefRefPtr<CefV8Value> index) {
OnigResult *result = [m_regex search:stringFromCefV8Value(string) start:index->GetIntValue()];
if ([result count] == 0) return CefV8Value::CreateNull();
CefRefPtr<CefV8Value> resultArray = CefV8Value::CreateArray(result.count);
CefRefPtr<CefV8Value> indicesArray = CefV8Value::CreateArray(result.count);
for (int i = 0; i < [result count]; i++) {
resultArray->SetValue(i, CefV8Value::CreateString([[result stringAt:i] UTF8String]));
indicesArray->SetValue(i, CefV8Value::CreateInt([result locationAt:i]));
}
resultArray->SetValue("index", CefV8Value::CreateInt([result locationAt:0]), V8_PROPERTY_ATTRIBUTE_NONE);
resultArray->SetValue("indices", indicesArray, V8_PROPERTY_ATTRIBUTE_NONE);
return resultArray;
}
CefRefPtr<CefV8Value> Test(CefRefPtr<CefV8Value> string, CefRefPtr<CefV8Value> index) {
OnigResult *result = [m_regex search:stringFromCefV8Value(string) start:index->GetIntValue()];
return CefV8Value::CreateBool(result);
}
OnigRegexp *m_regex;
IMPLEMENT_REFCOUNTING(OnigRegexpUserData);
};
OnigRegExp::OnigRegExp() : CefV8Handler() {
}
void OnigRegExp::CreateContextBinding(CefRefPtr<CefV8Context> context) {
const char* methodNames[] = { "search", "test", "buildOnigRegExp" };
CefRefPtr<CefV8Value> nativeObject = CefV8Value::CreateObject(NULL);
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, this);
nativeObject->SetValue(functionName, function, V8_PROPERTY_ATTRIBUTE_NONE);
}
CefRefPtr<CefV8Value> global = context->GetGlobal();
global->SetValue("$onigRegExp", nativeObject, V8_PROPERTY_ATTRIBUTE_NONE);
}
bool OnigRegExp::Execute(const CefString& name,
CefRefPtr<CefV8Value> object,
const CefV8ValueList& arguments,
CefRefPtr<CefV8Value>& retval,
CefString& exception) {
if (name == "search") {
CefRefPtr<CefV8Value> string = arguments[0];
CefRefPtr<CefV8Value> index = arguments.size() > 1 ? arguments[1] : CefV8Value::CreateInt(0);
OnigRegExpUserData *userData = (OnigRegExpUserData *)object->GetUserData().get();
retval = userData->Search(string, index);
return true;
}
else if (name == "test") {
CefRefPtr<CefV8Value> string = arguments[0];
CefRefPtr<CefV8Value> index = arguments.size() > 1 ? arguments[1] : CefV8Value::CreateInt(0);
OnigRegExpUserData *userData = (OnigRegExpUserData *)object->GetUserData().get();
retval = userData->Test(string, index);
return true;
}
else if (name == "buildOnigRegExp") {
CefRefPtr<CefV8Value> pattern = arguments[0];
CefRefPtr<OnigRegExpUserData> userData = new OnigRegExpUserData(pattern);
if (!userData->m_regex) {
exception = std::string("Failed to create OnigRegExp from pattern '") + pattern->GetStringValue().ToString() + "'";
}
retval = CefV8Value::CreateObject(NULL);
retval->SetUserData((CefRefPtr<CefBase>)userData);
return true;
}
return false;
}
} // namespace v8_extensions