| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374 |
- export const regexpMethods = new Set(["test", "exec", "toString"])
- export const regexpProperties = new Set([
- "source",
- "flags",
- "lastIndex",
- "global",
- "ignoreCase",
- "multiline",
- "sticky",
- "unicode",
- "dotAll",
- ])
- export const regexFailureReason = (error: unknown): string =>
- (error instanceof Error ? error.message : String(error)).replace(/^Invalid regular expression:\s*/i, "")
- export const escapeRegexHint =
- 'To match special characters like ( ) [ ] { } + * ? . literally, escape them with a backslash (e.g. "\\\\(") or test for them with String.includes instead.'
- export const toHostRegex = (arg: unknown, method: string, node: AstNode, extraFlags = ""): RegExp => {
- if (arg instanceof SandboxRegExp) return arg.regex
- if (typeof arg === "string") {
- try {
- return new RegExp(arg, extraFlags)
- } catch (error) {
- throw new InterpreterRuntimeError(
- `String.${method} received the string ${JSON.stringify(arg)}, which is not a valid regular expression pattern (${regexFailureReason(error)}). ${escapeRegexHint}`,
- node,
- ).as("SyntaxError")
- }
- }
- throw new InterpreterRuntimeError(
- `String.${method} expects a regular expression (a /pattern/flags literal or new RegExp(...)) or a string pattern, not ${arg === null ? "null" : typeof arg}.`,
- node,
- )
- }
- export const matchToValue = (match: RegExpMatchArray): Array<unknown> => {
- const result: Array<unknown> = Array.from(match, (group) => group)
- if (match.index !== undefined) (result as Record<string, unknown> & Array<unknown>).index = match.index
- if (match.groups) {
- const groups: SafeObject = Object.create(null) as SafeObject
- for (const [key, group] of Object.entries(match.groups)) {
- if (!isBlockedMember(key)) groups[key] = group
- }
- ;(result as Record<string, unknown> & Array<unknown>).groups = groups
- }
- return result
- }
- export const invokeRegExpMethod = (
- value: SandboxRegExp,
- name: string,
- args: Array<unknown>,
- node: AstNode,
- ): unknown => {
- switch (name) {
- case "test":
- return value.regex.test(coerceToString(args[0]))
- case "exec": {
- const matched = value.regex.exec(coerceToString(args[0]))
- return matched === null ? null : matchToValue(matched)
- }
- case "toString":
- return coerceToString(value)
- default:
- throw new InterpreterRuntimeError(`RegExp method '${name}' is not available in CodeMode.`, node)
- }
- }
- import { type AstNode, InterpreterRuntimeError } from "../interpreter/model.js"
- import { isBlockedMember, type SafeObject } from "../tool-runtime.js"
- import { SandboxRegExp } from "../values.js"
- import { coerceToString } from "./value.js"
|