mirror of
https://github.com/TheBinaryNinja/tvapp2.git
synced 2026-06-04 11:35:42 -04:00
build: push tvapp v2 docker files
This commit is contained in:
31
node_modules/playwright-core/lib/utils/ascii.js
generated
vendored
Normal file
31
node_modules/playwright-core/lib/utils/ascii.js
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.jsonStringifyForceASCII = jsonStringifyForceASCII;
|
||||
exports.wrapInASCIIBox = wrapInASCIIBox;
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
function wrapInASCIIBox(text, padding = 0) {
|
||||
const lines = text.split('\n');
|
||||
const maxLength = Math.max(...lines.map(line => line.length));
|
||||
return ['╔' + '═'.repeat(maxLength + padding * 2) + '╗', ...lines.map(line => '║' + ' '.repeat(padding) + line + ' '.repeat(maxLength - line.length + padding) + '║'), '╚' + '═'.repeat(maxLength + padding * 2) + '╝'].join('\n');
|
||||
}
|
||||
function jsonStringifyForceASCII(object) {
|
||||
return JSON.stringify(object).replace(/[\u007f-\uffff]/g, c => '\\u' + ('0000' + c.charCodeAt(0).toString(16)).slice(-4));
|
||||
}
|
||||
153
node_modules/playwright-core/lib/utils/comparators.js
generated
vendored
Normal file
153
node_modules/playwright-core/lib/utils/comparators.js
generated
vendored
Normal file
@@ -0,0 +1,153 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.getComparator = getComparator;
|
||||
var _utilsBundle = require("../utilsBundle");
|
||||
var _pixelmatch = _interopRequireDefault(require("../third_party/pixelmatch"));
|
||||
var _compare = require("../image_tools/compare");
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
/**
|
||||
* Copyright 2017 Google Inc. All rights reserved.
|
||||
* Modifications copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// @ts-ignore
|
||||
|
||||
function getComparator(mimeType) {
|
||||
if (mimeType === 'image/png') return compareImages.bind(null, 'image/png');
|
||||
if (mimeType === 'image/jpeg') return compareImages.bind(null, 'image/jpeg');
|
||||
if (mimeType === 'text/plain') return compareText;
|
||||
return compareBuffersOrStrings;
|
||||
}
|
||||
const JPEG_JS_MAX_BUFFER_SIZE_IN_MB = 5 * 1024; // ~5 GB
|
||||
|
||||
function compareBuffersOrStrings(actualBuffer, expectedBuffer) {
|
||||
if (typeof actualBuffer === 'string') return compareText(actualBuffer, expectedBuffer);
|
||||
if (!actualBuffer || !(actualBuffer instanceof Buffer)) return {
|
||||
errorMessage: 'Actual result should be a Buffer or a string.'
|
||||
};
|
||||
if (Buffer.compare(actualBuffer, expectedBuffer)) return {
|
||||
errorMessage: 'Buffers differ'
|
||||
};
|
||||
return null;
|
||||
}
|
||||
function compareImages(mimeType, actualBuffer, expectedBuffer, options = {}) {
|
||||
var _options$comparator, _ref;
|
||||
if (!actualBuffer || !(actualBuffer instanceof Buffer)) return {
|
||||
errorMessage: 'Actual result should be a Buffer.'
|
||||
};
|
||||
validateBuffer(expectedBuffer, mimeType);
|
||||
let actual = mimeType === 'image/png' ? _utilsBundle.PNG.sync.read(actualBuffer) : _utilsBundle.jpegjs.decode(actualBuffer, {
|
||||
maxMemoryUsageInMB: JPEG_JS_MAX_BUFFER_SIZE_IN_MB
|
||||
});
|
||||
let expected = mimeType === 'image/png' ? _utilsBundle.PNG.sync.read(expectedBuffer) : _utilsBundle.jpegjs.decode(expectedBuffer, {
|
||||
maxMemoryUsageInMB: JPEG_JS_MAX_BUFFER_SIZE_IN_MB
|
||||
});
|
||||
const size = {
|
||||
width: Math.max(expected.width, actual.width),
|
||||
height: Math.max(expected.height, actual.height)
|
||||
};
|
||||
let sizesMismatchError = '';
|
||||
if (expected.width !== actual.width || expected.height !== actual.height) {
|
||||
sizesMismatchError = `Expected an image ${expected.width}px by ${expected.height}px, received ${actual.width}px by ${actual.height}px. `;
|
||||
actual = resizeImage(actual, size);
|
||||
expected = resizeImage(expected, size);
|
||||
}
|
||||
const diff = new _utilsBundle.PNG({
|
||||
width: size.width,
|
||||
height: size.height
|
||||
});
|
||||
let count;
|
||||
if (options.comparator === 'ssim-cie94') {
|
||||
count = (0, _compare.compare)(expected.data, actual.data, diff.data, size.width, size.height, {
|
||||
// All ΔE* formulae are originally designed to have the difference of 1.0 stand for a "just noticeable difference" (JND).
|
||||
// See https://en.wikipedia.org/wiki/Color_difference#CIELAB_%CE%94E*
|
||||
maxColorDeltaE94: 1.0
|
||||
});
|
||||
} else if (((_options$comparator = options.comparator) !== null && _options$comparator !== void 0 ? _options$comparator : 'pixelmatch') === 'pixelmatch') {
|
||||
var _options$threshold;
|
||||
count = (0, _pixelmatch.default)(expected.data, actual.data, diff.data, size.width, size.height, {
|
||||
threshold: (_options$threshold = options.threshold) !== null && _options$threshold !== void 0 ? _options$threshold : 0.2
|
||||
});
|
||||
} else {
|
||||
throw new Error(`Configuration specifies unknown comparator "${options.comparator}"`);
|
||||
}
|
||||
const maxDiffPixels1 = options.maxDiffPixels;
|
||||
const maxDiffPixels2 = options.maxDiffPixelRatio !== undefined ? expected.width * expected.height * options.maxDiffPixelRatio : undefined;
|
||||
let maxDiffPixels;
|
||||
if (maxDiffPixels1 !== undefined && maxDiffPixels2 !== undefined) maxDiffPixels = Math.min(maxDiffPixels1, maxDiffPixels2);else maxDiffPixels = (_ref = maxDiffPixels1 !== null && maxDiffPixels1 !== void 0 ? maxDiffPixels1 : maxDiffPixels2) !== null && _ref !== void 0 ? _ref : 0;
|
||||
const ratio = Math.ceil(count / (expected.width * expected.height) * 100) / 100;
|
||||
const pixelsMismatchError = count > maxDiffPixels ? `${count} pixels (ratio ${ratio.toFixed(2)} of all image pixels) are different.` : '';
|
||||
if (pixelsMismatchError || sizesMismatchError) return {
|
||||
errorMessage: sizesMismatchError + pixelsMismatchError,
|
||||
diff: _utilsBundle.PNG.sync.write(diff)
|
||||
};
|
||||
return null;
|
||||
}
|
||||
function validateBuffer(buffer, mimeType) {
|
||||
if (mimeType === 'image/png') {
|
||||
const pngMagicNumber = [137, 80, 78, 71, 13, 10, 26, 10];
|
||||
if (buffer.length < pngMagicNumber.length || !pngMagicNumber.every((byte, index) => buffer[index] === byte)) throw new Error('could not decode image as PNG.');
|
||||
} else if (mimeType === 'image/jpeg') {
|
||||
const jpegMagicNumber = [255, 216];
|
||||
if (buffer.length < jpegMagicNumber.length || !jpegMagicNumber.every((byte, index) => buffer[index] === byte)) throw new Error('could not decode image as JPEG.');
|
||||
}
|
||||
}
|
||||
function compareText(actual, expectedBuffer) {
|
||||
if (typeof actual !== 'string') return {
|
||||
errorMessage: 'Actual result should be a string'
|
||||
};
|
||||
const expected = expectedBuffer.toString('utf-8');
|
||||
if (expected === actual) return null;
|
||||
const diffs = _utilsBundle.diff.diffChars(expected, actual);
|
||||
return {
|
||||
errorMessage: diff_prettyTerminal(diffs)
|
||||
};
|
||||
}
|
||||
function diff_prettyTerminal(diffs) {
|
||||
const result = diffs.map(part => {
|
||||
const text = part.value;
|
||||
if (part.added) return _utilsBundle.colors.green(text);else if (part.removed) return _utilsBundle.colors.reset(_utilsBundle.colors.strikethrough(_utilsBundle.colors.red(text)));else return text;
|
||||
});
|
||||
return result.join('');
|
||||
}
|
||||
function resizeImage(image, size) {
|
||||
if (image.width === size.width && image.height === size.height) return image;
|
||||
const buffer = new Uint8Array(size.width * size.height * 4);
|
||||
for (let y = 0; y < size.height; y++) {
|
||||
for (let x = 0; x < size.width; x++) {
|
||||
const to = (y * size.width + x) * 4;
|
||||
if (y < image.height && x < image.width) {
|
||||
const from = (y * image.width + x) * 4;
|
||||
buffer[to] = image.data[from];
|
||||
buffer[to + 1] = image.data[from + 1];
|
||||
buffer[to + 2] = image.data[from + 2];
|
||||
buffer[to + 3] = image.data[from + 3];
|
||||
} else {
|
||||
buffer[to] = 0;
|
||||
buffer[to + 1] = 0;
|
||||
buffer[to + 2] = 0;
|
||||
buffer[to + 3] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
data: Buffer.from(buffer),
|
||||
width: size.width,
|
||||
height: size.height
|
||||
};
|
||||
}
|
||||
171
node_modules/playwright-core/lib/utils/crypto.js
generated
vendored
Normal file
171
node_modules/playwright-core/lib/utils/crypto.js
generated
vendored
Normal file
@@ -0,0 +1,171 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.calculateSha1 = calculateSha1;
|
||||
exports.createGuid = createGuid;
|
||||
exports.generateSelfSignedCertificate = generateSelfSignedCertificate;
|
||||
var _crypto = _interopRequireDefault(require("crypto"));
|
||||
var _debug = require("./debug");
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
function createGuid() {
|
||||
return _crypto.default.randomBytes(16).toString('hex');
|
||||
}
|
||||
function calculateSha1(buffer) {
|
||||
const hash = _crypto.default.createHash('sha1');
|
||||
hash.update(buffer);
|
||||
return hash.digest('hex');
|
||||
}
|
||||
|
||||
// Variable-length quantity encoding aka. base-128 encoding
|
||||
function encodeBase128(value) {
|
||||
const bytes = [];
|
||||
do {
|
||||
let byte = value & 0x7f;
|
||||
value >>>= 7;
|
||||
if (bytes.length > 0) byte |= 0x80;
|
||||
bytes.push(byte);
|
||||
} while (value > 0);
|
||||
return Buffer.from(bytes.reverse());
|
||||
}
|
||||
|
||||
// ASN1/DER Speficiation: https://www.itu.int/rec/T-REC-X.680-X.693-202102-I/en
|
||||
class DER {
|
||||
static encodeSequence(data) {
|
||||
return this._encode(0x30, Buffer.concat(data));
|
||||
}
|
||||
static encodeInteger(data) {
|
||||
(0, _debug.assert)(data >= -128 && data <= 127);
|
||||
return this._encode(0x02, Buffer.from([data]));
|
||||
}
|
||||
static encodeObjectIdentifier(oid) {
|
||||
const parts = oid.split('.').map(v => Number(v));
|
||||
// Encode the second part, which could be large, using base-128 encoding if necessary
|
||||
const output = [encodeBase128(40 * parts[0] + parts[1])];
|
||||
for (let i = 2; i < parts.length; i++) output.push(encodeBase128(parts[i]));
|
||||
return this._encode(0x06, Buffer.concat(output));
|
||||
}
|
||||
static encodeNull() {
|
||||
return Buffer.from([0x05, 0x00]);
|
||||
}
|
||||
static encodeSet(data) {
|
||||
(0, _debug.assert)(data.length === 1, 'Only one item in the set is supported. We\'d need to sort the data to support more.');
|
||||
// We expect the data to be already sorted.
|
||||
return this._encode(0x31, Buffer.concat(data));
|
||||
}
|
||||
static encodeExplicitContextDependent(tag, data) {
|
||||
return this._encode(0xa0 + tag, data);
|
||||
}
|
||||
static encodePrintableString(data) {
|
||||
return this._encode(0x13, Buffer.from(data));
|
||||
}
|
||||
static encodeBitString(data) {
|
||||
// The first byte of the content is the number of unused bits at the end
|
||||
const unusedBits = 0; // Assuming all bits are used
|
||||
const content = Buffer.concat([Buffer.from([unusedBits]), data]);
|
||||
return this._encode(0x03, content);
|
||||
}
|
||||
static encodeDate(date) {
|
||||
const year = date.getUTCFullYear();
|
||||
const isGeneralizedTime = year >= 2050;
|
||||
const parts = [isGeneralizedTime ? year.toString() : year.toString().slice(-2), (date.getUTCMonth() + 1).toString().padStart(2, '0'), date.getUTCDate().toString().padStart(2, '0'), date.getUTCHours().toString().padStart(2, '0'), date.getUTCMinutes().toString().padStart(2, '0'), date.getUTCSeconds().toString().padStart(2, '0')];
|
||||
const encodedDate = parts.join('') + 'Z';
|
||||
const tag = isGeneralizedTime ? 0x18 : 0x17; // 0x18 for GeneralizedTime, 0x17 for UTCTime
|
||||
return this._encode(tag, Buffer.from(encodedDate));
|
||||
}
|
||||
static _encode(tag, data) {
|
||||
const lengthBytes = this._encodeLength(data.length);
|
||||
return Buffer.concat([Buffer.from([tag]), lengthBytes, data]);
|
||||
}
|
||||
static _encodeLength(length) {
|
||||
if (length < 128) {
|
||||
return Buffer.from([length]);
|
||||
} else {
|
||||
const lengthBytes = [];
|
||||
while (length > 0) {
|
||||
lengthBytes.unshift(length & 0xFF);
|
||||
length >>= 8;
|
||||
}
|
||||
return Buffer.from([0x80 | lengthBytes.length, ...lengthBytes]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// X.509 Specification: https://datatracker.ietf.org/doc/html/rfc2459#section-4.1
|
||||
function generateSelfSignedCertificate() {
|
||||
const {
|
||||
privateKey,
|
||||
publicKey
|
||||
} = _crypto.default.generateKeyPairSync('rsa', {
|
||||
modulusLength: 2048
|
||||
});
|
||||
const publicKeyDer = publicKey.export({
|
||||
type: 'pkcs1',
|
||||
format: 'der'
|
||||
});
|
||||
const oneYearInMilliseconds = 365 * 24 * 60 * 60 * 1_000;
|
||||
const notBefore = new Date(new Date().getTime() - oneYearInMilliseconds);
|
||||
const notAfter = new Date(new Date().getTime() + oneYearInMilliseconds);
|
||||
|
||||
// List of fields / structure: https://datatracker.ietf.org/doc/html/rfc2459#section-4.1
|
||||
const tbsCertificate = DER.encodeSequence([DER.encodeExplicitContextDependent(0, DER.encodeInteger(1)),
|
||||
// version
|
||||
DER.encodeInteger(1),
|
||||
// serialNumber
|
||||
DER.encodeSequence([DER.encodeObjectIdentifier('1.2.840.113549.1.1.11'),
|
||||
// sha256WithRSAEncryption PKCS #1
|
||||
DER.encodeNull()]),
|
||||
// signature
|
||||
DER.encodeSequence([DER.encodeSet([DER.encodeSequence([DER.encodeObjectIdentifier('2.5.4.3'),
|
||||
// commonName X.520 DN component
|
||||
DER.encodePrintableString('localhost')])]), DER.encodeSet([DER.encodeSequence([DER.encodeObjectIdentifier('2.5.4.10'),
|
||||
// organizationName X.520 DN component
|
||||
DER.encodePrintableString('Playwright Client Certificate Support')])])]),
|
||||
// issuer
|
||||
DER.encodeSequence([DER.encodeDate(notBefore),
|
||||
// notBefore
|
||||
DER.encodeDate(notAfter) // notAfter
|
||||
]),
|
||||
// validity
|
||||
DER.encodeSequence([DER.encodeSet([DER.encodeSequence([DER.encodeObjectIdentifier('2.5.4.3'),
|
||||
// commonName X.520 DN component
|
||||
DER.encodePrintableString('localhost')])]), DER.encodeSet([DER.encodeSequence([DER.encodeObjectIdentifier('2.5.4.10'),
|
||||
// organizationName X.520 DN component
|
||||
DER.encodePrintableString('Playwright Client Certificate Support')])])]),
|
||||
// subject
|
||||
DER.encodeSequence([DER.encodeSequence([DER.encodeObjectIdentifier('1.2.840.113549.1.1.1'),
|
||||
// rsaEncryption PKCS #1
|
||||
DER.encodeNull()]), DER.encodeBitString(publicKeyDer)]) // SubjectPublicKeyInfo
|
||||
]);
|
||||
const signature = _crypto.default.sign('sha256', tbsCertificate, privateKey);
|
||||
const certificate = DER.encodeSequence([tbsCertificate, DER.encodeSequence([DER.encodeObjectIdentifier('1.2.840.113549.1.1.11'),
|
||||
// sha256WithRSAEncryption PKCS #1
|
||||
DER.encodeNull()]), DER.encodeBitString(signature)]);
|
||||
const certPem = ['-----BEGIN CERTIFICATE-----',
|
||||
// Split the base64 string into lines of 64 characters
|
||||
certificate.toString('base64').match(/.{1,64}/g).join('\n'), '-----END CERTIFICATE-----'].join('\n');
|
||||
return {
|
||||
cert: certPem,
|
||||
key: privateKey.export({
|
||||
type: 'pkcs1',
|
||||
format: 'pem'
|
||||
})
|
||||
};
|
||||
}
|
||||
46
node_modules/playwright-core/lib/utils/debug.js
generated
vendored
Normal file
46
node_modules/playwright-core/lib/utils/debug.js
generated
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.assert = assert;
|
||||
exports.debugAssert = debugAssert;
|
||||
exports.debugMode = debugMode;
|
||||
exports.isUnderTest = isUnderTest;
|
||||
exports.setUnderTest = setUnderTest;
|
||||
var _env = require("./env");
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
function assert(value, message) {
|
||||
if (!value) throw new Error(message || 'Assertion error');
|
||||
}
|
||||
function debugAssert(value, message) {
|
||||
if (isUnderTest() && !value) throw new Error(message);
|
||||
}
|
||||
const debugEnv = (0, _env.getFromENV)('PWDEBUG') || '';
|
||||
function debugMode() {
|
||||
if (debugEnv === 'console') return 'console';
|
||||
if (debugEnv === '0' || debugEnv === 'false') return '';
|
||||
return debugEnv ? 'inspector' : '';
|
||||
}
|
||||
let _isUnderTest = !!process.env.PWTEST_UNDER_TEST;
|
||||
function setUnderTest() {
|
||||
_isUnderTest = true;
|
||||
}
|
||||
function isUnderTest() {
|
||||
return _isUnderTest;
|
||||
}
|
||||
91
node_modules/playwright-core/lib/utils/debugLogger.js
generated
vendored
Normal file
91
node_modules/playwright-core/lib/utils/debugLogger.js
generated
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.debugLogger = exports.RecentLogsCollector = void 0;
|
||||
var _utilsBundle = require("../utilsBundle");
|
||||
var _fs = _interopRequireDefault(require("fs"));
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
const debugLoggerColorMap = {
|
||||
'api': 45,
|
||||
// cyan
|
||||
'protocol': 34,
|
||||
// green
|
||||
'install': 34,
|
||||
// green
|
||||
'download': 34,
|
||||
// green
|
||||
'browser': 0,
|
||||
// reset
|
||||
'socks': 92,
|
||||
// purple
|
||||
'client-certificates': 92,
|
||||
// purple
|
||||
'error': 160,
|
||||
// red,
|
||||
'channel': 33,
|
||||
// blue
|
||||
'server': 45,
|
||||
// cyan
|
||||
'server:channel': 34,
|
||||
// green
|
||||
'server:metadata': 33 // blue
|
||||
};
|
||||
class DebugLogger {
|
||||
constructor() {
|
||||
this._debuggers = new Map();
|
||||
if (process.env.DEBUG_FILE) {
|
||||
const ansiRegex = new RegExp(['[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)', '(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))'].join('|'), 'g');
|
||||
const stream = _fs.default.createWriteStream(process.env.DEBUG_FILE);
|
||||
_utilsBundle.debug.log = data => {
|
||||
stream.write(data.replace(ansiRegex, ''));
|
||||
stream.write('\n');
|
||||
};
|
||||
}
|
||||
}
|
||||
log(name, message) {
|
||||
let cachedDebugger = this._debuggers.get(name);
|
||||
if (!cachedDebugger) {
|
||||
cachedDebugger = (0, _utilsBundle.debug)(`pw:${name}`);
|
||||
this._debuggers.set(name, cachedDebugger);
|
||||
cachedDebugger.color = debugLoggerColorMap[name] || 0;
|
||||
}
|
||||
cachedDebugger(message);
|
||||
}
|
||||
isEnabled(name) {
|
||||
return _utilsBundle.debug.enabled(`pw:${name}`);
|
||||
}
|
||||
}
|
||||
const debugLogger = exports.debugLogger = new DebugLogger();
|
||||
const kLogCount = 150;
|
||||
class RecentLogsCollector {
|
||||
constructor() {
|
||||
this._logs = [];
|
||||
}
|
||||
log(message) {
|
||||
this._logs.push(message);
|
||||
if (this._logs.length === kLogCount * 2) this._logs.splice(0, kLogCount);
|
||||
}
|
||||
recentLogs() {
|
||||
if (this._logs.length > kLogCount) return this._logs.slice(-kLogCount);
|
||||
return this._logs;
|
||||
}
|
||||
}
|
||||
exports.RecentLogsCollector = RecentLogsCollector;
|
||||
49
node_modules/playwright-core/lib/utils/env.js
generated
vendored
Normal file
49
node_modules/playwright-core/lib/utils/env.js
generated
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.getAsBooleanFromENV = getAsBooleanFromENV;
|
||||
exports.getFromENV = getFromENV;
|
||||
exports.getPackageManager = getPackageManager;
|
||||
exports.getPackageManagerExecCommand = getPackageManagerExecCommand;
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
function getFromENV(name) {
|
||||
let value = process.env[name];
|
||||
value = value === undefined ? process.env[`npm_config_${name.toLowerCase()}`] : value;
|
||||
value = value === undefined ? process.env[`npm_package_config_${name.toLowerCase()}`] : value;
|
||||
return value;
|
||||
}
|
||||
function getAsBooleanFromENV(name, defaultValue) {
|
||||
const value = getFromENV(name);
|
||||
if (value === 'false' || value === '0') return false;
|
||||
if (value) return true;
|
||||
return !!defaultValue;
|
||||
}
|
||||
function getPackageManager() {
|
||||
const env = process.env.npm_config_user_agent || '';
|
||||
if (env.includes('yarn')) return 'yarn';
|
||||
if (env.includes('pnpm')) return 'pnpm';
|
||||
return 'npm';
|
||||
}
|
||||
function getPackageManagerExecCommand() {
|
||||
const packageManager = getPackageManager();
|
||||
if (packageManager === 'yarn') return 'yarn';
|
||||
if (packageManager === 'pnpm') return 'pnpm exec';
|
||||
return 'npx';
|
||||
}
|
||||
38
node_modules/playwright-core/lib/utils/eventsHelper.js
generated
vendored
Normal file
38
node_modules/playwright-core/lib/utils/eventsHelper.js
generated
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.eventsHelper = void 0;
|
||||
/**
|
||||
* Copyright 2017 Google Inc. All rights reserved.
|
||||
* Modifications copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
class EventsHelper {
|
||||
static addEventListener(emitter, eventName, handler) {
|
||||
emitter.on(eventName, handler);
|
||||
return {
|
||||
emitter,
|
||||
eventName,
|
||||
handler
|
||||
};
|
||||
}
|
||||
static removeEventListeners(listeners) {
|
||||
for (const listener of listeners) listener.emitter.removeListener(listener.eventName, listener.handler);
|
||||
listeners.splice(0, listeners.length);
|
||||
}
|
||||
}
|
||||
const eventsHelper = exports.eventsHelper = EventsHelper;
|
||||
33
node_modules/playwright-core/lib/utils/expectUtils.js
generated
vendored
Normal file
33
node_modules/playwright-core/lib/utils/expectUtils.js
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.serializeExpectedTextValues = serializeExpectedTextValues;
|
||||
var _rtti = require("./rtti");
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
function serializeExpectedTextValues(items, options = {}) {
|
||||
return items.map(i => ({
|
||||
string: (0, _rtti.isString)(i) ? i : undefined,
|
||||
regexSource: (0, _rtti.isRegExp)(i) ? i.source : undefined,
|
||||
regexFlags: (0, _rtti.isRegExp)(i) ? i.flags : undefined,
|
||||
matchSubstring: options.matchSubstring,
|
||||
ignoreCase: options.ignoreCase,
|
||||
normalizeWhiteSpace: options.normalizeWhiteSpace
|
||||
}));
|
||||
}
|
||||
205
node_modules/playwright-core/lib/utils/fileUtils.js
generated
vendored
Normal file
205
node_modules/playwright-core/lib/utils/fileUtils.js
generated
vendored
Normal file
@@ -0,0 +1,205 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.SerializedFS = void 0;
|
||||
exports.canAccessFile = canAccessFile;
|
||||
exports.copyFileAndMakeWritable = copyFileAndMakeWritable;
|
||||
exports.fileUploadSizeLimit = exports.existsAsync = void 0;
|
||||
exports.mkdirIfNeeded = mkdirIfNeeded;
|
||||
exports.removeFolders = removeFolders;
|
||||
exports.sanitizeForFilePath = sanitizeForFilePath;
|
||||
exports.toPosixPath = toPosixPath;
|
||||
var _fs = _interopRequireDefault(require("fs"));
|
||||
var _path = _interopRequireDefault(require("path"));
|
||||
var _manualPromise = require("./manualPromise");
|
||||
var _zipBundle = require("../zipBundle");
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
const fileUploadSizeLimit = exports.fileUploadSizeLimit = 50 * 1024 * 1024;
|
||||
const existsAsync = path => new Promise(resolve => _fs.default.stat(path, err => resolve(!err)));
|
||||
exports.existsAsync = existsAsync;
|
||||
async function mkdirIfNeeded(filePath) {
|
||||
// This will harmlessly throw on windows if the dirname is the root directory.
|
||||
await _fs.default.promises.mkdir(_path.default.dirname(filePath), {
|
||||
recursive: true
|
||||
}).catch(() => {});
|
||||
}
|
||||
async function removeFolders(dirs) {
|
||||
return await Promise.all(dirs.map(dir => _fs.default.promises.rm(dir, {
|
||||
recursive: true,
|
||||
force: true,
|
||||
maxRetries: 10
|
||||
}).catch(e => e)));
|
||||
}
|
||||
function canAccessFile(file) {
|
||||
if (!file) return false;
|
||||
try {
|
||||
_fs.default.accessSync(file);
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
async function copyFileAndMakeWritable(from, to) {
|
||||
await _fs.default.promises.copyFile(from, to);
|
||||
await _fs.default.promises.chmod(to, 0o664);
|
||||
}
|
||||
function sanitizeForFilePath(s) {
|
||||
return s.replace(/[\x00-\x2C\x2E-\x2F\x3A-\x40\x5B-\x60\x7B-\x7F]+/g, '-');
|
||||
}
|
||||
function toPosixPath(aPath) {
|
||||
return aPath.split(_path.default.sep).join(_path.default.posix.sep);
|
||||
}
|
||||
class SerializedFS {
|
||||
constructor() {
|
||||
this._buffers = new Map();
|
||||
// Should never be accessed from within appendOperation.
|
||||
this._error = void 0;
|
||||
this._operations = [];
|
||||
this._operationsDone = void 0;
|
||||
this._operationsDone = new _manualPromise.ManualPromise();
|
||||
this._operationsDone.resolve(); // No operations scheduled yet.
|
||||
}
|
||||
mkdir(dir) {
|
||||
this._appendOperation({
|
||||
op: 'mkdir',
|
||||
dir
|
||||
});
|
||||
}
|
||||
writeFile(file, content, skipIfExists) {
|
||||
this._buffers.delete(file); // No need to flush the buffer since we'll overwrite anyway.
|
||||
this._appendOperation({
|
||||
op: 'writeFile',
|
||||
file,
|
||||
content,
|
||||
skipIfExists
|
||||
});
|
||||
}
|
||||
appendFile(file, text, flush) {
|
||||
if (!this._buffers.has(file)) this._buffers.set(file, []);
|
||||
this._buffers.get(file).push(text);
|
||||
if (flush) this._flushFile(file);
|
||||
}
|
||||
_flushFile(file) {
|
||||
const buffer = this._buffers.get(file);
|
||||
if (buffer === undefined) return;
|
||||
const content = buffer.join('');
|
||||
this._buffers.delete(file);
|
||||
this._appendOperation({
|
||||
op: 'appendFile',
|
||||
file,
|
||||
content
|
||||
});
|
||||
}
|
||||
copyFile(from, to) {
|
||||
this._flushFile(from);
|
||||
this._buffers.delete(to); // No need to flush the buffer since we'll overwrite anyway.
|
||||
this._appendOperation({
|
||||
op: 'copyFile',
|
||||
from,
|
||||
to
|
||||
});
|
||||
}
|
||||
async syncAndGetError() {
|
||||
for (const file of this._buffers.keys()) this._flushFile(file);
|
||||
await this._operationsDone;
|
||||
return this._error;
|
||||
}
|
||||
zip(entries, zipFileName) {
|
||||
for (const file of this._buffers.keys()) this._flushFile(file);
|
||||
|
||||
// Chain the export operation against write operations,
|
||||
// so that files do not change during the export.
|
||||
this._appendOperation({
|
||||
op: 'zip',
|
||||
entries,
|
||||
zipFileName
|
||||
});
|
||||
}
|
||||
|
||||
// This method serializes all writes to the trace.
|
||||
_appendOperation(op) {
|
||||
const last = this._operations[this._operations.length - 1];
|
||||
if ((last === null || last === void 0 ? void 0 : last.op) === 'appendFile' && op.op === 'appendFile' && last.file === op.file) {
|
||||
// Merge pending appendFile operations for performance.
|
||||
last.content += op.content;
|
||||
return;
|
||||
}
|
||||
this._operations.push(op);
|
||||
if (this._operationsDone.isDone()) this._performOperations();
|
||||
}
|
||||
async _performOperations() {
|
||||
this._operationsDone = new _manualPromise.ManualPromise();
|
||||
while (this._operations.length) {
|
||||
const op = this._operations.shift();
|
||||
// Ignore all operations after the first error.
|
||||
if (this._error) continue;
|
||||
try {
|
||||
await this._performOperation(op);
|
||||
} catch (e) {
|
||||
this._error = e;
|
||||
}
|
||||
}
|
||||
this._operationsDone.resolve();
|
||||
}
|
||||
async _performOperation(op) {
|
||||
switch (op.op) {
|
||||
case 'mkdir':
|
||||
{
|
||||
await _fs.default.promises.mkdir(op.dir, {
|
||||
recursive: true
|
||||
});
|
||||
return;
|
||||
}
|
||||
case 'writeFile':
|
||||
{
|
||||
// Note: 'wx' flag only writes when the file does not exist.
|
||||
// See https://nodejs.org/api/fs.html#file-system-flags.
|
||||
// This way tracing never have to write the same resource twice.
|
||||
if (op.skipIfExists) await _fs.default.promises.writeFile(op.file, op.content, {
|
||||
flag: 'wx'
|
||||
}).catch(() => {});else await _fs.default.promises.writeFile(op.file, op.content);
|
||||
return;
|
||||
}
|
||||
case 'copyFile':
|
||||
{
|
||||
await _fs.default.promises.copyFile(op.from, op.to);
|
||||
return;
|
||||
}
|
||||
case 'appendFile':
|
||||
{
|
||||
await _fs.default.promises.appendFile(op.file, op.content);
|
||||
return;
|
||||
}
|
||||
case 'zip':
|
||||
{
|
||||
const zipFile = new _zipBundle.yazl.ZipFile();
|
||||
const result = new _manualPromise.ManualPromise();
|
||||
zipFile.on('error', error => result.reject(error));
|
||||
for (const entry of op.entries) zipFile.addFile(entry.value, entry.name);
|
||||
zipFile.end();
|
||||
zipFile.outputStream.pipe(_fs.default.createWriteStream(op.zipFileName)).on('close', () => result.resolve()).on('error', error => result.reject(error));
|
||||
await result;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.SerializedFS = SerializedFS;
|
||||
194
node_modules/playwright-core/lib/utils/happy-eyeballs.js
generated
vendored
Normal file
194
node_modules/playwright-core/lib/utils/happy-eyeballs.js
generated
vendored
Normal file
@@ -0,0 +1,194 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.createConnectionAsync = createConnectionAsync;
|
||||
exports.createSocket = createSocket;
|
||||
exports.createTLSSocket = createTLSSocket;
|
||||
exports.httpsHappyEyeballsAgent = exports.httpHappyEyeballsAgent = void 0;
|
||||
exports.timingForSocket = timingForSocket;
|
||||
var dns = _interopRequireWildcard(require("dns"));
|
||||
var http = _interopRequireWildcard(require("http"));
|
||||
var https = _interopRequireWildcard(require("https"));
|
||||
var net = _interopRequireWildcard(require("net"));
|
||||
var tls = _interopRequireWildcard(require("tls"));
|
||||
var _manualPromise = require("./manualPromise");
|
||||
var _debug = require("./debug");
|
||||
var _time = require("./time");
|
||||
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
||||
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// Implementation(partial) of Happy Eyeballs 2 algorithm described in
|
||||
// https://www.rfc-editor.org/rfc/rfc8305
|
||||
|
||||
// Same as in Chromium (https://source.chromium.org/chromium/chromium/src/+/5666ff4f5077a7e2f72902f3a95f5d553ea0d88d:net/socket/transport_connect_job.cc;l=102)
|
||||
const connectionAttemptDelayMs = 300;
|
||||
const kDNSLookupAt = Symbol('kDNSLookupAt');
|
||||
const kTCPConnectionAt = Symbol('kTCPConnectionAt');
|
||||
class HttpHappyEyeballsAgent extends http.Agent {
|
||||
createConnection(options, oncreate) {
|
||||
// There is no ambiguity in case of IP address.
|
||||
if (net.isIP(clientRequestArgsToHostName(options))) return net.createConnection(options);
|
||||
createConnectionAsync(options, oncreate, /* useTLS */false).catch(err => oncreate === null || oncreate === void 0 ? void 0 : oncreate(err));
|
||||
}
|
||||
}
|
||||
class HttpsHappyEyeballsAgent extends https.Agent {
|
||||
createConnection(options, oncreate) {
|
||||
// There is no ambiguity in case of IP address.
|
||||
if (net.isIP(clientRequestArgsToHostName(options))) return tls.connect(options);
|
||||
createConnectionAsync(options, oncreate, /* useTLS */true).catch(err => oncreate === null || oncreate === void 0 ? void 0 : oncreate(err));
|
||||
}
|
||||
}
|
||||
|
||||
// These options are aligned with the default Node.js globalAgent options.
|
||||
const httpsHappyEyeballsAgent = exports.httpsHappyEyeballsAgent = new HttpsHappyEyeballsAgent({
|
||||
keepAlive: true
|
||||
});
|
||||
const httpHappyEyeballsAgent = exports.httpHappyEyeballsAgent = new HttpHappyEyeballsAgent({
|
||||
keepAlive: true
|
||||
});
|
||||
async function createSocket(host, port) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (net.isIP(host)) {
|
||||
const socket = net.createConnection({
|
||||
host,
|
||||
port
|
||||
});
|
||||
socket.on('connect', () => resolve(socket));
|
||||
socket.on('error', error => reject(error));
|
||||
} else {
|
||||
createConnectionAsync({
|
||||
host,
|
||||
port
|
||||
}, (err, socket) => {
|
||||
if (err) reject(err);
|
||||
if (socket) resolve(socket);
|
||||
}, /* useTLS */false).catch(err => reject(err));
|
||||
}
|
||||
});
|
||||
}
|
||||
async function createTLSSocket(options) {
|
||||
return new Promise((resolve, reject) => {
|
||||
(0, _debug.assert)(options.host, 'host is required');
|
||||
if (net.isIP(options.host)) {
|
||||
const socket = tls.connect(options);
|
||||
socket.on('secureConnect', () => resolve(socket));
|
||||
socket.on('error', error => reject(error));
|
||||
} else {
|
||||
createConnectionAsync(options, (err, socket) => {
|
||||
if (err) reject(err);
|
||||
if (socket) {
|
||||
socket.on('secureConnect', () => resolve(socket));
|
||||
socket.on('error', error => reject(error));
|
||||
}
|
||||
}, true).catch(err => reject(err));
|
||||
}
|
||||
});
|
||||
}
|
||||
async function createConnectionAsync(options, oncreate, useTLS) {
|
||||
const lookup = options.__testHookLookup || lookupAddresses;
|
||||
const hostname = clientRequestArgsToHostName(options);
|
||||
const addresses = await lookup(hostname);
|
||||
const dnsLookupAt = (0, _time.monotonicTime)();
|
||||
const sockets = new Set();
|
||||
let firstError;
|
||||
let errorCount = 0;
|
||||
const handleError = (socket, err) => {
|
||||
var _firstError;
|
||||
if (!sockets.delete(socket)) return;
|
||||
++errorCount;
|
||||
(_firstError = firstError) !== null && _firstError !== void 0 ? _firstError : firstError = err;
|
||||
if (errorCount === addresses.length) oncreate === null || oncreate === void 0 || oncreate(firstError);
|
||||
};
|
||||
const connected = new _manualPromise.ManualPromise();
|
||||
for (const {
|
||||
address
|
||||
} of addresses) {
|
||||
const socket = useTLS ? tls.connect({
|
||||
...options,
|
||||
port: options.port,
|
||||
host: address,
|
||||
servername: hostname
|
||||
}) : net.createConnection({
|
||||
...options,
|
||||
port: options.port,
|
||||
host: address
|
||||
});
|
||||
socket[kDNSLookupAt] = dnsLookupAt;
|
||||
|
||||
// Each socket may fire only one of 'connect', 'timeout' or 'error' events.
|
||||
// None of these events are fired after socket.destroy() is called.
|
||||
socket.on('connect', () => {
|
||||
socket[kTCPConnectionAt] = (0, _time.monotonicTime)();
|
||||
connected.resolve();
|
||||
oncreate === null || oncreate === void 0 || oncreate(null, socket);
|
||||
// TODO: Cache the result?
|
||||
// Close other outstanding sockets.
|
||||
sockets.delete(socket);
|
||||
for (const s of sockets) s.destroy();
|
||||
sockets.clear();
|
||||
});
|
||||
socket.on('timeout', () => {
|
||||
// Timeout is not an error, so we have to manually close the socket.
|
||||
socket.destroy();
|
||||
handleError(socket, new Error('Connection timeout'));
|
||||
});
|
||||
socket.on('error', e => handleError(socket, e));
|
||||
sockets.add(socket);
|
||||
await Promise.race([connected, new Promise(f => setTimeout(f, connectionAttemptDelayMs))]);
|
||||
if (connected.isDone()) break;
|
||||
}
|
||||
}
|
||||
async function lookupAddresses(hostname) {
|
||||
const addresses = await dns.promises.lookup(hostname, {
|
||||
all: true,
|
||||
family: 0,
|
||||
verbatim: true
|
||||
});
|
||||
let firstFamily = addresses.filter(({
|
||||
family
|
||||
}) => family === 6);
|
||||
let secondFamily = addresses.filter(({
|
||||
family
|
||||
}) => family === 4);
|
||||
// Make sure first address in the list is the same as in the original order.
|
||||
if (firstFamily.length && firstFamily[0] !== addresses[0]) {
|
||||
const tmp = firstFamily;
|
||||
firstFamily = secondFamily;
|
||||
secondFamily = tmp;
|
||||
}
|
||||
const result = [];
|
||||
// Alternate ipv6 and ipv4 addresses.
|
||||
for (let i = 0; i < Math.max(firstFamily.length, secondFamily.length); i++) {
|
||||
if (firstFamily[i]) result.push(firstFamily[i]);
|
||||
if (secondFamily[i]) result.push(secondFamily[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
function clientRequestArgsToHostName(options) {
|
||||
if (options.hostname) return options.hostname;
|
||||
if (options.host) return options.host;
|
||||
throw new Error('Either options.hostname or options.host must be provided');
|
||||
}
|
||||
function timingForSocket(socket) {
|
||||
return {
|
||||
dnsLookupAt: socket[kDNSLookupAt],
|
||||
tcpConnectionAt: socket[kTCPConnectionAt]
|
||||
};
|
||||
}
|
||||
52
node_modules/playwright-core/lib/utils/headers.js
generated
vendored
Normal file
52
node_modules/playwright-core/lib/utils/headers.js
generated
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.headersArrayToObject = headersArrayToObject;
|
||||
exports.headersObjectToArray = headersObjectToArray;
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
function headersObjectToArray(headers, separator, setCookieSeparator) {
|
||||
if (!setCookieSeparator) setCookieSeparator = separator;
|
||||
const result = [];
|
||||
for (const name in headers) {
|
||||
const values = headers[name];
|
||||
if (values === undefined) continue;
|
||||
if (separator) {
|
||||
const sep = name.toLowerCase() === 'set-cookie' ? setCookieSeparator : separator;
|
||||
for (const value of values.split(sep)) result.push({
|
||||
name,
|
||||
value: value.trim()
|
||||
});
|
||||
} else {
|
||||
result.push({
|
||||
name,
|
||||
value: values
|
||||
});
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
function headersArrayToObject(headers, lowerCase) {
|
||||
const result = {};
|
||||
for (const {
|
||||
name,
|
||||
value
|
||||
} of headers) result[lowerCase ? name.toLowerCase() : name] = value;
|
||||
return result;
|
||||
}
|
||||
139
node_modules/playwright-core/lib/utils/hostPlatform.js
generated
vendored
Normal file
139
node_modules/playwright-core/lib/utils/hostPlatform.js
generated
vendored
Normal file
@@ -0,0 +1,139 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.isOfficiallySupportedPlatform = exports.hostPlatform = void 0;
|
||||
var _os = _interopRequireDefault(require("os"));
|
||||
var _linuxUtils = require("./linuxUtils");
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
function calculatePlatform() {
|
||||
if (process.env.PLAYWRIGHT_HOST_PLATFORM_OVERRIDE) {
|
||||
return {
|
||||
hostPlatform: process.env.PLAYWRIGHT_HOST_PLATFORM_OVERRIDE,
|
||||
isOfficiallySupportedPlatform: false
|
||||
};
|
||||
}
|
||||
const platform = _os.default.platform();
|
||||
if (platform === 'darwin') {
|
||||
const ver = _os.default.release().split('.').map(a => parseInt(a, 10));
|
||||
let macVersion = '';
|
||||
if (ver[0] < 18) {
|
||||
// Everything before 10.14 is considered 10.13.
|
||||
macVersion = 'mac10.13';
|
||||
} else if (ver[0] === 18) {
|
||||
macVersion = 'mac10.14';
|
||||
} else if (ver[0] === 19) {
|
||||
macVersion = 'mac10.15';
|
||||
} else {
|
||||
// ver[0] >= 20
|
||||
const LAST_STABLE_MACOS_MAJOR_VERSION = 15;
|
||||
// Best-effort support for MacOS beta versions.
|
||||
macVersion = 'mac' + Math.min(ver[0] - 9, LAST_STABLE_MACOS_MAJOR_VERSION);
|
||||
// BigSur is the first version that might run on Apple Silicon.
|
||||
if (_os.default.cpus().some(cpu => cpu.model.includes('Apple'))) macVersion += '-arm64';
|
||||
}
|
||||
return {
|
||||
hostPlatform: macVersion,
|
||||
isOfficiallySupportedPlatform: true
|
||||
};
|
||||
}
|
||||
if (platform === 'linux') {
|
||||
if (!['x64', 'arm64'].includes(_os.default.arch())) return {
|
||||
hostPlatform: '<unknown>',
|
||||
isOfficiallySupportedPlatform: false
|
||||
};
|
||||
const archSuffix = '-' + _os.default.arch();
|
||||
const distroInfo = (0, _linuxUtils.getLinuxDistributionInfoSync)();
|
||||
|
||||
// Pop!_OS is ubuntu-based and has the same versions.
|
||||
// KDE Neon is ubuntu-based and has the same versions.
|
||||
// TUXEDO OS is ubuntu-based and has the same versions.
|
||||
if ((distroInfo === null || distroInfo === void 0 ? void 0 : distroInfo.id) === 'ubuntu' || (distroInfo === null || distroInfo === void 0 ? void 0 : distroInfo.id) === 'pop' || (distroInfo === null || distroInfo === void 0 ? void 0 : distroInfo.id) === 'neon' || (distroInfo === null || distroInfo === void 0 ? void 0 : distroInfo.id) === 'tuxedo') {
|
||||
const isOfficiallySupportedPlatform = (distroInfo === null || distroInfo === void 0 ? void 0 : distroInfo.id) === 'ubuntu';
|
||||
if (parseInt(distroInfo.version, 10) <= 19) return {
|
||||
hostPlatform: 'ubuntu18.04' + archSuffix,
|
||||
isOfficiallySupportedPlatform: false
|
||||
};
|
||||
if (parseInt(distroInfo.version, 10) <= 21) return {
|
||||
hostPlatform: 'ubuntu20.04' + archSuffix,
|
||||
isOfficiallySupportedPlatform
|
||||
};
|
||||
if (parseInt(distroInfo.version, 10) <= 22) return {
|
||||
hostPlatform: 'ubuntu22.04' + archSuffix,
|
||||
isOfficiallySupportedPlatform
|
||||
};
|
||||
return {
|
||||
hostPlatform: 'ubuntu24.04' + archSuffix,
|
||||
isOfficiallySupportedPlatform
|
||||
};
|
||||
}
|
||||
// Linux Mint is ubuntu-based but does not have the same versions
|
||||
if ((distroInfo === null || distroInfo === void 0 ? void 0 : distroInfo.id) === 'linuxmint') {
|
||||
const mintMajor = parseInt(distroInfo.version, 10);
|
||||
if (mintMajor <= 20) return {
|
||||
hostPlatform: 'ubuntu20.04' + archSuffix,
|
||||
isOfficiallySupportedPlatform: false
|
||||
};
|
||||
if (mintMajor === 21) return {
|
||||
hostPlatform: 'ubuntu22.04' + archSuffix,
|
||||
isOfficiallySupportedPlatform: false
|
||||
};
|
||||
return {
|
||||
hostPlatform: 'ubuntu24.04' + archSuffix,
|
||||
isOfficiallySupportedPlatform: false
|
||||
};
|
||||
}
|
||||
if ((distroInfo === null || distroInfo === void 0 ? void 0 : distroInfo.id) === 'debian' || (distroInfo === null || distroInfo === void 0 ? void 0 : distroInfo.id) === 'raspbian') {
|
||||
const isOfficiallySupportedPlatform = (distroInfo === null || distroInfo === void 0 ? void 0 : distroInfo.id) === 'debian';
|
||||
if ((distroInfo === null || distroInfo === void 0 ? void 0 : distroInfo.version) === '11') return {
|
||||
hostPlatform: 'debian11' + archSuffix,
|
||||
isOfficiallySupportedPlatform
|
||||
};
|
||||
if ((distroInfo === null || distroInfo === void 0 ? void 0 : distroInfo.version) === '12') return {
|
||||
hostPlatform: 'debian12' + archSuffix,
|
||||
isOfficiallySupportedPlatform
|
||||
};
|
||||
// use most recent supported release for 'debian testing' and 'unstable'.
|
||||
// they never include a numeric version entry in /etc/os-release.
|
||||
if ((distroInfo === null || distroInfo === void 0 ? void 0 : distroInfo.version) === '') return {
|
||||
hostPlatform: 'debian12' + archSuffix,
|
||||
isOfficiallySupportedPlatform
|
||||
};
|
||||
}
|
||||
return {
|
||||
hostPlatform: 'ubuntu20.04' + archSuffix,
|
||||
isOfficiallySupportedPlatform: false
|
||||
};
|
||||
}
|
||||
if (platform === 'win32') return {
|
||||
hostPlatform: 'win64',
|
||||
isOfficiallySupportedPlatform: true
|
||||
};
|
||||
return {
|
||||
hostPlatform: '<unknown>',
|
||||
isOfficiallySupportedPlatform: false
|
||||
};
|
||||
}
|
||||
const {
|
||||
hostPlatform,
|
||||
isOfficiallySupportedPlatform
|
||||
} = calculatePlatform();
|
||||
exports.isOfficiallySupportedPlatform = isOfficiallySupportedPlatform;
|
||||
exports.hostPlatform = hostPlatform;
|
||||
237
node_modules/playwright-core/lib/utils/httpServer.js
generated
vendored
Normal file
237
node_modules/playwright-core/lib/utils/httpServer.js
generated
vendored
Normal file
@@ -0,0 +1,237 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.HttpServer = void 0;
|
||||
var _fs = _interopRequireDefault(require("fs"));
|
||||
var _path = _interopRequireDefault(require("path"));
|
||||
var _utilsBundle = require("../utilsBundle");
|
||||
var _debug = require("./debug");
|
||||
var _network = require("./network");
|
||||
var _manualPromise = require("./manualPromise");
|
||||
var _crypto = require("./crypto");
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
class HttpServer {
|
||||
constructor() {
|
||||
this._server = void 0;
|
||||
this._urlPrefixPrecise = '';
|
||||
this._urlPrefixHumanReadable = '';
|
||||
this._port = 0;
|
||||
this._started = false;
|
||||
this._routes = [];
|
||||
this._wsGuid = void 0;
|
||||
this._server = (0, _network.createHttpServer)(this._onRequest.bind(this));
|
||||
}
|
||||
server() {
|
||||
return this._server;
|
||||
}
|
||||
routePrefix(prefix, handler) {
|
||||
this._routes.push({
|
||||
prefix,
|
||||
handler
|
||||
});
|
||||
}
|
||||
routePath(path, handler) {
|
||||
this._routes.push({
|
||||
exact: path,
|
||||
handler
|
||||
});
|
||||
}
|
||||
port() {
|
||||
return this._port;
|
||||
}
|
||||
async _tryStart(port, host) {
|
||||
const errorPromise = new _manualPromise.ManualPromise();
|
||||
const errorListener = error => errorPromise.reject(error);
|
||||
this._server.on('error', errorListener);
|
||||
try {
|
||||
this._server.listen(port, host);
|
||||
await Promise.race([new Promise(cb => this._server.once('listening', cb)), errorPromise]);
|
||||
} finally {
|
||||
this._server.removeListener('error', errorListener);
|
||||
}
|
||||
}
|
||||
createWebSocket(transport, guid) {
|
||||
(0, _debug.assert)(!this._wsGuid, 'can only create one main websocket transport per server');
|
||||
this._wsGuid = guid || (0, _crypto.createGuid)();
|
||||
const wss = new _utilsBundle.wsServer({
|
||||
server: this._server,
|
||||
path: '/' + this._wsGuid
|
||||
});
|
||||
wss.on('connection', ws => {
|
||||
transport.onconnect();
|
||||
transport.sendEvent = (method, params) => ws.send(JSON.stringify({
|
||||
method,
|
||||
params
|
||||
}));
|
||||
transport.close = () => ws.close();
|
||||
ws.on('message', async message => {
|
||||
const {
|
||||
id,
|
||||
method,
|
||||
params
|
||||
} = JSON.parse(String(message));
|
||||
try {
|
||||
const result = await transport.dispatch(method, params);
|
||||
ws.send(JSON.stringify({
|
||||
id,
|
||||
result
|
||||
}));
|
||||
} catch (e) {
|
||||
ws.send(JSON.stringify({
|
||||
id,
|
||||
error: String(e)
|
||||
}));
|
||||
}
|
||||
});
|
||||
ws.on('close', () => transport.onclose());
|
||||
ws.on('error', () => transport.onclose());
|
||||
});
|
||||
}
|
||||
wsGuid() {
|
||||
return this._wsGuid;
|
||||
}
|
||||
async start(options = {}) {
|
||||
(0, _debug.assert)(!this._started, 'server already started');
|
||||
this._started = true;
|
||||
const host = options.host || 'localhost';
|
||||
if (options.preferredPort) {
|
||||
try {
|
||||
await this._tryStart(options.preferredPort, host);
|
||||
} catch (e) {
|
||||
if (!e || !e.message || !e.message.includes('EADDRINUSE')) throw e;
|
||||
await this._tryStart(undefined, host);
|
||||
}
|
||||
} else {
|
||||
await this._tryStart(options.port, host);
|
||||
}
|
||||
const address = this._server.address();
|
||||
(0, _debug.assert)(address, 'Could not bind server socket');
|
||||
if (typeof address === 'string') {
|
||||
this._urlPrefixPrecise = address;
|
||||
this._urlPrefixHumanReadable = address;
|
||||
} else {
|
||||
this._port = address.port;
|
||||
const resolvedHost = address.family === 'IPv4' ? address.address : `[${address.address}]`;
|
||||
this._urlPrefixPrecise = `http://${resolvedHost}:${address.port}`;
|
||||
this._urlPrefixHumanReadable = `http://${host}:${address.port}`;
|
||||
}
|
||||
}
|
||||
async stop() {
|
||||
await new Promise(cb => this._server.close(cb));
|
||||
}
|
||||
urlPrefix(purpose) {
|
||||
return purpose === 'human-readable' ? this._urlPrefixHumanReadable : this._urlPrefixPrecise;
|
||||
}
|
||||
serveFile(request, response, absoluteFilePath, headers) {
|
||||
try {
|
||||
for (const [name, value] of Object.entries(headers || {})) response.setHeader(name, value);
|
||||
if (request.headers.range) this._serveRangeFile(request, response, absoluteFilePath);else this._serveFile(response, absoluteFilePath);
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
_serveFile(response, absoluteFilePath) {
|
||||
const content = _fs.default.readFileSync(absoluteFilePath);
|
||||
response.statusCode = 200;
|
||||
const contentType = _utilsBundle.mime.getType(_path.default.extname(absoluteFilePath)) || 'application/octet-stream';
|
||||
response.setHeader('Content-Type', contentType);
|
||||
response.setHeader('Content-Length', content.byteLength);
|
||||
response.end(content);
|
||||
}
|
||||
_serveRangeFile(request, response, absoluteFilePath) {
|
||||
const range = request.headers.range;
|
||||
if (!range || !range.startsWith('bytes=') || range.includes(', ') || [...range].filter(char => char === '-').length !== 1) {
|
||||
response.statusCode = 400;
|
||||
return response.end('Bad request');
|
||||
}
|
||||
|
||||
// Parse the range header: https://datatracker.ietf.org/doc/html/rfc7233#section-2.1
|
||||
const [startStr, endStr] = range.replace(/bytes=/, '').split('-');
|
||||
|
||||
// Both start and end (when passing to fs.createReadStream) and the range header are inclusive and start counting at 0.
|
||||
let start;
|
||||
let end;
|
||||
const size = _fs.default.statSync(absoluteFilePath).size;
|
||||
if (startStr !== '' && endStr === '') {
|
||||
// No end specified: use the whole file
|
||||
start = +startStr;
|
||||
end = size - 1;
|
||||
} else if (startStr === '' && endStr !== '') {
|
||||
// No start specified: calculate start manually
|
||||
start = size - +endStr;
|
||||
end = size - 1;
|
||||
} else {
|
||||
start = +startStr;
|
||||
end = +endStr;
|
||||
}
|
||||
|
||||
// Handle unavailable range request
|
||||
if (Number.isNaN(start) || Number.isNaN(end) || start >= size || end >= size || start > end) {
|
||||
// Return the 416 Range Not Satisfiable: https://datatracker.ietf.org/doc/html/rfc7233#section-4.4
|
||||
response.writeHead(416, {
|
||||
'Content-Range': `bytes */${size}`
|
||||
});
|
||||
return response.end();
|
||||
}
|
||||
|
||||
// Sending Partial Content: https://datatracker.ietf.org/doc/html/rfc7233#section-4.1
|
||||
response.writeHead(206, {
|
||||
'Content-Range': `bytes ${start}-${end}/${size}`,
|
||||
'Accept-Ranges': 'bytes',
|
||||
'Content-Length': end - start + 1,
|
||||
'Content-Type': _utilsBundle.mime.getType(_path.default.extname(absoluteFilePath))
|
||||
});
|
||||
const readable = _fs.default.createReadStream(absoluteFilePath, {
|
||||
start,
|
||||
end
|
||||
});
|
||||
readable.pipe(response);
|
||||
}
|
||||
_onRequest(request, response) {
|
||||
response.setHeader('Access-Control-Allow-Origin', '*');
|
||||
response.setHeader('Access-Control-Request-Method', '*');
|
||||
response.setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET');
|
||||
if (request.headers.origin) response.setHeader('Access-Control-Allow-Headers', request.headers.origin);
|
||||
if (request.method === 'OPTIONS') {
|
||||
response.writeHead(200);
|
||||
response.end();
|
||||
return;
|
||||
}
|
||||
request.on('error', () => response.end());
|
||||
try {
|
||||
if (!request.url) {
|
||||
response.end();
|
||||
return;
|
||||
}
|
||||
const url = new URL('http://localhost' + request.url);
|
||||
for (const route of this._routes) {
|
||||
if (route.exact && url.pathname === route.exact && route.handler(request, response)) return;
|
||||
if (route.prefix && url.pathname.startsWith(route.prefix) && route.handler(request, response)) return;
|
||||
}
|
||||
response.statusCode = 404;
|
||||
response.end();
|
||||
} catch (e) {
|
||||
response.end();
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.HttpServer = HttpServer;
|
||||
368
node_modules/playwright-core/lib/utils/index.js
generated
vendored
Normal file
368
node_modules/playwright-core/lib/utils/index.js
generated
vendored
Normal file
@@ -0,0 +1,368 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
var _ascii = require("./ascii");
|
||||
Object.keys(_ascii).forEach(function (key) {
|
||||
if (key === "default" || key === "__esModule") return;
|
||||
if (key in exports && exports[key] === _ascii[key]) return;
|
||||
Object.defineProperty(exports, key, {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _ascii[key];
|
||||
}
|
||||
});
|
||||
});
|
||||
var _comparators = require("./comparators");
|
||||
Object.keys(_comparators).forEach(function (key) {
|
||||
if (key === "default" || key === "__esModule") return;
|
||||
if (key in exports && exports[key] === _comparators[key]) return;
|
||||
Object.defineProperty(exports, key, {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _comparators[key];
|
||||
}
|
||||
});
|
||||
});
|
||||
var _crypto = require("./crypto");
|
||||
Object.keys(_crypto).forEach(function (key) {
|
||||
if (key === "default" || key === "__esModule") return;
|
||||
if (key in exports && exports[key] === _crypto[key]) return;
|
||||
Object.defineProperty(exports, key, {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _crypto[key];
|
||||
}
|
||||
});
|
||||
});
|
||||
var _debug = require("./debug");
|
||||
Object.keys(_debug).forEach(function (key) {
|
||||
if (key === "default" || key === "__esModule") return;
|
||||
if (key in exports && exports[key] === _debug[key]) return;
|
||||
Object.defineProperty(exports, key, {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _debug[key];
|
||||
}
|
||||
});
|
||||
});
|
||||
var _debugLogger = require("./debugLogger");
|
||||
Object.keys(_debugLogger).forEach(function (key) {
|
||||
if (key === "default" || key === "__esModule") return;
|
||||
if (key in exports && exports[key] === _debugLogger[key]) return;
|
||||
Object.defineProperty(exports, key, {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _debugLogger[key];
|
||||
}
|
||||
});
|
||||
});
|
||||
var _env = require("./env");
|
||||
Object.keys(_env).forEach(function (key) {
|
||||
if (key === "default" || key === "__esModule") return;
|
||||
if (key in exports && exports[key] === _env[key]) return;
|
||||
Object.defineProperty(exports, key, {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _env[key];
|
||||
}
|
||||
});
|
||||
});
|
||||
var _eventsHelper = require("./eventsHelper");
|
||||
Object.keys(_eventsHelper).forEach(function (key) {
|
||||
if (key === "default" || key === "__esModule") return;
|
||||
if (key in exports && exports[key] === _eventsHelper[key]) return;
|
||||
Object.defineProperty(exports, key, {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _eventsHelper[key];
|
||||
}
|
||||
});
|
||||
});
|
||||
var _expectUtils = require("./expectUtils");
|
||||
Object.keys(_expectUtils).forEach(function (key) {
|
||||
if (key === "default" || key === "__esModule") return;
|
||||
if (key in exports && exports[key] === _expectUtils[key]) return;
|
||||
Object.defineProperty(exports, key, {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _expectUtils[key];
|
||||
}
|
||||
});
|
||||
});
|
||||
var _fileUtils = require("./fileUtils");
|
||||
Object.keys(_fileUtils).forEach(function (key) {
|
||||
if (key === "default" || key === "__esModule") return;
|
||||
if (key in exports && exports[key] === _fileUtils[key]) return;
|
||||
Object.defineProperty(exports, key, {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _fileUtils[key];
|
||||
}
|
||||
});
|
||||
});
|
||||
var _headers = require("./headers");
|
||||
Object.keys(_headers).forEach(function (key) {
|
||||
if (key === "default" || key === "__esModule") return;
|
||||
if (key in exports && exports[key] === _headers[key]) return;
|
||||
Object.defineProperty(exports, key, {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _headers[key];
|
||||
}
|
||||
});
|
||||
});
|
||||
var _hostPlatform = require("./hostPlatform");
|
||||
Object.keys(_hostPlatform).forEach(function (key) {
|
||||
if (key === "default" || key === "__esModule") return;
|
||||
if (key in exports && exports[key] === _hostPlatform[key]) return;
|
||||
Object.defineProperty(exports, key, {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _hostPlatform[key];
|
||||
}
|
||||
});
|
||||
});
|
||||
var _httpServer = require("./httpServer");
|
||||
Object.keys(_httpServer).forEach(function (key) {
|
||||
if (key === "default" || key === "__esModule") return;
|
||||
if (key in exports && exports[key] === _httpServer[key]) return;
|
||||
Object.defineProperty(exports, key, {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _httpServer[key];
|
||||
}
|
||||
});
|
||||
});
|
||||
var _manualPromise = require("./manualPromise");
|
||||
Object.keys(_manualPromise).forEach(function (key) {
|
||||
if (key === "default" || key === "__esModule") return;
|
||||
if (key in exports && exports[key] === _manualPromise[key]) return;
|
||||
Object.defineProperty(exports, key, {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _manualPromise[key];
|
||||
}
|
||||
});
|
||||
});
|
||||
var _locatorGenerators = require("./isomorphic/locatorGenerators");
|
||||
Object.keys(_locatorGenerators).forEach(function (key) {
|
||||
if (key === "default" || key === "__esModule") return;
|
||||
if (key in exports && exports[key] === _locatorGenerators[key]) return;
|
||||
Object.defineProperty(exports, key, {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _locatorGenerators[key];
|
||||
}
|
||||
});
|
||||
});
|
||||
var _mimeType = require("./isomorphic/mimeType");
|
||||
Object.keys(_mimeType).forEach(function (key) {
|
||||
if (key === "default" || key === "__esModule") return;
|
||||
if (key in exports && exports[key] === _mimeType[key]) return;
|
||||
Object.defineProperty(exports, key, {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _mimeType[key];
|
||||
}
|
||||
});
|
||||
});
|
||||
var _stringUtils = require("./isomorphic/stringUtils");
|
||||
Object.keys(_stringUtils).forEach(function (key) {
|
||||
if (key === "default" || key === "__esModule") return;
|
||||
if (key in exports && exports[key] === _stringUtils[key]) return;
|
||||
Object.defineProperty(exports, key, {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _stringUtils[key];
|
||||
}
|
||||
});
|
||||
});
|
||||
var _urlMatch = require("./isomorphic/urlMatch");
|
||||
Object.keys(_urlMatch).forEach(function (key) {
|
||||
if (key === "default" || key === "__esModule") return;
|
||||
if (key in exports && exports[key] === _urlMatch[key]) return;
|
||||
Object.defineProperty(exports, key, {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _urlMatch[key];
|
||||
}
|
||||
});
|
||||
});
|
||||
var _multimap = require("./multimap");
|
||||
Object.keys(_multimap).forEach(function (key) {
|
||||
if (key === "default" || key === "__esModule") return;
|
||||
if (key in exports && exports[key] === _multimap[key]) return;
|
||||
Object.defineProperty(exports, key, {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _multimap[key];
|
||||
}
|
||||
});
|
||||
});
|
||||
var _network = require("./network");
|
||||
Object.keys(_network).forEach(function (key) {
|
||||
if (key === "default" || key === "__esModule") return;
|
||||
if (key in exports && exports[key] === _network[key]) return;
|
||||
Object.defineProperty(exports, key, {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _network[key];
|
||||
}
|
||||
});
|
||||
});
|
||||
var _processLauncher = require("./processLauncher");
|
||||
Object.keys(_processLauncher).forEach(function (key) {
|
||||
if (key === "default" || key === "__esModule") return;
|
||||
if (key in exports && exports[key] === _processLauncher[key]) return;
|
||||
Object.defineProperty(exports, key, {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _processLauncher[key];
|
||||
}
|
||||
});
|
||||
});
|
||||
var _profiler = require("./profiler");
|
||||
Object.keys(_profiler).forEach(function (key) {
|
||||
if (key === "default" || key === "__esModule") return;
|
||||
if (key in exports && exports[key] === _profiler[key]) return;
|
||||
Object.defineProperty(exports, key, {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _profiler[key];
|
||||
}
|
||||
});
|
||||
});
|
||||
var _rtti = require("./rtti");
|
||||
Object.keys(_rtti).forEach(function (key) {
|
||||
if (key === "default" || key === "__esModule") return;
|
||||
if (key in exports && exports[key] === _rtti[key]) return;
|
||||
Object.defineProperty(exports, key, {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _rtti[key];
|
||||
}
|
||||
});
|
||||
});
|
||||
var _semaphore = require("./semaphore");
|
||||
Object.keys(_semaphore).forEach(function (key) {
|
||||
if (key === "default" || key === "__esModule") return;
|
||||
if (key in exports && exports[key] === _semaphore[key]) return;
|
||||
Object.defineProperty(exports, key, {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _semaphore[key];
|
||||
}
|
||||
});
|
||||
});
|
||||
var _spawnAsync = require("./spawnAsync");
|
||||
Object.keys(_spawnAsync).forEach(function (key) {
|
||||
if (key === "default" || key === "__esModule") return;
|
||||
if (key in exports && exports[key] === _spawnAsync[key]) return;
|
||||
Object.defineProperty(exports, key, {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _spawnAsync[key];
|
||||
}
|
||||
});
|
||||
});
|
||||
var _stackTrace = require("./stackTrace");
|
||||
Object.keys(_stackTrace).forEach(function (key) {
|
||||
if (key === "default" || key === "__esModule") return;
|
||||
if (key in exports && exports[key] === _stackTrace[key]) return;
|
||||
Object.defineProperty(exports, key, {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _stackTrace[key];
|
||||
}
|
||||
});
|
||||
});
|
||||
var _task = require("./task");
|
||||
Object.keys(_task).forEach(function (key) {
|
||||
if (key === "default" || key === "__esModule") return;
|
||||
if (key in exports && exports[key] === _task[key]) return;
|
||||
Object.defineProperty(exports, key, {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _task[key];
|
||||
}
|
||||
});
|
||||
});
|
||||
var _time = require("./time");
|
||||
Object.keys(_time).forEach(function (key) {
|
||||
if (key === "default" || key === "__esModule") return;
|
||||
if (key in exports && exports[key] === _time[key]) return;
|
||||
Object.defineProperty(exports, key, {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _time[key];
|
||||
}
|
||||
});
|
||||
});
|
||||
var _timeoutRunner = require("./timeoutRunner");
|
||||
Object.keys(_timeoutRunner).forEach(function (key) {
|
||||
if (key === "default" || key === "__esModule") return;
|
||||
if (key in exports && exports[key] === _timeoutRunner[key]) return;
|
||||
Object.defineProperty(exports, key, {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _timeoutRunner[key];
|
||||
}
|
||||
});
|
||||
});
|
||||
var _traceUtils = require("./traceUtils");
|
||||
Object.keys(_traceUtils).forEach(function (key) {
|
||||
if (key === "default" || key === "__esModule") return;
|
||||
if (key in exports && exports[key] === _traceUtils[key]) return;
|
||||
Object.defineProperty(exports, key, {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _traceUtils[key];
|
||||
}
|
||||
});
|
||||
});
|
||||
var _userAgent = require("./userAgent");
|
||||
Object.keys(_userAgent).forEach(function (key) {
|
||||
if (key === "default" || key === "__esModule") return;
|
||||
if (key in exports && exports[key] === _userAgent[key]) return;
|
||||
Object.defineProperty(exports, key, {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _userAgent[key];
|
||||
}
|
||||
});
|
||||
});
|
||||
var _wsServer = require("./wsServer");
|
||||
Object.keys(_wsServer).forEach(function (key) {
|
||||
if (key === "default" || key === "__esModule") return;
|
||||
if (key in exports && exports[key] === _wsServer[key]) return;
|
||||
Object.defineProperty(exports, key, {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _wsServer[key];
|
||||
}
|
||||
});
|
||||
});
|
||||
var _zipFile = require("./zipFile");
|
||||
Object.keys(_zipFile).forEach(function (key) {
|
||||
if (key === "default" || key === "__esModule") return;
|
||||
if (key in exports && exports[key] === _zipFile[key]) return;
|
||||
Object.defineProperty(exports, key, {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _zipFile[key];
|
||||
}
|
||||
});
|
||||
});
|
||||
var _zones = require("./zones");
|
||||
Object.keys(_zones).forEach(function (key) {
|
||||
if (key === "default" || key === "__esModule") return;
|
||||
if (key in exports && exports[key] === _zones[key]) return;
|
||||
Object.defineProperty(exports, key, {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _zones[key];
|
||||
}
|
||||
});
|
||||
});
|
||||
267
node_modules/playwright-core/lib/utils/isomorphic/ariaSnapshot.js
generated
vendored
Normal file
267
node_modules/playwright-core/lib/utils/isomorphic/ariaSnapshot.js
generated
vendored
Normal file
@@ -0,0 +1,267 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.AriaKeyError = void 0;
|
||||
exports.parseAriaKey = parseAriaKey;
|
||||
exports.parseYamlTemplate = parseYamlTemplate;
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// https://www.w3.org/TR/wai-aria-1.2/#role_definitions
|
||||
|
||||
function parseYamlTemplate(fragment) {
|
||||
const result = {
|
||||
kind: 'role',
|
||||
role: 'fragment'
|
||||
};
|
||||
populateNode(result, fragment);
|
||||
if (result.children && result.children.length === 1) return result.children[0];
|
||||
return result;
|
||||
}
|
||||
function populateNode(node, container) {
|
||||
for (const object of container) {
|
||||
if (typeof object === 'string') {
|
||||
const childNode = KeyParser.parse(object);
|
||||
node.children = node.children || [];
|
||||
node.children.push(childNode);
|
||||
continue;
|
||||
}
|
||||
for (const key of Object.keys(object)) {
|
||||
node.children = node.children || [];
|
||||
const value = object[key];
|
||||
if (key === 'text') {
|
||||
node.children.push({
|
||||
kind: 'text',
|
||||
text: valueOrRegex(value)
|
||||
});
|
||||
continue;
|
||||
}
|
||||
const childNode = KeyParser.parse(key);
|
||||
if (childNode.kind === 'text') {
|
||||
node.children.push({
|
||||
kind: 'text',
|
||||
text: valueOrRegex(value)
|
||||
});
|
||||
continue;
|
||||
}
|
||||
if (typeof value === 'string') {
|
||||
node.children.push({
|
||||
...childNode,
|
||||
children: [{
|
||||
kind: 'text',
|
||||
text: valueOrRegex(value)
|
||||
}]
|
||||
});
|
||||
continue;
|
||||
}
|
||||
node.children.push(childNode);
|
||||
populateNode(childNode, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
function normalizeWhitespace(text) {
|
||||
return text.replace(/[\r\n\s\t]+/g, ' ').trim();
|
||||
}
|
||||
function valueOrRegex(value) {
|
||||
return value.startsWith('/') && value.endsWith('/') ? new RegExp(value.slice(1, -1)) : normalizeWhitespace(value);
|
||||
}
|
||||
class KeyParser {
|
||||
static parse(input) {
|
||||
return new KeyParser(input)._parse();
|
||||
}
|
||||
constructor(input) {
|
||||
this._input = void 0;
|
||||
this._pos = void 0;
|
||||
this._length = void 0;
|
||||
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, pos) {
|
||||
throw new AriaKeyError(message, this._input, pos || 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 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 this._readString();
|
||||
}
|
||||
if (ch === '/') {
|
||||
this._next();
|
||||
return new RegExp(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(); // Consume ']'
|
||||
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 === '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);
|
||||
}
|
||||
}
|
||||
function parseAriaKey(key) {
|
||||
return KeyParser.parse(key);
|
||||
}
|
||||
class AriaKeyError extends Error {
|
||||
constructor(message, input, pos) {
|
||||
super(message + ':\n\n' + input + '\n' + ' '.repeat(pos) + '^\n');
|
||||
this.shortMessage = void 0;
|
||||
this.pos = void 0;
|
||||
this.shortMessage = message;
|
||||
this.pos = pos;
|
||||
this.stack = undefined;
|
||||
}
|
||||
}
|
||||
exports.AriaKeyError = AriaKeyError;
|
||||
250
node_modules/playwright-core/lib/utils/isomorphic/cssParser.js
generated
vendored
Normal file
250
node_modules/playwright-core/lib/utils/isomorphic/cssParser.js
generated
vendored
Normal file
@@ -0,0 +1,250 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.InvalidSelectorError = void 0;
|
||||
exports.isInvalidSelectorError = isInvalidSelectorError;
|
||||
exports.parseCSS = parseCSS;
|
||||
exports.serializeSelector = serializeSelector;
|
||||
var css = _interopRequireWildcard(require("./cssTokenizer"));
|
||||
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
||||
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
class InvalidSelectorError extends Error {}
|
||||
exports.InvalidSelectorError = InvalidSelectorError;
|
||||
function isInvalidSelectorError(error) {
|
||||
return error instanceof InvalidSelectorError;
|
||||
}
|
||||
|
||||
// Note: '>=' is used internally for text engine to preserve backwards compatibility.
|
||||
|
||||
// TODO: consider
|
||||
// - key=value
|
||||
// - operators like `=`, `|=`, `~=`, `*=`, `/`
|
||||
// - <empty>~=value
|
||||
// - argument modes: "parse all", "parse commas", "just a string"
|
||||
|
||||
function parseCSS(selector, customNames) {
|
||||
let tokens;
|
||||
try {
|
||||
tokens = css.tokenize(selector);
|
||||
if (!(tokens[tokens.length - 1] instanceof css.EOFToken)) tokens.push(new css.EOFToken());
|
||||
} catch (e) {
|
||||
const newMessage = e.message + ` while parsing selector "${selector}"`;
|
||||
const index = (e.stack || '').indexOf(e.message);
|
||||
if (index !== -1) e.stack = e.stack.substring(0, index) + newMessage + e.stack.substring(index + e.message.length);
|
||||
e.message = newMessage;
|
||||
throw e;
|
||||
}
|
||||
const unsupportedToken = tokens.find(token => {
|
||||
return token instanceof css.AtKeywordToken || token instanceof css.BadStringToken || token instanceof css.BadURLToken || token instanceof css.ColumnToken || token instanceof css.CDOToken || token instanceof css.CDCToken || token instanceof css.SemicolonToken ||
|
||||
// TODO: Consider using these for something, e.g. to escape complex strings.
|
||||
// For example :xpath{ (//div/bar[@attr="foo"])[2]/baz }
|
||||
// Or this way :xpath( {complex-xpath-goes-here("hello")} )
|
||||
token instanceof css.OpenCurlyToken || token instanceof css.CloseCurlyToken ||
|
||||
// TODO: Consider treating these as strings?
|
||||
token instanceof css.URLToken || token instanceof css.PercentageToken;
|
||||
});
|
||||
if (unsupportedToken) throw new InvalidSelectorError(`Unsupported token "${unsupportedToken.toSource()}" while parsing selector "${selector}"`);
|
||||
let pos = 0;
|
||||
const names = new Set();
|
||||
function unexpected() {
|
||||
return new InvalidSelectorError(`Unexpected token "${tokens[pos].toSource()}" while parsing selector "${selector}"`);
|
||||
}
|
||||
function skipWhitespace() {
|
||||
while (tokens[pos] instanceof css.WhitespaceToken) pos++;
|
||||
}
|
||||
function isIdent(p = pos) {
|
||||
return tokens[p] instanceof css.IdentToken;
|
||||
}
|
||||
function isString(p = pos) {
|
||||
return tokens[p] instanceof css.StringToken;
|
||||
}
|
||||
function isNumber(p = pos) {
|
||||
return tokens[p] instanceof css.NumberToken;
|
||||
}
|
||||
function isComma(p = pos) {
|
||||
return tokens[p] instanceof css.CommaToken;
|
||||
}
|
||||
function isOpenParen(p = pos) {
|
||||
return tokens[p] instanceof css.OpenParenToken;
|
||||
}
|
||||
function isCloseParen(p = pos) {
|
||||
return tokens[p] instanceof css.CloseParenToken;
|
||||
}
|
||||
function isFunction(p = pos) {
|
||||
return tokens[p] instanceof css.FunctionToken;
|
||||
}
|
||||
function isStar(p = pos) {
|
||||
return tokens[p] instanceof css.DelimToken && tokens[p].value === '*';
|
||||
}
|
||||
function isEOF(p = pos) {
|
||||
return tokens[p] instanceof css.EOFToken;
|
||||
}
|
||||
function isClauseCombinator(p = pos) {
|
||||
return tokens[p] instanceof css.DelimToken && ['>', '+', '~'].includes(tokens[p].value);
|
||||
}
|
||||
function isSelectorClauseEnd(p = pos) {
|
||||
return isComma(p) || isCloseParen(p) || isEOF(p) || isClauseCombinator(p) || tokens[p] instanceof css.WhitespaceToken;
|
||||
}
|
||||
function consumeFunctionArguments() {
|
||||
const result = [consumeArgument()];
|
||||
while (true) {
|
||||
skipWhitespace();
|
||||
if (!isComma()) break;
|
||||
pos++;
|
||||
result.push(consumeArgument());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
function consumeArgument() {
|
||||
skipWhitespace();
|
||||
if (isNumber()) return tokens[pos++].value;
|
||||
if (isString()) return tokens[pos++].value;
|
||||
return consumeComplexSelector();
|
||||
}
|
||||
function consumeComplexSelector() {
|
||||
const result = {
|
||||
simples: []
|
||||
};
|
||||
skipWhitespace();
|
||||
if (isClauseCombinator()) {
|
||||
// Put implicit ":scope" at the start. https://drafts.csswg.org/selectors-4/#relative
|
||||
result.simples.push({
|
||||
selector: {
|
||||
functions: [{
|
||||
name: 'scope',
|
||||
args: []
|
||||
}]
|
||||
},
|
||||
combinator: ''
|
||||
});
|
||||
} else {
|
||||
result.simples.push({
|
||||
selector: consumeSimpleSelector(),
|
||||
combinator: ''
|
||||
});
|
||||
}
|
||||
while (true) {
|
||||
skipWhitespace();
|
||||
if (isClauseCombinator()) {
|
||||
result.simples[result.simples.length - 1].combinator = tokens[pos++].value;
|
||||
skipWhitespace();
|
||||
} else if (isSelectorClauseEnd()) {
|
||||
break;
|
||||
}
|
||||
result.simples.push({
|
||||
combinator: '',
|
||||
selector: consumeSimpleSelector()
|
||||
});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
function consumeSimpleSelector() {
|
||||
let rawCSSString = '';
|
||||
const functions = [];
|
||||
while (!isSelectorClauseEnd()) {
|
||||
if (isIdent() || isStar()) {
|
||||
rawCSSString += tokens[pos++].toSource();
|
||||
} else if (tokens[pos] instanceof css.HashToken) {
|
||||
rawCSSString += tokens[pos++].toSource();
|
||||
} else if (tokens[pos] instanceof css.DelimToken && tokens[pos].value === '.') {
|
||||
pos++;
|
||||
if (isIdent()) rawCSSString += '.' + tokens[pos++].toSource();else throw unexpected();
|
||||
} else if (tokens[pos] instanceof css.ColonToken) {
|
||||
pos++;
|
||||
if (isIdent()) {
|
||||
if (!customNames.has(tokens[pos].value.toLowerCase())) {
|
||||
rawCSSString += ':' + tokens[pos++].toSource();
|
||||
} else {
|
||||
const name = tokens[pos++].value.toLowerCase();
|
||||
functions.push({
|
||||
name,
|
||||
args: []
|
||||
});
|
||||
names.add(name);
|
||||
}
|
||||
} else if (isFunction()) {
|
||||
const name = tokens[pos++].value.toLowerCase();
|
||||
if (!customNames.has(name)) {
|
||||
rawCSSString += `:${name}(${consumeBuiltinFunctionArguments()})`;
|
||||
} else {
|
||||
functions.push({
|
||||
name,
|
||||
args: consumeFunctionArguments()
|
||||
});
|
||||
names.add(name);
|
||||
}
|
||||
skipWhitespace();
|
||||
if (!isCloseParen()) throw unexpected();
|
||||
pos++;
|
||||
} else {
|
||||
throw unexpected();
|
||||
}
|
||||
} else if (tokens[pos] instanceof css.OpenSquareToken) {
|
||||
rawCSSString += '[';
|
||||
pos++;
|
||||
while (!(tokens[pos] instanceof css.CloseSquareToken) && !isEOF()) rawCSSString += tokens[pos++].toSource();
|
||||
if (!(tokens[pos] instanceof css.CloseSquareToken)) throw unexpected();
|
||||
rawCSSString += ']';
|
||||
pos++;
|
||||
} else {
|
||||
throw unexpected();
|
||||
}
|
||||
}
|
||||
if (!rawCSSString && !functions.length) throw unexpected();
|
||||
return {
|
||||
css: rawCSSString || undefined,
|
||||
functions
|
||||
};
|
||||
}
|
||||
function consumeBuiltinFunctionArguments() {
|
||||
let s = '';
|
||||
let balance = 1; // First open paren is a part of a function token.
|
||||
while (!isEOF()) {
|
||||
if (isOpenParen() || isFunction()) balance++;
|
||||
if (isCloseParen()) balance--;
|
||||
if (!balance) break;
|
||||
s += tokens[pos++].toSource();
|
||||
}
|
||||
return s;
|
||||
}
|
||||
const result = consumeFunctionArguments();
|
||||
if (!isEOF()) throw unexpected();
|
||||
if (result.some(arg => typeof arg !== 'object' || !('simples' in arg))) throw new InvalidSelectorError(`Error while parsing selector "${selector}"`);
|
||||
return {
|
||||
selector: result,
|
||||
names: Array.from(names)
|
||||
};
|
||||
}
|
||||
function serializeSelector(args) {
|
||||
return args.map(arg => {
|
||||
if (typeof arg === 'string') return `"${arg}"`;
|
||||
if (typeof arg === 'number') return String(arg);
|
||||
return arg.simples.map(({
|
||||
selector,
|
||||
combinator
|
||||
}) => {
|
||||
let s = selector.css || '';
|
||||
s = s + selector.functions.map(func => `:${func.name}(${serializeSelector(func.args)})`).join('');
|
||||
if (combinator) s += ' ' + combinator;
|
||||
return s;
|
||||
}).join(' ');
|
||||
}).join(', ');
|
||||
}
|
||||
979
node_modules/playwright-core/lib/utils/isomorphic/cssTokenizer.js
generated
vendored
Normal file
979
node_modules/playwright-core/lib/utils/isomorphic/cssTokenizer.js
generated
vendored
Normal file
@@ -0,0 +1,979 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.WhitespaceToken = exports.URLToken = exports.SuffixMatchToken = exports.SubstringMatchToken = exports.StringValuedToken = exports.StringToken = exports.SemicolonToken = exports.PrefixMatchToken = exports.PercentageToken = exports.OpenSquareToken = exports.OpenParenToken = exports.OpenCurlyToken = exports.NumberToken = exports.InvalidCharacterError = exports.IncludeMatchToken = exports.IdentToken = exports.HashToken = exports.GroupingToken = exports.FunctionToken = exports.EOFToken = exports.DimensionToken = exports.DelimToken = exports.DashMatchToken = exports.CommaToken = exports.ColumnToken = exports.ColonToken = exports.CloseSquareToken = exports.CloseParenToken = exports.CloseCurlyToken = exports.CSSParserToken = exports.CDOToken = exports.CDCToken = exports.BadURLToken = exports.BadStringToken = exports.AtKeywordToken = void 0;
|
||||
exports.tokenize = tokenize;
|
||||
/* eslint-disable notice/notice */
|
||||
|
||||
/*
|
||||
* The code in this file is licensed under the CC0 license.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
* It is free to use for any purpose. No attribution, permission, or reproduction of this license is required.
|
||||
*/
|
||||
|
||||
// Original at https://github.com/tabatkins/parse-css
|
||||
// Changes:
|
||||
// - JS is replaced with TS.
|
||||
// - Universal Module Definition wrapper is removed.
|
||||
// - Everything not related to tokenizing - below the first exports block - is removed.
|
||||
|
||||
const between = function (num, first, last) {
|
||||
return num >= first && num <= last;
|
||||
};
|
||||
function digit(code) {
|
||||
return between(code, 0x30, 0x39);
|
||||
}
|
||||
function hexdigit(code) {
|
||||
return digit(code) || between(code, 0x41, 0x46) || between(code, 0x61, 0x66);
|
||||
}
|
||||
function uppercaseletter(code) {
|
||||
return between(code, 0x41, 0x5a);
|
||||
}
|
||||
function lowercaseletter(code) {
|
||||
return between(code, 0x61, 0x7a);
|
||||
}
|
||||
function letter(code) {
|
||||
return uppercaseletter(code) || lowercaseletter(code);
|
||||
}
|
||||
function nonascii(code) {
|
||||
return code >= 0x80;
|
||||
}
|
||||
function namestartchar(code) {
|
||||
return letter(code) || nonascii(code) || code === 0x5f;
|
||||
}
|
||||
function namechar(code) {
|
||||
return namestartchar(code) || digit(code) || code === 0x2d;
|
||||
}
|
||||
function nonprintable(code) {
|
||||
return between(code, 0, 8) || code === 0xb || between(code, 0xe, 0x1f) || code === 0x7f;
|
||||
}
|
||||
function newline(code) {
|
||||
return code === 0xa;
|
||||
}
|
||||
function whitespace(code) {
|
||||
return newline(code) || code === 9 || code === 0x20;
|
||||
}
|
||||
const maximumallowedcodepoint = 0x10ffff;
|
||||
class InvalidCharacterError extends Error {
|
||||
constructor(message) {
|
||||
super(message);
|
||||
this.name = 'InvalidCharacterError';
|
||||
}
|
||||
}
|
||||
exports.InvalidCharacterError = InvalidCharacterError;
|
||||
function preprocess(str) {
|
||||
// Turn a string into an array of code points,
|
||||
// following the preprocessing cleanup rules.
|
||||
const codepoints = [];
|
||||
for (let i = 0; i < str.length; i++) {
|
||||
let code = str.charCodeAt(i);
|
||||
if (code === 0xd && str.charCodeAt(i + 1) === 0xa) {
|
||||
code = 0xa;
|
||||
i++;
|
||||
}
|
||||
if (code === 0xd || code === 0xc) code = 0xa;
|
||||
if (code === 0x0) code = 0xfffd;
|
||||
if (between(code, 0xd800, 0xdbff) && between(str.charCodeAt(i + 1), 0xdc00, 0xdfff)) {
|
||||
// Decode a surrogate pair into an astral codepoint.
|
||||
const lead = code - 0xd800;
|
||||
const trail = str.charCodeAt(i + 1) - 0xdc00;
|
||||
code = Math.pow(2, 16) + lead * Math.pow(2, 10) + trail;
|
||||
i++;
|
||||
}
|
||||
codepoints.push(code);
|
||||
}
|
||||
return codepoints;
|
||||
}
|
||||
function stringFromCode(code) {
|
||||
if (code <= 0xffff) return String.fromCharCode(code);
|
||||
// Otherwise, encode astral char as surrogate pair.
|
||||
code -= Math.pow(2, 16);
|
||||
const lead = Math.floor(code / Math.pow(2, 10)) + 0xd800;
|
||||
const trail = code % Math.pow(2, 10) + 0xdc00;
|
||||
return String.fromCharCode(lead) + String.fromCharCode(trail);
|
||||
}
|
||||
function tokenize(str1) {
|
||||
const str = preprocess(str1);
|
||||
let i = -1;
|
||||
const tokens = [];
|
||||
let code;
|
||||
|
||||
// Line number information.
|
||||
let line = 0;
|
||||
let column = 0;
|
||||
// The only use of lastLineLength is in reconsume().
|
||||
let lastLineLength = 0;
|
||||
const incrLineno = function () {
|
||||
line += 1;
|
||||
lastLineLength = column;
|
||||
column = 0;
|
||||
};
|
||||
const locStart = {
|
||||
line: line,
|
||||
column: column
|
||||
};
|
||||
const codepoint = function (i) {
|
||||
if (i >= str.length) return -1;
|
||||
return str[i];
|
||||
};
|
||||
const next = function (num) {
|
||||
if (num === undefined) num = 1;
|
||||
if (num > 3) throw 'Spec Error: no more than three codepoints of lookahead.';
|
||||
return codepoint(i + num);
|
||||
};
|
||||
const consume = function (num) {
|
||||
if (num === undefined) num = 1;
|
||||
i += num;
|
||||
code = codepoint(i);
|
||||
if (newline(code)) incrLineno();else column += num;
|
||||
// console.log('Consume '+i+' '+String.fromCharCode(code) + ' 0x' + code.toString(16));
|
||||
return true;
|
||||
};
|
||||
const reconsume = function () {
|
||||
i -= 1;
|
||||
if (newline(code)) {
|
||||
line -= 1;
|
||||
column = lastLineLength;
|
||||
} else {
|
||||
column -= 1;
|
||||
}
|
||||
locStart.line = line;
|
||||
locStart.column = column;
|
||||
return true;
|
||||
};
|
||||
const eof = function (codepoint) {
|
||||
if (codepoint === undefined) codepoint = code;
|
||||
return codepoint === -1;
|
||||
};
|
||||
const donothing = function () {};
|
||||
const parseerror = function () {
|
||||
// Language bindings don't like writing to stdout!
|
||||
// console.log('Parse error at index ' + i + ', processing codepoint 0x' + code.toString(16) + '.'); return true;
|
||||
};
|
||||
const consumeAToken = function () {
|
||||
consumeComments();
|
||||
consume();
|
||||
if (whitespace(code)) {
|
||||
while (whitespace(next())) consume();
|
||||
return new WhitespaceToken();
|
||||
} else if (code === 0x22) {
|
||||
return consumeAStringToken();
|
||||
} else if (code === 0x23) {
|
||||
if (namechar(next()) || areAValidEscape(next(1), next(2))) {
|
||||
const token = new HashToken('');
|
||||
if (wouldStartAnIdentifier(next(1), next(2), next(3))) token.type = 'id';
|
||||
token.value = consumeAName();
|
||||
return token;
|
||||
} else {
|
||||
return new DelimToken(code);
|
||||
}
|
||||
} else if (code === 0x24) {
|
||||
if (next() === 0x3d) {
|
||||
consume();
|
||||
return new SuffixMatchToken();
|
||||
} else {
|
||||
return new DelimToken(code);
|
||||
}
|
||||
} else if (code === 0x27) {
|
||||
return consumeAStringToken();
|
||||
} else if (code === 0x28) {
|
||||
return new OpenParenToken();
|
||||
} else if (code === 0x29) {
|
||||
return new CloseParenToken();
|
||||
} else if (code === 0x2a) {
|
||||
if (next() === 0x3d) {
|
||||
consume();
|
||||
return new SubstringMatchToken();
|
||||
} else {
|
||||
return new DelimToken(code);
|
||||
}
|
||||
} else if (code === 0x2b) {
|
||||
if (startsWithANumber()) {
|
||||
reconsume();
|
||||
return consumeANumericToken();
|
||||
} else {
|
||||
return new DelimToken(code);
|
||||
}
|
||||
} else if (code === 0x2c) {
|
||||
return new CommaToken();
|
||||
} else if (code === 0x2d) {
|
||||
if (startsWithANumber()) {
|
||||
reconsume();
|
||||
return consumeANumericToken();
|
||||
} else if (next(1) === 0x2d && next(2) === 0x3e) {
|
||||
consume(2);
|
||||
return new CDCToken();
|
||||
} else if (startsWithAnIdentifier()) {
|
||||
reconsume();
|
||||
return consumeAnIdentlikeToken();
|
||||
} else {
|
||||
return new DelimToken(code);
|
||||
}
|
||||
} else if (code === 0x2e) {
|
||||
if (startsWithANumber()) {
|
||||
reconsume();
|
||||
return consumeANumericToken();
|
||||
} else {
|
||||
return new DelimToken(code);
|
||||
}
|
||||
} else if (code === 0x3a) {
|
||||
return new ColonToken();
|
||||
} else if (code === 0x3b) {
|
||||
return new SemicolonToken();
|
||||
} else if (code === 0x3c) {
|
||||
if (next(1) === 0x21 && next(2) === 0x2d && next(3) === 0x2d) {
|
||||
consume(3);
|
||||
return new CDOToken();
|
||||
} else {
|
||||
return new DelimToken(code);
|
||||
}
|
||||
} else if (code === 0x40) {
|
||||
if (wouldStartAnIdentifier(next(1), next(2), next(3))) return new AtKeywordToken(consumeAName());else return new DelimToken(code);
|
||||
} else if (code === 0x5b) {
|
||||
return new OpenSquareToken();
|
||||
} else if (code === 0x5c) {
|
||||
if (startsWithAValidEscape()) {
|
||||
reconsume();
|
||||
return consumeAnIdentlikeToken();
|
||||
} else {
|
||||
parseerror();
|
||||
return new DelimToken(code);
|
||||
}
|
||||
} else if (code === 0x5d) {
|
||||
return new CloseSquareToken();
|
||||
} else if (code === 0x5e) {
|
||||
if (next() === 0x3d) {
|
||||
consume();
|
||||
return new PrefixMatchToken();
|
||||
} else {
|
||||
return new DelimToken(code);
|
||||
}
|
||||
} else if (code === 0x7b) {
|
||||
return new OpenCurlyToken();
|
||||
} else if (code === 0x7c) {
|
||||
if (next() === 0x3d) {
|
||||
consume();
|
||||
return new DashMatchToken();
|
||||
} else if (next() === 0x7c) {
|
||||
consume();
|
||||
return new ColumnToken();
|
||||
} else {
|
||||
return new DelimToken(code);
|
||||
}
|
||||
} else if (code === 0x7d) {
|
||||
return new CloseCurlyToken();
|
||||
} else if (code === 0x7e) {
|
||||
if (next() === 0x3d) {
|
||||
consume();
|
||||
return new IncludeMatchToken();
|
||||
} else {
|
||||
return new DelimToken(code);
|
||||
}
|
||||
} else if (digit(code)) {
|
||||
reconsume();
|
||||
return consumeANumericToken();
|
||||
} else if (namestartchar(code)) {
|
||||
reconsume();
|
||||
return consumeAnIdentlikeToken();
|
||||
} else if (eof()) {
|
||||
return new EOFToken();
|
||||
} else {
|
||||
return new DelimToken(code);
|
||||
}
|
||||
};
|
||||
const consumeComments = function () {
|
||||
while (next(1) === 0x2f && next(2) === 0x2a) {
|
||||
consume(2);
|
||||
while (true) {
|
||||
consume();
|
||||
if (code === 0x2a && next() === 0x2f) {
|
||||
consume();
|
||||
break;
|
||||
} else if (eof()) {
|
||||
parseerror();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
const consumeANumericToken = function () {
|
||||
const num = consumeANumber();
|
||||
if (wouldStartAnIdentifier(next(1), next(2), next(3))) {
|
||||
const token = new DimensionToken();
|
||||
token.value = num.value;
|
||||
token.repr = num.repr;
|
||||
token.type = num.type;
|
||||
token.unit = consumeAName();
|
||||
return token;
|
||||
} else if (next() === 0x25) {
|
||||
consume();
|
||||
const token = new PercentageToken();
|
||||
token.value = num.value;
|
||||
token.repr = num.repr;
|
||||
return token;
|
||||
} else {
|
||||
const token = new NumberToken();
|
||||
token.value = num.value;
|
||||
token.repr = num.repr;
|
||||
token.type = num.type;
|
||||
return token;
|
||||
}
|
||||
};
|
||||
const consumeAnIdentlikeToken = function () {
|
||||
const str = consumeAName();
|
||||
if (str.toLowerCase() === 'url' && next() === 0x28) {
|
||||
consume();
|
||||
while (whitespace(next(1)) && whitespace(next(2))) consume();
|
||||
if (next() === 0x22 || next() === 0x27) return new FunctionToken(str);else if (whitespace(next()) && (next(2) === 0x22 || next(2) === 0x27)) return new FunctionToken(str);else return consumeAURLToken();
|
||||
} else if (next() === 0x28) {
|
||||
consume();
|
||||
return new FunctionToken(str);
|
||||
} else {
|
||||
return new IdentToken(str);
|
||||
}
|
||||
};
|
||||
const consumeAStringToken = function (endingCodePoint) {
|
||||
if (endingCodePoint === undefined) endingCodePoint = code;
|
||||
let string = '';
|
||||
while (consume()) {
|
||||
if (code === endingCodePoint || eof()) {
|
||||
return new StringToken(string);
|
||||
} else if (newline(code)) {
|
||||
parseerror();
|
||||
reconsume();
|
||||
return new BadStringToken();
|
||||
} else if (code === 0x5c) {
|
||||
if (eof(next())) donothing();else if (newline(next())) consume();else string += stringFromCode(consumeEscape());
|
||||
} else {
|
||||
string += stringFromCode(code);
|
||||
}
|
||||
}
|
||||
throw new Error('Internal error');
|
||||
};
|
||||
const consumeAURLToken = function () {
|
||||
const token = new URLToken('');
|
||||
while (whitespace(next())) consume();
|
||||
if (eof(next())) return token;
|
||||
while (consume()) {
|
||||
if (code === 0x29 || eof()) {
|
||||
return token;
|
||||
} else if (whitespace(code)) {
|
||||
while (whitespace(next())) consume();
|
||||
if (next() === 0x29 || eof(next())) {
|
||||
consume();
|
||||
return token;
|
||||
} else {
|
||||
consumeTheRemnantsOfABadURL();
|
||||
return new BadURLToken();
|
||||
}
|
||||
} else if (code === 0x22 || code === 0x27 || code === 0x28 || nonprintable(code)) {
|
||||
parseerror();
|
||||
consumeTheRemnantsOfABadURL();
|
||||
return new BadURLToken();
|
||||
} else if (code === 0x5c) {
|
||||
if (startsWithAValidEscape()) {
|
||||
token.value += stringFromCode(consumeEscape());
|
||||
} else {
|
||||
parseerror();
|
||||
consumeTheRemnantsOfABadURL();
|
||||
return new BadURLToken();
|
||||
}
|
||||
} else {
|
||||
token.value += stringFromCode(code);
|
||||
}
|
||||
}
|
||||
throw new Error('Internal error');
|
||||
};
|
||||
const consumeEscape = function () {
|
||||
// Assume the current character is the \
|
||||
// and the next code point is not a newline.
|
||||
consume();
|
||||
if (hexdigit(code)) {
|
||||
// Consume 1-6 hex digits
|
||||
const digits = [code];
|
||||
for (let total = 0; total < 5; total++) {
|
||||
if (hexdigit(next())) {
|
||||
consume();
|
||||
digits.push(code);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (whitespace(next())) consume();
|
||||
let value = parseInt(digits.map(function (x) {
|
||||
return String.fromCharCode(x);
|
||||
}).join(''), 16);
|
||||
if (value > maximumallowedcodepoint) value = 0xfffd;
|
||||
return value;
|
||||
} else if (eof()) {
|
||||
return 0xfffd;
|
||||
} else {
|
||||
return code;
|
||||
}
|
||||
};
|
||||
const areAValidEscape = function (c1, c2) {
|
||||
if (c1 !== 0x5c) return false;
|
||||
if (newline(c2)) return false;
|
||||
return true;
|
||||
};
|
||||
const startsWithAValidEscape = function () {
|
||||
return areAValidEscape(code, next());
|
||||
};
|
||||
const wouldStartAnIdentifier = function (c1, c2, c3) {
|
||||
if (c1 === 0x2d) return namestartchar(c2) || c2 === 0x2d || areAValidEscape(c2, c3);else if (namestartchar(c1)) return true;else if (c1 === 0x5c) return areAValidEscape(c1, c2);else return false;
|
||||
};
|
||||
const startsWithAnIdentifier = function () {
|
||||
return wouldStartAnIdentifier(code, next(1), next(2));
|
||||
};
|
||||
const wouldStartANumber = function (c1, c2, c3) {
|
||||
if (c1 === 0x2b || c1 === 0x2d) {
|
||||
if (digit(c2)) return true;
|
||||
if (c2 === 0x2e && digit(c3)) return true;
|
||||
return false;
|
||||
} else if (c1 === 0x2e) {
|
||||
if (digit(c2)) return true;
|
||||
return false;
|
||||
} else if (digit(c1)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
const startsWithANumber = function () {
|
||||
return wouldStartANumber(code, next(1), next(2));
|
||||
};
|
||||
const consumeAName = function () {
|
||||
let result = '';
|
||||
while (consume()) {
|
||||
if (namechar(code)) {
|
||||
result += stringFromCode(code);
|
||||
} else if (startsWithAValidEscape()) {
|
||||
result += stringFromCode(consumeEscape());
|
||||
} else {
|
||||
reconsume();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
throw new Error('Internal parse error');
|
||||
};
|
||||
const consumeANumber = function () {
|
||||
let repr = '';
|
||||
let type = 'integer';
|
||||
if (next() === 0x2b || next() === 0x2d) {
|
||||
consume();
|
||||
repr += stringFromCode(code);
|
||||
}
|
||||
while (digit(next())) {
|
||||
consume();
|
||||
repr += stringFromCode(code);
|
||||
}
|
||||
if (next(1) === 0x2e && digit(next(2))) {
|
||||
consume();
|
||||
repr += stringFromCode(code);
|
||||
consume();
|
||||
repr += stringFromCode(code);
|
||||
type = 'number';
|
||||
while (digit(next())) {
|
||||
consume();
|
||||
repr += stringFromCode(code);
|
||||
}
|
||||
}
|
||||
const c1 = next(1),
|
||||
c2 = next(2),
|
||||
c3 = next(3);
|
||||
if ((c1 === 0x45 || c1 === 0x65) && digit(c2)) {
|
||||
consume();
|
||||
repr += stringFromCode(code);
|
||||
consume();
|
||||
repr += stringFromCode(code);
|
||||
type = 'number';
|
||||
while (digit(next())) {
|
||||
consume();
|
||||
repr += stringFromCode(code);
|
||||
}
|
||||
} else if ((c1 === 0x45 || c1 === 0x65) && (c2 === 0x2b || c2 === 0x2d) && digit(c3)) {
|
||||
consume();
|
||||
repr += stringFromCode(code);
|
||||
consume();
|
||||
repr += stringFromCode(code);
|
||||
consume();
|
||||
repr += stringFromCode(code);
|
||||
type = 'number';
|
||||
while (digit(next())) {
|
||||
consume();
|
||||
repr += stringFromCode(code);
|
||||
}
|
||||
}
|
||||
const value = convertAStringToANumber(repr);
|
||||
return {
|
||||
type: type,
|
||||
value: value,
|
||||
repr: repr
|
||||
};
|
||||
};
|
||||
const convertAStringToANumber = function (string) {
|
||||
// CSS's number rules are identical to JS, afaik.
|
||||
return +string;
|
||||
};
|
||||
const consumeTheRemnantsOfABadURL = function () {
|
||||
while (consume()) {
|
||||
if (code === 0x29 || eof()) {
|
||||
return;
|
||||
} else if (startsWithAValidEscape()) {
|
||||
consumeEscape();
|
||||
donothing();
|
||||
} else {
|
||||
donothing();
|
||||
}
|
||||
}
|
||||
};
|
||||
let iterationCount = 0;
|
||||
while (!eof(next())) {
|
||||
tokens.push(consumeAToken());
|
||||
iterationCount++;
|
||||
if (iterationCount > str.length * 2) throw new Error("I'm infinite-looping!");
|
||||
}
|
||||
return tokens;
|
||||
}
|
||||
class CSSParserToken {
|
||||
constructor() {
|
||||
this.tokenType = '';
|
||||
this.value = void 0;
|
||||
}
|
||||
toJSON() {
|
||||
return {
|
||||
token: this.tokenType
|
||||
};
|
||||
}
|
||||
toString() {
|
||||
return this.tokenType;
|
||||
}
|
||||
toSource() {
|
||||
return '' + this;
|
||||
}
|
||||
}
|
||||
exports.CSSParserToken = CSSParserToken;
|
||||
class BadStringToken extends CSSParserToken {
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
this.tokenType = 'BADSTRING';
|
||||
}
|
||||
}
|
||||
exports.BadStringToken = BadStringToken;
|
||||
class BadURLToken extends CSSParserToken {
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
this.tokenType = 'BADURL';
|
||||
}
|
||||
}
|
||||
exports.BadURLToken = BadURLToken;
|
||||
class WhitespaceToken extends CSSParserToken {
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
this.tokenType = 'WHITESPACE';
|
||||
}
|
||||
toString() {
|
||||
return 'WS';
|
||||
}
|
||||
toSource() {
|
||||
return ' ';
|
||||
}
|
||||
}
|
||||
exports.WhitespaceToken = WhitespaceToken;
|
||||
class CDOToken extends CSSParserToken {
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
this.tokenType = 'CDO';
|
||||
}
|
||||
toSource() {
|
||||
return '<!--';
|
||||
}
|
||||
}
|
||||
exports.CDOToken = CDOToken;
|
||||
class CDCToken extends CSSParserToken {
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
this.tokenType = 'CDC';
|
||||
}
|
||||
toSource() {
|
||||
return '-->';
|
||||
}
|
||||
}
|
||||
exports.CDCToken = CDCToken;
|
||||
class ColonToken extends CSSParserToken {
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
this.tokenType = ':';
|
||||
}
|
||||
}
|
||||
exports.ColonToken = ColonToken;
|
||||
class SemicolonToken extends CSSParserToken {
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
this.tokenType = ';';
|
||||
}
|
||||
}
|
||||
exports.SemicolonToken = SemicolonToken;
|
||||
class CommaToken extends CSSParserToken {
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
this.tokenType = ',';
|
||||
}
|
||||
}
|
||||
exports.CommaToken = CommaToken;
|
||||
class GroupingToken extends CSSParserToken {
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
this.value = '';
|
||||
this.mirror = '';
|
||||
}
|
||||
}
|
||||
exports.GroupingToken = GroupingToken;
|
||||
class OpenCurlyToken extends GroupingToken {
|
||||
constructor() {
|
||||
super();
|
||||
this.tokenType = '{';
|
||||
this.value = '{';
|
||||
this.mirror = '}';
|
||||
}
|
||||
}
|
||||
exports.OpenCurlyToken = OpenCurlyToken;
|
||||
class CloseCurlyToken extends GroupingToken {
|
||||
constructor() {
|
||||
super();
|
||||
this.tokenType = '}';
|
||||
this.value = '}';
|
||||
this.mirror = '{';
|
||||
}
|
||||
}
|
||||
exports.CloseCurlyToken = CloseCurlyToken;
|
||||
class OpenSquareToken extends GroupingToken {
|
||||
constructor() {
|
||||
super();
|
||||
this.tokenType = '[';
|
||||
this.value = '[';
|
||||
this.mirror = ']';
|
||||
}
|
||||
}
|
||||
exports.OpenSquareToken = OpenSquareToken;
|
||||
class CloseSquareToken extends GroupingToken {
|
||||
constructor() {
|
||||
super();
|
||||
this.tokenType = ']';
|
||||
this.value = ']';
|
||||
this.mirror = '[';
|
||||
}
|
||||
}
|
||||
exports.CloseSquareToken = CloseSquareToken;
|
||||
class OpenParenToken extends GroupingToken {
|
||||
constructor() {
|
||||
super();
|
||||
this.tokenType = '(';
|
||||
this.value = '(';
|
||||
this.mirror = ')';
|
||||
}
|
||||
}
|
||||
exports.OpenParenToken = OpenParenToken;
|
||||
class CloseParenToken extends GroupingToken {
|
||||
constructor() {
|
||||
super();
|
||||
this.tokenType = ')';
|
||||
this.value = ')';
|
||||
this.mirror = '(';
|
||||
}
|
||||
}
|
||||
exports.CloseParenToken = CloseParenToken;
|
||||
class IncludeMatchToken extends CSSParserToken {
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
this.tokenType = '~=';
|
||||
}
|
||||
}
|
||||
exports.IncludeMatchToken = IncludeMatchToken;
|
||||
class DashMatchToken extends CSSParserToken {
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
this.tokenType = '|=';
|
||||
}
|
||||
}
|
||||
exports.DashMatchToken = DashMatchToken;
|
||||
class PrefixMatchToken extends CSSParserToken {
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
this.tokenType = '^=';
|
||||
}
|
||||
}
|
||||
exports.PrefixMatchToken = PrefixMatchToken;
|
||||
class SuffixMatchToken extends CSSParserToken {
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
this.tokenType = '$=';
|
||||
}
|
||||
}
|
||||
exports.SuffixMatchToken = SuffixMatchToken;
|
||||
class SubstringMatchToken extends CSSParserToken {
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
this.tokenType = '*=';
|
||||
}
|
||||
}
|
||||
exports.SubstringMatchToken = SubstringMatchToken;
|
||||
class ColumnToken extends CSSParserToken {
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
this.tokenType = '||';
|
||||
}
|
||||
}
|
||||
exports.ColumnToken = ColumnToken;
|
||||
class EOFToken extends CSSParserToken {
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
this.tokenType = 'EOF';
|
||||
}
|
||||
toSource() {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
exports.EOFToken = EOFToken;
|
||||
class DelimToken extends CSSParserToken {
|
||||
constructor(code) {
|
||||
super();
|
||||
this.tokenType = 'DELIM';
|
||||
this.value = '';
|
||||
this.value = stringFromCode(code);
|
||||
}
|
||||
toString() {
|
||||
return 'DELIM(' + this.value + ')';
|
||||
}
|
||||
toJSON() {
|
||||
const json = this.constructor.prototype.constructor.prototype.toJSON.call(this);
|
||||
json.value = this.value;
|
||||
return json;
|
||||
}
|
||||
toSource() {
|
||||
if (this.value === '\\') return '\\\n';else return this.value;
|
||||
}
|
||||
}
|
||||
exports.DelimToken = DelimToken;
|
||||
class StringValuedToken extends CSSParserToken {
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
this.value = '';
|
||||
}
|
||||
ASCIIMatch(str) {
|
||||
return this.value.toLowerCase() === str.toLowerCase();
|
||||
}
|
||||
toJSON() {
|
||||
const json = this.constructor.prototype.constructor.prototype.toJSON.call(this);
|
||||
json.value = this.value;
|
||||
return json;
|
||||
}
|
||||
}
|
||||
exports.StringValuedToken = StringValuedToken;
|
||||
class IdentToken extends StringValuedToken {
|
||||
constructor(val) {
|
||||
super();
|
||||
this.tokenType = 'IDENT';
|
||||
this.value = val;
|
||||
}
|
||||
toString() {
|
||||
return 'IDENT(' + this.value + ')';
|
||||
}
|
||||
toSource() {
|
||||
return escapeIdent(this.value);
|
||||
}
|
||||
}
|
||||
exports.IdentToken = IdentToken;
|
||||
class FunctionToken extends StringValuedToken {
|
||||
constructor(val) {
|
||||
super();
|
||||
this.tokenType = 'FUNCTION';
|
||||
this.mirror = void 0;
|
||||
this.value = val;
|
||||
this.mirror = ')';
|
||||
}
|
||||
toString() {
|
||||
return 'FUNCTION(' + this.value + ')';
|
||||
}
|
||||
toSource() {
|
||||
return escapeIdent(this.value) + '(';
|
||||
}
|
||||
}
|
||||
exports.FunctionToken = FunctionToken;
|
||||
class AtKeywordToken extends StringValuedToken {
|
||||
constructor(val) {
|
||||
super();
|
||||
this.tokenType = 'AT-KEYWORD';
|
||||
this.value = val;
|
||||
}
|
||||
toString() {
|
||||
return 'AT(' + this.value + ')';
|
||||
}
|
||||
toSource() {
|
||||
return '@' + escapeIdent(this.value);
|
||||
}
|
||||
}
|
||||
exports.AtKeywordToken = AtKeywordToken;
|
||||
class HashToken extends StringValuedToken {
|
||||
constructor(val) {
|
||||
super();
|
||||
this.tokenType = 'HASH';
|
||||
this.type = void 0;
|
||||
this.value = val;
|
||||
this.type = 'unrestricted';
|
||||
}
|
||||
toString() {
|
||||
return 'HASH(' + this.value + ')';
|
||||
}
|
||||
toJSON() {
|
||||
const json = this.constructor.prototype.constructor.prototype.toJSON.call(this);
|
||||
json.value = this.value;
|
||||
json.type = this.type;
|
||||
return json;
|
||||
}
|
||||
toSource() {
|
||||
if (this.type === 'id') return '#' + escapeIdent(this.value);else return '#' + escapeHash(this.value);
|
||||
}
|
||||
}
|
||||
exports.HashToken = HashToken;
|
||||
class StringToken extends StringValuedToken {
|
||||
constructor(val) {
|
||||
super();
|
||||
this.tokenType = 'STRING';
|
||||
this.value = val;
|
||||
}
|
||||
toString() {
|
||||
return '"' + escapeString(this.value) + '"';
|
||||
}
|
||||
}
|
||||
exports.StringToken = StringToken;
|
||||
class URLToken extends StringValuedToken {
|
||||
constructor(val) {
|
||||
super();
|
||||
this.tokenType = 'URL';
|
||||
this.value = val;
|
||||
}
|
||||
toString() {
|
||||
return 'URL(' + this.value + ')';
|
||||
}
|
||||
toSource() {
|
||||
return 'url("' + escapeString(this.value) + '")';
|
||||
}
|
||||
}
|
||||
exports.URLToken = URLToken;
|
||||
class NumberToken extends CSSParserToken {
|
||||
constructor() {
|
||||
super();
|
||||
this.tokenType = 'NUMBER';
|
||||
this.type = void 0;
|
||||
this.repr = void 0;
|
||||
this.type = 'integer';
|
||||
this.repr = '';
|
||||
}
|
||||
toString() {
|
||||
if (this.type === 'integer') return 'INT(' + this.value + ')';
|
||||
return 'NUMBER(' + this.value + ')';
|
||||
}
|
||||
toJSON() {
|
||||
const json = super.toJSON();
|
||||
json.value = this.value;
|
||||
json.type = this.type;
|
||||
json.repr = this.repr;
|
||||
return json;
|
||||
}
|
||||
toSource() {
|
||||
return this.repr;
|
||||
}
|
||||
}
|
||||
exports.NumberToken = NumberToken;
|
||||
class PercentageToken extends CSSParserToken {
|
||||
constructor() {
|
||||
super();
|
||||
this.tokenType = 'PERCENTAGE';
|
||||
this.repr = void 0;
|
||||
this.repr = '';
|
||||
}
|
||||
toString() {
|
||||
return 'PERCENTAGE(' + this.value + ')';
|
||||
}
|
||||
toJSON() {
|
||||
const json = this.constructor.prototype.constructor.prototype.toJSON.call(this);
|
||||
json.value = this.value;
|
||||
json.repr = this.repr;
|
||||
return json;
|
||||
}
|
||||
toSource() {
|
||||
return this.repr + '%';
|
||||
}
|
||||
}
|
||||
exports.PercentageToken = PercentageToken;
|
||||
class DimensionToken extends CSSParserToken {
|
||||
constructor() {
|
||||
super();
|
||||
this.tokenType = 'DIMENSION';
|
||||
this.type = void 0;
|
||||
this.repr = void 0;
|
||||
this.unit = void 0;
|
||||
this.type = 'integer';
|
||||
this.repr = '';
|
||||
this.unit = '';
|
||||
}
|
||||
toString() {
|
||||
return 'DIM(' + this.value + ',' + this.unit + ')';
|
||||
}
|
||||
toJSON() {
|
||||
const json = this.constructor.prototype.constructor.prototype.toJSON.call(this);
|
||||
json.value = this.value;
|
||||
json.type = this.type;
|
||||
json.repr = this.repr;
|
||||
json.unit = this.unit;
|
||||
return json;
|
||||
}
|
||||
toSource() {
|
||||
const source = this.repr;
|
||||
let unit = escapeIdent(this.unit);
|
||||
if (unit[0].toLowerCase() === 'e' && (unit[1] === '-' || between(unit.charCodeAt(1), 0x30, 0x39))) {
|
||||
// Unit is ambiguous with scinot
|
||||
// Remove the leading "e", replace with escape.
|
||||
unit = '\\65 ' + unit.slice(1, unit.length);
|
||||
}
|
||||
return source + unit;
|
||||
}
|
||||
}
|
||||
exports.DimensionToken = DimensionToken;
|
||||
function escapeIdent(string) {
|
||||
string = '' + string;
|
||||
let result = '';
|
||||
const firstcode = string.charCodeAt(0);
|
||||
for (let i = 0; i < string.length; i++) {
|
||||
const code = string.charCodeAt(i);
|
||||
if (code === 0x0) throw new InvalidCharacterError('Invalid character: the input contains U+0000.');
|
||||
if (between(code, 0x1, 0x1f) || code === 0x7f || i === 0 && between(code, 0x30, 0x39) || i === 1 && between(code, 0x30, 0x39) && firstcode === 0x2d) result += '\\' + code.toString(16) + ' ';else if (code >= 0x80 || code === 0x2d || code === 0x5f || between(code, 0x30, 0x39) || between(code, 0x41, 0x5a) || between(code, 0x61, 0x7a)) result += string[i];else result += '\\' + string[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
function escapeHash(string) {
|
||||
// Escapes the contents of "unrestricted"-type hash tokens.
|
||||
// Won't preserve the ID-ness of "id"-type hash tokens;
|
||||
// use escapeIdent() for that.
|
||||
string = '' + string;
|
||||
let result = '';
|
||||
for (let i = 0; i < string.length; i++) {
|
||||
const code = string.charCodeAt(i);
|
||||
if (code === 0x0) throw new InvalidCharacterError('Invalid character: the input contains U+0000.');
|
||||
if (code >= 0x80 || code === 0x2d || code === 0x5f || between(code, 0x30, 0x39) || between(code, 0x41, 0x5a) || between(code, 0x61, 0x7a)) result += string[i];else result += '\\' + code.toString(16) + ' ';
|
||||
}
|
||||
return result;
|
||||
}
|
||||
function escapeString(string) {
|
||||
string = '' + string;
|
||||
let result = '';
|
||||
for (let i = 0; i < string.length; i++) {
|
||||
const code = string.charCodeAt(i);
|
||||
if (code === 0x0) throw new InvalidCharacterError('Invalid character: the input contains U+0000.');
|
||||
if (between(code, 0x1, 0x1f) || code === 0x7f) result += '\\' + code.toString(16) + ' ';else if (code === 0x22 || code === 0x5c) result += '\\' + string[i];else result += string[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
660
node_modules/playwright-core/lib/utils/isomorphic/locatorGenerators.js
generated
vendored
Normal file
660
node_modules/playwright-core/lib/utils/isomorphic/locatorGenerators.js
generated
vendored
Normal file
@@ -0,0 +1,660 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.PythonLocatorFactory = exports.JsonlLocatorFactory = exports.JavaScriptLocatorFactory = exports.JavaLocatorFactory = exports.CSharpLocatorFactory = void 0;
|
||||
exports.asLocator = asLocator;
|
||||
exports.asLocators = asLocators;
|
||||
var _stringUtils = require("./stringUtils");
|
||||
var _selectorParser = require("./selectorParser");
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
function asLocator(lang, selector, isFrameLocator = false) {
|
||||
return asLocators(lang, selector, isFrameLocator)[0];
|
||||
}
|
||||
function asLocators(lang, selector, isFrameLocator = false, maxOutputSize = 20, preferredQuote) {
|
||||
try {
|
||||
return innerAsLocators(new generators[lang](preferredQuote), (0, _selectorParser.parseSelector)(selector), isFrameLocator, maxOutputSize);
|
||||
} catch (e) {
|
||||
// Tolerate invalid input.
|
||||
return [selector];
|
||||
}
|
||||
}
|
||||
function innerAsLocators(factory, parsed, isFrameLocator = false, maxOutputSize = 20) {
|
||||
const parts = [...parsed.parts];
|
||||
const tokens = [];
|
||||
let nextBase = isFrameLocator ? 'frame-locator' : 'page';
|
||||
for (let index = 0; index < parts.length; index++) {
|
||||
const part = parts[index];
|
||||
const base = nextBase;
|
||||
nextBase = 'locator';
|
||||
if (part.name === 'nth') {
|
||||
if (part.body === '0') tokens.push([factory.generateLocator(base, 'first', ''), factory.generateLocator(base, 'nth', '0')]);else if (part.body === '-1') tokens.push([factory.generateLocator(base, 'last', ''), factory.generateLocator(base, 'nth', '-1')]);else tokens.push([factory.generateLocator(base, 'nth', part.body)]);
|
||||
continue;
|
||||
}
|
||||
if (part.name === 'internal:text') {
|
||||
const {
|
||||
exact,
|
||||
text
|
||||
} = detectExact(part.body);
|
||||
tokens.push([factory.generateLocator(base, 'text', text, {
|
||||
exact
|
||||
})]);
|
||||
continue;
|
||||
}
|
||||
if (part.name === 'internal:has-text') {
|
||||
const {
|
||||
exact,
|
||||
text
|
||||
} = detectExact(part.body);
|
||||
// There is no locator equivalent for strict has-text, leave it as is.
|
||||
if (!exact) {
|
||||
tokens.push([factory.generateLocator(base, 'has-text', text, {
|
||||
exact
|
||||
})]);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (part.name === 'internal:has-not-text') {
|
||||
const {
|
||||
exact,
|
||||
text
|
||||
} = detectExact(part.body);
|
||||
// There is no locator equivalent for strict has-not-text, leave it as is.
|
||||
if (!exact) {
|
||||
tokens.push([factory.generateLocator(base, 'has-not-text', text, {
|
||||
exact
|
||||
})]);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (part.name === 'internal:has') {
|
||||
const inners = innerAsLocators(factory, part.body.parsed, false, maxOutputSize);
|
||||
tokens.push(inners.map(inner => factory.generateLocator(base, 'has', inner)));
|
||||
continue;
|
||||
}
|
||||
if (part.name === 'internal:has-not') {
|
||||
const inners = innerAsLocators(factory, part.body.parsed, false, maxOutputSize);
|
||||
tokens.push(inners.map(inner => factory.generateLocator(base, 'hasNot', inner)));
|
||||
continue;
|
||||
}
|
||||
if (part.name === 'internal:and') {
|
||||
const inners = innerAsLocators(factory, part.body.parsed, false, maxOutputSize);
|
||||
tokens.push(inners.map(inner => factory.generateLocator(base, 'and', inner)));
|
||||
continue;
|
||||
}
|
||||
if (part.name === 'internal:or') {
|
||||
const inners = innerAsLocators(factory, part.body.parsed, false, maxOutputSize);
|
||||
tokens.push(inners.map(inner => factory.generateLocator(base, 'or', inner)));
|
||||
continue;
|
||||
}
|
||||
if (part.name === 'internal:chain') {
|
||||
const inners = innerAsLocators(factory, part.body.parsed, false, maxOutputSize);
|
||||
tokens.push(inners.map(inner => factory.generateLocator(base, 'chain', inner)));
|
||||
continue;
|
||||
}
|
||||
if (part.name === 'internal:label') {
|
||||
const {
|
||||
exact,
|
||||
text
|
||||
} = detectExact(part.body);
|
||||
tokens.push([factory.generateLocator(base, 'label', text, {
|
||||
exact
|
||||
})]);
|
||||
continue;
|
||||
}
|
||||
if (part.name === 'internal:role') {
|
||||
const attrSelector = (0, _selectorParser.parseAttributeSelector)(part.body, true);
|
||||
const options = {
|
||||
attrs: []
|
||||
};
|
||||
for (const attr of attrSelector.attributes) {
|
||||
if (attr.name === 'name') {
|
||||
options.exact = attr.caseSensitive;
|
||||
options.name = attr.value;
|
||||
} else {
|
||||
if (attr.name === 'level' && typeof attr.value === 'string') attr.value = +attr.value;
|
||||
options.attrs.push({
|
||||
name: attr.name === 'include-hidden' ? 'includeHidden' : attr.name,
|
||||
value: attr.value
|
||||
});
|
||||
}
|
||||
}
|
||||
tokens.push([factory.generateLocator(base, 'role', attrSelector.name, options)]);
|
||||
continue;
|
||||
}
|
||||
if (part.name === 'internal:testid') {
|
||||
const attrSelector = (0, _selectorParser.parseAttributeSelector)(part.body, true);
|
||||
const {
|
||||
value
|
||||
} = attrSelector.attributes[0];
|
||||
tokens.push([factory.generateLocator(base, 'test-id', value)]);
|
||||
continue;
|
||||
}
|
||||
if (part.name === 'internal:attr') {
|
||||
const attrSelector = (0, _selectorParser.parseAttributeSelector)(part.body, true);
|
||||
const {
|
||||
name,
|
||||
value,
|
||||
caseSensitive
|
||||
} = attrSelector.attributes[0];
|
||||
const text = value;
|
||||
const exact = !!caseSensitive;
|
||||
if (name === 'placeholder') {
|
||||
tokens.push([factory.generateLocator(base, 'placeholder', text, {
|
||||
exact
|
||||
})]);
|
||||
continue;
|
||||
}
|
||||
if (name === 'alt') {
|
||||
tokens.push([factory.generateLocator(base, 'alt', text, {
|
||||
exact
|
||||
})]);
|
||||
continue;
|
||||
}
|
||||
if (name === 'title') {
|
||||
tokens.push([factory.generateLocator(base, 'title', text, {
|
||||
exact
|
||||
})]);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (part.name === 'internal:control' && part.body === 'enter-frame') {
|
||||
// transform last tokens from `${selector}` into `${selector}.contentFrame()` and `frameLocator(${selector})`
|
||||
const lastTokens = tokens[tokens.length - 1];
|
||||
const lastPart = parts[index - 1];
|
||||
const transformed = lastTokens.map(token => factory.chainLocators([token, factory.generateLocator(base, 'frame', '')]));
|
||||
if (['xpath', 'css'].includes(lastPart.name)) {
|
||||
transformed.push(factory.generateLocator(base, 'frame-locator', (0, _selectorParser.stringifySelector)({
|
||||
parts: [lastPart]
|
||||
})), factory.generateLocator(base, 'frame-locator', (0, _selectorParser.stringifySelector)({
|
||||
parts: [lastPart]
|
||||
}, true)));
|
||||
}
|
||||
lastTokens.splice(0, lastTokens.length, ...transformed);
|
||||
nextBase = 'frame-locator';
|
||||
continue;
|
||||
}
|
||||
const nextPart = parts[index + 1];
|
||||
const selectorPart = (0, _selectorParser.stringifySelector)({
|
||||
parts: [part]
|
||||
});
|
||||
const locatorPart = factory.generateLocator(base, 'default', selectorPart);
|
||||
if (nextPart && ['internal:has-text', 'internal:has-not-text'].includes(nextPart.name)) {
|
||||
const {
|
||||
exact,
|
||||
text
|
||||
} = detectExact(nextPart.body);
|
||||
// There is no locator equivalent for strict has-text and has-not-text, leave it as is.
|
||||
if (!exact) {
|
||||
const nextLocatorPart = factory.generateLocator('locator', nextPart.name === 'internal:has-text' ? 'has-text' : 'has-not-text', text, {
|
||||
exact
|
||||
});
|
||||
const options = {};
|
||||
if (nextPart.name === 'internal:has-text') options.hasText = text;else options.hasNotText = text;
|
||||
const combinedPart = factory.generateLocator(base, 'default', selectorPart, options);
|
||||
// Two options:
|
||||
// - locator('div').filter({ hasText: 'foo' })
|
||||
// - locator('div', { hasText: 'foo' })
|
||||
tokens.push([factory.chainLocators([locatorPart, nextLocatorPart]), combinedPart]);
|
||||
index++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Selectors can be prefixed with engine name, e.g. xpath=//foo
|
||||
let locatorPartWithEngine;
|
||||
if (['xpath', 'css'].includes(part.name)) {
|
||||
const selectorPart = (0, _selectorParser.stringifySelector)({
|
||||
parts: [part]
|
||||
}, /* forceEngineName */true);
|
||||
locatorPartWithEngine = factory.generateLocator(base, 'default', selectorPart);
|
||||
}
|
||||
tokens.push([locatorPart, locatorPartWithEngine].filter(Boolean));
|
||||
}
|
||||
return combineTokens(factory, tokens, maxOutputSize);
|
||||
}
|
||||
function combineTokens(factory, tokens, maxOutputSize) {
|
||||
const currentTokens = tokens.map(() => '');
|
||||
const result = [];
|
||||
const visit = index => {
|
||||
if (index === tokens.length) {
|
||||
result.push(factory.chainLocators(currentTokens));
|
||||
return currentTokens.length < maxOutputSize;
|
||||
}
|
||||
for (const taken of tokens[index]) {
|
||||
currentTokens[index] = taken;
|
||||
if (!visit(index + 1)) return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
visit(0);
|
||||
return result;
|
||||
}
|
||||
function detectExact(text) {
|
||||
let exact = false;
|
||||
const match = text.match(/^\/(.*)\/([igm]*)$/);
|
||||
if (match) return {
|
||||
text: new RegExp(match[1], match[2])
|
||||
};
|
||||
if (text.endsWith('"')) {
|
||||
text = JSON.parse(text);
|
||||
exact = true;
|
||||
} else if (text.endsWith('"s')) {
|
||||
text = JSON.parse(text.substring(0, text.length - 1));
|
||||
exact = true;
|
||||
} else if (text.endsWith('"i')) {
|
||||
text = JSON.parse(text.substring(0, text.length - 1));
|
||||
exact = false;
|
||||
}
|
||||
return {
|
||||
exact,
|
||||
text
|
||||
};
|
||||
}
|
||||
class JavaScriptLocatorFactory {
|
||||
constructor(preferredQuote) {
|
||||
this.preferredQuote = preferredQuote;
|
||||
}
|
||||
generateLocator(base, kind, body, options = {}) {
|
||||
switch (kind) {
|
||||
case 'default':
|
||||
if (options.hasText !== undefined) return `locator(${this.quote(body)}, { hasText: ${this.toHasText(options.hasText)} })`;
|
||||
if (options.hasNotText !== undefined) return `locator(${this.quote(body)}, { hasNotText: ${this.toHasText(options.hasNotText)} })`;
|
||||
return `locator(${this.quote(body)})`;
|
||||
case 'frame-locator':
|
||||
return `frameLocator(${this.quote(body)})`;
|
||||
case 'frame':
|
||||
return `contentFrame()`;
|
||||
case 'nth':
|
||||
return `nth(${body})`;
|
||||
case 'first':
|
||||
return `first()`;
|
||||
case 'last':
|
||||
return `last()`;
|
||||
case 'role':
|
||||
const attrs = [];
|
||||
if (isRegExp(options.name)) {
|
||||
attrs.push(`name: ${this.regexToSourceString(options.name)}`);
|
||||
} else if (typeof options.name === 'string') {
|
||||
attrs.push(`name: ${this.quote(options.name)}`);
|
||||
if (options.exact) attrs.push(`exact: true`);
|
||||
}
|
||||
for (const {
|
||||
name,
|
||||
value
|
||||
} of options.attrs) attrs.push(`${name}: ${typeof value === 'string' ? this.quote(value) : value}`);
|
||||
const attrString = attrs.length ? `, { ${attrs.join(', ')} }` : '';
|
||||
return `getByRole(${this.quote(body)}${attrString})`;
|
||||
case 'has-text':
|
||||
return `filter({ hasText: ${this.toHasText(body)} })`;
|
||||
case 'has-not-text':
|
||||
return `filter({ hasNotText: ${this.toHasText(body)} })`;
|
||||
case 'has':
|
||||
return `filter({ has: ${body} })`;
|
||||
case 'hasNot':
|
||||
return `filter({ hasNot: ${body} })`;
|
||||
case 'and':
|
||||
return `and(${body})`;
|
||||
case 'or':
|
||||
return `or(${body})`;
|
||||
case 'chain':
|
||||
return `locator(${body})`;
|
||||
case 'test-id':
|
||||
return `getByTestId(${this.toTestIdValue(body)})`;
|
||||
case 'text':
|
||||
return this.toCallWithExact('getByText', body, !!options.exact);
|
||||
case 'alt':
|
||||
return this.toCallWithExact('getByAltText', body, !!options.exact);
|
||||
case 'placeholder':
|
||||
return this.toCallWithExact('getByPlaceholder', body, !!options.exact);
|
||||
case 'label':
|
||||
return this.toCallWithExact('getByLabel', body, !!options.exact);
|
||||
case 'title':
|
||||
return this.toCallWithExact('getByTitle', body, !!options.exact);
|
||||
default:
|
||||
throw new Error('Unknown selector kind ' + kind);
|
||||
}
|
||||
}
|
||||
chainLocators(locators) {
|
||||
return locators.join('.');
|
||||
}
|
||||
regexToSourceString(re) {
|
||||
return (0, _stringUtils.normalizeEscapedRegexQuotes)(String(re));
|
||||
}
|
||||
toCallWithExact(method, body, exact) {
|
||||
if (isRegExp(body)) return `${method}(${this.regexToSourceString(body)})`;
|
||||
return exact ? `${method}(${this.quote(body)}, { exact: true })` : `${method}(${this.quote(body)})`;
|
||||
}
|
||||
toHasText(body) {
|
||||
if (isRegExp(body)) return this.regexToSourceString(body);
|
||||
return this.quote(body);
|
||||
}
|
||||
toTestIdValue(value) {
|
||||
if (isRegExp(value)) return this.regexToSourceString(value);
|
||||
return this.quote(value);
|
||||
}
|
||||
quote(text) {
|
||||
var _this$preferredQuote;
|
||||
return (0, _stringUtils.escapeWithQuotes)(text, (_this$preferredQuote = this.preferredQuote) !== null && _this$preferredQuote !== void 0 ? _this$preferredQuote : '\'');
|
||||
}
|
||||
}
|
||||
exports.JavaScriptLocatorFactory = JavaScriptLocatorFactory;
|
||||
class PythonLocatorFactory {
|
||||
generateLocator(base, kind, body, options = {}) {
|
||||
switch (kind) {
|
||||
case 'default':
|
||||
if (options.hasText !== undefined) return `locator(${this.quote(body)}, has_text=${this.toHasText(options.hasText)})`;
|
||||
if (options.hasNotText !== undefined) return `locator(${this.quote(body)}, has_not_text=${this.toHasText(options.hasNotText)})`;
|
||||
return `locator(${this.quote(body)})`;
|
||||
case 'frame-locator':
|
||||
return `frame_locator(${this.quote(body)})`;
|
||||
case 'frame':
|
||||
return `content_frame`;
|
||||
case 'nth':
|
||||
return `nth(${body})`;
|
||||
case 'first':
|
||||
return `first`;
|
||||
case 'last':
|
||||
return `last`;
|
||||
case 'role':
|
||||
const attrs = [];
|
||||
if (isRegExp(options.name)) {
|
||||
attrs.push(`name=${this.regexToString(options.name)}`);
|
||||
} else if (typeof options.name === 'string') {
|
||||
attrs.push(`name=${this.quote(options.name)}`);
|
||||
if (options.exact) attrs.push(`exact=True`);
|
||||
}
|
||||
for (const {
|
||||
name,
|
||||
value
|
||||
} of options.attrs) {
|
||||
let valueString = typeof value === 'string' ? this.quote(value) : value;
|
||||
if (typeof value === 'boolean') valueString = value ? 'True' : 'False';
|
||||
attrs.push(`${(0, _stringUtils.toSnakeCase)(name)}=${valueString}`);
|
||||
}
|
||||
const attrString = attrs.length ? `, ${attrs.join(', ')}` : '';
|
||||
return `get_by_role(${this.quote(body)}${attrString})`;
|
||||
case 'has-text':
|
||||
return `filter(has_text=${this.toHasText(body)})`;
|
||||
case 'has-not-text':
|
||||
return `filter(has_not_text=${this.toHasText(body)})`;
|
||||
case 'has':
|
||||
return `filter(has=${body})`;
|
||||
case 'hasNot':
|
||||
return `filter(has_not=${body})`;
|
||||
case 'and':
|
||||
return `and_(${body})`;
|
||||
case 'or':
|
||||
return `or_(${body})`;
|
||||
case 'chain':
|
||||
return `locator(${body})`;
|
||||
case 'test-id':
|
||||
return `get_by_test_id(${this.toTestIdValue(body)})`;
|
||||
case 'text':
|
||||
return this.toCallWithExact('get_by_text', body, !!options.exact);
|
||||
case 'alt':
|
||||
return this.toCallWithExact('get_by_alt_text', body, !!options.exact);
|
||||
case 'placeholder':
|
||||
return this.toCallWithExact('get_by_placeholder', body, !!options.exact);
|
||||
case 'label':
|
||||
return this.toCallWithExact('get_by_label', body, !!options.exact);
|
||||
case 'title':
|
||||
return this.toCallWithExact('get_by_title', body, !!options.exact);
|
||||
default:
|
||||
throw new Error('Unknown selector kind ' + kind);
|
||||
}
|
||||
}
|
||||
chainLocators(locators) {
|
||||
return locators.join('.');
|
||||
}
|
||||
regexToString(body) {
|
||||
const suffix = body.flags.includes('i') ? ', re.IGNORECASE' : '';
|
||||
return `re.compile(r"${(0, _stringUtils.normalizeEscapedRegexQuotes)(body.source).replace(/\\\//, '/').replace(/"/g, '\\"')}"${suffix})`;
|
||||
}
|
||||
toCallWithExact(method, body, exact) {
|
||||
if (isRegExp(body)) return `${method}(${this.regexToString(body)})`;
|
||||
if (exact) return `${method}(${this.quote(body)}, exact=True)`;
|
||||
return `${method}(${this.quote(body)})`;
|
||||
}
|
||||
toHasText(body) {
|
||||
if (isRegExp(body)) return this.regexToString(body);
|
||||
return `${this.quote(body)}`;
|
||||
}
|
||||
toTestIdValue(value) {
|
||||
if (isRegExp(value)) return this.regexToString(value);
|
||||
return this.quote(value);
|
||||
}
|
||||
quote(text) {
|
||||
return (0, _stringUtils.escapeWithQuotes)(text, '\"');
|
||||
}
|
||||
}
|
||||
exports.PythonLocatorFactory = PythonLocatorFactory;
|
||||
class JavaLocatorFactory {
|
||||
generateLocator(base, kind, body, options = {}) {
|
||||
let clazz;
|
||||
switch (base) {
|
||||
case 'page':
|
||||
clazz = 'Page';
|
||||
break;
|
||||
case 'frame-locator':
|
||||
clazz = 'FrameLocator';
|
||||
break;
|
||||
case 'locator':
|
||||
clazz = 'Locator';
|
||||
break;
|
||||
}
|
||||
switch (kind) {
|
||||
case 'default':
|
||||
if (options.hasText !== undefined) return `locator(${this.quote(body)}, new ${clazz}.LocatorOptions().setHasText(${this.toHasText(options.hasText)}))`;
|
||||
if (options.hasNotText !== undefined) return `locator(${this.quote(body)}, new ${clazz}.LocatorOptions().setHasNotText(${this.toHasText(options.hasNotText)}))`;
|
||||
return `locator(${this.quote(body)})`;
|
||||
case 'frame-locator':
|
||||
return `frameLocator(${this.quote(body)})`;
|
||||
case 'frame':
|
||||
return `contentFrame()`;
|
||||
case 'nth':
|
||||
return `nth(${body})`;
|
||||
case 'first':
|
||||
return `first()`;
|
||||
case 'last':
|
||||
return `last()`;
|
||||
case 'role':
|
||||
const attrs = [];
|
||||
if (isRegExp(options.name)) {
|
||||
attrs.push(`.setName(${this.regexToString(options.name)})`);
|
||||
} else if (typeof options.name === 'string') {
|
||||
attrs.push(`.setName(${this.quote(options.name)})`);
|
||||
if (options.exact) attrs.push(`.setExact(true)`);
|
||||
}
|
||||
for (const {
|
||||
name,
|
||||
value
|
||||
} of options.attrs) attrs.push(`.set${(0, _stringUtils.toTitleCase)(name)}(${typeof value === 'string' ? this.quote(value) : value})`);
|
||||
const attrString = attrs.length ? `, new ${clazz}.GetByRoleOptions()${attrs.join('')}` : '';
|
||||
return `getByRole(AriaRole.${(0, _stringUtils.toSnakeCase)(body).toUpperCase()}${attrString})`;
|
||||
case 'has-text':
|
||||
return `filter(new ${clazz}.FilterOptions().setHasText(${this.toHasText(body)}))`;
|
||||
case 'has-not-text':
|
||||
return `filter(new ${clazz}.FilterOptions().setHasNotText(${this.toHasText(body)}))`;
|
||||
case 'has':
|
||||
return `filter(new ${clazz}.FilterOptions().setHas(${body}))`;
|
||||
case 'hasNot':
|
||||
return `filter(new ${clazz}.FilterOptions().setHasNot(${body}))`;
|
||||
case 'and':
|
||||
return `and(${body})`;
|
||||
case 'or':
|
||||
return `or(${body})`;
|
||||
case 'chain':
|
||||
return `locator(${body})`;
|
||||
case 'test-id':
|
||||
return `getByTestId(${this.toTestIdValue(body)})`;
|
||||
case 'text':
|
||||
return this.toCallWithExact(clazz, 'getByText', body, !!options.exact);
|
||||
case 'alt':
|
||||
return this.toCallWithExact(clazz, 'getByAltText', body, !!options.exact);
|
||||
case 'placeholder':
|
||||
return this.toCallWithExact(clazz, 'getByPlaceholder', body, !!options.exact);
|
||||
case 'label':
|
||||
return this.toCallWithExact(clazz, 'getByLabel', body, !!options.exact);
|
||||
case 'title':
|
||||
return this.toCallWithExact(clazz, 'getByTitle', body, !!options.exact);
|
||||
default:
|
||||
throw new Error('Unknown selector kind ' + kind);
|
||||
}
|
||||
}
|
||||
chainLocators(locators) {
|
||||
return locators.join('.');
|
||||
}
|
||||
regexToString(body) {
|
||||
const suffix = body.flags.includes('i') ? ', Pattern.CASE_INSENSITIVE' : '';
|
||||
return `Pattern.compile(${this.quote((0, _stringUtils.normalizeEscapedRegexQuotes)(body.source))}${suffix})`;
|
||||
}
|
||||
toCallWithExact(clazz, method, body, exact) {
|
||||
if (isRegExp(body)) return `${method}(${this.regexToString(body)})`;
|
||||
if (exact) return `${method}(${this.quote(body)}, new ${clazz}.${(0, _stringUtils.toTitleCase)(method)}Options().setExact(true))`;
|
||||
return `${method}(${this.quote(body)})`;
|
||||
}
|
||||
toHasText(body) {
|
||||
if (isRegExp(body)) return this.regexToString(body);
|
||||
return this.quote(body);
|
||||
}
|
||||
toTestIdValue(value) {
|
||||
if (isRegExp(value)) return this.regexToString(value);
|
||||
return this.quote(value);
|
||||
}
|
||||
quote(text) {
|
||||
return (0, _stringUtils.escapeWithQuotes)(text, '\"');
|
||||
}
|
||||
}
|
||||
exports.JavaLocatorFactory = JavaLocatorFactory;
|
||||
class CSharpLocatorFactory {
|
||||
generateLocator(base, kind, body, options = {}) {
|
||||
switch (kind) {
|
||||
case 'default':
|
||||
if (options.hasText !== undefined) return `Locator(${this.quote(body)}, new() { ${this.toHasText(options.hasText)} })`;
|
||||
if (options.hasNotText !== undefined) return `Locator(${this.quote(body)}, new() { ${this.toHasNotText(options.hasNotText)} })`;
|
||||
return `Locator(${this.quote(body)})`;
|
||||
case 'frame-locator':
|
||||
return `FrameLocator(${this.quote(body)})`;
|
||||
case 'frame':
|
||||
return `ContentFrame`;
|
||||
case 'nth':
|
||||
return `Nth(${body})`;
|
||||
case 'first':
|
||||
return `First`;
|
||||
case 'last':
|
||||
return `Last`;
|
||||
case 'role':
|
||||
const attrs = [];
|
||||
if (isRegExp(options.name)) {
|
||||
attrs.push(`NameRegex = ${this.regexToString(options.name)}`);
|
||||
} else if (typeof options.name === 'string') {
|
||||
attrs.push(`Name = ${this.quote(options.name)}`);
|
||||
if (options.exact) attrs.push(`Exact = true`);
|
||||
}
|
||||
for (const {
|
||||
name,
|
||||
value
|
||||
} of options.attrs) attrs.push(`${(0, _stringUtils.toTitleCase)(name)} = ${typeof value === 'string' ? this.quote(value) : value}`);
|
||||
const attrString = attrs.length ? `, new() { ${attrs.join(', ')} }` : '';
|
||||
return `GetByRole(AriaRole.${(0, _stringUtils.toTitleCase)(body)}${attrString})`;
|
||||
case 'has-text':
|
||||
return `Filter(new() { ${this.toHasText(body)} })`;
|
||||
case 'has-not-text':
|
||||
return `Filter(new() { ${this.toHasNotText(body)} })`;
|
||||
case 'has':
|
||||
return `Filter(new() { Has = ${body} })`;
|
||||
case 'hasNot':
|
||||
return `Filter(new() { HasNot = ${body} })`;
|
||||
case 'and':
|
||||
return `And(${body})`;
|
||||
case 'or':
|
||||
return `Or(${body})`;
|
||||
case 'chain':
|
||||
return `Locator(${body})`;
|
||||
case 'test-id':
|
||||
return `GetByTestId(${this.toTestIdValue(body)})`;
|
||||
case 'text':
|
||||
return this.toCallWithExact('GetByText', body, !!options.exact);
|
||||
case 'alt':
|
||||
return this.toCallWithExact('GetByAltText', body, !!options.exact);
|
||||
case 'placeholder':
|
||||
return this.toCallWithExact('GetByPlaceholder', body, !!options.exact);
|
||||
case 'label':
|
||||
return this.toCallWithExact('GetByLabel', body, !!options.exact);
|
||||
case 'title':
|
||||
return this.toCallWithExact('GetByTitle', body, !!options.exact);
|
||||
default:
|
||||
throw new Error('Unknown selector kind ' + kind);
|
||||
}
|
||||
}
|
||||
chainLocators(locators) {
|
||||
return locators.join('.');
|
||||
}
|
||||
regexToString(body) {
|
||||
const suffix = body.flags.includes('i') ? ', RegexOptions.IgnoreCase' : '';
|
||||
return `new Regex(${this.quote((0, _stringUtils.normalizeEscapedRegexQuotes)(body.source))}${suffix})`;
|
||||
}
|
||||
toCallWithExact(method, body, exact) {
|
||||
if (isRegExp(body)) return `${method}(${this.regexToString(body)})`;
|
||||
if (exact) return `${method}(${this.quote(body)}, new() { Exact = true })`;
|
||||
return `${method}(${this.quote(body)})`;
|
||||
}
|
||||
toHasText(body) {
|
||||
if (isRegExp(body)) return `HasTextRegex = ${this.regexToString(body)}`;
|
||||
return `HasText = ${this.quote(body)}`;
|
||||
}
|
||||
toTestIdValue(value) {
|
||||
if (isRegExp(value)) return this.regexToString(value);
|
||||
return this.quote(value);
|
||||
}
|
||||
toHasNotText(body) {
|
||||
if (isRegExp(body)) return `HasNotTextRegex = ${this.regexToString(body)}`;
|
||||
return `HasNotText = ${this.quote(body)}`;
|
||||
}
|
||||
quote(text) {
|
||||
return (0, _stringUtils.escapeWithQuotes)(text, '\"');
|
||||
}
|
||||
}
|
||||
exports.CSharpLocatorFactory = CSharpLocatorFactory;
|
||||
class JsonlLocatorFactory {
|
||||
generateLocator(base, kind, body, options = {}) {
|
||||
return JSON.stringify({
|
||||
kind,
|
||||
body,
|
||||
options
|
||||
});
|
||||
}
|
||||
chainLocators(locators) {
|
||||
const objects = locators.map(l => JSON.parse(l));
|
||||
for (let i = 0; i < objects.length - 1; ++i) objects[i].next = objects[i + 1];
|
||||
return JSON.stringify(objects[0]);
|
||||
}
|
||||
}
|
||||
exports.JsonlLocatorFactory = JsonlLocatorFactory;
|
||||
const generators = {
|
||||
javascript: JavaScriptLocatorFactory,
|
||||
python: PythonLocatorFactory,
|
||||
java: JavaLocatorFactory,
|
||||
csharp: CSharpLocatorFactory,
|
||||
jsonl: JsonlLocatorFactory
|
||||
};
|
||||
function isRegExp(obj) {
|
||||
return obj instanceof RegExp;
|
||||
}
|
||||
179
node_modules/playwright-core/lib/utils/isomorphic/locatorParser.js
generated
vendored
Normal file
179
node_modules/playwright-core/lib/utils/isomorphic/locatorParser.js
generated
vendored
Normal file
@@ -0,0 +1,179 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.locatorOrSelectorAsSelector = locatorOrSelectorAsSelector;
|
||||
var _stringUtils = require("./stringUtils");
|
||||
var _locatorGenerators = require("./locatorGenerators");
|
||||
var _selectorParser = require("./selectorParser");
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
function parseLocator(locator, testIdAttributeName) {
|
||||
locator = locator.replace(/AriaRole\s*\.\s*([\w]+)/g, (_, group) => group.toLowerCase()).replace(/(get_by_role|getByRole)\s*\(\s*(?:["'`])([^'"`]+)['"`]/g, (_, group1, group2) => `${group1}(${group2.toLowerCase()}`);
|
||||
const params = [];
|
||||
let template = '';
|
||||
for (let i = 0; i < locator.length; ++i) {
|
||||
const quote = locator[i];
|
||||
if (quote !== '"' && quote !== '\'' && quote !== '`' && quote !== '/') {
|
||||
template += quote;
|
||||
continue;
|
||||
}
|
||||
const isRegexEscaping = locator[i - 1] === 'r' || locator[i] === '/';
|
||||
++i;
|
||||
let text = '';
|
||||
while (i < locator.length) {
|
||||
if (locator[i] === '\\') {
|
||||
if (isRegexEscaping) {
|
||||
if (locator[i + 1] !== quote) text += locator[i];
|
||||
++i;
|
||||
text += locator[i];
|
||||
} else {
|
||||
++i;
|
||||
if (locator[i] === 'n') text += '\n';else if (locator[i] === 'r') text += '\r';else if (locator[i] === 't') text += '\t';else text += locator[i];
|
||||
}
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
if (locator[i] !== quote) {
|
||||
text += locator[i++];
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
params.push({
|
||||
quote,
|
||||
text
|
||||
});
|
||||
template += (quote === '/' ? 'r' : '') + '$' + params.length;
|
||||
}
|
||||
|
||||
// Equalize languages.
|
||||
template = template.toLowerCase().replace(/get_by_alt_text/g, 'getbyalttext').replace(/get_by_test_id/g, 'getbytestid').replace(/get_by_([\w]+)/g, 'getby$1').replace(/has_not_text/g, 'hasnottext').replace(/has_text/g, 'hastext').replace(/has_not/g, 'hasnot').replace(/frame_locator/g, 'framelocator').replace(/content_frame/g, 'contentframe').replace(/[{}\s]/g, '').replace(/new\(\)/g, '').replace(/new[\w]+\.[\w]+options\(\)/g, '').replace(/\.set/g, ',set').replace(/\.or_\(/g, 'or(') // Python has "or_" instead of "or".
|
||||
.replace(/\.and_\(/g, 'and(') // Python has "and_" instead of "and".
|
||||
.replace(/:/g, '=').replace(/,re\.ignorecase/g, 'i').replace(/,pattern.case_insensitive/g, 'i').replace(/,regexoptions.ignorecase/g, 'i').replace(/re.compile\(([^)]+)\)/g, '$1') // Python has regex strings as r"foo"
|
||||
.replace(/pattern.compile\(([^)]+)\)/g, 'r$1').replace(/newregex\(([^)]+)\)/g, 'r$1').replace(/string=/g, '=').replace(/regex=/g, '=').replace(/,,/g, ',');
|
||||
const preferredQuote = params.map(p => p.quote).filter(quote => '\'"`'.includes(quote))[0];
|
||||
return {
|
||||
selector: transform(template, params, testIdAttributeName),
|
||||
preferredQuote
|
||||
};
|
||||
}
|
||||
function countParams(template) {
|
||||
return [...template.matchAll(/\$\d+/g)].length;
|
||||
}
|
||||
function shiftParams(template, sub) {
|
||||
return template.replace(/\$(\d+)/g, (_, ordinal) => `$${ordinal - sub}`);
|
||||
}
|
||||
function transform(template, params, testIdAttributeName) {
|
||||
// Recursively handle filter(has=, hasnot=, sethas(), sethasnot()).
|
||||
// TODO: handle and(locator), or(locator), locator(locator), locator(has=, hasnot=, sethas(), sethasnot()).
|
||||
while (true) {
|
||||
const hasMatch = template.match(/filter\(,?(has=|hasnot=|sethas\(|sethasnot\()/);
|
||||
if (!hasMatch) break;
|
||||
|
||||
// Extract inner locator based on balanced parens.
|
||||
const start = hasMatch.index + hasMatch[0].length;
|
||||
let balance = 0;
|
||||
let end = start;
|
||||
for (; end < template.length; end++) {
|
||||
if (template[end] === '(') balance++;else if (template[end] === ')') balance--;
|
||||
if (balance < 0) break;
|
||||
}
|
||||
|
||||
// Replace Java sethas(...) and sethasnot(...) with has=... and hasnot=...
|
||||
let prefix = template.substring(0, start);
|
||||
let extraSymbol = 0;
|
||||
if (['sethas(', 'sethasnot('].includes(hasMatch[1])) {
|
||||
// Eat extra ) symbol at the end of sethas(...)
|
||||
extraSymbol = 1;
|
||||
prefix = prefix.replace(/sethas\($/, 'has=').replace(/sethasnot\($/, 'hasnot=');
|
||||
}
|
||||
const paramsCountBeforeHas = countParams(template.substring(0, start));
|
||||
const hasTemplate = shiftParams(template.substring(start, end), paramsCountBeforeHas);
|
||||
const paramsCountInHas = countParams(hasTemplate);
|
||||
const hasParams = params.slice(paramsCountBeforeHas, paramsCountBeforeHas + paramsCountInHas);
|
||||
const hasSelector = JSON.stringify(transform(hasTemplate, hasParams, testIdAttributeName));
|
||||
|
||||
// Replace filter(has=...) with filter(has2=$5). Use has2 to avoid matching the same filter again.
|
||||
// Replace filter(hasnot=...) with filter(hasnot2=$5). Use hasnot2 to avoid matching the same filter again.
|
||||
template = prefix.replace(/=$/, '2=') + `$${paramsCountBeforeHas + 1}` + shiftParams(template.substring(end + extraSymbol), paramsCountInHas - 1);
|
||||
|
||||
// Replace inner params with $5 value.
|
||||
const paramsBeforeHas = params.slice(0, paramsCountBeforeHas);
|
||||
const paramsAfterHas = params.slice(paramsCountBeforeHas + paramsCountInHas);
|
||||
params = paramsBeforeHas.concat([{
|
||||
quote: '"',
|
||||
text: hasSelector
|
||||
}]).concat(paramsAfterHas);
|
||||
}
|
||||
|
||||
// Transform to selector engines.
|
||||
template = template.replace(/\,set([\w]+)\(([^)]+)\)/g, (_, group1, group2) => ',' + group1.toLowerCase() + '=' + group2.toLowerCase()).replace(/framelocator\(([^)]+)\)/g, '$1.internal:control=enter-frame').replace(/contentframe(\(\))?/g, 'internal:control=enter-frame').replace(/locator\(([^)]+),hastext=([^),]+)\)/g, 'locator($1).internal:has-text=$2').replace(/locator\(([^)]+),hasnottext=([^),]+)\)/g, 'locator($1).internal:has-not-text=$2').replace(/locator\(([^)]+),hastext=([^),]+)\)/g, 'locator($1).internal:has-text=$2').replace(/locator\(([^)]+)\)/g, '$1').replace(/getbyrole\(([^)]+)\)/g, 'internal:role=$1').replace(/getbytext\(([^)]+)\)/g, 'internal:text=$1').replace(/getbylabel\(([^)]+)\)/g, 'internal:label=$1').replace(/getbytestid\(([^)]+)\)/g, `internal:testid=[${testIdAttributeName}=$1]`).replace(/getby(placeholder|alt|title)(?:text)?\(([^)]+)\)/g, 'internal:attr=[$1=$2]').replace(/first(\(\))?/g, 'nth=0').replace(/last(\(\))?/g, 'nth=-1').replace(/nth\(([^)]+)\)/g, 'nth=$1').replace(/filter\(,?hastext=([^)]+)\)/g, 'internal:has-text=$1').replace(/filter\(,?hasnottext=([^)]+)\)/g, 'internal:has-not-text=$1').replace(/filter\(,?has2=([^)]+)\)/g, 'internal:has=$1').replace(/filter\(,?hasnot2=([^)]+)\)/g, 'internal:has-not=$1').replace(/,exact=false/g, '').replace(/,exact=true/g, 's').replace(/\,/g, '][');
|
||||
const parts = template.split('.');
|
||||
// Turn "internal:control=enter-frame >> nth=0" into "nth=0 >> internal:control=enter-frame"
|
||||
// because these are swapped in locators vs selectors.
|
||||
for (let index = 0; index < parts.length - 1; index++) {
|
||||
if (parts[index] === 'internal:control=enter-frame' && parts[index + 1].startsWith('nth=')) {
|
||||
// Swap nth and enter-frame.
|
||||
const [nth] = parts.splice(index, 1);
|
||||
parts.splice(index + 1, 0, nth);
|
||||
}
|
||||
}
|
||||
|
||||
// Substitute params.
|
||||
return parts.map(t => {
|
||||
if (!t.startsWith('internal:') || t === 'internal:control') return t.replace(/\$(\d+)/g, (_, ordinal) => {
|
||||
const param = params[+ordinal - 1];
|
||||
return param.text;
|
||||
});
|
||||
t = t.includes('[') ? t.replace(/\]/, '') + ']' : t;
|
||||
t = t.replace(/(?:r)\$(\d+)(i)?/g, (_, ordinal, suffix) => {
|
||||
const param = params[+ordinal - 1];
|
||||
if (t.startsWith('internal:attr') || t.startsWith('internal:testid') || t.startsWith('internal:role')) return (0, _stringUtils.escapeForAttributeSelector)(new RegExp(param.text), false) + (suffix || '');
|
||||
return (0, _stringUtils.escapeForTextSelector)(new RegExp(param.text, suffix), false);
|
||||
}).replace(/\$(\d+)(i|s)?/g, (_, ordinal, suffix) => {
|
||||
const param = params[+ordinal - 1];
|
||||
if (t.startsWith('internal:has=') || t.startsWith('internal:has-not=')) return param.text;
|
||||
if (t.startsWith('internal:testid')) return (0, _stringUtils.escapeForAttributeSelector)(param.text, true);
|
||||
if (t.startsWith('internal:attr') || t.startsWith('internal:role')) return (0, _stringUtils.escapeForAttributeSelector)(param.text, suffix === 's');
|
||||
return (0, _stringUtils.escapeForTextSelector)(param.text, suffix === 's');
|
||||
});
|
||||
return t;
|
||||
}).join(' >> ');
|
||||
}
|
||||
function locatorOrSelectorAsSelector(language, locator, testIdAttributeName) {
|
||||
try {
|
||||
(0, _selectorParser.parseSelector)(locator);
|
||||
return locator;
|
||||
} catch (e) {}
|
||||
try {
|
||||
const {
|
||||
selector,
|
||||
preferredQuote
|
||||
} = parseLocator(locator, testIdAttributeName);
|
||||
const locators = (0, _locatorGenerators.asLocators)(language, selector, undefined, undefined, preferredQuote);
|
||||
const digest = digestForComparison(language, locator);
|
||||
if (locators.some(candidate => digestForComparison(language, candidate) === digest)) return selector;
|
||||
} catch (e) {}
|
||||
return '';
|
||||
}
|
||||
function digestForComparison(language, locator) {
|
||||
locator = locator.replace(/\s/g, '');
|
||||
if (language === 'javascript') locator = locator.replace(/\\?["`]/g, '\'');
|
||||
return locator;
|
||||
}
|
||||
62
node_modules/playwright-core/lib/utils/isomorphic/locatorUtils.js
generated
vendored
Normal file
62
node_modules/playwright-core/lib/utils/isomorphic/locatorUtils.js
generated
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.getByAltTextSelector = getByAltTextSelector;
|
||||
exports.getByLabelSelector = getByLabelSelector;
|
||||
exports.getByPlaceholderSelector = getByPlaceholderSelector;
|
||||
exports.getByRoleSelector = getByRoleSelector;
|
||||
exports.getByTestIdSelector = getByTestIdSelector;
|
||||
exports.getByTextSelector = getByTextSelector;
|
||||
exports.getByTitleSelector = getByTitleSelector;
|
||||
var _stringUtils = require("./stringUtils");
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
function getByAttributeTextSelector(attrName, text, options) {
|
||||
return `internal:attr=[${attrName}=${(0, _stringUtils.escapeForAttributeSelector)(text, (options === null || options === void 0 ? void 0 : options.exact) || false)}]`;
|
||||
}
|
||||
function getByTestIdSelector(testIdAttributeName, testId) {
|
||||
return `internal:testid=[${testIdAttributeName}=${(0, _stringUtils.escapeForAttributeSelector)(testId, true)}]`;
|
||||
}
|
||||
function getByLabelSelector(text, options) {
|
||||
return 'internal:label=' + (0, _stringUtils.escapeForTextSelector)(text, !!(options !== null && options !== void 0 && options.exact));
|
||||
}
|
||||
function getByAltTextSelector(text, options) {
|
||||
return getByAttributeTextSelector('alt', text, options);
|
||||
}
|
||||
function getByTitleSelector(text, options) {
|
||||
return getByAttributeTextSelector('title', text, options);
|
||||
}
|
||||
function getByPlaceholderSelector(text, options) {
|
||||
return getByAttributeTextSelector('placeholder', text, options);
|
||||
}
|
||||
function getByTextSelector(text, options) {
|
||||
return 'internal:text=' + (0, _stringUtils.escapeForTextSelector)(text, !!(options !== null && options !== void 0 && options.exact));
|
||||
}
|
||||
function getByRoleSelector(role, options = {}) {
|
||||
const props = [];
|
||||
if (options.checked !== undefined) props.push(['checked', String(options.checked)]);
|
||||
if (options.disabled !== undefined) props.push(['disabled', String(options.disabled)]);
|
||||
if (options.selected !== undefined) props.push(['selected', String(options.selected)]);
|
||||
if (options.expanded !== undefined) props.push(['expanded', String(options.expanded)]);
|
||||
if (options.includeHidden !== undefined) props.push(['include-hidden', String(options.includeHidden)]);
|
||||
if (options.level !== undefined) props.push(['level', String(options.level)]);
|
||||
if (options.name !== undefined) props.push(['name', (0, _stringUtils.escapeForAttributeSelector)(options.name, !!options.exact)]);
|
||||
if (options.pressed !== undefined) props.push(['pressed', String(options.pressed)]);
|
||||
return `internal:role=${role}${props.map(([n, v]) => `[${n}=${v}]`).join('')}`;
|
||||
}
|
||||
29
node_modules/playwright-core/lib/utils/isomorphic/mimeType.js
generated
vendored
Normal file
29
node_modules/playwright-core/lib/utils/isomorphic/mimeType.js
generated
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.isJsonMimeType = isJsonMimeType;
|
||||
exports.isTextualMimeType = isTextualMimeType;
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
function isJsonMimeType(mimeType) {
|
||||
return !!mimeType.match(/^(application\/json|application\/.*?\+json|text\/(x-)?json)(;\s*charset=.*)?$/);
|
||||
}
|
||||
function isTextualMimeType(mimeType) {
|
||||
return !!mimeType.match(/^(text\/.*?|application\/(json|(x-)?javascript|xml.*?|ecmascript|graphql|x-www-form-urlencoded)|image\/svg(\+xml)?|application\/.*?(\+json|\+xml))(;\s*charset=.*)?$/);
|
||||
}
|
||||
227
node_modules/playwright-core/lib/utils/isomorphic/recorderUtils.js
generated
vendored
Normal file
227
node_modules/playwright-core/lib/utils/isomorphic/recorderUtils.js
generated
vendored
Normal file
@@ -0,0 +1,227 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.buildFullSelector = buildFullSelector;
|
||||
exports.toKeyboardModifiers = toKeyboardModifiers;
|
||||
exports.traceParamsForAction = traceParamsForAction;
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
function buildFullSelector(framePath, selector) {
|
||||
return [...framePath, selector].join(' >> internal:control=enter-frame >> ');
|
||||
}
|
||||
const kDefaultTimeout = 5_000;
|
||||
function traceParamsForAction(actionInContext) {
|
||||
const {
|
||||
action
|
||||
} = actionInContext;
|
||||
switch (action.name) {
|
||||
case 'navigate':
|
||||
{
|
||||
const params = {
|
||||
url: action.url
|
||||
};
|
||||
return {
|
||||
method: 'goto',
|
||||
apiName: 'page.goto',
|
||||
params
|
||||
};
|
||||
}
|
||||
case 'openPage':
|
||||
case 'closePage':
|
||||
throw new Error('Not reached');
|
||||
}
|
||||
const selector = buildFullSelector(actionInContext.frame.framePath, action.selector);
|
||||
switch (action.name) {
|
||||
case 'click':
|
||||
{
|
||||
const params = {
|
||||
selector,
|
||||
strict: true,
|
||||
modifiers: toKeyboardModifiers(action.modifiers),
|
||||
button: action.button,
|
||||
clickCount: action.clickCount,
|
||||
position: action.position
|
||||
};
|
||||
return {
|
||||
method: 'click',
|
||||
apiName: 'locator.click',
|
||||
params
|
||||
};
|
||||
}
|
||||
case 'press':
|
||||
{
|
||||
const params = {
|
||||
selector,
|
||||
strict: true,
|
||||
key: [...toKeyboardModifiers(action.modifiers), action.key].join('+')
|
||||
};
|
||||
return {
|
||||
method: 'press',
|
||||
apiName: 'locator.press',
|
||||
params
|
||||
};
|
||||
}
|
||||
case 'fill':
|
||||
{
|
||||
const params = {
|
||||
selector,
|
||||
strict: true,
|
||||
value: action.text
|
||||
};
|
||||
return {
|
||||
method: 'fill',
|
||||
apiName: 'locator.fill',
|
||||
params
|
||||
};
|
||||
}
|
||||
case 'setInputFiles':
|
||||
{
|
||||
const params = {
|
||||
selector,
|
||||
strict: true,
|
||||
localPaths: action.files
|
||||
};
|
||||
return {
|
||||
method: 'setInputFiles',
|
||||
apiName: 'locator.setInputFiles',
|
||||
params
|
||||
};
|
||||
}
|
||||
case 'check':
|
||||
{
|
||||
const params = {
|
||||
selector,
|
||||
strict: true
|
||||
};
|
||||
return {
|
||||
method: 'check',
|
||||
apiName: 'locator.check',
|
||||
params
|
||||
};
|
||||
}
|
||||
case 'uncheck':
|
||||
{
|
||||
const params = {
|
||||
selector,
|
||||
strict: true
|
||||
};
|
||||
return {
|
||||
method: 'uncheck',
|
||||
apiName: 'locator.uncheck',
|
||||
params
|
||||
};
|
||||
}
|
||||
case 'select':
|
||||
{
|
||||
const params = {
|
||||
selector,
|
||||
strict: true,
|
||||
options: action.options.map(option => ({
|
||||
value: option
|
||||
}))
|
||||
};
|
||||
return {
|
||||
method: 'selectOption',
|
||||
apiName: 'locator.selectOption',
|
||||
params
|
||||
};
|
||||
}
|
||||
case 'assertChecked':
|
||||
{
|
||||
const params = {
|
||||
selector: action.selector,
|
||||
expression: 'to.be.checked',
|
||||
isNot: !action.checked,
|
||||
timeout: kDefaultTimeout
|
||||
};
|
||||
return {
|
||||
method: 'expect',
|
||||
apiName: 'expect.toBeChecked',
|
||||
params
|
||||
};
|
||||
}
|
||||
case 'assertText':
|
||||
{
|
||||
const params = {
|
||||
selector,
|
||||
expression: 'to.have.text',
|
||||
expectedText: [],
|
||||
isNot: false,
|
||||
timeout: kDefaultTimeout
|
||||
};
|
||||
return {
|
||||
method: 'expect',
|
||||
apiName: 'expect.toContainText',
|
||||
params
|
||||
};
|
||||
}
|
||||
case 'assertValue':
|
||||
{
|
||||
const params = {
|
||||
selector,
|
||||
expression: 'to.have.value',
|
||||
expectedValue: undefined,
|
||||
isNot: false,
|
||||
timeout: kDefaultTimeout
|
||||
};
|
||||
return {
|
||||
method: 'expect',
|
||||
apiName: 'expect.toHaveValue',
|
||||
params
|
||||
};
|
||||
}
|
||||
case 'assertVisible':
|
||||
{
|
||||
const params = {
|
||||
selector,
|
||||
expression: 'to.be.visible',
|
||||
isNot: false,
|
||||
timeout: kDefaultTimeout
|
||||
};
|
||||
return {
|
||||
method: 'expect',
|
||||
apiName: 'expect.toBeVisible',
|
||||
params
|
||||
};
|
||||
}
|
||||
case 'assertSnapshot':
|
||||
{
|
||||
const params = {
|
||||
selector,
|
||||
expression: 'to.match.snapshot',
|
||||
expectedText: [],
|
||||
isNot: false,
|
||||
timeout: kDefaultTimeout
|
||||
};
|
||||
return {
|
||||
method: 'expect',
|
||||
apiName: 'expect.toMatchAriaSnapshot',
|
||||
params
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
function toKeyboardModifiers(modifiers) {
|
||||
const result = [];
|
||||
if (modifiers & 1) result.push('Alt');
|
||||
if (modifiers & 2) result.push('ControlOrMeta');
|
||||
if (modifiers & 4) result.push('ControlOrMeta');
|
||||
if (modifiers & 8) result.push('Shift');
|
||||
return result;
|
||||
}
|
||||
397
node_modules/playwright-core/lib/utils/isomorphic/selectorParser.js
generated
vendored
Normal file
397
node_modules/playwright-core/lib/utils/isomorphic/selectorParser.js
generated
vendored
Normal file
@@ -0,0 +1,397 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
Object.defineProperty(exports, "InvalidSelectorError", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _cssParser.InvalidSelectorError;
|
||||
}
|
||||
});
|
||||
exports.customCSSNames = void 0;
|
||||
Object.defineProperty(exports, "isInvalidSelectorError", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _cssParser.isInvalidSelectorError;
|
||||
}
|
||||
});
|
||||
exports.parseAttributeSelector = parseAttributeSelector;
|
||||
exports.parseSelector = parseSelector;
|
||||
exports.splitSelectorByFrame = splitSelectorByFrame;
|
||||
exports.stringifySelector = stringifySelector;
|
||||
exports.visitAllSelectorParts = visitAllSelectorParts;
|
||||
var _cssParser = require("./cssParser");
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
const kNestedSelectorNames = new Set(['internal:has', 'internal:has-not', 'internal:and', 'internal:or', 'internal:chain', 'left-of', 'right-of', 'above', 'below', 'near']);
|
||||
const kNestedSelectorNamesWithDistance = new Set(['left-of', 'right-of', 'above', 'below', 'near']);
|
||||
const customCSSNames = exports.customCSSNames = new Set(['not', 'is', 'where', 'has', 'scope', 'light', 'visible', 'text', 'text-matches', 'text-is', 'has-text', 'above', 'below', 'right-of', 'left-of', 'near', 'nth-match']);
|
||||
function parseSelector(selector) {
|
||||
const parsedStrings = parseSelectorString(selector);
|
||||
const parts = [];
|
||||
for (const part of parsedStrings.parts) {
|
||||
if (part.name === 'css' || part.name === 'css:light') {
|
||||
if (part.name === 'css:light') part.body = ':light(' + part.body + ')';
|
||||
const parsedCSS = (0, _cssParser.parseCSS)(part.body, customCSSNames);
|
||||
parts.push({
|
||||
name: 'css',
|
||||
body: parsedCSS.selector,
|
||||
source: part.body
|
||||
});
|
||||
continue;
|
||||
}
|
||||
if (kNestedSelectorNames.has(part.name)) {
|
||||
let innerSelector;
|
||||
let distance;
|
||||
try {
|
||||
const unescaped = JSON.parse('[' + part.body + ']');
|
||||
if (!Array.isArray(unescaped) || unescaped.length < 1 || unescaped.length > 2 || typeof unescaped[0] !== 'string') throw new _cssParser.InvalidSelectorError(`Malformed selector: ${part.name}=` + part.body);
|
||||
innerSelector = unescaped[0];
|
||||
if (unescaped.length === 2) {
|
||||
if (typeof unescaped[1] !== 'number' || !kNestedSelectorNamesWithDistance.has(part.name)) throw new _cssParser.InvalidSelectorError(`Malformed selector: ${part.name}=` + part.body);
|
||||
distance = unescaped[1];
|
||||
}
|
||||
} catch (e) {
|
||||
throw new _cssParser.InvalidSelectorError(`Malformed selector: ${part.name}=` + part.body);
|
||||
}
|
||||
const nested = {
|
||||
name: part.name,
|
||||
source: part.body,
|
||||
body: {
|
||||
parsed: parseSelector(innerSelector),
|
||||
distance
|
||||
}
|
||||
};
|
||||
const lastFrame = [...nested.body.parsed.parts].reverse().find(part => part.name === 'internal:control' && part.body === 'enter-frame');
|
||||
const lastFrameIndex = lastFrame ? nested.body.parsed.parts.indexOf(lastFrame) : -1;
|
||||
// Allow nested selectors to start with the same frame selector.
|
||||
if (lastFrameIndex !== -1 && selectorPartsEqual(nested.body.parsed.parts.slice(0, lastFrameIndex + 1), parts.slice(0, lastFrameIndex + 1))) nested.body.parsed.parts.splice(0, lastFrameIndex + 1);
|
||||
parts.push(nested);
|
||||
continue;
|
||||
}
|
||||
parts.push({
|
||||
...part,
|
||||
source: part.body
|
||||
});
|
||||
}
|
||||
if (kNestedSelectorNames.has(parts[0].name)) throw new _cssParser.InvalidSelectorError(`"${parts[0].name}" selector cannot be first`);
|
||||
return {
|
||||
capture: parsedStrings.capture,
|
||||
parts
|
||||
};
|
||||
}
|
||||
function splitSelectorByFrame(selectorText) {
|
||||
const selector = parseSelector(selectorText);
|
||||
const result = [];
|
||||
let chunk = {
|
||||
parts: []
|
||||
};
|
||||
let chunkStartIndex = 0;
|
||||
for (let i = 0; i < selector.parts.length; ++i) {
|
||||
const part = selector.parts[i];
|
||||
if (part.name === 'internal:control' && part.body === 'enter-frame') {
|
||||
if (!chunk.parts.length) throw new _cssParser.InvalidSelectorError('Selector cannot start with entering frame, select the iframe first');
|
||||
result.push(chunk);
|
||||
chunk = {
|
||||
parts: []
|
||||
};
|
||||
chunkStartIndex = i + 1;
|
||||
continue;
|
||||
}
|
||||
if (selector.capture === i) chunk.capture = i - chunkStartIndex;
|
||||
chunk.parts.push(part);
|
||||
}
|
||||
if (!chunk.parts.length) throw new _cssParser.InvalidSelectorError(`Selector cannot end with entering frame, while parsing selector ${selectorText}`);
|
||||
result.push(chunk);
|
||||
if (typeof selector.capture === 'number' && typeof result[result.length - 1].capture !== 'number') throw new _cssParser.InvalidSelectorError(`Can not capture the selector before diving into the frame. Only use * after the last frame has been selected`);
|
||||
return result;
|
||||
}
|
||||
function selectorPartsEqual(list1, list2) {
|
||||
return stringifySelector({
|
||||
parts: list1
|
||||
}) === stringifySelector({
|
||||
parts: list2
|
||||
});
|
||||
}
|
||||
function stringifySelector(selector, forceEngineName) {
|
||||
if (typeof selector === 'string') return selector;
|
||||
return selector.parts.map((p, i) => {
|
||||
let includeEngine = true;
|
||||
if (!forceEngineName && i !== selector.capture) {
|
||||
if (p.name === 'css') includeEngine = false;else if (p.name === 'xpath' && p.source.startsWith('//') || p.source.startsWith('..')) includeEngine = false;
|
||||
}
|
||||
const prefix = includeEngine ? p.name + '=' : '';
|
||||
return `${i === selector.capture ? '*' : ''}${prefix}${p.source}`;
|
||||
}).join(' >> ');
|
||||
}
|
||||
function visitAllSelectorParts(selector, visitor) {
|
||||
const visit = (selector, nested) => {
|
||||
for (const part of selector.parts) {
|
||||
visitor(part, nested);
|
||||
if (kNestedSelectorNames.has(part.name)) visit(part.body.parsed, true);
|
||||
}
|
||||
};
|
||||
visit(selector, false);
|
||||
}
|
||||
function parseSelectorString(selector) {
|
||||
let index = 0;
|
||||
let quote;
|
||||
let start = 0;
|
||||
const result = {
|
||||
parts: []
|
||||
};
|
||||
const append = () => {
|
||||
const part = selector.substring(start, index).trim();
|
||||
const eqIndex = part.indexOf('=');
|
||||
let name;
|
||||
let body;
|
||||
if (eqIndex !== -1 && part.substring(0, eqIndex).trim().match(/^[a-zA-Z_0-9-+:*]+$/)) {
|
||||
name = part.substring(0, eqIndex).trim();
|
||||
body = part.substring(eqIndex + 1);
|
||||
} else if (part.length > 1 && part[0] === '"' && part[part.length - 1] === '"') {
|
||||
name = 'text';
|
||||
body = part;
|
||||
} else if (part.length > 1 && part[0] === "'" && part[part.length - 1] === "'") {
|
||||
name = 'text';
|
||||
body = part;
|
||||
} else if (/^\(*\/\//.test(part) || part.startsWith('..')) {
|
||||
// If selector starts with '//' or '//' prefixed with multiple opening
|
||||
// parenthesis, consider xpath. @see https://github.com/microsoft/playwright/issues/817
|
||||
// If selector starts with '..', consider xpath as well.
|
||||
name = 'xpath';
|
||||
body = part;
|
||||
} else {
|
||||
name = 'css';
|
||||
body = part;
|
||||
}
|
||||
let capture = false;
|
||||
if (name[0] === '*') {
|
||||
capture = true;
|
||||
name = name.substring(1);
|
||||
}
|
||||
result.parts.push({
|
||||
name,
|
||||
body
|
||||
});
|
||||
if (capture) {
|
||||
if (result.capture !== undefined) throw new _cssParser.InvalidSelectorError(`Only one of the selectors can capture using * modifier`);
|
||||
result.capture = result.parts.length - 1;
|
||||
}
|
||||
};
|
||||
if (!selector.includes('>>')) {
|
||||
index = selector.length;
|
||||
append();
|
||||
return result;
|
||||
}
|
||||
const shouldIgnoreTextSelectorQuote = () => {
|
||||
const prefix = selector.substring(start, index);
|
||||
const match = prefix.match(/^\s*text\s*=(.*)$/);
|
||||
// Must be a text selector with some text before the quote.
|
||||
return !!match && !!match[1];
|
||||
};
|
||||
while (index < selector.length) {
|
||||
const c = selector[index];
|
||||
if (c === '\\' && index + 1 < selector.length) {
|
||||
index += 2;
|
||||
} else if (c === quote) {
|
||||
quote = undefined;
|
||||
index++;
|
||||
} else if (!quote && (c === '"' || c === '\'' || c === '`') && !shouldIgnoreTextSelectorQuote()) {
|
||||
quote = c;
|
||||
index++;
|
||||
} else if (!quote && c === '>' && selector[index + 1] === '>') {
|
||||
append();
|
||||
index += 2;
|
||||
start = index;
|
||||
} else {
|
||||
index++;
|
||||
}
|
||||
}
|
||||
append();
|
||||
return result;
|
||||
}
|
||||
function parseAttributeSelector(selector, allowUnquotedStrings) {
|
||||
let wp = 0;
|
||||
let EOL = selector.length === 0;
|
||||
const next = () => selector[wp] || '';
|
||||
const eat1 = () => {
|
||||
const result = next();
|
||||
++wp;
|
||||
EOL = wp >= selector.length;
|
||||
return result;
|
||||
};
|
||||
const syntaxError = stage => {
|
||||
if (EOL) throw new _cssParser.InvalidSelectorError(`Unexpected end of selector while parsing selector \`${selector}\``);
|
||||
throw new _cssParser.InvalidSelectorError(`Error while parsing selector \`${selector}\` - unexpected symbol "${next()}" at position ${wp}` + (stage ? ' during ' + stage : ''));
|
||||
};
|
||||
function skipSpaces() {
|
||||
while (!EOL && /\s/.test(next())) eat1();
|
||||
}
|
||||
function isCSSNameChar(char) {
|
||||
// https://www.w3.org/TR/css-syntax-3/#ident-token-diagram
|
||||
return char >= '\u0080' // non-ascii
|
||||
|| char >= '\u0030' && char <= '\u0039' // digit
|
||||
|| char >= '\u0041' && char <= '\u005a' // uppercase letter
|
||||
|| char >= '\u0061' && char <= '\u007a' // lowercase letter
|
||||
|| char >= '\u0030' && char <= '\u0039' // digit
|
||||
|| char === '\u005f' // "_"
|
||||
|| char === '\u002d'; // "-"
|
||||
}
|
||||
function readIdentifier() {
|
||||
let result = '';
|
||||
skipSpaces();
|
||||
while (!EOL && isCSSNameChar(next())) result += eat1();
|
||||
return result;
|
||||
}
|
||||
function readQuotedString(quote) {
|
||||
let result = eat1();
|
||||
if (result !== quote) syntaxError('parsing quoted string');
|
||||
while (!EOL && next() !== quote) {
|
||||
if (next() === '\\') eat1();
|
||||
result += eat1();
|
||||
}
|
||||
if (next() !== quote) syntaxError('parsing quoted string');
|
||||
result += eat1();
|
||||
return result;
|
||||
}
|
||||
function readRegularExpression() {
|
||||
if (eat1() !== '/') syntaxError('parsing regular expression');
|
||||
let source = '';
|
||||
let inClass = false;
|
||||
// https://262.ecma-international.org/11.0/#sec-literals-regular-expression-literals
|
||||
while (!EOL) {
|
||||
if (next() === '\\') {
|
||||
source += eat1();
|
||||
if (EOL) syntaxError('parsing regular expression');
|
||||
} else if (inClass && next() === ']') {
|
||||
inClass = false;
|
||||
} else if (!inClass && next() === '[') {
|
||||
inClass = true;
|
||||
} else if (!inClass && next() === '/') {
|
||||
break;
|
||||
}
|
||||
source += eat1();
|
||||
}
|
||||
if (eat1() !== '/') syntaxError('parsing regular expression');
|
||||
let flags = '';
|
||||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions
|
||||
while (!EOL && next().match(/[dgimsuy]/)) flags += eat1();
|
||||
try {
|
||||
return new RegExp(source, flags);
|
||||
} catch (e) {
|
||||
throw new _cssParser.InvalidSelectorError(`Error while parsing selector \`${selector}\`: ${e.message}`);
|
||||
}
|
||||
}
|
||||
function readAttributeToken() {
|
||||
let token = '';
|
||||
skipSpaces();
|
||||
if (next() === `'` || next() === `"`) token = readQuotedString(next()).slice(1, -1);else token = readIdentifier();
|
||||
if (!token) syntaxError('parsing property path');
|
||||
return token;
|
||||
}
|
||||
function readOperator() {
|
||||
skipSpaces();
|
||||
let op = '';
|
||||
if (!EOL) op += eat1();
|
||||
if (!EOL && op !== '=') op += eat1();
|
||||
if (!['=', '*=', '^=', '$=', '|=', '~='].includes(op)) syntaxError('parsing operator');
|
||||
return op;
|
||||
}
|
||||
function readAttribute() {
|
||||
// skip leading [
|
||||
eat1();
|
||||
|
||||
// read attribute name:
|
||||
// foo.bar
|
||||
// 'foo' . "ba zz"
|
||||
const jsonPath = [];
|
||||
jsonPath.push(readAttributeToken());
|
||||
skipSpaces();
|
||||
while (next() === '.') {
|
||||
eat1();
|
||||
jsonPath.push(readAttributeToken());
|
||||
skipSpaces();
|
||||
}
|
||||
// check property is truthy: [enabled]
|
||||
if (next() === ']') {
|
||||
eat1();
|
||||
return {
|
||||
name: jsonPath.join('.'),
|
||||
jsonPath,
|
||||
op: '<truthy>',
|
||||
value: null,
|
||||
caseSensitive: false
|
||||
};
|
||||
}
|
||||
const operator = readOperator();
|
||||
let value = undefined;
|
||||
let caseSensitive = true;
|
||||
skipSpaces();
|
||||
if (next() === '/') {
|
||||
if (operator !== '=') throw new _cssParser.InvalidSelectorError(`Error while parsing selector \`${selector}\` - cannot use ${operator} in attribute with regular expression`);
|
||||
value = readRegularExpression();
|
||||
} else if (next() === `'` || next() === `"`) {
|
||||
value = readQuotedString(next()).slice(1, -1);
|
||||
skipSpaces();
|
||||
if (next() === 'i' || next() === 'I') {
|
||||
caseSensitive = false;
|
||||
eat1();
|
||||
} else if (next() === 's' || next() === 'S') {
|
||||
caseSensitive = true;
|
||||
eat1();
|
||||
}
|
||||
} else {
|
||||
value = '';
|
||||
while (!EOL && (isCSSNameChar(next()) || next() === '+' || next() === '.')) value += eat1();
|
||||
if (value === 'true') {
|
||||
value = true;
|
||||
} else if (value === 'false') {
|
||||
value = false;
|
||||
} else {
|
||||
if (!allowUnquotedStrings) {
|
||||
value = +value;
|
||||
if (Number.isNaN(value)) syntaxError('parsing attribute value');
|
||||
}
|
||||
}
|
||||
}
|
||||
skipSpaces();
|
||||
if (next() !== ']') syntaxError('parsing attribute value');
|
||||
eat1();
|
||||
if (operator !== '=' && typeof value !== 'string') throw new _cssParser.InvalidSelectorError(`Error while parsing selector \`${selector}\` - cannot use ${operator} in attribute with non-string matching value - ${value}`);
|
||||
return {
|
||||
name: jsonPath.join('.'),
|
||||
jsonPath,
|
||||
op: operator,
|
||||
value,
|
||||
caseSensitive
|
||||
};
|
||||
}
|
||||
const result = {
|
||||
name: '',
|
||||
attributes: []
|
||||
};
|
||||
result.name = readIdentifier();
|
||||
skipSpaces();
|
||||
while (next() === '[') {
|
||||
result.attributes.push(readAttribute());
|
||||
skipSpaces();
|
||||
}
|
||||
if (!EOL) syntaxError(undefined);
|
||||
if (!result.name && !result.attributes.length) throw new _cssParser.InvalidSelectorError(`Error while parsing selector \`${selector}\` - selector cannot be empty`);
|
||||
return result;
|
||||
}
|
||||
169
node_modules/playwright-core/lib/utils/isomorphic/stringUtils.js
generated
vendored
Normal file
169
node_modules/playwright-core/lib/utils/isomorphic/stringUtils.js
generated
vendored
Normal file
@@ -0,0 +1,169 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.cacheNormalizedWhitespaces = cacheNormalizedWhitespaces;
|
||||
exports.cssEscape = cssEscape;
|
||||
exports.escapeForAttributeSelector = escapeForAttributeSelector;
|
||||
exports.escapeForTextSelector = escapeForTextSelector;
|
||||
exports.escapeHTML = escapeHTML;
|
||||
exports.escapeHTMLAttribute = escapeHTMLAttribute;
|
||||
exports.escapeRegExp = escapeRegExp;
|
||||
exports.escapeTemplateString = escapeTemplateString;
|
||||
exports.escapeWithQuotes = escapeWithQuotes;
|
||||
exports.isString = isString;
|
||||
exports.longestCommonSubstring = longestCommonSubstring;
|
||||
exports.normalizeEscapedRegexQuotes = normalizeEscapedRegexQuotes;
|
||||
exports.normalizeWhiteSpace = normalizeWhiteSpace;
|
||||
exports.quoteCSSAttributeValue = quoteCSSAttributeValue;
|
||||
exports.toSnakeCase = toSnakeCase;
|
||||
exports.toTitleCase = toTitleCase;
|
||||
exports.trimString = trimString;
|
||||
exports.trimStringWithEllipsis = trimStringWithEllipsis;
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// NOTE: this function should not be used to escape any selectors.
|
||||
function escapeWithQuotes(text, char = '\'') {
|
||||
const stringified = JSON.stringify(text);
|
||||
const escapedText = stringified.substring(1, stringified.length - 1).replace(/\\"/g, '"');
|
||||
if (char === '\'') return char + escapedText.replace(/[']/g, '\\\'') + char;
|
||||
if (char === '"') return char + escapedText.replace(/["]/g, '\\"') + char;
|
||||
if (char === '`') return char + escapedText.replace(/[`]/g, '`') + char;
|
||||
throw new Error('Invalid escape char');
|
||||
}
|
||||
function escapeTemplateString(text) {
|
||||
return text.replace(/\\/g, '\\\\').replace(/`/g, '\\`').replace(/\$\{/g, '\\${');
|
||||
}
|
||||
function isString(obj) {
|
||||
return typeof obj === 'string' || obj instanceof String;
|
||||
}
|
||||
function toTitleCase(name) {
|
||||
return name.charAt(0).toUpperCase() + name.substring(1);
|
||||
}
|
||||
function toSnakeCase(name) {
|
||||
// E.g. ignoreHTTPSErrors => ignore_https_errors.
|
||||
return name.replace(/([a-z0-9])([A-Z])/g, '$1_$2').replace(/([A-Z])([A-Z][a-z])/g, '$1_$2').toLowerCase();
|
||||
}
|
||||
function cssEscape(s) {
|
||||
let result = '';
|
||||
for (let i = 0; i < s.length; i++) result += cssEscapeOne(s, i);
|
||||
return result;
|
||||
}
|
||||
function quoteCSSAttributeValue(text) {
|
||||
return `"${cssEscape(text).replace(/\\ /g, ' ')}"`;
|
||||
}
|
||||
function cssEscapeOne(s, i) {
|
||||
// https://drafts.csswg.org/cssom/#serialize-an-identifier
|
||||
const c = s.charCodeAt(i);
|
||||
if (c === 0x0000) return '\uFFFD';
|
||||
if (c >= 0x0001 && c <= 0x001f || c >= 0x0030 && c <= 0x0039 && (i === 0 || i === 1 && s.charCodeAt(0) === 0x002d)) return '\\' + c.toString(16) + ' ';
|
||||
if (i === 0 && c === 0x002d && s.length === 1) return '\\' + s.charAt(i);
|
||||
if (c >= 0x0080 || c === 0x002d || c === 0x005f || c >= 0x0030 && c <= 0x0039 || c >= 0x0041 && c <= 0x005a || c >= 0x0061 && c <= 0x007a) return s.charAt(i);
|
||||
return '\\' + s.charAt(i);
|
||||
}
|
||||
let normalizedWhitespaceCache;
|
||||
function cacheNormalizedWhitespaces() {
|
||||
normalizedWhitespaceCache = new Map();
|
||||
}
|
||||
function normalizeWhiteSpace(text) {
|
||||
var _normalizedWhitespace;
|
||||
let result = (_normalizedWhitespace = normalizedWhitespaceCache) === null || _normalizedWhitespace === void 0 ? void 0 : _normalizedWhitespace.get(text);
|
||||
if (result === undefined) {
|
||||
var _normalizedWhitespace2;
|
||||
result = text.replace(/\u200b/g, '').trim().replace(/\s+/g, ' ');
|
||||
(_normalizedWhitespace2 = normalizedWhitespaceCache) === null || _normalizedWhitespace2 === void 0 || _normalizedWhitespace2.set(text, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
function normalizeEscapedRegexQuotes(source) {
|
||||
// This function reverses the effect of escapeRegexForSelector below.
|
||||
// Odd number of backslashes followed by the quote -> remove unneeded backslash.
|
||||
return source.replace(/(^|[^\\])(\\\\)*\\(['"`])/g, '$1$2$3');
|
||||
}
|
||||
function escapeRegexForSelector(re) {
|
||||
// Unicode mode does not allow "identity character escapes", so we do not escape and
|
||||
// hope that it does not contain quotes and/or >> signs.
|
||||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Regular_expressions/Character_escape
|
||||
// TODO: rework RE usages in internal selectors away from literal representation to json, e.g. {source,flags}.
|
||||
if (re.unicode || re.unicodeSets) return String(re);
|
||||
// Even number of backslashes followed by the quote -> insert a backslash.
|
||||
return String(re).replace(/(^|[^\\])(\\\\)*(["'`])/g, '$1$2\\$3').replace(/>>/g, '\\>\\>');
|
||||
}
|
||||
function escapeForTextSelector(text, exact) {
|
||||
if (typeof text !== 'string') return escapeRegexForSelector(text);
|
||||
return `${JSON.stringify(text)}${exact ? 's' : 'i'}`;
|
||||
}
|
||||
function escapeForAttributeSelector(value, exact) {
|
||||
if (typeof value !== 'string') return escapeRegexForSelector(value);
|
||||
// TODO: this should actually be
|
||||
// cssEscape(value).replace(/\\ /g, ' ')
|
||||
// However, our attribute selectors do not conform to CSS parsing spec,
|
||||
// so we escape them differently.
|
||||
return `"${value.replace(/\\/g, '\\\\').replace(/["]/g, '\\"')}"${exact ? 's' : 'i'}`;
|
||||
}
|
||||
function trimString(input, cap, suffix = '') {
|
||||
if (input.length <= cap) return input;
|
||||
const chars = [...input];
|
||||
if (chars.length > cap) return chars.slice(0, cap - suffix.length).join('') + suffix;
|
||||
return chars.join('');
|
||||
}
|
||||
function trimStringWithEllipsis(input, cap) {
|
||||
return trimString(input, cap, '\u2026');
|
||||
}
|
||||
function escapeRegExp(s) {
|
||||
// From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping
|
||||
return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
|
||||
}
|
||||
const escaped = {
|
||||
'&': '&',
|
||||
'<': '<',
|
||||
'>': '>',
|
||||
'"': '"',
|
||||
'\'': '''
|
||||
};
|
||||
function escapeHTMLAttribute(s) {
|
||||
return s.replace(/[&<>"']/ug, char => escaped[char]);
|
||||
}
|
||||
function escapeHTML(s) {
|
||||
return s.replace(/[&<]/ug, char => escaped[char]);
|
||||
}
|
||||
function longestCommonSubstring(s1, s2) {
|
||||
const n = s1.length;
|
||||
const m = s2.length;
|
||||
let maxLen = 0;
|
||||
let endingIndex = 0;
|
||||
|
||||
// Initialize a 2D array with zeros
|
||||
const dp = Array(n + 1).fill(null).map(() => Array(m + 1).fill(0));
|
||||
|
||||
// Build the dp table
|
||||
for (let i = 1; i <= n; i++) {
|
||||
for (let j = 1; j <= m; j++) {
|
||||
if (s1[i - 1] === s2[j - 1]) {
|
||||
dp[i][j] = dp[i - 1][j - 1] + 1;
|
||||
if (dp[i][j] > maxLen) {
|
||||
maxLen = dp[i][j];
|
||||
endingIndex = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Extract the longest common substring
|
||||
return s1.slice(endingIndex - maxLen, endingIndex);
|
||||
}
|
||||
39
node_modules/playwright-core/lib/utils/isomorphic/traceUtils.js
generated
vendored
Normal file
39
node_modules/playwright-core/lib/utils/isomorphic/traceUtils.js
generated
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.parseClientSideCallMetadata = parseClientSideCallMetadata;
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
function parseClientSideCallMetadata(data) {
|
||||
const result = new Map();
|
||||
const {
|
||||
files,
|
||||
stacks
|
||||
} = data;
|
||||
for (const s of stacks) {
|
||||
const [id, ff] = s;
|
||||
result.set(`call@${id}`, ff.map(f => ({
|
||||
file: files[f[0]],
|
||||
line: f[1],
|
||||
column: f[2],
|
||||
function: f[3]
|
||||
})));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
124
node_modules/playwright-core/lib/utils/isomorphic/urlMatch.js
generated
vendored
Normal file
124
node_modules/playwright-core/lib/utils/isomorphic/urlMatch.js
generated
vendored
Normal file
@@ -0,0 +1,124 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.constructURLBasedOnBaseURL = constructURLBasedOnBaseURL;
|
||||
exports.globToRegex = globToRegex;
|
||||
exports.urlMatches = urlMatches;
|
||||
exports.urlMatchesEqual = urlMatchesEqual;
|
||||
var _stringUtils = require("./stringUtils");
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions#escaping
|
||||
const escapedChars = new Set(['$', '^', '+', '.', '*', '(', ')', '|', '\\', '?', '{', '}', '[', ']']);
|
||||
function globToRegex(glob) {
|
||||
const tokens = ['^'];
|
||||
let inGroup = false;
|
||||
for (let i = 0; i < glob.length; ++i) {
|
||||
const c = glob[i];
|
||||
if (c === '\\' && i + 1 < glob.length) {
|
||||
const char = glob[++i];
|
||||
tokens.push(escapedChars.has(char) ? '\\' + char : char);
|
||||
continue;
|
||||
}
|
||||
if (c === '*') {
|
||||
const beforeDeep = glob[i - 1];
|
||||
let starCount = 1;
|
||||
while (glob[i + 1] === '*') {
|
||||
starCount++;
|
||||
i++;
|
||||
}
|
||||
const afterDeep = glob[i + 1];
|
||||
const isDeep = starCount > 1 && (beforeDeep === '/' || beforeDeep === undefined) && (afterDeep === '/' || afterDeep === undefined);
|
||||
if (isDeep) {
|
||||
tokens.push('((?:[^/]*(?:\/|$))*)');
|
||||
i++;
|
||||
} else {
|
||||
tokens.push('([^/]*)');
|
||||
}
|
||||
continue;
|
||||
}
|
||||
switch (c) {
|
||||
case '?':
|
||||
tokens.push('.');
|
||||
break;
|
||||
case '[':
|
||||
tokens.push('[');
|
||||
break;
|
||||
case ']':
|
||||
tokens.push(']');
|
||||
break;
|
||||
case '{':
|
||||
inGroup = true;
|
||||
tokens.push('(');
|
||||
break;
|
||||
case '}':
|
||||
inGroup = false;
|
||||
tokens.push(')');
|
||||
break;
|
||||
case ',':
|
||||
if (inGroup) {
|
||||
tokens.push('|');
|
||||
break;
|
||||
}
|
||||
tokens.push('\\' + c);
|
||||
break;
|
||||
default:
|
||||
tokens.push(escapedChars.has(c) ? '\\' + c : c);
|
||||
}
|
||||
}
|
||||
tokens.push('$');
|
||||
return new RegExp(tokens.join(''));
|
||||
}
|
||||
function isRegExp(obj) {
|
||||
return obj instanceof RegExp || Object.prototype.toString.call(obj) === '[object RegExp]';
|
||||
}
|
||||
function urlMatchesEqual(match1, match2) {
|
||||
if (isRegExp(match1) && isRegExp(match2)) return match1.source === match2.source && match1.flags === match2.flags;
|
||||
return match1 === match2;
|
||||
}
|
||||
function urlMatches(baseURL, urlString, match) {
|
||||
if (match === undefined || match === '') return true;
|
||||
if ((0, _stringUtils.isString)(match) && !match.startsWith('*')) {
|
||||
// Allow http(s) baseURL to match ws(s) urls.
|
||||
if (baseURL && /^https?:\/\//.test(baseURL) && /^wss?:\/\//.test(urlString)) baseURL = baseURL.replace(/^http/, 'ws');
|
||||
match = constructURLBasedOnBaseURL(baseURL, match);
|
||||
}
|
||||
if ((0, _stringUtils.isString)(match)) match = globToRegex(match);
|
||||
if (isRegExp(match)) return match.test(urlString);
|
||||
if (typeof match === 'string' && match === urlString) return true;
|
||||
const url = parsedURL(urlString);
|
||||
if (!url) return false;
|
||||
if (typeof match === 'string') return url.pathname === match;
|
||||
if (typeof match !== 'function') throw new Error('url parameter should be string, RegExp or function');
|
||||
return match(url);
|
||||
}
|
||||
function parsedURL(url) {
|
||||
try {
|
||||
return new URL(url);
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
function constructURLBasedOnBaseURL(baseURL, givenURL) {
|
||||
try {
|
||||
return new URL(givenURL, baseURL).toString();
|
||||
} catch (e) {
|
||||
return givenURL;
|
||||
}
|
||||
}
|
||||
78
node_modules/playwright-core/lib/utils/linuxUtils.js
generated
vendored
Normal file
78
node_modules/playwright-core/lib/utils/linuxUtils.js
generated
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.getLinuxDistributionInfo = getLinuxDistributionInfo;
|
||||
exports.getLinuxDistributionInfoSync = getLinuxDistributionInfoSync;
|
||||
var _fs = _interopRequireDefault(require("fs"));
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
/**
|
||||
* Copyright 2017 Google Inc. All rights reserved.
|
||||
* Modifications copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
let didFailToReadOSRelease = false;
|
||||
let osRelease;
|
||||
async function getLinuxDistributionInfo() {
|
||||
if (process.platform !== 'linux') return undefined;
|
||||
if (!osRelease && !didFailToReadOSRelease) {
|
||||
try {
|
||||
var _fields$get, _fields$get2;
|
||||
// List of /etc/os-release values for different distributions could be
|
||||
// found here: https://gist.github.com/aslushnikov/8ceddb8288e4cf9db3039c02e0f4fb75
|
||||
const osReleaseText = await _fs.default.promises.readFile('/etc/os-release', 'utf8');
|
||||
const fields = parseOSReleaseText(osReleaseText);
|
||||
osRelease = {
|
||||
id: (_fields$get = fields.get('id')) !== null && _fields$get !== void 0 ? _fields$get : '',
|
||||
version: (_fields$get2 = fields.get('version_id')) !== null && _fields$get2 !== void 0 ? _fields$get2 : ''
|
||||
};
|
||||
} catch (e) {
|
||||
didFailToReadOSRelease = true;
|
||||
}
|
||||
}
|
||||
return osRelease;
|
||||
}
|
||||
function getLinuxDistributionInfoSync() {
|
||||
if (process.platform !== 'linux') return undefined;
|
||||
if (!osRelease && !didFailToReadOSRelease) {
|
||||
try {
|
||||
var _fields$get3, _fields$get4;
|
||||
// List of /etc/os-release values for different distributions could be
|
||||
// found here: https://gist.github.com/aslushnikov/8ceddb8288e4cf9db3039c02e0f4fb75
|
||||
const osReleaseText = _fs.default.readFileSync('/etc/os-release', 'utf8');
|
||||
const fields = parseOSReleaseText(osReleaseText);
|
||||
osRelease = {
|
||||
id: (_fields$get3 = fields.get('id')) !== null && _fields$get3 !== void 0 ? _fields$get3 : '',
|
||||
version: (_fields$get4 = fields.get('version_id')) !== null && _fields$get4 !== void 0 ? _fields$get4 : ''
|
||||
};
|
||||
} catch (e) {
|
||||
didFailToReadOSRelease = true;
|
||||
}
|
||||
}
|
||||
return osRelease;
|
||||
}
|
||||
function parseOSReleaseText(osReleaseText) {
|
||||
const fields = new Map();
|
||||
for (const line of osReleaseText.split('\n')) {
|
||||
const tokens = line.split('=');
|
||||
const name = tokens.shift();
|
||||
let value = tokens.join('=').trim();
|
||||
if (value.startsWith('"') && value.endsWith('"')) value = value.substring(1, value.length - 1);
|
||||
if (!name) continue;
|
||||
fields.set(name.toLowerCase(), value);
|
||||
}
|
||||
return fields;
|
||||
}
|
||||
109
node_modules/playwright-core/lib/utils/manualPromise.js
generated
vendored
Normal file
109
node_modules/playwright-core/lib/utils/manualPromise.js
generated
vendored
Normal file
@@ -0,0 +1,109 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.ManualPromise = exports.LongStandingScope = void 0;
|
||||
var _stackTrace = require("./stackTrace");
|
||||
let _Symbol$species, _Symbol$toStringTag;
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
_Symbol$species = Symbol.species;
|
||||
_Symbol$toStringTag = Symbol.toStringTag;
|
||||
class ManualPromise extends Promise {
|
||||
constructor() {
|
||||
let resolve;
|
||||
let reject;
|
||||
super((f, r) => {
|
||||
resolve = f;
|
||||
reject = r;
|
||||
});
|
||||
this._resolve = void 0;
|
||||
this._reject = void 0;
|
||||
this._isDone = void 0;
|
||||
this._isDone = false;
|
||||
this._resolve = resolve;
|
||||
this._reject = reject;
|
||||
}
|
||||
isDone() {
|
||||
return this._isDone;
|
||||
}
|
||||
resolve(t) {
|
||||
this._isDone = true;
|
||||
this._resolve(t);
|
||||
}
|
||||
reject(e) {
|
||||
this._isDone = true;
|
||||
this._reject(e);
|
||||
}
|
||||
static get [_Symbol$species]() {
|
||||
return Promise;
|
||||
}
|
||||
get [_Symbol$toStringTag]() {
|
||||
return 'ManualPromise';
|
||||
}
|
||||
}
|
||||
exports.ManualPromise = ManualPromise;
|
||||
class LongStandingScope {
|
||||
constructor() {
|
||||
this._terminateError = void 0;
|
||||
this._closeError = void 0;
|
||||
this._terminatePromises = new Map();
|
||||
this._isClosed = false;
|
||||
}
|
||||
reject(error) {
|
||||
this._isClosed = true;
|
||||
this._terminateError = error;
|
||||
for (const p of this._terminatePromises.keys()) p.resolve(error);
|
||||
}
|
||||
close(error) {
|
||||
this._isClosed = true;
|
||||
this._closeError = error;
|
||||
for (const [p, frames] of this._terminatePromises) p.resolve(cloneError(error, frames));
|
||||
}
|
||||
isClosed() {
|
||||
return this._isClosed;
|
||||
}
|
||||
static async raceMultiple(scopes, promise) {
|
||||
return Promise.race(scopes.map(s => s.race(promise)));
|
||||
}
|
||||
async race(promise) {
|
||||
return this._race(Array.isArray(promise) ? promise : [promise], false);
|
||||
}
|
||||
async safeRace(promise, defaultValue) {
|
||||
return this._race([promise], true, defaultValue);
|
||||
}
|
||||
async _race(promises, safe, defaultValue) {
|
||||
const terminatePromise = new ManualPromise();
|
||||
const frames = (0, _stackTrace.captureRawStack)();
|
||||
if (this._terminateError) terminatePromise.resolve(this._terminateError);
|
||||
if (this._closeError) terminatePromise.resolve(cloneError(this._closeError, frames));
|
||||
this._terminatePromises.set(terminatePromise, frames);
|
||||
try {
|
||||
return await Promise.race([terminatePromise.then(e => safe ? defaultValue : Promise.reject(e)), ...promises]);
|
||||
} finally {
|
||||
this._terminatePromises.delete(terminatePromise);
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.LongStandingScope = LongStandingScope;
|
||||
function cloneError(error, frames) {
|
||||
const clone = new Error();
|
||||
clone.name = error.name;
|
||||
clone.message = error.message;
|
||||
clone.stack = [error.name + ':' + error.message, ...frames].join('\n');
|
||||
return clone;
|
||||
}
|
||||
75
node_modules/playwright-core/lib/utils/multimap.js
generated
vendored
Normal file
75
node_modules/playwright-core/lib/utils/multimap.js
generated
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.MultiMap = void 0;
|
||||
let _Symbol$iterator;
|
||||
_Symbol$iterator = Symbol.iterator;
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
class MultiMap {
|
||||
constructor() {
|
||||
this._map = void 0;
|
||||
this._map = new Map();
|
||||
}
|
||||
set(key, value) {
|
||||
let values = this._map.get(key);
|
||||
if (!values) {
|
||||
values = [];
|
||||
this._map.set(key, values);
|
||||
}
|
||||
values.push(value);
|
||||
}
|
||||
get(key) {
|
||||
return this._map.get(key) || [];
|
||||
}
|
||||
has(key) {
|
||||
return this._map.has(key);
|
||||
}
|
||||
delete(key, value) {
|
||||
const values = this._map.get(key);
|
||||
if (!values) return;
|
||||
if (values.includes(value)) this._map.set(key, values.filter(v => value !== v));
|
||||
}
|
||||
deleteAll(key) {
|
||||
this._map.delete(key);
|
||||
}
|
||||
hasValue(key, value) {
|
||||
const values = this._map.get(key);
|
||||
if (!values) return false;
|
||||
return values.includes(value);
|
||||
}
|
||||
get size() {
|
||||
return this._map.size;
|
||||
}
|
||||
[_Symbol$iterator]() {
|
||||
return this._map[Symbol.iterator]();
|
||||
}
|
||||
keys() {
|
||||
return this._map.keys();
|
||||
}
|
||||
values() {
|
||||
const result = [];
|
||||
for (const key of this.keys()) result.push(...this.get(key));
|
||||
return result;
|
||||
}
|
||||
clear() {
|
||||
this._map.clear();
|
||||
}
|
||||
}
|
||||
exports.MultiMap = MultiMap;
|
||||
160
node_modules/playwright-core/lib/utils/network.js
generated
vendored
Normal file
160
node_modules/playwright-core/lib/utils/network.js
generated
vendored
Normal file
@@ -0,0 +1,160 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.NET_DEFAULT_TIMEOUT = void 0;
|
||||
exports.createHttp2Server = createHttp2Server;
|
||||
exports.createHttpServer = createHttpServer;
|
||||
exports.createHttpsServer = createHttpsServer;
|
||||
exports.fetchData = fetchData;
|
||||
exports.httpRequest = httpRequest;
|
||||
exports.isURLAvailable = isURLAvailable;
|
||||
var _http = _interopRequireDefault(require("http"));
|
||||
var _https = _interopRequireDefault(require("https"));
|
||||
var _http2 = _interopRequireDefault(require("http2"));
|
||||
var _utilsBundle = require("../utilsBundle");
|
||||
var _url = _interopRequireDefault(require("url"));
|
||||
var _happyEyeballs = require("./happy-eyeballs");
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
const NET_DEFAULT_TIMEOUT = exports.NET_DEFAULT_TIMEOUT = 30_000;
|
||||
function httpRequest(params, onResponse, onError) {
|
||||
var _params$timeout;
|
||||
const parsedUrl = _url.default.parse(params.url);
|
||||
let options = {
|
||||
...parsedUrl,
|
||||
agent: parsedUrl.protocol === 'https:' ? _happyEyeballs.httpsHappyEyeballsAgent : _happyEyeballs.httpHappyEyeballsAgent,
|
||||
method: params.method || 'GET',
|
||||
headers: params.headers
|
||||
};
|
||||
if (params.rejectUnauthorized !== undefined) options.rejectUnauthorized = params.rejectUnauthorized;
|
||||
const timeout = (_params$timeout = params.timeout) !== null && _params$timeout !== void 0 ? _params$timeout : NET_DEFAULT_TIMEOUT;
|
||||
const proxyURL = (0, _utilsBundle.getProxyForUrl)(params.url);
|
||||
if (proxyURL) {
|
||||
const parsedProxyURL = new URL(proxyURL);
|
||||
if (params.url.startsWith('http:')) {
|
||||
options = {
|
||||
path: parsedUrl.href,
|
||||
host: parsedProxyURL.hostname,
|
||||
port: parsedProxyURL.port,
|
||||
headers: options.headers,
|
||||
method: options.method
|
||||
};
|
||||
} else {
|
||||
parsedProxyURL.secureProxy = parsedProxyURL.protocol === 'https:';
|
||||
options.agent = new _utilsBundle.HttpsProxyAgent(parsedProxyURL);
|
||||
options.rejectUnauthorized = false;
|
||||
}
|
||||
}
|
||||
const requestCallback = res => {
|
||||
const statusCode = res.statusCode || 0;
|
||||
if (statusCode >= 300 && statusCode < 400 && res.headers.location) httpRequest({
|
||||
...params,
|
||||
url: new URL(res.headers.location, params.url).toString()
|
||||
}, onResponse, onError);else onResponse(res);
|
||||
};
|
||||
const request = options.protocol === 'https:' ? _https.default.request(options, requestCallback) : _http.default.request(options, requestCallback);
|
||||
request.on('error', onError);
|
||||
if (timeout !== undefined) {
|
||||
const rejectOnTimeout = () => {
|
||||
onError(new Error(`Request to ${params.url} timed out after ${timeout}ms`));
|
||||
request.abort();
|
||||
};
|
||||
if (timeout <= 0) {
|
||||
rejectOnTimeout();
|
||||
return;
|
||||
}
|
||||
request.setTimeout(timeout, rejectOnTimeout);
|
||||
}
|
||||
request.end(params.data);
|
||||
}
|
||||
function fetchData(params, onError) {
|
||||
return new Promise((resolve, reject) => {
|
||||
httpRequest(params, async response => {
|
||||
if (response.statusCode !== 200) {
|
||||
const error = onError ? await onError(params, response) : new Error(`fetch failed: server returned code ${response.statusCode}. URL: ${params.url}`);
|
||||
reject(error);
|
||||
return;
|
||||
}
|
||||
let body = '';
|
||||
response.on('data', chunk => body += chunk);
|
||||
response.on('error', error => reject(error));
|
||||
response.on('end', () => resolve(body));
|
||||
}, reject);
|
||||
});
|
||||
}
|
||||
function createHttpServer(...args) {
|
||||
const server = _http.default.createServer(...args);
|
||||
decorateServer(server);
|
||||
return server;
|
||||
}
|
||||
function createHttpsServer(...args) {
|
||||
const server = _https.default.createServer(...args);
|
||||
decorateServer(server);
|
||||
return server;
|
||||
}
|
||||
function createHttp2Server(...args) {
|
||||
const server = _http2.default.createSecureServer(...args);
|
||||
decorateServer(server);
|
||||
return server;
|
||||
}
|
||||
async function isURLAvailable(url, ignoreHTTPSErrors, onLog, onStdErr) {
|
||||
let statusCode = await httpStatusCode(url, ignoreHTTPSErrors, onLog, onStdErr);
|
||||
if (statusCode === 404 && url.pathname === '/') {
|
||||
const indexUrl = new URL(url);
|
||||
indexUrl.pathname = '/index.html';
|
||||
statusCode = await httpStatusCode(indexUrl, ignoreHTTPSErrors, onLog, onStdErr);
|
||||
}
|
||||
return statusCode >= 200 && statusCode < 404;
|
||||
}
|
||||
async function httpStatusCode(url, ignoreHTTPSErrors, onLog, onStdErr) {
|
||||
return new Promise(resolve => {
|
||||
onLog === null || onLog === void 0 || onLog(`HTTP GET: ${url}`);
|
||||
httpRequest({
|
||||
url: url.toString(),
|
||||
headers: {
|
||||
Accept: '*/*'
|
||||
},
|
||||
rejectUnauthorized: !ignoreHTTPSErrors
|
||||
}, res => {
|
||||
var _res$statusCode;
|
||||
res.resume();
|
||||
const statusCode = (_res$statusCode = res.statusCode) !== null && _res$statusCode !== void 0 ? _res$statusCode : 0;
|
||||
onLog === null || onLog === void 0 || onLog(`HTTP Status: ${statusCode}`);
|
||||
resolve(statusCode);
|
||||
}, error => {
|
||||
if (error.code === 'DEPTH_ZERO_SELF_SIGNED_CERT') onStdErr === null || onStdErr === void 0 || onStdErr(`[WebServer] Self-signed certificate detected. Try adding ignoreHTTPSErrors: true to config.webServer.`);
|
||||
onLog === null || onLog === void 0 || onLog(`Error while checking if ${url} is available: ${error.message}`);
|
||||
resolve(0);
|
||||
});
|
||||
});
|
||||
}
|
||||
function decorateServer(server) {
|
||||
const sockets = new Set();
|
||||
server.on('connection', socket => {
|
||||
sockets.add(socket);
|
||||
socket.once('close', () => sockets.delete(socket));
|
||||
});
|
||||
const close = server.close;
|
||||
server.close = callback => {
|
||||
for (const socket of sockets) socket.destroy();
|
||||
sockets.clear();
|
||||
return close.call(server, callback);
|
||||
};
|
||||
}
|
||||
248
node_modules/playwright-core/lib/utils/processLauncher.js
generated
vendored
Normal file
248
node_modules/playwright-core/lib/utils/processLauncher.js
generated
vendored
Normal file
@@ -0,0 +1,248 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.envArrayToObject = envArrayToObject;
|
||||
exports.gracefullyCloseAll = gracefullyCloseAll;
|
||||
exports.gracefullyCloseSet = void 0;
|
||||
exports.gracefullyProcessExitDoNotHang = gracefullyProcessExitDoNotHang;
|
||||
exports.launchProcess = launchProcess;
|
||||
var _fs = _interopRequireDefault(require("fs"));
|
||||
var childProcess = _interopRequireWildcard(require("child_process"));
|
||||
var readline = _interopRequireWildcard(require("readline"));
|
||||
var _ = require("./");
|
||||
var _fileUtils = require("./fileUtils");
|
||||
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
||||
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
/**
|
||||
* Copyright 2017 Google Inc. All rights reserved.
|
||||
* Modifications copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
const gracefullyCloseSet = exports.gracefullyCloseSet = new Set();
|
||||
const killSet = new Set();
|
||||
async function gracefullyCloseAll() {
|
||||
await Promise.all(Array.from(gracefullyCloseSet).map(gracefullyClose => gracefullyClose().catch(e => {})));
|
||||
}
|
||||
function gracefullyProcessExitDoNotHang(code) {
|
||||
// Force exit after 30 seconds.
|
||||
// eslint-disable-next-line no-restricted-properties
|
||||
setTimeout(() => process.exit(code), 30000);
|
||||
// Meanwhile, try to gracefully close all browsers.
|
||||
gracefullyCloseAll().then(() => {
|
||||
// eslint-disable-next-line no-restricted-properties
|
||||
process.exit(code);
|
||||
});
|
||||
}
|
||||
function exitHandler() {
|
||||
for (const kill of killSet) kill();
|
||||
}
|
||||
let sigintHandlerCalled = false;
|
||||
function sigintHandler() {
|
||||
const exitWithCode130 = () => {
|
||||
// Give tests a chance to see that launched process did exit and dispatch any async calls.
|
||||
if ((0, _.isUnderTest)()) {
|
||||
// eslint-disable-next-line no-restricted-properties
|
||||
setTimeout(() => process.exit(130), 1000);
|
||||
} else {
|
||||
// eslint-disable-next-line no-restricted-properties
|
||||
process.exit(130);
|
||||
}
|
||||
};
|
||||
if (sigintHandlerCalled) {
|
||||
// Resort to default handler from this point on, just in case we hang/stall.
|
||||
process.off('SIGINT', sigintHandler);
|
||||
|
||||
// Upon second Ctrl+C, immediately kill browsers and exit.
|
||||
// This prevents hanging in the case where closing the browser takes a lot of time or is buggy.
|
||||
for (const kill of killSet) kill();
|
||||
exitWithCode130();
|
||||
} else {
|
||||
sigintHandlerCalled = true;
|
||||
gracefullyCloseAll().then(() => exitWithCode130());
|
||||
}
|
||||
}
|
||||
function sigtermHandler() {
|
||||
gracefullyCloseAll();
|
||||
}
|
||||
function sighupHandler() {
|
||||
gracefullyCloseAll();
|
||||
}
|
||||
const installedHandlers = new Set();
|
||||
const processHandlers = {
|
||||
exit: exitHandler,
|
||||
SIGINT: sigintHandler,
|
||||
SIGTERM: sigtermHandler,
|
||||
SIGHUP: sighupHandler
|
||||
};
|
||||
function addProcessHandlerIfNeeded(name) {
|
||||
if (!installedHandlers.has(name)) {
|
||||
installedHandlers.add(name);
|
||||
process.on(name, processHandlers[name]);
|
||||
}
|
||||
}
|
||||
function removeProcessHandlersIfNeeded() {
|
||||
if (killSet.size) return;
|
||||
for (const handler of installedHandlers) process.off(handler, processHandlers[handler]);
|
||||
installedHandlers.clear();
|
||||
}
|
||||
async function launchProcess(options) {
|
||||
const stdio = options.stdio === 'pipe' ? ['ignore', 'pipe', 'pipe', 'pipe', 'pipe'] : ['pipe', 'pipe', 'pipe'];
|
||||
options.log(`<launching> ${options.command} ${options.args ? options.args.join(' ') : ''}`);
|
||||
const spawnOptions = {
|
||||
// On non-windows platforms, `detached: true` makes child process a leader of a new
|
||||
// process group, making it possible to kill child process tree with `.kill(-pid)` command.
|
||||
// @see https://nodejs.org/api/child_process.html#child_process_options_detached
|
||||
detached: process.platform !== 'win32',
|
||||
env: options.env,
|
||||
cwd: options.cwd,
|
||||
shell: options.shell,
|
||||
stdio
|
||||
};
|
||||
const spawnedProcess = childProcess.spawn(options.command, options.args || [], spawnOptions);
|
||||
const cleanup = async () => {
|
||||
options.log(`[pid=${spawnedProcess.pid || 'N/A'}] starting temporary directories cleanup`);
|
||||
const errors = await (0, _fileUtils.removeFolders)(options.tempDirectories);
|
||||
for (let i = 0; i < options.tempDirectories.length; ++i) {
|
||||
if (errors[i]) options.log(`[pid=${spawnedProcess.pid || 'N/A'}] exception while removing ${options.tempDirectories[i]}: ${errors[i]}`);
|
||||
}
|
||||
options.log(`[pid=${spawnedProcess.pid || 'N/A'}] finished temporary directories cleanup`);
|
||||
};
|
||||
|
||||
// Prevent Unhandled 'error' event.
|
||||
spawnedProcess.on('error', () => {});
|
||||
if (!spawnedProcess.pid) {
|
||||
let failed;
|
||||
const failedPromise = new Promise((f, r) => failed = f);
|
||||
spawnedProcess.once('error', error => {
|
||||
failed(new Error('Failed to launch: ' + error));
|
||||
});
|
||||
return cleanup().then(() => failedPromise).then(e => Promise.reject(e));
|
||||
}
|
||||
options.log(`<launched> pid=${spawnedProcess.pid}`);
|
||||
const stdout = readline.createInterface({
|
||||
input: spawnedProcess.stdout
|
||||
});
|
||||
stdout.on('line', data => {
|
||||
options.log(`[pid=${spawnedProcess.pid}][out] ` + data);
|
||||
});
|
||||
const stderr = readline.createInterface({
|
||||
input: spawnedProcess.stderr
|
||||
});
|
||||
stderr.on('line', data => {
|
||||
options.log(`[pid=${spawnedProcess.pid}][err] ` + data);
|
||||
});
|
||||
let processClosed = false;
|
||||
let fulfillCleanup = () => {};
|
||||
const waitForCleanup = new Promise(f => fulfillCleanup = f);
|
||||
spawnedProcess.once('exit', (exitCode, signal) => {
|
||||
options.log(`[pid=${spawnedProcess.pid}] <process did exit: exitCode=${exitCode}, signal=${signal}>`);
|
||||
processClosed = true;
|
||||
gracefullyCloseSet.delete(gracefullyClose);
|
||||
killSet.delete(killProcessAndCleanup);
|
||||
removeProcessHandlersIfNeeded();
|
||||
options.onExit(exitCode, signal);
|
||||
// Cleanup as process exits.
|
||||
cleanup().then(fulfillCleanup);
|
||||
});
|
||||
addProcessHandlerIfNeeded('exit');
|
||||
if (options.handleSIGINT) addProcessHandlerIfNeeded('SIGINT');
|
||||
if (options.handleSIGTERM) addProcessHandlerIfNeeded('SIGTERM');
|
||||
if (options.handleSIGHUP) addProcessHandlerIfNeeded('SIGHUP');
|
||||
gracefullyCloseSet.add(gracefullyClose);
|
||||
killSet.add(killProcessAndCleanup);
|
||||
let gracefullyClosing = false;
|
||||
async function gracefullyClose() {
|
||||
// We keep listeners until we are done, to handle 'exit' and 'SIGINT' while
|
||||
// asynchronously closing to prevent zombie processes. This might introduce
|
||||
// reentrancy to this function, for example user sends SIGINT second time.
|
||||
// In this case, let's forcefully kill the process.
|
||||
if (gracefullyClosing) {
|
||||
options.log(`[pid=${spawnedProcess.pid}] <forcefully close>`);
|
||||
killProcess();
|
||||
await waitForCleanup; // Ensure the process is dead and we have cleaned up.
|
||||
return;
|
||||
}
|
||||
gracefullyClosing = true;
|
||||
options.log(`[pid=${spawnedProcess.pid}] <gracefully close start>`);
|
||||
await options.attemptToGracefullyClose().catch(() => killProcess());
|
||||
await waitForCleanup; // Ensure the process is dead and we have cleaned up.
|
||||
options.log(`[pid=${spawnedProcess.pid}] <gracefully close end>`);
|
||||
}
|
||||
|
||||
// This method has to be sync to be used in the 'exit' event handler.
|
||||
function killProcess() {
|
||||
gracefullyCloseSet.delete(gracefullyClose);
|
||||
killSet.delete(killProcessAndCleanup);
|
||||
removeProcessHandlersIfNeeded();
|
||||
options.log(`[pid=${spawnedProcess.pid}] <kill>`);
|
||||
if (spawnedProcess.pid && !spawnedProcess.killed && !processClosed) {
|
||||
options.log(`[pid=${spawnedProcess.pid}] <will force kill>`);
|
||||
// Force kill the browser.
|
||||
try {
|
||||
if (process.platform === 'win32') {
|
||||
const taskkillProcess = childProcess.spawnSync(`taskkill /pid ${spawnedProcess.pid} /T /F`, {
|
||||
shell: true
|
||||
});
|
||||
const [stdout, stderr] = [taskkillProcess.stdout.toString(), taskkillProcess.stderr.toString()];
|
||||
if (stdout) options.log(`[pid=${spawnedProcess.pid}] taskkill stdout: ${stdout}`);
|
||||
if (stderr) options.log(`[pid=${spawnedProcess.pid}] taskkill stderr: ${stderr}`);
|
||||
} else {
|
||||
process.kill(-spawnedProcess.pid, 'SIGKILL');
|
||||
}
|
||||
} catch (e) {
|
||||
options.log(`[pid=${spawnedProcess.pid}] exception while trying to kill process: ${e}`);
|
||||
// the process might have already stopped
|
||||
}
|
||||
} else {
|
||||
options.log(`[pid=${spawnedProcess.pid}] <skipped force kill spawnedProcess.killed=${spawnedProcess.killed} processClosed=${processClosed}>`);
|
||||
}
|
||||
}
|
||||
function killProcessAndCleanup() {
|
||||
killProcess();
|
||||
options.log(`[pid=${spawnedProcess.pid || 'N/A'}] starting temporary directories cleanup`);
|
||||
for (const dir of options.tempDirectories) {
|
||||
try {
|
||||
_fs.default.rmSync(dir, {
|
||||
force: true,
|
||||
recursive: true,
|
||||
maxRetries: 5
|
||||
});
|
||||
} catch (e) {
|
||||
options.log(`[pid=${spawnedProcess.pid || 'N/A'}] exception while removing ${dir}: ${e}`);
|
||||
}
|
||||
}
|
||||
options.log(`[pid=${spawnedProcess.pid || 'N/A'}] finished temporary directories cleanup`);
|
||||
}
|
||||
function killAndWait() {
|
||||
killProcess();
|
||||
return waitForCleanup;
|
||||
}
|
||||
return {
|
||||
launchedProcess: spawnedProcess,
|
||||
gracefullyClose,
|
||||
kill: killAndWait
|
||||
};
|
||||
}
|
||||
function envArrayToObject(env) {
|
||||
const result = {};
|
||||
for (const {
|
||||
name,
|
||||
value
|
||||
} of env) result[name] = value;
|
||||
return result;
|
||||
}
|
||||
53
node_modules/playwright-core/lib/utils/profiler.js
generated
vendored
Normal file
53
node_modules/playwright-core/lib/utils/profiler.js
generated
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.startProfiling = startProfiling;
|
||||
exports.stopProfiling = stopProfiling;
|
||||
var fs = _interopRequireWildcard(require("fs"));
|
||||
var path = _interopRequireWildcard(require("path"));
|
||||
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
||||
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
||||
/**
|
||||
* Copyright Microsoft Corporation. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
const profileDir = process.env.PWTEST_PROFILE_DIR || '';
|
||||
let session;
|
||||
async function startProfiling() {
|
||||
if (!profileDir) return;
|
||||
session = new (require('inspector').Session)();
|
||||
session.connect();
|
||||
await new Promise(f => {
|
||||
session.post('Profiler.enable', () => {
|
||||
session.post('Profiler.start', f);
|
||||
});
|
||||
});
|
||||
}
|
||||
async function stopProfiling(profileName) {
|
||||
if (!profileDir) return;
|
||||
await new Promise(f => session.post('Profiler.stop', (err, {
|
||||
profile
|
||||
}) => {
|
||||
if (!err) {
|
||||
fs.mkdirSync(profileDir, {
|
||||
recursive: true
|
||||
});
|
||||
fs.writeFileSync(path.join(profileDir, profileName + '.json'), JSON.stringify(profile));
|
||||
}
|
||||
f();
|
||||
}));
|
||||
}
|
||||
44
node_modules/playwright-core/lib/utils/rtti.js
generated
vendored
Normal file
44
node_modules/playwright-core/lib/utils/rtti.js
generated
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.isError = isError;
|
||||
exports.isLikelyNpxGlobal = void 0;
|
||||
exports.isObject = isObject;
|
||||
exports.isRegExp = isRegExp;
|
||||
Object.defineProperty(exports, "isString", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _stringUtils.isString;
|
||||
}
|
||||
});
|
||||
var _stringUtils = require("./isomorphic/stringUtils");
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
function isRegExp(obj) {
|
||||
return obj instanceof RegExp || Object.prototype.toString.call(obj) === '[object RegExp]';
|
||||
}
|
||||
function isObject(obj) {
|
||||
return typeof obj === 'object' && obj !== null;
|
||||
}
|
||||
function isError(obj) {
|
||||
var _Object$getPrototypeO;
|
||||
return obj instanceof Error || obj && ((_Object$getPrototypeO = Object.getPrototypeOf(obj)) === null || _Object$getPrototypeO === void 0 ? void 0 : _Object$getPrototypeO.name) === 'Error';
|
||||
}
|
||||
const isLikelyNpxGlobal = () => process.argv.length >= 2 && process.argv[1].includes('_npx');
|
||||
exports.isLikelyNpxGlobal = isLikelyNpxGlobal;
|
||||
51
node_modules/playwright-core/lib/utils/semaphore.js
generated
vendored
Normal file
51
node_modules/playwright-core/lib/utils/semaphore.js
generated
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.Semaphore = void 0;
|
||||
var _manualPromise = require("./manualPromise");
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
class Semaphore {
|
||||
constructor(max) {
|
||||
this._max = void 0;
|
||||
this._acquired = 0;
|
||||
this._queue = [];
|
||||
this._max = max;
|
||||
}
|
||||
setMax(max) {
|
||||
this._max = max;
|
||||
}
|
||||
acquire() {
|
||||
const lock = new _manualPromise.ManualPromise();
|
||||
this._queue.push(lock);
|
||||
this._flush();
|
||||
return lock;
|
||||
}
|
||||
release() {
|
||||
--this._acquired;
|
||||
this._flush();
|
||||
}
|
||||
_flush() {
|
||||
while (this._acquired < this._max && this._queue.length) {
|
||||
++this._acquired;
|
||||
this._queue.shift().resolve();
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.Semaphore = Semaphore;
|
||||
64
node_modules/playwright-core/lib/utils/sequence.js
generated
vendored
Normal file
64
node_modules/playwright-core/lib/utils/sequence.js
generated
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.findRepeatedSubsequences = findRepeatedSubsequences;
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
function findRepeatedSubsequences(s) {
|
||||
const n = s.length;
|
||||
const result = [];
|
||||
let i = 0;
|
||||
const arraysEqual = (a1, a2) => {
|
||||
if (a1.length !== a2.length) return false;
|
||||
for (let j = 0; j < a1.length; j++) {
|
||||
if (a1[j] !== a2[j]) return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
while (i < n) {
|
||||
let maxRepeatCount = 1;
|
||||
let maxRepeatSubstr = [s[i]]; // Initialize with the element at index i
|
||||
let maxRepeatLength = 1;
|
||||
|
||||
// Try substrings of length from 1 to the remaining length of the array
|
||||
for (let p = 1; p <= n - i; p++) {
|
||||
const substr = s.slice(i, i + p); // Extract substring as array
|
||||
let k = 1;
|
||||
|
||||
// Count how many times the substring repeats consecutively
|
||||
while (i + p * k <= n && arraysEqual(s.slice(i + p * (k - 1), i + p * k), substr)) k += 1;
|
||||
k -= 1; // Adjust k since it increments one extra time in the loop
|
||||
|
||||
// Update the maximal repeating substring if necessary
|
||||
if (k > 1 && k * p > maxRepeatCount * maxRepeatLength) {
|
||||
maxRepeatCount = k;
|
||||
maxRepeatSubstr = substr;
|
||||
maxRepeatLength = p;
|
||||
}
|
||||
}
|
||||
|
||||
// Record the substring and its count
|
||||
result.push({
|
||||
sequence: maxRepeatSubstr,
|
||||
count: maxRepeatCount
|
||||
});
|
||||
i += maxRepeatLength * maxRepeatCount; // Move index forward
|
||||
}
|
||||
return result;
|
||||
}
|
||||
45
node_modules/playwright-core/lib/utils/spawnAsync.js
generated
vendored
Normal file
45
node_modules/playwright-core/lib/utils/spawnAsync.js
generated
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.spawnAsync = spawnAsync;
|
||||
var _child_process = require("child_process");
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
function spawnAsync(cmd, args, options = {}) {
|
||||
const process = (0, _child_process.spawn)(cmd, args, Object.assign({
|
||||
windowsHide: true
|
||||
}, options));
|
||||
return new Promise(resolve => {
|
||||
let stdout = '';
|
||||
let stderr = '';
|
||||
if (process.stdout) process.stdout.on('data', data => stdout += data.toString());
|
||||
if (process.stderr) process.stderr.on('data', data => stderr += data.toString());
|
||||
process.on('close', code => resolve({
|
||||
stdout,
|
||||
stderr,
|
||||
code
|
||||
}));
|
||||
process.on('error', error => resolve({
|
||||
stdout,
|
||||
stderr,
|
||||
code: 0,
|
||||
error
|
||||
}));
|
||||
});
|
||||
}
|
||||
134
node_modules/playwright-core/lib/utils/stackTrace.js
generated
vendored
Normal file
134
node_modules/playwright-core/lib/utils/stackTrace.js
generated
vendored
Normal file
@@ -0,0 +1,134 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.addInternalStackPrefix = void 0;
|
||||
exports.captureLibraryStackText = captureLibraryStackText;
|
||||
exports.captureLibraryStackTrace = captureLibraryStackTrace;
|
||||
exports.captureRawStack = captureRawStack;
|
||||
exports.compressCallLog = compressCallLog;
|
||||
exports.formatCallLog = formatCallLog;
|
||||
exports.rewriteErrorMessage = rewriteErrorMessage;
|
||||
exports.splitErrorMessage = splitErrorMessage;
|
||||
exports.stringifyStackFrames = stringifyStackFrames;
|
||||
var _path = _interopRequireDefault(require("path"));
|
||||
var _utilsBundle = require("../utilsBundle");
|
||||
var _sequence = require("./sequence");
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
function rewriteErrorMessage(e, newMessage) {
|
||||
var _e$stack;
|
||||
const lines = (((_e$stack = e.stack) === null || _e$stack === void 0 ? void 0 : _e$stack.split('\n')) || []).filter(l => l.startsWith(' at '));
|
||||
e.message = newMessage;
|
||||
const errorTitle = `${e.name}: ${e.message}`;
|
||||
if (lines.length) e.stack = `${errorTitle}\n${lines.join('\n')}`;
|
||||
return e;
|
||||
}
|
||||
const CORE_DIR = _path.default.resolve(__dirname, '..', '..');
|
||||
const internalStackPrefixes = [CORE_DIR];
|
||||
const addInternalStackPrefix = prefix => internalStackPrefixes.push(prefix);
|
||||
exports.addInternalStackPrefix = addInternalStackPrefix;
|
||||
function captureRawStack() {
|
||||
const stackTraceLimit = Error.stackTraceLimit;
|
||||
Error.stackTraceLimit = 50;
|
||||
const error = new Error();
|
||||
const stack = error.stack || '';
|
||||
Error.stackTraceLimit = stackTraceLimit;
|
||||
return stack.split('\n');
|
||||
}
|
||||
function captureLibraryStackTrace() {
|
||||
const stack = captureRawStack();
|
||||
let parsedFrames = stack.map(line => {
|
||||
const frame = (0, _utilsBundle.parseStackTraceLine)(line);
|
||||
if (!frame || !frame.file) return null;
|
||||
const isPlaywrightLibrary = frame.file.startsWith(CORE_DIR);
|
||||
const parsed = {
|
||||
frame,
|
||||
frameText: line,
|
||||
isPlaywrightLibrary
|
||||
};
|
||||
return parsed;
|
||||
}).filter(Boolean);
|
||||
let apiName = '';
|
||||
|
||||
// Deepest transition between non-client code calling into client
|
||||
// code is the api entry.
|
||||
for (let i = 0; i < parsedFrames.length - 1; i++) {
|
||||
const parsedFrame = parsedFrames[i];
|
||||
if (parsedFrame.isPlaywrightLibrary && !parsedFrames[i + 1].isPlaywrightLibrary) {
|
||||
apiName = apiName || normalizeAPIName(parsedFrame.frame.function);
|
||||
break;
|
||||
}
|
||||
}
|
||||
function normalizeAPIName(name) {
|
||||
if (!name) return '';
|
||||
const match = name.match(/(API|JS|CDP|[A-Z])(.*)/);
|
||||
if (!match) return name;
|
||||
return match[1].toLowerCase() + match[2];
|
||||
}
|
||||
|
||||
// This is for the inspector so that it did not include the test runner stack frames.
|
||||
parsedFrames = parsedFrames.filter(f => {
|
||||
if (process.env.PWDEBUGIMPL) return true;
|
||||
if (internalStackPrefixes.some(prefix => f.frame.file.startsWith(prefix))) return false;
|
||||
return true;
|
||||
});
|
||||
return {
|
||||
frames: parsedFrames.map(p => p.frame),
|
||||
apiName
|
||||
};
|
||||
}
|
||||
function stringifyStackFrames(frames) {
|
||||
const stackLines = [];
|
||||
for (const frame of frames) {
|
||||
if (frame.function) stackLines.push(` at ${frame.function} (${frame.file}:${frame.line}:${frame.column})`);else stackLines.push(` at ${frame.file}:${frame.line}:${frame.column}`);
|
||||
}
|
||||
return stackLines;
|
||||
}
|
||||
function captureLibraryStackText() {
|
||||
const parsed = captureLibraryStackTrace();
|
||||
return stringifyStackFrames(parsed.frames).join('\n');
|
||||
}
|
||||
function splitErrorMessage(message) {
|
||||
const separationIdx = message.indexOf(':');
|
||||
return {
|
||||
name: separationIdx !== -1 ? message.slice(0, separationIdx) : '',
|
||||
message: separationIdx !== -1 && separationIdx + 2 <= message.length ? message.substring(separationIdx + 2) : message
|
||||
};
|
||||
}
|
||||
function formatCallLog(log) {
|
||||
if (!log || !log.some(l => !!l)) return '';
|
||||
return `
|
||||
Call log:
|
||||
${_utilsBundle.colors.dim(log.join('\n'))}
|
||||
`;
|
||||
}
|
||||
function compressCallLog(log) {
|
||||
const lines = [];
|
||||
for (const block of (0, _sequence.findRepeatedSubsequences)(log)) {
|
||||
for (let i = 0; i < block.sequence.length; i++) {
|
||||
const line = block.sequence[i];
|
||||
const leadingWhitespace = line.match(/^\s*/);
|
||||
const whitespacePrefix = ' ' + (leadingWhitespace === null || leadingWhitespace === void 0 ? void 0 : leadingWhitespace[0]) || '';
|
||||
const countPrefix = `${block.count} × `;
|
||||
if (block.count > 1 && i === 0) lines.push(whitespacePrefix + countPrefix + line.trim());else if (block.count > 1) lines.push(whitespacePrefix + ' '.repeat(countPrefix.length - 2) + '- ' + line.trim());else lines.push(whitespacePrefix + '- ' + line.trim());
|
||||
}
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
58
node_modules/playwright-core/lib/utils/task.js
generated
vendored
Normal file
58
node_modules/playwright-core/lib/utils/task.js
generated
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.makeWaitForNextTask = makeWaitForNextTask;
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// See https://joel.tools/microtasks/
|
||||
function makeWaitForNextTask() {
|
||||
// As of Mar 2021, Electron v12 doesn't create new task with `setImmediate` despite
|
||||
// using Node 14 internally, so we fallback to `setTimeout(0)` instead.
|
||||
// @see https://github.com/electron/electron/issues/28261
|
||||
if (process.versions.electron) return callback => setTimeout(callback, 0);
|
||||
if (parseInt(process.versions.node, 10) >= 11) return setImmediate;
|
||||
|
||||
// Unlike Node 11, Node 10 and less have a bug with Task and MicroTask execution order:
|
||||
// - https://github.com/nodejs/node/issues/22257
|
||||
//
|
||||
// So we can't simply run setImmediate to dispatch code in a following task.
|
||||
// However, we can run setImmediate from-inside setImmediate to make sure we're getting
|
||||
// in the following task.
|
||||
|
||||
let spinning = false;
|
||||
const callbacks = [];
|
||||
const loop = () => {
|
||||
const callback = callbacks.shift();
|
||||
if (!callback) {
|
||||
spinning = false;
|
||||
return;
|
||||
}
|
||||
setImmediate(loop);
|
||||
// Make sure to call callback() as the last thing since it's
|
||||
// untrusted code that might throw.
|
||||
callback();
|
||||
};
|
||||
return callback => {
|
||||
callbacks.push(callback);
|
||||
if (!spinning) {
|
||||
spinning = true;
|
||||
setImmediate(loop);
|
||||
}
|
||||
};
|
||||
}
|
||||
37
node_modules/playwright-core/lib/utils/time.js
generated
vendored
Normal file
37
node_modules/playwright-core/lib/utils/time.js
generated
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.monotonicTime = monotonicTime;
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// The `process.hrtime()` returns a time from some arbitrary
|
||||
// date in the past; on certain systems, this is the time from the system boot.
|
||||
// The `monotonicTime()` converts this to milliseconds.
|
||||
//
|
||||
// For a Linux server with uptime of 36 days, the `monotonicTime()` value
|
||||
// will be 36 * 86400 * 1000 = 3_110_400_000, which is larger than
|
||||
// the maximum value that `setTimeout` accepts as an argument: 2_147_483_647.
|
||||
//
|
||||
// To make the `monotonicTime()` a reasonable value, we anchor
|
||||
// it to the time of the first import of this utility.
|
||||
const initialTime = process.hrtime();
|
||||
function monotonicTime() {
|
||||
const [seconds, nanoseconds] = process.hrtime(initialTime);
|
||||
return seconds * 1000 + (nanoseconds / 1000 | 0) / 1000;
|
||||
}
|
||||
66
node_modules/playwright-core/lib/utils/timeoutRunner.js
generated
vendored
Normal file
66
node_modules/playwright-core/lib/utils/timeoutRunner.js
generated
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.pollAgainstDeadline = pollAgainstDeadline;
|
||||
exports.raceAgainstDeadline = raceAgainstDeadline;
|
||||
var _ = require("./");
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
async function raceAgainstDeadline(cb, deadline) {
|
||||
let timer;
|
||||
return Promise.race([cb().then(result => {
|
||||
return {
|
||||
result,
|
||||
timedOut: false
|
||||
};
|
||||
}), new Promise(resolve => {
|
||||
const kMaxDeadline = 2147483647; // 2^31-1
|
||||
const timeout = (deadline || kMaxDeadline) - (0, _.monotonicTime)();
|
||||
timer = setTimeout(() => resolve({
|
||||
timedOut: true
|
||||
}), timeout);
|
||||
})]).finally(() => {
|
||||
clearTimeout(timer);
|
||||
});
|
||||
}
|
||||
async function pollAgainstDeadline(callback, deadline, pollIntervals = [100, 250, 500, 1000]) {
|
||||
var _pollIntervals$pop;
|
||||
const lastPollInterval = (_pollIntervals$pop = pollIntervals.pop()) !== null && _pollIntervals$pop !== void 0 ? _pollIntervals$pop : 1000;
|
||||
let lastResult;
|
||||
const wrappedCallback = () => Promise.resolve().then(callback);
|
||||
while (true) {
|
||||
var _shift;
|
||||
const time = (0, _.monotonicTime)();
|
||||
if (deadline && time >= deadline) break;
|
||||
const received = await raceAgainstDeadline(wrappedCallback, deadline);
|
||||
if (received.timedOut) break;
|
||||
lastResult = received.result.result;
|
||||
if (!received.result.continuePolling) return {
|
||||
result: lastResult,
|
||||
timedOut: false
|
||||
};
|
||||
const interval = (_shift = pollIntervals.shift()) !== null && _shift !== void 0 ? _shift : lastPollInterval;
|
||||
if (deadline && deadline <= (0, _.monotonicTime)() + interval) break;
|
||||
await new Promise(x => setTimeout(x, interval));
|
||||
}
|
||||
return {
|
||||
timedOut: true,
|
||||
result: lastResult
|
||||
};
|
||||
}
|
||||
44
node_modules/playwright-core/lib/utils/traceUtils.js
generated
vendored
Normal file
44
node_modules/playwright-core/lib/utils/traceUtils.js
generated
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.serializeClientSideCallMetadata = serializeClientSideCallMetadata;
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
function serializeClientSideCallMetadata(metadatas) {
|
||||
const fileNames = new Map();
|
||||
const stacks = [];
|
||||
for (const m of metadatas) {
|
||||
if (!m.stack || !m.stack.length) continue;
|
||||
const stack = [];
|
||||
for (const frame of m.stack) {
|
||||
let ordinal = fileNames.get(frame.file);
|
||||
if (typeof ordinal !== 'number') {
|
||||
ordinal = fileNames.size;
|
||||
fileNames.set(frame.file, ordinal);
|
||||
}
|
||||
const stackFrame = [ordinal, frame.line || 0, frame.column || 0, frame.function || ''];
|
||||
stack.push(stackFrame);
|
||||
}
|
||||
stacks.push([m.id, stack]);
|
||||
}
|
||||
return {
|
||||
files: [...fileNames.keys()],
|
||||
stacks
|
||||
};
|
||||
}
|
||||
105
node_modules/playwright-core/lib/utils/userAgent.js
generated
vendored
Normal file
105
node_modules/playwright-core/lib/utils/userAgent.js
generated
vendored
Normal file
@@ -0,0 +1,105 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.getEmbedderName = getEmbedderName;
|
||||
exports.getPlaywrightVersion = getPlaywrightVersion;
|
||||
exports.getUserAgent = getUserAgent;
|
||||
exports.userAgentVersionMatchesErrorMessage = userAgentVersionMatchesErrorMessage;
|
||||
var _child_process = require("child_process");
|
||||
var _os = _interopRequireDefault(require("os"));
|
||||
var _linuxUtils = require("../utils/linuxUtils");
|
||||
var _ascii = require("./ascii");
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
let cachedUserAgent;
|
||||
function getUserAgent() {
|
||||
if (cachedUserAgent) return cachedUserAgent;
|
||||
try {
|
||||
cachedUserAgent = determineUserAgent();
|
||||
} catch (e) {
|
||||
cachedUserAgent = 'Playwright/unknown';
|
||||
}
|
||||
return cachedUserAgent;
|
||||
}
|
||||
function determineUserAgent() {
|
||||
let osIdentifier = 'unknown';
|
||||
let osVersion = 'unknown';
|
||||
if (process.platform === 'win32') {
|
||||
const version = _os.default.release().split('.');
|
||||
osIdentifier = 'windows';
|
||||
osVersion = `${version[0]}.${version[1]}`;
|
||||
} else if (process.platform === 'darwin') {
|
||||
const version = (0, _child_process.execSync)('sw_vers -productVersion', {
|
||||
stdio: ['ignore', 'pipe', 'ignore']
|
||||
}).toString().trim().split('.');
|
||||
osIdentifier = 'macOS';
|
||||
osVersion = `${version[0]}.${version[1]}`;
|
||||
} else if (process.platform === 'linux') {
|
||||
const distroInfo = (0, _linuxUtils.getLinuxDistributionInfoSync)();
|
||||
if (distroInfo) {
|
||||
osIdentifier = distroInfo.id || 'linux';
|
||||
osVersion = distroInfo.version || 'unknown';
|
||||
} else {
|
||||
// Linux distribution without /etc/os-release.
|
||||
// Default to linux/unknown.
|
||||
osIdentifier = 'linux';
|
||||
}
|
||||
}
|
||||
const additionalTokens = [];
|
||||
if (process.env.CI) additionalTokens.push('CI/1');
|
||||
const serializedTokens = additionalTokens.length ? ' ' + additionalTokens.join(' ') : '';
|
||||
const {
|
||||
embedderName,
|
||||
embedderVersion
|
||||
} = getEmbedderName();
|
||||
return `Playwright/${getPlaywrightVersion()} (${_os.default.arch()}; ${osIdentifier} ${osVersion}) ${embedderName}/${embedderVersion}${serializedTokens}`;
|
||||
}
|
||||
function getEmbedderName() {
|
||||
let embedderName = 'unknown';
|
||||
let embedderVersion = 'unknown';
|
||||
if (!process.env.PW_LANG_NAME) {
|
||||
embedderName = 'node';
|
||||
embedderVersion = process.version.substring(1).split('.').slice(0, 2).join('.');
|
||||
} else if (['node', 'python', 'java', 'csharp'].includes(process.env.PW_LANG_NAME)) {
|
||||
var _process$env$PW_LANG_;
|
||||
embedderName = process.env.PW_LANG_NAME;
|
||||
embedderVersion = (_process$env$PW_LANG_ = process.env.PW_LANG_NAME_VERSION) !== null && _process$env$PW_LANG_ !== void 0 ? _process$env$PW_LANG_ : 'unknown';
|
||||
}
|
||||
return {
|
||||
embedderName,
|
||||
embedderVersion
|
||||
};
|
||||
}
|
||||
function getPlaywrightVersion(majorMinorOnly = false) {
|
||||
const version = process.env.PW_VERSION_OVERRIDE || require('./../../package.json').version;
|
||||
return majorMinorOnly ? version.split('.').slice(0, 2).join('.') : version;
|
||||
}
|
||||
function userAgentVersionMatchesErrorMessage(userAgent) {
|
||||
const match = userAgent.match(/^Playwright\/(\d+\.\d+\.\d+)/);
|
||||
if (!match) {
|
||||
// Cannot parse user agent - be lax.
|
||||
return;
|
||||
}
|
||||
const received = match[1].split('.').slice(0, 2).join('.');
|
||||
const expected = getPlaywrightVersion(true);
|
||||
if (received !== expected) {
|
||||
return (0, _ascii.wrapInASCIIBox)([`Playwright version mismatch:`, ` - server version: v${expected}`, ` - client version: v${received}`, ``, `If you are using VSCode extension, restart VSCode.`, ``, `If you are connecting to a remote service,`, `keep your local Playwright version in sync`, `with the remote service version.`, ``, `<3 Playwright Team`].join('\n'), 1);
|
||||
}
|
||||
}
|
||||
127
node_modules/playwright-core/lib/utils/wsServer.js
generated
vendored
Normal file
127
node_modules/playwright-core/lib/utils/wsServer.js
generated
vendored
Normal file
@@ -0,0 +1,127 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.perMessageDeflate = exports.WSServer = void 0;
|
||||
var _utils = require("../utils");
|
||||
var _utilsBundle = require("../utilsBundle");
|
||||
var _debugLogger = require("./debugLogger");
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
let lastConnectionId = 0;
|
||||
const kConnectionSymbol = Symbol('kConnection');
|
||||
const perMessageDeflate = exports.perMessageDeflate = {
|
||||
zlibDeflateOptions: {
|
||||
level: 3
|
||||
},
|
||||
zlibInflateOptions: {
|
||||
chunkSize: 10 * 1024
|
||||
},
|
||||
threshold: 10 * 1024
|
||||
};
|
||||
class WSServer {
|
||||
constructor(delegate) {
|
||||
this._wsServer = void 0;
|
||||
this.server = void 0;
|
||||
this._delegate = void 0;
|
||||
this._delegate = delegate;
|
||||
}
|
||||
async listen(port = 0, hostname, path) {
|
||||
_debugLogger.debugLogger.log('server', `Server started at ${new Date()}`);
|
||||
const server = (0, _utils.createHttpServer)((request, response) => {
|
||||
if (request.method === 'GET' && request.url === '/json') {
|
||||
response.setHeader('Content-Type', 'application/json');
|
||||
response.end(JSON.stringify({
|
||||
wsEndpointPath: path
|
||||
}));
|
||||
return;
|
||||
}
|
||||
response.end('Running');
|
||||
});
|
||||
server.on('error', error => _debugLogger.debugLogger.log('server', String(error)));
|
||||
this.server = server;
|
||||
const wsEndpoint = await new Promise((resolve, reject) => {
|
||||
server.listen(port, hostname, () => {
|
||||
const address = server.address();
|
||||
if (!address) {
|
||||
reject(new Error('Could not bind server socket'));
|
||||
return;
|
||||
}
|
||||
const wsEndpoint = typeof address === 'string' ? `${address}${path}` : `ws://${hostname || 'localhost'}:${address.port}${path}`;
|
||||
resolve(wsEndpoint);
|
||||
}).on('error', reject);
|
||||
});
|
||||
_debugLogger.debugLogger.log('server', 'Listening at ' + wsEndpoint);
|
||||
this._wsServer = new _utilsBundle.wsServer({
|
||||
noServer: true,
|
||||
perMessageDeflate
|
||||
});
|
||||
if (this._delegate.onHeaders) this._wsServer.on('headers', headers => this._delegate.onHeaders(headers));
|
||||
server.on('upgrade', (request, socket, head) => {
|
||||
var _this$_delegate$onUpg, _this$_delegate, _this$_wsServer;
|
||||
const pathname = new URL('http://localhost' + request.url).pathname;
|
||||
if (pathname !== path) {
|
||||
socket.write(`HTTP/${request.httpVersion} 400 Bad Request\r\n\r\n`);
|
||||
socket.destroy();
|
||||
return;
|
||||
}
|
||||
const upgradeResult = (_this$_delegate$onUpg = (_this$_delegate = this._delegate).onUpgrade) === null || _this$_delegate$onUpg === void 0 ? void 0 : _this$_delegate$onUpg.call(_this$_delegate, request, socket);
|
||||
if (upgradeResult) {
|
||||
socket.write(upgradeResult.error);
|
||||
socket.destroy();
|
||||
return;
|
||||
}
|
||||
(_this$_wsServer = this._wsServer) === null || _this$_wsServer === void 0 || _this$_wsServer.handleUpgrade(request, socket, head, ws => {
|
||||
var _this$_wsServer2;
|
||||
return (_this$_wsServer2 = this._wsServer) === null || _this$_wsServer2 === void 0 ? void 0 : _this$_wsServer2.emit('connection', ws, request);
|
||||
});
|
||||
});
|
||||
this._wsServer.on('connection', (ws, request) => {
|
||||
_debugLogger.debugLogger.log('server', 'Connected client ws.extension=' + ws.extensions);
|
||||
const url = new URL('http://localhost' + (request.url || ''));
|
||||
const id = String(++lastConnectionId);
|
||||
_debugLogger.debugLogger.log('server', `[${id}] serving connection: ${request.url}`);
|
||||
const connection = this._delegate.onConnection(request, url, ws, id);
|
||||
ws[kConnectionSymbol] = connection;
|
||||
});
|
||||
return wsEndpoint;
|
||||
}
|
||||
async close() {
|
||||
var _this$_delegate$onClo, _this$_delegate2;
|
||||
const server = this._wsServer;
|
||||
if (!server) return;
|
||||
_debugLogger.debugLogger.log('server', 'closing websocket server');
|
||||
const waitForClose = new Promise(f => server.close(f));
|
||||
// First disconnect all remaining clients.
|
||||
await Promise.all(Array.from(server.clients).map(async ws => {
|
||||
const connection = ws[kConnectionSymbol];
|
||||
if (connection) await connection.close();
|
||||
try {
|
||||
ws.terminate();
|
||||
} catch (e) {}
|
||||
}));
|
||||
await waitForClose;
|
||||
_debugLogger.debugLogger.log('server', 'closing http server');
|
||||
if (this.server) await new Promise(f => this.server.close(f));
|
||||
this._wsServer = undefined;
|
||||
this.server = undefined;
|
||||
_debugLogger.debugLogger.log('server', 'closed server');
|
||||
await ((_this$_delegate$onClo = (_this$_delegate2 = this._delegate).onClose) === null || _this$_delegate$onClo === void 0 ? void 0 : _this$_delegate$onClo.call(_this$_delegate2));
|
||||
}
|
||||
}
|
||||
exports.WSServer = WSServer;
|
||||
75
node_modules/playwright-core/lib/utils/zipFile.js
generated
vendored
Normal file
75
node_modules/playwright-core/lib/utils/zipFile.js
generated
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.ZipFile = void 0;
|
||||
var _zipBundle = require("../zipBundle");
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
class ZipFile {
|
||||
constructor(fileName) {
|
||||
this._fileName = void 0;
|
||||
this._zipFile = void 0;
|
||||
this._entries = new Map();
|
||||
this._openedPromise = void 0;
|
||||
this._fileName = fileName;
|
||||
this._openedPromise = this._open();
|
||||
}
|
||||
async _open() {
|
||||
await new Promise((fulfill, reject) => {
|
||||
_zipBundle.yauzl.open(this._fileName, {
|
||||
autoClose: false
|
||||
}, (e, z) => {
|
||||
if (e) {
|
||||
reject(e);
|
||||
return;
|
||||
}
|
||||
this._zipFile = z;
|
||||
this._zipFile.on('entry', entry => {
|
||||
this._entries.set(entry.fileName, entry);
|
||||
});
|
||||
this._zipFile.on('end', fulfill);
|
||||
});
|
||||
});
|
||||
}
|
||||
async entries() {
|
||||
await this._openedPromise;
|
||||
return [...this._entries.keys()];
|
||||
}
|
||||
async read(entryPath) {
|
||||
await this._openedPromise;
|
||||
const entry = this._entries.get(entryPath);
|
||||
if (!entry) throw new Error(`${entryPath} not found in file ${this._fileName}`);
|
||||
return new Promise((resolve, reject) => {
|
||||
this._zipFile.openReadStream(entry, (error, readStream) => {
|
||||
if (error || !readStream) {
|
||||
reject(error || 'Entry not found');
|
||||
return;
|
||||
}
|
||||
const buffers = [];
|
||||
readStream.on('data', data => buffers.push(data));
|
||||
readStream.on('end', () => resolve(Buffer.concat(buffers)));
|
||||
});
|
||||
});
|
||||
}
|
||||
close() {
|
||||
var _this$_zipFile;
|
||||
(_this$_zipFile = this._zipFile) === null || _this$_zipFile === void 0 || _this$_zipFile.close();
|
||||
}
|
||||
}
|
||||
exports.ZipFile = ZipFile;
|
||||
71
node_modules/playwright-core/lib/utils/zones.js
generated
vendored
Normal file
71
node_modules/playwright-core/lib/utils/zones.js
generated
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.zones = exports.Zone = void 0;
|
||||
var _async_hooks = require("async_hooks");
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
class ZoneManager {
|
||||
constructor() {
|
||||
this._asyncLocalStorage = new _async_hooks.AsyncLocalStorage();
|
||||
}
|
||||
run(type, data, func) {
|
||||
const zone = Zone._createWithData(this._asyncLocalStorage, type, data);
|
||||
return this._asyncLocalStorage.run(zone, func);
|
||||
}
|
||||
zoneData(type) {
|
||||
const zone = this._asyncLocalStorage.getStore();
|
||||
return zone === null || zone === void 0 ? void 0 : zone.get(type);
|
||||
}
|
||||
currentZone() {
|
||||
var _this$_asyncLocalStor;
|
||||
return (_this$_asyncLocalStor = this._asyncLocalStorage.getStore()) !== null && _this$_asyncLocalStor !== void 0 ? _this$_asyncLocalStor : Zone._createEmpty(this._asyncLocalStorage);
|
||||
}
|
||||
exitZones(func) {
|
||||
return this._asyncLocalStorage.run(undefined, func);
|
||||
}
|
||||
}
|
||||
class Zone {
|
||||
static _createWithData(asyncLocalStorage, type, data) {
|
||||
var _asyncLocalStorage$ge;
|
||||
const store = new Map((_asyncLocalStorage$ge = asyncLocalStorage.getStore()) === null || _asyncLocalStorage$ge === void 0 ? void 0 : _asyncLocalStorage$ge._data);
|
||||
store.set(type, data);
|
||||
return new Zone(asyncLocalStorage, store);
|
||||
}
|
||||
static _createEmpty(asyncLocalStorage) {
|
||||
return new Zone(asyncLocalStorage, new Map());
|
||||
}
|
||||
constructor(asyncLocalStorage, store) {
|
||||
this._asyncLocalStorage = void 0;
|
||||
this._data = void 0;
|
||||
this._asyncLocalStorage = asyncLocalStorage;
|
||||
this._data = store;
|
||||
}
|
||||
run(func) {
|
||||
// Reset apiZone and expectZone, but restore stepZone.
|
||||
const entries = [...this._data.entries()].filter(([type]) => type !== 'apiZone' && type !== 'expectZone');
|
||||
const resetZone = new Zone(this._asyncLocalStorage, new Map(entries));
|
||||
return this._asyncLocalStorage.run(resetZone, func);
|
||||
}
|
||||
get(type) {
|
||||
return this._data.get(type);
|
||||
}
|
||||
}
|
||||
exports.Zone = Zone;
|
||||
const zones = exports.zones = new ZoneManager();
|
||||
Reference in New Issue
Block a user