зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1537978 - Move regular expression-related functionality out of jsapi.h into a new js/public/RegExp.h header, further slimming jsapi.h. r=arai
Differential Revision: https://phabricator.services.mozilla.com/D24426 --HG-- rename : js/src/jsapi.h => js/public/RegExp.h extra : moz-landing-system : lando
This commit is contained in:
Родитель
50ed75f8c1
Коммит
dad7f9f2be
|
@ -22,6 +22,7 @@
|
|||
#include "jsfriendapi.h"
|
||||
#include "js/ArrayBuffer.h" // JS::{GetArrayBufferData,IsArrayBufferObject,NewArrayBuffer}
|
||||
#include "js/JSON.h"
|
||||
#include "js/RegExp.h" // JS::ExecuteRegExpNoStatics, JS::NewUCRegExpObject, JS::RegExpFlags
|
||||
#include "js/Value.h"
|
||||
#include "Layers.h"
|
||||
#include "nsAppRunner.h"
|
||||
|
@ -6511,8 +6512,8 @@ bool nsContentUtils::IsPatternMatching(nsAString& aValue, nsAString& aPattern,
|
|||
|
||||
JS::Rooted<JSObject*> re(
|
||||
cx,
|
||||
JS_NewUCRegExpObject(cx, static_cast<char16_t*>(aPattern.BeginWriting()),
|
||||
aPattern.Length(), JSREG_UNICODE));
|
||||
JS::NewUCRegExpObject(cx, static_cast<char16_t*>(aPattern.BeginWriting()),
|
||||
aPattern.Length(), JS::RegExpFlags::Unicode));
|
||||
if (!re) {
|
||||
// Remove extra patterns added above to report with the original pattern.
|
||||
aPattern.Cut(0, 4);
|
||||
|
@ -6523,9 +6524,9 @@ bool nsContentUtils::IsPatternMatching(nsAString& aValue, nsAString& aPattern,
|
|||
|
||||
JS::Rooted<JS::Value> rval(cx, JS::NullValue());
|
||||
size_t idx = 0;
|
||||
if (!JS_ExecuteRegExpNoStatics(cx, re,
|
||||
static_cast<char16_t*>(aValue.BeginWriting()),
|
||||
aValue.Length(), &idx, true, &rval)) {
|
||||
if (!JS::ExecuteRegExpNoStatics(cx, re,
|
||||
static_cast<char16_t*>(aValue.BeginWriting()),
|
||||
aValue.Length(), &idx, true, &rval)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "mozilla/dom/ScriptSettings.h"
|
||||
#include "xpcprivate.h"
|
||||
#include "js/Class.h"
|
||||
#include "js/RegExp.h"
|
||||
#include "jsfriendapi.h"
|
||||
|
||||
using namespace JS;
|
||||
|
@ -761,7 +762,7 @@ bool WrapperAnswer::RecvRegExpToShared(const ObjectId& objId, ReturnStatus* rs,
|
|||
return deadCPOW(jsapi, rs);
|
||||
}
|
||||
|
||||
RootedString sourceJSStr(cx, JS_GetRegExpSource(cx, obj));
|
||||
RootedString sourceJSStr(cx, JS::GetRegExpSource(cx, obj));
|
||||
if (!sourceJSStr) {
|
||||
return fail(jsapi, rs);
|
||||
}
|
||||
|
@ -771,7 +772,7 @@ bool WrapperAnswer::RecvRegExpToShared(const ObjectId& objId, ReturnStatus* rs,
|
|||
}
|
||||
source->Assign(sourceStr);
|
||||
|
||||
*flags = JS_GetRegExpFlags(cx, obj);
|
||||
*flags = JS::GetRegExpFlags(cx, obj);
|
||||
|
||||
return ok(rs);
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "mozilla/dom/BindingUtils.h"
|
||||
#include "jsfriendapi.h"
|
||||
#include "js/CharacterEncoding.h"
|
||||
#include "js/RegExp.h"
|
||||
#include "xpcprivate.h"
|
||||
#include "WrapperFactory.h"
|
||||
|
||||
|
@ -832,7 +833,7 @@ RegExpShared* WrapperOwner::regexp_toShared(JSContext* cx, HandleObject proxy) {
|
|||
}
|
||||
|
||||
RootedObject regexp(cx);
|
||||
regexp = JS_NewUCRegExpObject(cx, source.get(), source.Length(), flags);
|
||||
regexp = JS::NewUCRegExpObject(cx, source.get(), source.Length(), flags);
|
||||
if (!regexp) {
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,112 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: set ts=8 sts=2 et sw=2 tw=80:
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* Regular expression-related operations. */
|
||||
|
||||
#ifndef js_RegExp_h
|
||||
#define js_RegExp_h
|
||||
|
||||
#include <stddef.h> // size_t
|
||||
|
||||
#include "jstypes.h" // JS_PUBLIC_API
|
||||
|
||||
#include "js/RootingAPI.h" // JS::{,Mutable}Handle
|
||||
#include "js/Value.h" // JS::Value
|
||||
|
||||
struct JSContext;
|
||||
class JSString;
|
||||
|
||||
namespace JS {
|
||||
|
||||
/**
|
||||
* A namespace for all regular expression flags as they appear in the APIs below
|
||||
* as flags values.
|
||||
*/
|
||||
struct RegExpFlags {
|
||||
public:
|
||||
/**
|
||||
* Interpret regular expression source text case-insensitively by folding
|
||||
* uppercase letters to lowercase, i.e. /i.
|
||||
*/
|
||||
static constexpr unsigned IgnoreCase = 0b0'0001;
|
||||
|
||||
/**
|
||||
* Act globally and find *all* matches (rather than stopping after just the
|
||||
* first one), i.e. /g.
|
||||
*/
|
||||
static constexpr unsigned Global = 0b0'0010;
|
||||
|
||||
/** Treat ^ and $ as begin and end of line, i.e. /m. */
|
||||
static constexpr unsigned Multiline = 0b0'0100;
|
||||
|
||||
/** Only match starting from <regular expression>.lastIndex, i.e. /y. */
|
||||
static constexpr unsigned Sticky = 0b0'1000;
|
||||
|
||||
/** Use Unicode semantics, i.e. /u. */
|
||||
static constexpr unsigned Unicode = 0b1'0000;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new RegExp for the given Latin-1-encoded bytes and flags.
|
||||
*/
|
||||
extern JS_PUBLIC_API JSObject* NewRegExpObject(JSContext* cx, const char* bytes,
|
||||
size_t length, unsigned flags);
|
||||
|
||||
/**
|
||||
* Create a new RegExp for the given source and flags.
|
||||
*/
|
||||
extern JS_PUBLIC_API JSObject* NewUCRegExpObject(JSContext* cx,
|
||||
const char16_t* chars,
|
||||
size_t length, unsigned flags);
|
||||
|
||||
extern JS_PUBLIC_API bool SetRegExpInput(JSContext* cx, Handle<JSObject*> obj,
|
||||
Handle<JSString*> input);
|
||||
|
||||
extern JS_PUBLIC_API bool ClearRegExpStatics(JSContext* cx,
|
||||
Handle<JSObject*> obj);
|
||||
|
||||
extern JS_PUBLIC_API bool ExecuteRegExp(JSContext* cx, Handle<JSObject*> obj,
|
||||
Handle<JSObject*> reobj,
|
||||
char16_t* chars, size_t length,
|
||||
size_t* indexp, bool test,
|
||||
MutableHandle<Value> rval);
|
||||
|
||||
/* RegExp interface for clients without a global object. */
|
||||
|
||||
extern JS_PUBLIC_API bool ExecuteRegExpNoStatics(JSContext* cx,
|
||||
Handle<JSObject*> reobj,
|
||||
char16_t* chars, size_t length,
|
||||
size_t* indexp, bool test,
|
||||
MutableHandle<Value> rval);
|
||||
|
||||
/**
|
||||
* On success, returns true, setting |*isRegExp| to true if |obj| is a RegExp
|
||||
* object or a wrapper around one, or to false if not. Returns false on
|
||||
* failure.
|
||||
*
|
||||
* This method returns true with |*isRegExp == false| when passed an ES6 proxy
|
||||
* whose target is a RegExp, or when passed a revoked proxy.
|
||||
*/
|
||||
extern JS_PUBLIC_API bool ObjectIsRegExp(JSContext* cx, Handle<JSObject*> obj,
|
||||
bool* isRegExp);
|
||||
|
||||
/**
|
||||
* Given a RegExp object (or a wrapper around one), return the set of all
|
||||
* JS::RegExpFlags::* for it.
|
||||
*/
|
||||
extern JS_PUBLIC_API unsigned GetRegExpFlags(JSContext* cx,
|
||||
Handle<JSObject*> obj);
|
||||
|
||||
/**
|
||||
* Return the source text for a RegExp object (or a wrapper around one), or null
|
||||
* on failure.
|
||||
*/
|
||||
extern JS_PUBLIC_API JSString* GetRegExpSource(JSContext* cx,
|
||||
Handle<JSObject*> obj);
|
||||
|
||||
} // namespace JS
|
||||
|
||||
#endif // js_RegExp_h
|
|
@ -2,6 +2,7 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "js/RegExp.h"
|
||||
#include "jsapi-tests/tests.h"
|
||||
|
||||
BEGIN_TEST(testObjectIsRegExp) {
|
||||
|
@ -11,12 +12,12 @@ BEGIN_TEST(testObjectIsRegExp) {
|
|||
|
||||
EVAL("new Object", &val);
|
||||
JS::RootedObject obj(cx, val.toObjectOrNull());
|
||||
CHECK(JS_ObjectIsRegExp(cx, obj, &isRegExp));
|
||||
CHECK(JS::ObjectIsRegExp(cx, obj, &isRegExp));
|
||||
CHECK(!isRegExp);
|
||||
|
||||
EVAL("/foopy/", &val);
|
||||
obj = val.toObjectOrNull();
|
||||
CHECK(JS_ObjectIsRegExp(cx, obj, &isRegExp));
|
||||
CHECK(JS::ObjectIsRegExp(cx, obj, &isRegExp));
|
||||
CHECK(isRegExp);
|
||||
|
||||
return true;
|
||||
|
@ -29,15 +30,16 @@ BEGIN_TEST(testGetRegExpFlags) {
|
|||
|
||||
EVAL("/foopy/", &val);
|
||||
obj = val.toObjectOrNull();
|
||||
CHECK_EQUAL(JS_GetRegExpFlags(cx, obj), 0u);
|
||||
CHECK_EQUAL(JS::GetRegExpFlags(cx, obj), 0u);
|
||||
|
||||
EVAL("/foopy/g", &val);
|
||||
obj = val.toObjectOrNull();
|
||||
CHECK_EQUAL(JS_GetRegExpFlags(cx, obj), JSREG_GLOB);
|
||||
CHECK(JS::GetRegExpFlags(cx, obj) == JS::RegExpFlags::Global);
|
||||
|
||||
EVAL("/foopy/gi", &val);
|
||||
obj = val.toObjectOrNull();
|
||||
CHECK_EQUAL(JS_GetRegExpFlags(cx, obj), (JSREG_FOLD | JSREG_GLOB));
|
||||
CHECK(JS::GetRegExpFlags(cx, obj) ==
|
||||
(JS::RegExpFlags::Global | JS::RegExpFlags::IgnoreCase));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -49,7 +51,8 @@ BEGIN_TEST(testGetRegExpSource) {
|
|||
|
||||
EVAL("/foopy/", &val);
|
||||
obj = val.toObjectOrNull();
|
||||
JSString* source = JS_GetRegExpSource(cx, obj);
|
||||
JSString* source = JS::GetRegExpSource(cx, obj);
|
||||
CHECK(source);
|
||||
CHECK(JS_FlatStringEqualsAscii(JS_ASSERT_STRING_IS_FLAT(source), "foopy"));
|
||||
|
||||
return true;
|
||||
|
|
135
js/src/jsapi.cpp
135
js/src/jsapi.cpp
|
@ -37,7 +37,6 @@
|
|||
#include "builtin/JSON.h"
|
||||
#include "builtin/MapObject.h"
|
||||
#include "builtin/Promise.h"
|
||||
#include "builtin/RegExp.h"
|
||||
#include "builtin/Stream.h"
|
||||
#include "builtin/String.h"
|
||||
#include "builtin/Symbol.h"
|
||||
|
@ -88,7 +87,6 @@
|
|||
#include "vm/JSFunction.h"
|
||||
#include "vm/JSObject.h"
|
||||
#include "vm/JSScript.h"
|
||||
#include "vm/RegExpStatics.h"
|
||||
#include "vm/Runtime.h"
|
||||
#include "vm/SavedStacks.h"
|
||||
#include "vm/SelfHosting.h"
|
||||
|
@ -4983,139 +4981,6 @@ JS_PUBLIC_API JS::WarningReporter JS::SetWarningReporter(
|
|||
|
||||
/************************************************************************/
|
||||
|
||||
/*
|
||||
* Regular Expressions.
|
||||
*/
|
||||
JS_PUBLIC_API JSObject* JS_NewRegExpObject(JSContext* cx, const char* bytes,
|
||||
size_t length, unsigned flags) {
|
||||
AssertHeapIsIdle();
|
||||
CHECK_THREAD(cx);
|
||||
|
||||
UniqueTwoByteChars chars(InflateString(cx, bytes, length));
|
||||
if (!chars) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return RegExpObject::create(cx, chars.get(), length, RegExpFlag(flags),
|
||||
GenericObject);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API JSObject* JS_NewUCRegExpObject(JSContext* cx,
|
||||
const char16_t* chars,
|
||||
size_t length, unsigned flags) {
|
||||
AssertHeapIsIdle();
|
||||
CHECK_THREAD(cx);
|
||||
|
||||
return RegExpObject::create(cx, chars, length, RegExpFlag(flags),
|
||||
GenericObject);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API bool JS_SetRegExpInput(JSContext* cx, HandleObject obj,
|
||||
HandleString input) {
|
||||
AssertHeapIsIdle();
|
||||
CHECK_THREAD(cx);
|
||||
cx->check(input);
|
||||
|
||||
Handle<GlobalObject*> global = obj.as<GlobalObject>();
|
||||
RegExpStatics* res = GlobalObject::getRegExpStatics(cx, global);
|
||||
if (!res) {
|
||||
return false;
|
||||
}
|
||||
|
||||
res->reset(input);
|
||||
return true;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API bool JS_ClearRegExpStatics(JSContext* cx, HandleObject obj) {
|
||||
AssertHeapIsIdle();
|
||||
CHECK_THREAD(cx);
|
||||
MOZ_ASSERT(obj);
|
||||
|
||||
Handle<GlobalObject*> global = obj.as<GlobalObject>();
|
||||
RegExpStatics* res = GlobalObject::getRegExpStatics(cx, global);
|
||||
if (!res) {
|
||||
return false;
|
||||
}
|
||||
|
||||
res->clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API bool JS_ExecuteRegExp(JSContext* cx, HandleObject obj,
|
||||
HandleObject reobj, char16_t* chars,
|
||||
size_t length, size_t* indexp, bool test,
|
||||
MutableHandleValue rval) {
|
||||
AssertHeapIsIdle();
|
||||
CHECK_THREAD(cx);
|
||||
|
||||
Handle<GlobalObject*> global = obj.as<GlobalObject>();
|
||||
RegExpStatics* res = GlobalObject::getRegExpStatics(cx, global);
|
||||
if (!res) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RootedLinearString input(cx, NewStringCopyN<CanGC>(cx, chars, length));
|
||||
if (!input) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ExecuteRegExpLegacy(cx, res, reobj.as<RegExpObject>(), input, indexp,
|
||||
test, rval);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API bool JS_ExecuteRegExpNoStatics(JSContext* cx, HandleObject obj,
|
||||
char16_t* chars, size_t length,
|
||||
size_t* indexp, bool test,
|
||||
MutableHandleValue rval) {
|
||||
AssertHeapIsIdle();
|
||||
CHECK_THREAD(cx);
|
||||
|
||||
RootedLinearString input(cx, NewStringCopyN<CanGC>(cx, chars, length));
|
||||
if (!input) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ExecuteRegExpLegacy(cx, nullptr, obj.as<RegExpObject>(), input, indexp,
|
||||
test, rval);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API bool JS_ObjectIsRegExp(JSContext* cx, HandleObject obj,
|
||||
bool* isRegExp) {
|
||||
cx->check(obj);
|
||||
|
||||
ESClass cls;
|
||||
if (!GetBuiltinClass(cx, obj, &cls)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*isRegExp = cls == ESClass::RegExp;
|
||||
return true;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API unsigned JS_GetRegExpFlags(JSContext* cx, HandleObject obj) {
|
||||
AssertHeapIsIdle();
|
||||
CHECK_THREAD(cx);
|
||||
|
||||
RegExpShared* shared = RegExpToShared(cx, obj);
|
||||
if (!shared) {
|
||||
return false;
|
||||
}
|
||||
return shared->getFlags();
|
||||
}
|
||||
|
||||
JS_PUBLIC_API JSString* JS_GetRegExpSource(JSContext* cx, HandleObject obj) {
|
||||
AssertHeapIsIdle();
|
||||
CHECK_THREAD(cx);
|
||||
|
||||
RegExpShared* shared = RegExpToShared(cx, obj);
|
||||
if (!shared) {
|
||||
return nullptr;
|
||||
}
|
||||
return shared->getSource();
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
JS_PUBLIC_API bool JS_SetDefaultLocale(JSRuntime* rt, const char* locale) {
|
||||
AssertHeapIsIdle();
|
||||
return rt->setDefaultLocale(locale);
|
||||
|
|
|
@ -2817,62 +2817,6 @@ extern JS_PUBLIC_API bool SetForEach(JSContext* cx, HandleObject obj,
|
|||
|
||||
/************************************************************************/
|
||||
|
||||
/*
|
||||
* Regular Expressions.
|
||||
*/
|
||||
#define JSREG_FOLD 0x01u /* fold uppercase to lowercase */
|
||||
#define JSREG_GLOB 0x02u /* global exec, creates array of matches */
|
||||
#define JSREG_MULTILINE 0x04u /* treat ^ and $ as begin and end of line */
|
||||
#define JSREG_STICKY 0x08u /* only match starting at lastIndex */
|
||||
#define JSREG_UNICODE 0x10u /* unicode */
|
||||
|
||||
extern JS_PUBLIC_API JSObject* JS_NewRegExpObject(JSContext* cx,
|
||||
const char* bytes,
|
||||
size_t length,
|
||||
unsigned flags);
|
||||
|
||||
extern JS_PUBLIC_API JSObject* JS_NewUCRegExpObject(JSContext* cx,
|
||||
const char16_t* chars,
|
||||
size_t length,
|
||||
unsigned flags);
|
||||
|
||||
extern JS_PUBLIC_API bool JS_SetRegExpInput(JSContext* cx, JS::HandleObject obj,
|
||||
JS::HandleString input);
|
||||
|
||||
extern JS_PUBLIC_API bool JS_ClearRegExpStatics(JSContext* cx,
|
||||
JS::HandleObject obj);
|
||||
|
||||
extern JS_PUBLIC_API bool JS_ExecuteRegExp(JSContext* cx, JS::HandleObject obj,
|
||||
JS::HandleObject reobj,
|
||||
char16_t* chars, size_t length,
|
||||
size_t* indexp, bool test,
|
||||
JS::MutableHandleValue rval);
|
||||
|
||||
/* RegExp interface for clients without a global object. */
|
||||
|
||||
extern JS_PUBLIC_API bool JS_ExecuteRegExpNoStatics(
|
||||
JSContext* cx, JS::HandleObject reobj, char16_t* chars, size_t length,
|
||||
size_t* indexp, bool test, JS::MutableHandleValue rval);
|
||||
|
||||
/**
|
||||
* On success, returns true, setting |*isRegExp| to true if |obj| is a RegExp
|
||||
* object or a wrapper around one, or to false if not. Returns false on
|
||||
* failure.
|
||||
*
|
||||
* This method returns true with |*isRegExp == false| when passed an ES6 proxy
|
||||
* whose target is a RegExp, or when passed a revoked proxy.
|
||||
*/
|
||||
extern JS_PUBLIC_API bool JS_ObjectIsRegExp(JSContext* cx, JS::HandleObject obj,
|
||||
bool* isRegExp);
|
||||
|
||||
extern JS_PUBLIC_API unsigned JS_GetRegExpFlags(JSContext* cx,
|
||||
JS::HandleObject obj);
|
||||
|
||||
extern JS_PUBLIC_API JSString* JS_GetRegExpSource(JSContext* cx,
|
||||
JS::HandleObject obj);
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
extern JS_PUBLIC_API bool JS_IsExceptionPending(JSContext* cx);
|
||||
|
||||
extern JS_PUBLIC_API bool JS_GetPendingException(JSContext* cx,
|
||||
|
|
|
@ -159,6 +159,7 @@ EXPORTS.js += [
|
|||
'../public/Realm.h',
|
||||
'../public/RealmOptions.h',
|
||||
'../public/RefCounted.h',
|
||||
'../public/RegExp.h',
|
||||
'../public/RequiredDefines.h',
|
||||
'../public/Result.h',
|
||||
'../public/RootingAPI.h',
|
||||
|
|
|
@ -99,6 +99,7 @@
|
|||
#include "js/Printf.h"
|
||||
#include "js/PropertySpec.h"
|
||||
#include "js/Realm.h"
|
||||
#include "js/RegExp.h" // JS::ObjectIsRegExp
|
||||
#include "js/SourceText.h"
|
||||
#include "js/StableStringChars.h"
|
||||
#include "js/StructuredClone.h"
|
||||
|
@ -9250,7 +9251,7 @@ static bool Help(JSContext* cx, unsigned argc, Value* vp) {
|
|||
return true;
|
||||
}
|
||||
bool isRegexp;
|
||||
if (!JS_ObjectIsRegExp(cx, obj, &isRegexp)) {
|
||||
if (!JS::ObjectIsRegExp(cx, obj, &isRegexp)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#endif
|
||||
#include "irregexp/RegExpParser.h"
|
||||
#include "jit/VMFunctions.h"
|
||||
#include "js/RegExp.h"
|
||||
#include "js/StableStringChars.h"
|
||||
#include "util/StringBuffer.h"
|
||||
#include "vm/MatchPairs.h"
|
||||
|
@ -48,11 +49,16 @@ using mozilla::PodCopy;
|
|||
|
||||
using JS::AutoCheckCannotGC;
|
||||
|
||||
JS_STATIC_ASSERT(IgnoreCaseFlag == JSREG_FOLD);
|
||||
JS_STATIC_ASSERT(GlobalFlag == JSREG_GLOB);
|
||||
JS_STATIC_ASSERT(MultilineFlag == JSREG_MULTILINE);
|
||||
JS_STATIC_ASSERT(StickyFlag == JSREG_STICKY);
|
||||
JS_STATIC_ASSERT(UnicodeFlag == JSREG_UNICODE);
|
||||
static_assert(IgnoreCaseFlag == JS::RegExpFlags::IgnoreCase,
|
||||
"public/internal /i flag bits must agree");
|
||||
static_assert(GlobalFlag == JS::RegExpFlags::Global,
|
||||
"public/internal /g flag bits must agree");
|
||||
static_assert(MultilineFlag == JS::RegExpFlags::Multiline,
|
||||
"public/internal /m flag bits must agree");
|
||||
static_assert(StickyFlag == JS::RegExpFlags::Sticky,
|
||||
"public/internal /y flag bits must agree");
|
||||
static_assert(UnicodeFlag == JS::RegExpFlags::Unicode,
|
||||
"public/internal /u flag bits must agree");
|
||||
|
||||
RegExpObject* js::RegExpAlloc(JSContext* cx, NewObjectKind newKind,
|
||||
HandleObject proto /* = nullptr */) {
|
||||
|
@ -1432,3 +1438,134 @@ JS::ubi::Node::Size JS::ubi::Concrete<RegExpShared>::size(
|
|||
return js::gc::Arena::thingSize(gc::AllocKind::REGEXP_SHARED) +
|
||||
get().sizeOfExcludingThis(mallocSizeOf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Regular Expressions.
|
||||
*/
|
||||
JS_PUBLIC_API JSObject* JS::NewRegExpObject(JSContext* cx, const char* bytes,
|
||||
size_t length, unsigned flags) {
|
||||
AssertHeapIsIdle();
|
||||
CHECK_THREAD(cx);
|
||||
|
||||
UniqueTwoByteChars chars(InflateString(cx, bytes, length));
|
||||
if (!chars) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return RegExpObject::create(cx, chars.get(), length, RegExpFlag(flags),
|
||||
GenericObject);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API JSObject* JS::NewUCRegExpObject(JSContext* cx,
|
||||
const char16_t* chars,
|
||||
size_t length, unsigned flags) {
|
||||
AssertHeapIsIdle();
|
||||
CHECK_THREAD(cx);
|
||||
|
||||
return RegExpObject::create(cx, chars, length, RegExpFlag(flags),
|
||||
GenericObject);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API bool JS::SetRegExpInput(JSContext* cx, HandleObject obj,
|
||||
HandleString input) {
|
||||
AssertHeapIsIdle();
|
||||
CHECK_THREAD(cx);
|
||||
cx->check(input);
|
||||
|
||||
Handle<GlobalObject*> global = obj.as<GlobalObject>();
|
||||
RegExpStatics* res = GlobalObject::getRegExpStatics(cx, global);
|
||||
if (!res) {
|
||||
return false;
|
||||
}
|
||||
|
||||
res->reset(input);
|
||||
return true;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API bool JS::ClearRegExpStatics(JSContext* cx, HandleObject obj) {
|
||||
AssertHeapIsIdle();
|
||||
CHECK_THREAD(cx);
|
||||
MOZ_ASSERT(obj);
|
||||
|
||||
Handle<GlobalObject*> global = obj.as<GlobalObject>();
|
||||
RegExpStatics* res = GlobalObject::getRegExpStatics(cx, global);
|
||||
if (!res) {
|
||||
return false;
|
||||
}
|
||||
|
||||
res->clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API bool JS::ExecuteRegExp(JSContext* cx, HandleObject obj,
|
||||
HandleObject reobj, char16_t* chars,
|
||||
size_t length, size_t* indexp, bool test,
|
||||
MutableHandleValue rval) {
|
||||
AssertHeapIsIdle();
|
||||
CHECK_THREAD(cx);
|
||||
|
||||
Handle<GlobalObject*> global = obj.as<GlobalObject>();
|
||||
RegExpStatics* res = GlobalObject::getRegExpStatics(cx, global);
|
||||
if (!res) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RootedLinearString input(cx, NewStringCopyN<CanGC>(cx, chars, length));
|
||||
if (!input) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ExecuteRegExpLegacy(cx, res, reobj.as<RegExpObject>(), input, indexp,
|
||||
test, rval);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API bool JS::ExecuteRegExpNoStatics(JSContext* cx, HandleObject obj,
|
||||
char16_t* chars, size_t length,
|
||||
size_t* indexp, bool test,
|
||||
MutableHandleValue rval) {
|
||||
AssertHeapIsIdle();
|
||||
CHECK_THREAD(cx);
|
||||
|
||||
RootedLinearString input(cx, NewStringCopyN<CanGC>(cx, chars, length));
|
||||
if (!input) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ExecuteRegExpLegacy(cx, nullptr, obj.as<RegExpObject>(), input, indexp,
|
||||
test, rval);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API bool JS::ObjectIsRegExp(JSContext* cx, HandleObject obj,
|
||||
bool* isRegExp) {
|
||||
cx->check(obj);
|
||||
|
||||
ESClass cls;
|
||||
if (!GetBuiltinClass(cx, obj, &cls)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*isRegExp = cls == ESClass::RegExp;
|
||||
return true;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API unsigned JS::GetRegExpFlags(JSContext* cx, HandleObject obj) {
|
||||
AssertHeapIsIdle();
|
||||
CHECK_THREAD(cx);
|
||||
|
||||
RegExpShared* shared = RegExpToShared(cx, obj);
|
||||
if (!shared) {
|
||||
return false;
|
||||
}
|
||||
return shared->getFlags();
|
||||
}
|
||||
|
||||
JS_PUBLIC_API JSString* JS::GetRegExpSource(JSContext* cx, HandleObject obj) {
|
||||
AssertHeapIsIdle();
|
||||
CHECK_THREAD(cx);
|
||||
|
||||
RegExpShared* shared = RegExpToShared(cx, obj);
|
||||
if (!shared) {
|
||||
return nullptr;
|
||||
}
|
||||
return shared->getSource();
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "mozilla/extensions/MatchPattern.h"
|
||||
#include "mozilla/extensions/MatchGlob.h"
|
||||
|
||||
#include "js/RegExp.h" // JS::NewUCRegExpObject, JS::ExecuteRegExpNoStatics
|
||||
#include "mozilla/dom/ScriptSettings.h"
|
||||
#include "mozilla/HoldDropJSObjects.h"
|
||||
#include "mozilla/Unused.h"
|
||||
|
@ -660,7 +661,7 @@ void MatchGlob::Init(JSContext* aCx, const nsAString& aGlob,
|
|||
// TODO: Switch to the Rust regexp crate, when Rust integration is easier.
|
||||
// It uses a much more efficient, linear time matching algorithm, and
|
||||
// doesn't require special casing for the literal and prefix cases.
|
||||
mRegExp = JS_NewUCRegExpObject(aCx, escaped.get(), escaped.Length(), 0);
|
||||
mRegExp = JS::NewUCRegExpObject(aCx, escaped.get(), escaped.Length(), 0);
|
||||
if (mRegExp) {
|
||||
mozilla::HoldJSObjects(this);
|
||||
} else {
|
||||
|
@ -682,8 +683,8 @@ bool MatchGlob::Matches(const nsAString& aString) const {
|
|||
nsString input(aString);
|
||||
|
||||
size_t index = 0;
|
||||
if (!JS_ExecuteRegExpNoStatics(cx, regexp, input.BeginWriting(),
|
||||
aString.Length(), &index, true, &result)) {
|
||||
if (!JS::ExecuteRegExpNoStatics(cx, regexp, input.BeginWriting(),
|
||||
aString.Length(), &index, true, &result)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче