Commit b999ae3c authored by vitalyr@chromium.org's avatar vitalyr@chromium.org

API: expose RegExp.

Review URL: http://codereview.chromium.org/3585010

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@5584 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent ea910460
......@@ -1359,6 +1359,36 @@ class Date : public Value {
};
/**
* An instance of the built-in RegExp constructor (ECMA-262, 15.10).
*/
class RegExp : public Value {
public:
enum Flags {
kNone = 0,
kGlobal = 1,
kIgnoreCase = 2,
kMultiline = 4
};
V8EXPORT static Local<RegExp> New(Handle<String> pattern,
Flags flags);
/**
* Returns the value of the source property: a string representing
* the regular expression.
*/
V8EXPORT Local<String> GetSource() const;
V8EXPORT Flags GetFlags() const;
static inline RegExp* Cast(v8::Value* obj);
private:
V8EXPORT static void CheckCast(v8::Value* obj);
};
enum PropertyAttribute {
None = 0,
ReadOnly = 1 << 0,
......@@ -3617,6 +3647,14 @@ Date* Date::Cast(v8::Value* value) {
}
RegExp* RegExp::Cast(v8::Value* value) {
#ifdef V8_ENABLE_CHECKS
CheckCast(value);
#endif
return static_cast<RegExp*>(value);
}
Object* Object::Cast(v8::Value* value) {
#ifdef V8_ENABLE_CHECKS
CheckCast(value);
......
......@@ -1991,6 +1991,15 @@ void v8::Date::CheckCast(v8::Value* that) {
}
void v8::RegExp::CheckCast(v8::Value* that) {
if (IsDeadCheck("v8::RegExp::Cast()")) return;
i::Handle<i::Object> obj = Utils::OpenHandle(that);
ApiCheck(obj->IsJSRegExp(),
"v8::RegExp::Cast()",
"Could not convert to regular expression");
}
bool Value::BooleanValue() const {
if (IsDeadCheck("v8::Value::BooleanValue()")) return false;
LOG_API("BooleanValue");
......@@ -3712,6 +3721,62 @@ double v8::Date::NumberValue() const {
}
static i::Handle<i::String> RegExpFlagsToString(RegExp::Flags flags) {
char flags_buf[3];
int num_flags = 0;
if ((flags & RegExp::kGlobal) != 0) flags_buf[num_flags++] = 'g';
if ((flags & RegExp::kMultiline) != 0) flags_buf[num_flags++] = 'm';
if ((flags & RegExp::kIgnoreCase) != 0) flags_buf[num_flags++] = 'i';
ASSERT(num_flags <= static_cast<int>(ARRAY_SIZE(flags_buf)));
return i::Factory::LookupSymbol(
i::Vector<const char>(flags_buf, num_flags));
}
Local<v8::RegExp> v8::RegExp::New(Handle<String> pattern,
Flags flags) {
EnsureInitialized("v8::RegExp::New()");
LOG_API("RegExp::New");
ENTER_V8;
EXCEPTION_PREAMBLE();
i::Handle<i::String> flags_string = RegExpFlagsToString(flags);
i::Object** argv[2] = {
i::Handle<i::Object>::cast(Utils::OpenHandle(*pattern)).location(),
i::Handle<i::Object>::cast(flags_string).location()
};
i::Handle<i::Object> obj = i::Execution::New(
i::Handle<i::JSFunction>(i::Top::global_context()->regexp_function()),
2, argv,
&has_pending_exception);
EXCEPTION_BAILOUT_CHECK(Local<v8::RegExp>());
return Utils::ToLocal(i::Handle<i::JSRegExp>::cast(obj));
}
Local<v8::String> v8::RegExp::GetSource() const {
if (IsDeadCheck("v8::RegExp::GetSource()")) return Local<v8::String>();
i::Handle<i::JSRegExp> obj = Utils::OpenHandle(this);
return Utils::ToLocal(i::Handle<i::String>(obj->Pattern()));
}
// Assert that the static flags cast in GetFlags is valid.
#define REGEXP_FLAG_ASSERT_EQ(api_flag, internal_flag) \
STATIC_ASSERT(static_cast<int>(v8::RegExp::api_flag) == \
static_cast<int>(i::JSRegExp::internal_flag))
REGEXP_FLAG_ASSERT_EQ(kNone, NONE);
REGEXP_FLAG_ASSERT_EQ(kGlobal, GLOBAL);
REGEXP_FLAG_ASSERT_EQ(kIgnoreCase, IGNORE_CASE);
REGEXP_FLAG_ASSERT_EQ(kMultiline, MULTILINE);
#undef REGEXP_FLAG_ASSERT_EQ
v8::RegExp::Flags v8::RegExp::GetFlags() const {
if (IsDeadCheck("v8::RegExp::GetFlags()")) return v8::RegExp::kNone;
i::Handle<i::JSRegExp> obj = Utils::OpenHandle(this);
return static_cast<RegExp::Flags>(obj->GetFlags().value());
}
Local<v8::Array> v8::Array::New(int length) {
EnsureInitialized("v8::Array::New()");
LOG_API("Array::New");
......
......@@ -174,6 +174,8 @@ class Utils {
v8::internal::Handle<v8::internal::JSFunction> obj);
static inline Local<String> ToLocal(
v8::internal::Handle<v8::internal::String> obj);
static inline Local<RegExp> ToLocal(
v8::internal::Handle<v8::internal::JSRegExp> obj);
static inline Local<Object> ToLocal(
v8::internal::Handle<v8::internal::JSObject> obj);
static inline Local<Array> ToLocal(
......@@ -209,6 +211,8 @@ class Utils {
OpenHandle(const ObjectTemplate* that);
static inline v8::internal::Handle<v8::internal::Object>
OpenHandle(const Data* data);
static inline v8::internal::Handle<v8::internal::JSRegExp>
OpenHandle(const RegExp* data);
static inline v8::internal::Handle<v8::internal::JSObject>
OpenHandle(const v8::Object* data);
static inline v8::internal::Handle<v8::internal::JSArray>
......@@ -265,6 +269,7 @@ MAKE_TO_LOCAL(ToLocal, Context, Context)
MAKE_TO_LOCAL(ToLocal, Object, Value)
MAKE_TO_LOCAL(ToLocal, JSFunction, Function)
MAKE_TO_LOCAL(ToLocal, String, String)
MAKE_TO_LOCAL(ToLocal, JSRegExp, RegExp)
MAKE_TO_LOCAL(ToLocal, JSObject, Object)
MAKE_TO_LOCAL(ToLocal, JSArray, Array)
MAKE_TO_LOCAL(ToLocal, Proxy, External)
......@@ -297,6 +302,7 @@ MAKE_OPEN_HANDLE(ObjectTemplate, ObjectTemplateInfo)
MAKE_OPEN_HANDLE(Signature, SignatureInfo)
MAKE_OPEN_HANDLE(TypeSwitch, TypeSwitchInfo)
MAKE_OPEN_HANDLE(Data, Object)
MAKE_OPEN_HANDLE(RegExp, JSRegExp)
MAKE_OPEN_HANDLE(Object, JSObject)
MAKE_OPEN_HANDLE(Array, JSArray)
MAKE_OPEN_HANDLE(String, String)
......
......@@ -11619,3 +11619,61 @@ TEST(GlobalLoadICGC) {
CheckSurvivingGlobalObjectsCount(1);
}
}
TEST(RegExp) {
v8::HandleScope scope;
LocalContext context;
v8::Handle<v8::RegExp> re = v8::RegExp::New(v8_str("foo"), v8::RegExp::kNone);
CHECK(re->IsRegExp());
CHECK(re->GetSource()->Equals(v8_str("foo")));
CHECK_EQ(re->GetFlags(), v8::RegExp::kNone);
re = v8::RegExp::New(v8_str("bar"),
static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
v8::RegExp::kGlobal));
CHECK(re->IsRegExp());
CHECK(re->GetSource()->Equals(v8_str("bar")));
CHECK_EQ(static_cast<int>(re->GetFlags()),
v8::RegExp::kIgnoreCase | v8::RegExp::kGlobal);
re = v8::RegExp::New(v8_str("baz"),
static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
v8::RegExp::kMultiline));
CHECK(re->IsRegExp());
CHECK(re->GetSource()->Equals(v8_str("baz")));
CHECK_EQ(static_cast<int>(re->GetFlags()),
v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline);
re = CompileRun("/quux/").As<v8::RegExp>();
CHECK(re->IsRegExp());
CHECK(re->GetSource()->Equals(v8_str("quux")));
CHECK_EQ(re->GetFlags(), v8::RegExp::kNone);
re = CompileRun("/quux/gm").As<v8::RegExp>();
CHECK(re->IsRegExp());
CHECK(re->GetSource()->Equals(v8_str("quux")));
CHECK_EQ(static_cast<int>(re->GetFlags()),
v8::RegExp::kGlobal | v8::RegExp::kMultiline);
// Override the RegExp constructor and check the API constructor
// still works.
CompileRun("RegExp = function() {}");
re = v8::RegExp::New(v8_str("foobar"), v8::RegExp::kNone);
CHECK(re->IsRegExp());
CHECK(re->GetSource()->Equals(v8_str("foobar")));
CHECK_EQ(re->GetFlags(), v8::RegExp::kNone);
re = v8::RegExp::New(v8_str("foobarbaz"),
static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
v8::RegExp::kMultiline));
CHECK(re->IsRegExp());
CHECK(re->GetSource()->Equals(v8_str("foobarbaz")));
CHECK_EQ(static_cast<int>(re->GetFlags()),
v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline);
context->Global()->Set(v8_str("re"), re);
ExpectTrue("re.test('FoobarbaZ')");
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment