UNPKG

brave-real-playwright-core

Version:

Brave-optimized Playwright Core (v1.56.1) with comprehensive stealth patches and error stack sanitization

393 lines (392 loc) 12.8 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var ariaSnapshot_exports = {}; __export(ariaSnapshot_exports, { KeyParser: () => KeyParser, ParserError: () => ParserError, parseAriaSnapshot: () => parseAriaSnapshot, parseAriaSnapshotUnsafe: () => parseAriaSnapshotUnsafe, textValue: () => textValue }); module.exports = __toCommonJS(ariaSnapshot_exports); function parseAriaSnapshotUnsafe(yaml, text, options = {}) { const result = parseAriaSnapshot(yaml, text, options); if (result.errors.length) throw new Error(result.errors[0].message); return result.fragment; } function parseAriaSnapshot(yaml, text, options = {}) { const lineCounter = new yaml.LineCounter(); const parseOptions = { keepSourceTokens: true, lineCounter, ...options }; const yamlDoc = yaml.parseDocument(text, parseOptions); const errors = []; const convertRange = (range) => { return [lineCounter.linePos(range[0]), lineCounter.linePos(range[1])]; }; const addError = (error) => { errors.push({ message: error.message, range: [lineCounter.linePos(error.pos[0]), lineCounter.linePos(error.pos[1])] }); }; const convertSeq = (container, seq) => { for (const item of seq.items) { const itemIsString = item instanceof yaml.Scalar && typeof item.value === "string"; if (itemIsString) { const childNode = KeyParser.parse(item, parseOptions, errors); if (childNode) { container.children = container.children || []; container.children.push(childNode); } continue; } const itemIsMap = item instanceof yaml.YAMLMap; if (itemIsMap) { convertMap(container, item); continue; } errors.push({ message: "Sequence items should be strings or maps", range: convertRange(item.range || seq.range) }); } }; const convertMap = (container, map) => { for (const entry of map.items) { container.children = container.children || []; const keyIsString = entry.key instanceof yaml.Scalar && typeof entry.key.value === "string"; if (!keyIsString) { errors.push({ message: "Only string keys are supported", range: convertRange(entry.key.range || map.range) }); continue; } const key = entry.key; const value = entry.value; if (key.value === "text") { const valueIsString = value instanceof yaml.Scalar && typeof value.value === "string"; if (!valueIsString) { errors.push({ message: "Text value should be a string", range: convertRange(entry.value.range || map.range) }); continue; } container.children.push({ kind: "text", text: textValue(value.value) }); continue; } if (key.value === "/children") { const valueIsString = value instanceof yaml.Scalar && typeof value.value === "string"; if (!valueIsString || value.value !== "contain" && value.value !== "equal" && value.value !== "deep-equal") { errors.push({ message: 'Strict value should be "contain", "equal" or "deep-equal"', range: convertRange(entry.value.range || map.range) }); continue; } container.containerMode = value.value; continue; } if (key.value.startsWith("/")) { const valueIsString = value instanceof yaml.Scalar && typeof value.value === "string"; if (!valueIsString) { errors.push({ message: "Property value should be a string", range: convertRange(entry.value.range || map.range) }); continue; } container.props = container.props ?? {}; container.props[key.value.slice(1)] = textValue(value.value); continue; } const childNode = KeyParser.parse(key, parseOptions, errors); if (!childNode) continue; const valueIsScalar = value instanceof yaml.Scalar; if (valueIsScalar) { const type = typeof value.value; if (type !== "string" && type !== "number" && type !== "boolean") { errors.push({ message: "Node value should be a string or a sequence", range: convertRange(entry.value.range || map.range) }); continue; } container.children.push({ ...childNode, children: [{ kind: "text", text: textValue(String(value.value)) }] }); continue; } const valueIsSequence = value instanceof yaml.YAMLSeq; if (valueIsSequence) { container.children.push(childNode); convertSeq(childNode, value); continue; } errors.push({ message: "Map values should be strings or sequences", range: convertRange(entry.value.range || map.range) }); } }; const fragment = { kind: "role", role: "fragment" }; yamlDoc.errors.forEach(addError); if (errors.length) return { errors, fragment }; if (!(yamlDoc.contents instanceof yaml.YAMLSeq)) { errors.push({ message: 'Aria snapshot must be a YAML sequence, elements starting with " -"', range: yamlDoc.contents ? convertRange(yamlDoc.contents.range) : [{ line: 0, col: 0 }, { line: 0, col: 0 }] }); } if (errors.length) return { errors, fragment }; convertSeq(fragment, yamlDoc.contents); if (errors.length) return { errors, fragment: emptyFragment }; if (fragment.children?.length === 1 && (!fragment.containerMode || fragment.containerMode === "contain")) return { fragment: fragment.children[0], errors: [] }; return { fragment, errors: [] }; } const emptyFragment = { kind: "role", role: "fragment" }; function normalizeWhitespace(text) { return text.replace(/[\u200b\u00ad]/g, "").replace(/[\r\n\s\t]+/g, " ").trim(); } function textValue(value) { return { raw: value, normalized: normalizeWhitespace(value) }; } class KeyParser { static parse(text, options, errors) { try { return new KeyParser(text.value)._parse(); } catch (e) { if (e instanceof ParserError) { const message = options.prettyErrors === false ? e.message : e.message + ":\n\n" + text.value + "\n" + " ".repeat(e.pos) + "^\n"; errors.push({ message, range: [options.lineCounter.linePos(text.range[0]), options.lineCounter.linePos(text.range[0] + e.pos)] }); return null; } throw e; } } constructor(input) { this._input = input; this._pos = 0; this._length = input.length; } _peek() { return this._input[this._pos] || ""; } _next() { if (this._pos < this._length) return this._input[this._pos++]; return null; } _eof() { return this._pos >= this._length; } _isWhitespace() { return !this._eof() && /\s/.test(this._peek()); } _skipWhitespace() { while (this._isWhitespace()) this._pos++; } _readIdentifier(type) { if (this._eof()) this._throwError(`Unexpected end of input when expecting ${type}`); const start = this._pos; while (!this._eof() && /[a-zA-Z]/.test(this._peek())) this._pos++; return this._input.slice(start, this._pos); } _readString() { let result = ""; let escaped = false; while (!this._eof()) { const ch = this._next(); if (escaped) { result += ch; escaped = false; } else if (ch === "\\") { escaped = true; } else if (ch === '"') { return result; } else { result += ch; } } this._throwError("Unterminated string"); } _throwError(message, offset = 0) { throw new ParserError(message, offset || this._pos); } _readRegex() { let result = ""; let escaped = false; let insideClass = false; while (!this._eof()) { const ch = this._next(); if (escaped) { result += ch; escaped = false; } else if (ch === "\\") { escaped = true; result += ch; } else if (ch === "/" && !insideClass) { return { pattern: result }; } else if (ch === "[") { insideClass = true; result += ch; } else if (ch === "]" && insideClass) { result += ch; insideClass = false; } else { result += ch; } } this._throwError("Unterminated regex"); } _readStringOrRegex() { const ch = this._peek(); if (ch === '"') { this._next(); return normalizeWhitespace(this._readString()); } if (ch === "/") { this._next(); return this._readRegex(); } return null; } _readAttributes(result) { let errorPos = this._pos; while (true) { this._skipWhitespace(); if (this._peek() === "[") { this._next(); this._skipWhitespace(); errorPos = this._pos; const flagName = this._readIdentifier("attribute"); this._skipWhitespace(); let flagValue = ""; if (this._peek() === "=") { this._next(); this._skipWhitespace(); errorPos = this._pos; while (this._peek() !== "]" && !this._isWhitespace() && !this._eof()) flagValue += this._next(); } this._skipWhitespace(); if (this._peek() !== "]") this._throwError("Expected ]"); this._next(); this._applyAttribute(result, flagName, flagValue || "true", errorPos); } else { break; } } } _parse() { this._skipWhitespace(); const role = this._readIdentifier("role"); this._skipWhitespace(); const name = this._readStringOrRegex() || ""; const result = { kind: "role", role, name }; this._readAttributes(result); this._skipWhitespace(); if (!this._eof()) this._throwError("Unexpected input"); return result; } _applyAttribute(node, key, value, errorPos) { if (key === "checked") { this._assert(value === "true" || value === "false" || value === "mixed", 'Value of "checked" attribute must be a boolean or "mixed"', errorPos); node.checked = value === "true" ? true : value === "false" ? false : "mixed"; return; } if (key === "disabled") { this._assert(value === "true" || value === "false", 'Value of "disabled" attribute must be a boolean', errorPos); node.disabled = value === "true"; return; } if (key === "expanded") { this._assert(value === "true" || value === "false", 'Value of "expanded" attribute must be a boolean', errorPos); node.expanded = value === "true"; return; } if (key === "active") { this._assert(value === "true" || value === "false", 'Value of "active" attribute must be a boolean', errorPos); node.active = value === "true"; return; } if (key === "level") { this._assert(!isNaN(Number(value)), 'Value of "level" attribute must be a number', errorPos); node.level = Number(value); return; } if (key === "pressed") { this._assert(value === "true" || value === "false" || value === "mixed", 'Value of "pressed" attribute must be a boolean or "mixed"', errorPos); node.pressed = value === "true" ? true : value === "false" ? false : "mixed"; return; } if (key === "selected") { this._assert(value === "true" || value === "false", 'Value of "selected" attribute must be a boolean', errorPos); node.selected = value === "true"; return; } this._assert(false, `Unsupported attribute [${key}]`, errorPos); } _assert(value, message, valuePos) { if (!value) this._throwError(message || "Assertion error", valuePos); } } class ParserError extends Error { constructor(message, pos) { super(message); this.pos = pos; } } // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { KeyParser, ParserError, parseAriaSnapshot, parseAriaSnapshotUnsafe, textValue });