NativeRegExpCtor.java
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* 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/. */
package org.mozilla.javascript.regexp;
import static org.mozilla.javascript.ScriptableObject.PERMANENT;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.LambdaConstructor;
import org.mozilla.javascript.ScriptRuntime;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.ScriptableObject;
import org.mozilla.javascript.TopLevel;
import org.mozilla.javascript.Undefined;
/**
* This class implements the RegExp constructor native object.
*
* <p>Revision History: Implementation in C by Brendan Eich Initial port to Java by Norris Boyd from
* jsregexp.c version 1.36 Merged up to version 1.38, which included Unicode support. Merged bug
* fixes in version 1.39. Merged JSFUN13_BRANCH changes up to 1.32.2.11
*
* @author Brendan Eich
* @author Norris Boyd
*/
class NativeRegExpCtor {
private static final long serialVersionUID = -5733330028285400526L;
public static LambdaConstructor init(Context cx, Scriptable scopeArg, boolean sealed) {
// We have to keep parameter types to match lazy evaluation.
ScriptableObject scope = (ScriptableObject) scopeArg;
var ctor =
new LambdaConstructor(
scope,
"RegExp",
2,
NativeRegExpCtor::js_constructCall,
NativeRegExpCtor::js_construct);
ctor.defineProperty(
cx,
"multiline",
(c) -> ScriptRuntime.wrapBoolean(getImpl().multiline),
(c, v) -> getImpl().multiline = ScriptRuntime.toBoolean(v),
PERMANENT);
ctor.defineProperty(
cx,
"$*",
(c) -> ScriptRuntime.wrapBoolean(getImpl().multiline),
(c, v) -> getImpl().multiline = ScriptRuntime.toBoolean(v),
PERMANENT);
ctor.defineProperty(
cx,
"input",
(c) -> toStr(getImpl().input),
(c, v) -> getImpl().input = ScriptRuntime.toString(v),
PERMANENT);
ctor.defineProperty(
cx,
"$_",
(c) -> toStr(getImpl().input),
(c, v) -> getImpl().input = ScriptRuntime.toString(v),
PERMANENT);
ctor.defineProperty(cx, "lastMatch", (c) -> toStr(getImpl().lastMatch), PERMANENT);
ctor.defineProperty(cx, "$&", (c) -> toStr(getImpl().lastMatch), PERMANENT);
ctor.defineProperty(cx, "lastParen", (c) -> toStr(getImpl().lastParen), PERMANENT);
ctor.defineProperty(cx, "$+", (c) -> toStr(getImpl().lastParen), PERMANENT);
ctor.defineProperty(cx, "leftContext", (c) -> toStr(getImpl().leftContext), PERMANENT);
ctor.defineProperty(cx, "$`", (c) -> toStr(getImpl().leftContext), PERMANENT);
ctor.defineProperty(cx, "rightContext", (c) -> toStr(getImpl().rightContext), PERMANENT);
ctor.defineProperty(cx, "$'", (c) -> toStr(getImpl().rightContext), PERMANENT);
for (int i = 1; i < 10; i++) {
int c = i - 1;
ctor.defineProperty(
cx,
String.format("$%d", i),
(x) -> toStr(getImpl().getParenSubString(c)),
null,
PERMANENT);
}
return ctor;
}
private static String toStr(String subStr) {
return subStr == null ? "" : subStr;
}
private static String toStr(SubString subStr) {
return subStr == null ? "" : subStr.toString();
}
private static Scriptable js_constructCall(
Context cx, Scriptable scope, Scriptable thisObj, Object[] args) {
if (args.length > 0
&& args[0] instanceof NativeRegExp
&& (args.length == 1 || args[1] == Undefined.instance)) {
return (Scriptable) args[0];
}
return js_construct(cx, scope, args);
}
private static Scriptable js_construct(Context cx, Scriptable scope, Object[] args) {
NativeRegExp re = NativeRegExpInstantiator.withLanguageVersion(cx.getLanguageVersion());
re.compile(cx, scope, args);
ScriptRuntime.setBuiltinProtoAndParent(re, scope, TopLevel.Builtins.RegExp);
return re;
}
private static RegExpImpl getImpl() {
Context cx = Context.getCurrentContext();
return (RegExpImpl) ScriptRuntime.getRegExpProxy(cx);
}
}