};
+/**
+ * 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,
}
+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);
}
+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");
}
+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");
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(
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>
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)
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)
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')");
+}