153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)/*
253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * Copyright (C) 2004, 2008, 2009 Apple Inc. All rights reserved.
353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * Copyright (C) 2008 Collabora Ltd.
453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * Copyright (C) 2011 Peter Varga (pvarga@webkit.org), University of Szeged
553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * Copyright (C) 2013 Google Inc. All rights reserved.
653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) *
753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * Redistribution and use in source and binary forms, with or without
853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * modification, are permitted provided that the following conditions
953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * are met:
1053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * 1. Redistributions of source code must retain the above copyright
1153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) *    notice, this list of conditions and the following disclaimer.
1253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * 2. Redistributions in binary form must reproduce the above copyright
1353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) *    notice, this list of conditions and the following disclaimer in the
1453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) *    documentation and/or other materials provided with the distribution.
1553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) *
1653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
1753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
1953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
2053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
2153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
2253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
2353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
2453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) */
2853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
2953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "config.h"
30a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "bindings/v8/ScriptRegexp.h"
3153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
3253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "bindings/v8/V8Binding.h"
3353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "bindings/v8/V8PerIsolateData.h"
34d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#include "bindings/v8/V8ScriptRunner.h"
35f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu#include "core/dom/ScriptForbiddenScope.h"
3653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
3753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)namespace WebCore {
3853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
39a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)ScriptRegexp::ScriptRegexp(const String& pattern, TextCaseSensitivity caseSensitivity, MultilineMode multilineMode)
4053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
4193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    v8::Isolate* isolate = v8::Isolate::GetCurrent();
4293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    v8::HandleScope handleScope(isolate);
43f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    v8::Context::Scope contextScope(V8PerIsolateData::from(isolate)->ensureScriptRegexpContext());
44d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    v8::TryCatch tryCatch;
4553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
4653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    unsigned flags = v8::RegExp::kNone;
4753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    if (caseSensitivity == TextCaseInsensitive)
4853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        flags |= v8::RegExp::kIgnoreCase;
4953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    if (multilineMode == MultilineEnabled)
5053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        flags |= v8::RegExp::kMultiline;
5153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
52d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    v8::Local<v8::RegExp> regex = v8::RegExp::New(v8String(isolate, pattern), static_cast<v8::RegExp::Flags>(flags));
5353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
5453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    // If the regex failed to compile we'll get an empty handle.
5553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    if (!regex.IsEmpty())
5693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        m_regex.set(isolate, regex);
5753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
5853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
59a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)int ScriptRegexp::match(const String& string, int startFrom, int* matchLength) const
6053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
6153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    if (matchLength)
6253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        *matchLength = 0;
6353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
6453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    if (m_regex.isEmpty() || string.isNull())
65a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        return -1;
6653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
6753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    // v8 strings are limited to int.
6853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    if (string.length() > INT_MAX)
69a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        return -1;
7053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
71f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    ScriptForbiddenScope::AllowUserAgentScript allowScript;
72f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu
7393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    v8::Isolate* isolate = v8::Isolate::GetCurrent();
7493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    v8::HandleScope handleScope(isolate);
75f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    v8::Context::Scope contextScope(V8PerIsolateData::from(isolate)->ensureScriptRegexpContext());
7653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    v8::TryCatch tryCatch;
7753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
78521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    v8::Local<v8::RegExp> regex = m_regex.newLocal(isolate);
79a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    v8::Local<v8::Function> exec = regex->Get(v8AtomicString(isolate, "exec")).As<v8::Function>();
80d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    v8::Handle<v8::Value> argv[] = { v8String(isolate, string.substring(startFrom)) };
81d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    v8::Local<v8::Value> returnValue = V8ScriptRunner::callInternalFunction(exec, regex, WTF_ARRAY_LENGTH(argv), argv, isolate);
8253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
83d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    if (tryCatch.HasCaught())
84d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        return -1;
85d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)
8653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    // RegExp#exec returns null if there's no match, otherwise it returns an
8753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    // Array of strings with the first being the whole match string and others
8853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    // being subgroups. The Array also has some random properties tacked on like
8953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    // "index" which is the offset of the match.
9053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    //
9153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    // https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/RegExp/exec
9253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
93d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    ASSERT(!returnValue.IsEmpty());
9453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    if (!returnValue->IsArray())
95a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        return -1;
9653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
9753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    v8::Local<v8::Array> result = returnValue.As<v8::Array>();
98a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    int matchOffset = result->Get(v8AtomicString(isolate, "index"))->ToInt32()->Value();
9953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    if (matchLength) {
10053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        v8::Local<v8::String> match = result->Get(0).As<v8::String>();
10153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        *matchLength = match->Length();
10253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    }
10353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
10453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    return matchOffset + startFrom;
10553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
10653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
10753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)} // namespace WebCore
108