screenshot/test_1
This commit is contained in:
31
node_modules/playwright-core/lib/server/utils/ascii.js
generated
vendored
Normal file
31
node_modules/playwright-core/lib/server/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));
|
||||
}
|
||||
159
node_modules/playwright-core/lib/server/utils/comparators.js
generated
vendored
Normal file
159
node_modules/playwright-core/lib/server/utils/comparators.js
generated
vendored
Normal file
@@ -0,0 +1,159 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.compareBuffersOrStrings = compareBuffersOrStrings;
|
||||
exports.getComparator = getComparator;
|
||||
var _compare = require("./image_tools/compare");
|
||||
var _pixelmatch = _interopRequireDefault(require("../../third_party/pixelmatch"));
|
||||
var _utilsBundle = require("../../utilsBundle");
|
||||
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
||||
/**
|
||||
* 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'
|
||||
};
|
||||
let expected = expectedBuffer.toString('utf-8');
|
||||
if (expected === actual) return null;
|
||||
// Eliminate '\\ No newline at end of file'
|
||||
if (!actual.endsWith('\n')) actual += '\n';
|
||||
if (!expected.endsWith('\n')) expected += '\n';
|
||||
const lines = _utilsBundle.diff.createPatch('file', expected, actual, undefined, undefined, {
|
||||
context: 5
|
||||
}).split('\n');
|
||||
const coloredLines = lines.slice(4).map(line => {
|
||||
if (line.startsWith('-')) return _utilsBundle.colors.red(line);
|
||||
if (line.startsWith('+')) return _utilsBundle.colors.green(line);
|
||||
if (line.startsWith('@@')) return _utilsBundle.colors.dim(line);
|
||||
return line;
|
||||
});
|
||||
const errorMessage = coloredLines.join('\n');
|
||||
return {
|
||||
errorMessage
|
||||
};
|
||||
}
|
||||
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/server/utils/crypto.js
generated
vendored
Normal file
171
node_modules/playwright-core/lib/server/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 _assert = require("../../utils/isomorphic/assert");
|
||||
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
||||
/**
|
||||
* 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, _assert.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, _assert.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'
|
||||
})
|
||||
};
|
||||
}
|
||||
38
node_modules/playwright-core/lib/server/utils/debug.js
generated
vendored
Normal file
38
node_modules/playwright-core/lib/server/utils/debug.js
generated
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
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.
|
||||
*/
|
||||
|
||||
const _debugMode = (0, _env.getFromENV)('PWDEBUG') || '';
|
||||
function debugMode() {
|
||||
if (_debugMode === 'console') return 'console';
|
||||
if (_debugMode === '0' || _debugMode === 'false') return '';
|
||||
return _debugMode ? 'inspector' : '';
|
||||
}
|
||||
let _isUnderTest = !!process.env.PWTEST_UNDER_TEST;
|
||||
function setUnderTest() {
|
||||
_isUnderTest = true;
|
||||
}
|
||||
function isUnderTest() {
|
||||
return _isUnderTest;
|
||||
}
|
||||
93
node_modules/playwright-core/lib/server/utils/debugLogger.js
generated
vendored
Normal file
93
node_modules/playwright-core/lib/server/utils/debugLogger.js
generated
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.debugLogger = exports.RecentLogsCollector = void 0;
|
||||
var _fs = _interopRequireDefault(require("fs"));
|
||||
var _utilsBundle = require("../../utilsBundle");
|
||||
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
||||
/**
|
||||
* 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,
|
||||
'recorder': 45 // cyan
|
||||
};
|
||||
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;
|
||||
53
node_modules/playwright-core/lib/server/utils/env.js
generated
vendored
Normal file
53
node_modules/playwright-core/lib/server/utils/env.js
generated
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.getAsBooleanFromENV = getAsBooleanFromENV;
|
||||
exports.getFromENV = getFromENV;
|
||||
exports.getPackageManager = getPackageManager;
|
||||
exports.getPackageManagerExecCommand = getPackageManagerExecCommand;
|
||||
exports.isLikelyNpxGlobal = isLikelyNpxGlobal;
|
||||
/**
|
||||
* 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';
|
||||
}
|
||||
function isLikelyNpxGlobal() {
|
||||
return process.argv.length >= 2 && process.argv[1].includes('_npx');
|
||||
}
|
||||
38
node_modules/playwright-core/lib/server/utils/eventsHelper.js
generated
vendored
Normal file
38
node_modules/playwright-core/lib/server/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/server/utils/expectUtils.js
generated
vendored
Normal file
33
node_modules/playwright-core/lib/server/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("../../utils/isomorphic/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
|
||||
}));
|
||||
}
|
||||
204
node_modules/playwright-core/lib/server/utils/fileUtils.js
generated
vendored
Normal file
204
node_modules/playwright-core/lib/server/utils/fileUtils.js
generated
vendored
Normal file
@@ -0,0 +1,204 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.SerializedFS = void 0;
|
||||
exports.canAccessFile = canAccessFile;
|
||||
exports.copyFileAndMakeWritable = copyFileAndMakeWritable;
|
||||
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("../../utils/isomorphic/manualPromise");
|
||||
var _zipBundle = require("../../zipBundle");
|
||||
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
||||
/**
|
||||
* 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 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;
|
||||
192
node_modules/playwright-core/lib/server/utils/happyEyeballs.js
generated
vendored
Normal file
192
node_modules/playwright-core/lib/server/utils/happyEyeballs.js
generated
vendored
Normal file
@@ -0,0 +1,192 @@
|
||||
"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 = _interopRequireDefault(require("dns"));
|
||||
var _http = _interopRequireDefault(require("http"));
|
||||
var _https = _interopRequireDefault(require("https"));
|
||||
var _net = _interopRequireDefault(require("net"));
|
||||
var _tls = _interopRequireDefault(require("tls"));
|
||||
var _assert = require("../../utils/isomorphic/assert");
|
||||
var _manualPromise = require("../../utils/isomorphic/manualPromise");
|
||||
var _time = require("../../utils/isomorphic/time");
|
||||
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
||||
/**
|
||||
* 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.default.Agent {
|
||||
createConnection(options, oncreate) {
|
||||
// There is no ambiguity in case of IP address.
|
||||
if (_net.default.isIP(clientRequestArgsToHostName(options))) return _net.default.createConnection(options);
|
||||
createConnectionAsync(options, oncreate, /* useTLS */false).catch(err => oncreate === null || oncreate === void 0 ? void 0 : oncreate(err));
|
||||
}
|
||||
}
|
||||
class HttpsHappyEyeballsAgent extends _https.default.Agent {
|
||||
createConnection(options, oncreate) {
|
||||
// There is no ambiguity in case of IP address.
|
||||
if (_net.default.isIP(clientRequestArgsToHostName(options))) return _tls.default.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.default.isIP(host)) {
|
||||
const socket = _net.default.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, _assert.assert)(options.host, 'host is required');
|
||||
if (_net.default.isIP(options.host)) {
|
||||
const socket = _tls.default.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) => {
|
||||
if (!sockets.delete(socket)) return;
|
||||
++errorCount;
|
||||
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.default.connect({
|
||||
...options,
|
||||
port: options.port,
|
||||
host: address,
|
||||
servername: hostname
|
||||
}) : _net.default.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.default.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]
|
||||
};
|
||||
}
|
||||
145
node_modules/playwright-core/lib/server/utils/hostPlatform.js
generated
vendored
Normal file
145
node_modules/playwright-core/lib/server/utils/hostPlatform.js
generated
vendored
Normal file
@@ -0,0 +1,145 @@
|
||||
"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(e) { return e && e.__esModule ? e : { default: e }; }
|
||||
/**
|
||||
* 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 isUbuntu = (distroInfo === null || distroInfo === void 0 ? void 0 : distroInfo.id) === 'ubuntu';
|
||||
const version = distroInfo === null || distroInfo === void 0 ? void 0 : distroInfo.version;
|
||||
const major = parseInt(distroInfo.version, 10);
|
||||
if (major < 20) return {
|
||||
hostPlatform: 'ubuntu18.04' + archSuffix,
|
||||
isOfficiallySupportedPlatform: false
|
||||
};
|
||||
if (major < 22) return {
|
||||
hostPlatform: 'ubuntu20.04' + archSuffix,
|
||||
isOfficiallySupportedPlatform: isUbuntu && version === '20.04'
|
||||
};
|
||||
if (major < 24) return {
|
||||
hostPlatform: 'ubuntu22.04' + archSuffix,
|
||||
isOfficiallySupportedPlatform: isUbuntu && version === '22.04'
|
||||
};
|
||||
if (major < 26) return {
|
||||
hostPlatform: 'ubuntu24.04' + archSuffix,
|
||||
isOfficiallySupportedPlatform: isUbuntu && version === '24.04'
|
||||
};
|
||||
return {
|
||||
hostPlatform: 'ubuntu' + distroInfo.version + archSuffix,
|
||||
isOfficiallySupportedPlatform: false
|
||||
};
|
||||
}
|
||||
// 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;
|
||||
233
node_modules/playwright-core/lib/server/utils/httpServer.js
generated
vendored
Normal file
233
node_modules/playwright-core/lib/server/utils/httpServer.js
generated
vendored
Normal file
@@ -0,0 +1,233 @@
|
||||
"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 _crypto = require("./crypto");
|
||||
var _assert = require("../../utils/isomorphic/assert");
|
||||
var _manualPromise = require("../../utils/isomorphic/manualPromise");
|
||||
var _network = require("./network");
|
||||
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
||||
/**
|
||||
* 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, _assert.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, _assert.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, _assert.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) {
|
||||
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;
|
||||
98
node_modules/playwright-core/lib/server/utils/image_tools/colorUtils.js
generated
vendored
Normal file
98
node_modules/playwright-core/lib/server/utils/image_tools/colorUtils.js
generated
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.blendWithWhite = blendWithWhite;
|
||||
exports.colorDeltaE94 = colorDeltaE94;
|
||||
exports.rgb2gray = rgb2gray;
|
||||
exports.srgb2xyz = srgb2xyz;
|
||||
exports.xyz2lab = xyz2lab;
|
||||
/**
|
||||
* 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 blendWithWhite(c, a) {
|
||||
return 255 + (c - 255) * a;
|
||||
}
|
||||
function rgb2gray(r, g, b) {
|
||||
// NOTE: this is the exact integer formula from SSIM.js.
|
||||
// See https://github.com/obartra/ssim/blob/ca8e3c6a6ff5f4f2e232239e0c3d91806f3c97d5/src/matlab/rgb2gray.ts#L56
|
||||
return 77 * r + 150 * g + 29 * b + 128 >> 8;
|
||||
}
|
||||
|
||||
// Perceived color difference defined by CIE94.
|
||||
// See https://en.wikipedia.org/wiki/Color_difference#CIE94
|
||||
//
|
||||
// The result of 1.0 is a "just-noticeable difference".
|
||||
//
|
||||
// Other results interpretation (taken from http://zschuessler.github.io/DeltaE/learn/):
|
||||
// < 1.0 Not perceptible by human eyes.
|
||||
// 1-2 Perceptible through close observation.
|
||||
// 2-10 Perceptible at a glance.
|
||||
// 11-49 Colors are more similar than opposite
|
||||
// 100 Colors are exact opposite
|
||||
function colorDeltaE94(rgb1, rgb2) {
|
||||
const [l1, a1, b1] = xyz2lab(srgb2xyz(rgb1));
|
||||
const [l2, a2, b2] = xyz2lab(srgb2xyz(rgb2));
|
||||
const deltaL = l1 - l2;
|
||||
const deltaA = a1 - a2;
|
||||
const deltaB = b1 - b2;
|
||||
const c1 = Math.sqrt(a1 ** 2 + b1 ** 2);
|
||||
const c2 = Math.sqrt(a2 ** 2 + b2 ** 2);
|
||||
const deltaC = c1 - c2;
|
||||
let deltaH = deltaA ** 2 + deltaB ** 2 - deltaC ** 2;
|
||||
deltaH = deltaH < 0 ? 0 : Math.sqrt(deltaH);
|
||||
// The k1, k2, kL, kC, kH values for "graphic arts" applications.
|
||||
// See https://en.wikipedia.org/wiki/Color_difference#CIE94
|
||||
const k1 = 0.045;
|
||||
const k2 = 0.015;
|
||||
const kL = 1;
|
||||
const kC = 1;
|
||||
const kH = 1;
|
||||
const sC = 1.0 + k1 * c1;
|
||||
const sH = 1.0 + k2 * c1;
|
||||
const sL = 1;
|
||||
return Math.sqrt((deltaL / sL / kL) ** 2 + (deltaC / sC / kC) ** 2 + (deltaH / sH / kH) ** 2);
|
||||
}
|
||||
|
||||
// sRGB -> 1-normalized XYZ (i.e. Y ∈ [0, 1]) with D65 illuminant
|
||||
// See https://en.wikipedia.org/wiki/SRGB#From_sRGB_to_CIE_XYZ
|
||||
function srgb2xyz(rgb) {
|
||||
let r = rgb[0] / 255;
|
||||
let g = rgb[1] / 255;
|
||||
let b = rgb[2] / 255;
|
||||
r = r > 0.04045 ? Math.pow((r + 0.055) / 1.055, 2.4) : r / 12.92;
|
||||
g = g > 0.04045 ? Math.pow((g + 0.055) / 1.055, 2.4) : g / 12.92;
|
||||
b = b > 0.04045 ? Math.pow((b + 0.055) / 1.055, 2.4) : b / 12.92;
|
||||
return [r * 0.4124 + g * 0.3576 + b * 0.1805, r * 0.2126 + g * 0.7152 + b * 0.0722, r * 0.0193 + g * 0.1192 + b * 0.9505];
|
||||
}
|
||||
const sigma_pow2 = 6 * 6 / 29 / 29;
|
||||
const sigma_pow3 = 6 * 6 * 6 / 29 / 29 / 29;
|
||||
|
||||
// 1-normalized CIE XYZ with D65 to L*a*b*
|
||||
// See https://en.wikipedia.org/wiki/CIELAB_color_space#From_CIEXYZ_to_CIELAB
|
||||
function xyz2lab(xyz) {
|
||||
const x = xyz[0] / 0.950489;
|
||||
const y = xyz[1];
|
||||
const z = xyz[2] / 1.088840;
|
||||
const fx = x > sigma_pow3 ? x ** (1 / 3) : x / 3 / sigma_pow2 + 4 / 29;
|
||||
const fy = y > sigma_pow3 ? y ** (1 / 3) : y / 3 / sigma_pow2 + 4 / 29;
|
||||
const fz = z > sigma_pow3 ? z ** (1 / 3) : z / 3 / sigma_pow2 + 4 / 29;
|
||||
const l = 116 * fy - 16;
|
||||
const a = 500 * (fx - fy);
|
||||
const b = 200 * (fy - fz);
|
||||
return [l, a, b];
|
||||
}
|
||||
108
node_modules/playwright-core/lib/server/utils/image_tools/compare.js
generated
vendored
Normal file
108
node_modules/playwright-core/lib/server/utils/image_tools/compare.js
generated
vendored
Normal file
@@ -0,0 +1,108 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.compare = compare;
|
||||
var _colorUtils = require("./colorUtils");
|
||||
var _imageChannel = require("./imageChannel");
|
||||
var _stats = require("./stats");
|
||||
/**
|
||||
* 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 SSIM_WINDOW_RADIUS = 15;
|
||||
const VARIANCE_WINDOW_RADIUS = 1;
|
||||
function drawPixel(width, data, x, y, r, g, b) {
|
||||
const idx = (y * width + x) * 4;
|
||||
data[idx + 0] = r;
|
||||
data[idx + 1] = g;
|
||||
data[idx + 2] = b;
|
||||
data[idx + 3] = 255;
|
||||
}
|
||||
function compare(actual, expected, diff, width, height, options = {}) {
|
||||
const {
|
||||
maxColorDeltaE94 = 1.0
|
||||
} = options;
|
||||
const paddingSize = Math.max(VARIANCE_WINDOW_RADIUS, SSIM_WINDOW_RADIUS);
|
||||
const paddingColorEven = [255, 0, 255];
|
||||
const paddingColorOdd = [0, 255, 0];
|
||||
const [r1, g1, b1] = _imageChannel.ImageChannel.intoRGB(width, height, expected, {
|
||||
paddingSize,
|
||||
paddingColorEven,
|
||||
paddingColorOdd
|
||||
});
|
||||
const [r2, g2, b2] = _imageChannel.ImageChannel.intoRGB(width, height, actual, {
|
||||
paddingSize,
|
||||
paddingColorEven,
|
||||
paddingColorOdd
|
||||
});
|
||||
const noop = (x, y) => {};
|
||||
const drawRedPixel = diff ? (x, y) => drawPixel(width, diff, x - paddingSize, y - paddingSize, 255, 0, 0) : noop;
|
||||
const drawYellowPixel = diff ? (x, y) => drawPixel(width, diff, x - paddingSize, y - paddingSize, 255, 255, 0) : noop;
|
||||
const drawGrayPixel = diff ? (x, y) => {
|
||||
const gray = (0, _colorUtils.rgb2gray)(r1.get(x, y), g1.get(x, y), b1.get(x, y));
|
||||
const value = (0, _colorUtils.blendWithWhite)(gray, 0.1);
|
||||
drawPixel(width, diff, x - paddingSize, y - paddingSize, value, value, value);
|
||||
} : noop;
|
||||
let fastR, fastG, fastB;
|
||||
let diffCount = 0;
|
||||
for (let y = paddingSize; y < r1.height - paddingSize; ++y) {
|
||||
for (let x = paddingSize; x < r1.width - paddingSize; ++x) {
|
||||
// Fast-path: equal pixels.
|
||||
if (r1.get(x, y) === r2.get(x, y) && g1.get(x, y) === g2.get(x, y) && b1.get(x, y) === b2.get(x, y)) {
|
||||
drawGrayPixel(x, y);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Compare pixel colors using the dE94 color difference formulae.
|
||||
// The dE94 is normalized so that the value of 1.0 is the "just-noticeable-difference".
|
||||
// Color difference below 1.0 is not noticeable to a human eye, so we can disregard it.
|
||||
// See https://en.wikipedia.org/wiki/Color_difference
|
||||
const delta = (0, _colorUtils.colorDeltaE94)([r1.get(x, y), g1.get(x, y), b1.get(x, y)], [r2.get(x, y), g2.get(x, y), b2.get(x, y)]);
|
||||
if (delta <= maxColorDeltaE94) {
|
||||
drawGrayPixel(x, y);
|
||||
continue;
|
||||
}
|
||||
if (!fastR || !fastG || !fastB) {
|
||||
fastR = new _stats.FastStats(r1, r2);
|
||||
fastG = new _stats.FastStats(g1, g2);
|
||||
fastB = new _stats.FastStats(b1, b2);
|
||||
}
|
||||
const [varX1, varY1] = r1.boundXY(x - VARIANCE_WINDOW_RADIUS, y - VARIANCE_WINDOW_RADIUS);
|
||||
const [varX2, varY2] = r1.boundXY(x + VARIANCE_WINDOW_RADIUS, y + VARIANCE_WINDOW_RADIUS);
|
||||
const var1 = fastR.varianceC1(varX1, varY1, varX2, varY2) + fastG.varianceC1(varX1, varY1, varX2, varY2) + fastB.varianceC1(varX1, varY1, varX2, varY2);
|
||||
const var2 = fastR.varianceC2(varX1, varY1, varX2, varY2) + fastG.varianceC2(varX1, varY1, varX2, varY2) + fastB.varianceC2(varX1, varY1, varX2, varY2);
|
||||
// if this pixel is a part of a flood fill of a 3x3 square of either of the images, then it cannot be
|
||||
// anti-aliasing pixel so it must be a pixel difference.
|
||||
if (var1 === 0 || var2 === 0) {
|
||||
drawRedPixel(x, y);
|
||||
++diffCount;
|
||||
continue;
|
||||
}
|
||||
const [ssimX1, ssimY1] = r1.boundXY(x - SSIM_WINDOW_RADIUS, y - SSIM_WINDOW_RADIUS);
|
||||
const [ssimX2, ssimY2] = r1.boundXY(x + SSIM_WINDOW_RADIUS, y + SSIM_WINDOW_RADIUS);
|
||||
const ssimRGB = ((0, _stats.ssim)(fastR, ssimX1, ssimY1, ssimX2, ssimY2) + (0, _stats.ssim)(fastG, ssimX1, ssimY1, ssimX2, ssimY2) + (0, _stats.ssim)(fastB, ssimX1, ssimY1, ssimX2, ssimY2)) / 3.0;
|
||||
const isAntialiased = ssimRGB >= 0.99;
|
||||
if (isAntialiased) {
|
||||
drawYellowPixel(x, y);
|
||||
} else {
|
||||
drawRedPixel(x, y);
|
||||
++diffCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
return diffCount;
|
||||
}
|
||||
70
node_modules/playwright-core/lib/server/utils/image_tools/imageChannel.js
generated
vendored
Normal file
70
node_modules/playwright-core/lib/server/utils/image_tools/imageChannel.js
generated
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.ImageChannel = void 0;
|
||||
var _colorUtils = require("./colorUtils");
|
||||
/**
|
||||
* 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 ImageChannel {
|
||||
static intoRGB(width, height, data, options = {}) {
|
||||
const {
|
||||
paddingSize = 0,
|
||||
paddingColorOdd = [255, 0, 255],
|
||||
paddingColorEven = [0, 255, 0]
|
||||
} = options;
|
||||
const newWidth = width + 2 * paddingSize;
|
||||
const newHeight = height + 2 * paddingSize;
|
||||
const r = new Uint8Array(newWidth * newHeight);
|
||||
const g = new Uint8Array(newWidth * newHeight);
|
||||
const b = new Uint8Array(newWidth * newHeight);
|
||||
for (let y = 0; y < newHeight; ++y) {
|
||||
for (let x = 0; x < newWidth; ++x) {
|
||||
const index = y * newWidth + x;
|
||||
if (y >= paddingSize && y < newHeight - paddingSize && x >= paddingSize && x < newWidth - paddingSize) {
|
||||
const offset = ((y - paddingSize) * width + (x - paddingSize)) * 4;
|
||||
const alpha = data[offset + 3] === 255 ? 1 : data[offset + 3] / 255;
|
||||
r[index] = (0, _colorUtils.blendWithWhite)(data[offset], alpha);
|
||||
g[index] = (0, _colorUtils.blendWithWhite)(data[offset + 1], alpha);
|
||||
b[index] = (0, _colorUtils.blendWithWhite)(data[offset + 2], alpha);
|
||||
} else {
|
||||
const color = (y + x) % 2 === 0 ? paddingColorEven : paddingColorOdd;
|
||||
r[index] = color[0];
|
||||
g[index] = color[1];
|
||||
b[index] = color[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
return [new ImageChannel(newWidth, newHeight, r), new ImageChannel(newWidth, newHeight, g), new ImageChannel(newWidth, newHeight, b)];
|
||||
}
|
||||
constructor(width, height, data) {
|
||||
this.data = void 0;
|
||||
this.width = void 0;
|
||||
this.height = void 0;
|
||||
this.data = data;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
}
|
||||
get(x, y) {
|
||||
return this.data[y * this.width + x];
|
||||
}
|
||||
boundXY(x, y) {
|
||||
return [Math.min(Math.max(x, 0), this.width - 1), Math.min(Math.max(y, 0), this.height - 1)];
|
||||
}
|
||||
}
|
||||
exports.ImageChannel = ImageChannel;
|
||||
102
node_modules/playwright-core/lib/server/utils/image_tools/stats.js
generated
vendored
Normal file
102
node_modules/playwright-core/lib/server/utils/image_tools/stats.js
generated
vendored
Normal file
@@ -0,0 +1,102 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.FastStats = void 0;
|
||||
exports.ssim = ssim;
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// Image channel has a 8-bit depth.
|
||||
const DYNAMIC_RANGE = 2 ** 8 - 1;
|
||||
function ssim(stats, x1, y1, x2, y2) {
|
||||
const mean1 = stats.meanC1(x1, y1, x2, y2);
|
||||
const mean2 = stats.meanC2(x1, y1, x2, y2);
|
||||
const var1 = stats.varianceC1(x1, y1, x2, y2);
|
||||
const var2 = stats.varianceC2(x1, y1, x2, y2);
|
||||
const cov = stats.covariance(x1, y1, x2, y2);
|
||||
const c1 = (0.01 * DYNAMIC_RANGE) ** 2;
|
||||
const c2 = (0.03 * DYNAMIC_RANGE) ** 2;
|
||||
return (2 * mean1 * mean2 + c1) * (2 * cov + c2) / (mean1 ** 2 + mean2 ** 2 + c1) / (var1 + var2 + c2);
|
||||
}
|
||||
class FastStats {
|
||||
constructor(c1, c2) {
|
||||
this.c1 = void 0;
|
||||
this.c2 = void 0;
|
||||
this._partialSumC1 = void 0;
|
||||
this._partialSumC2 = void 0;
|
||||
this._partialSumMult = void 0;
|
||||
this._partialSumSq1 = void 0;
|
||||
this._partialSumSq2 = void 0;
|
||||
this.c1 = c1;
|
||||
this.c2 = c2;
|
||||
const {
|
||||
width,
|
||||
height
|
||||
} = c1;
|
||||
this._partialSumC1 = new Array(width * height);
|
||||
this._partialSumC2 = new Array(width * height);
|
||||
this._partialSumSq1 = new Array(width * height);
|
||||
this._partialSumSq2 = new Array(width * height);
|
||||
this._partialSumMult = new Array(width * height);
|
||||
const recalc = (mx, idx, initial, x, y) => {
|
||||
mx[idx] = initial;
|
||||
if (y > 0) mx[idx] += mx[(y - 1) * width + x];
|
||||
if (x > 0) mx[idx] += mx[y * width + x - 1];
|
||||
if (x > 0 && y > 0) mx[idx] -= mx[(y - 1) * width + x - 1];
|
||||
};
|
||||
for (let y = 0; y < height; ++y) {
|
||||
for (let x = 0; x < width; ++x) {
|
||||
const idx = y * width + x;
|
||||
recalc(this._partialSumC1, idx, this.c1.data[idx], x, y);
|
||||
recalc(this._partialSumC2, idx, this.c2.data[idx], x, y);
|
||||
recalc(this._partialSumSq1, idx, this.c1.data[idx] * this.c1.data[idx], x, y);
|
||||
recalc(this._partialSumSq2, idx, this.c2.data[idx] * this.c2.data[idx], x, y);
|
||||
recalc(this._partialSumMult, idx, this.c1.data[idx] * this.c2.data[idx], x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
_sum(partialSum, x1, y1, x2, y2) {
|
||||
const width = this.c1.width;
|
||||
let result = partialSum[y2 * width + x2];
|
||||
if (y1 > 0) result -= partialSum[(y1 - 1) * width + x2];
|
||||
if (x1 > 0) result -= partialSum[y2 * width + x1 - 1];
|
||||
if (x1 > 0 && y1 > 0) result += partialSum[(y1 - 1) * width + x1 - 1];
|
||||
return result;
|
||||
}
|
||||
meanC1(x1, y1, x2, y2) {
|
||||
const N = (y2 - y1 + 1) * (x2 - x1 + 1);
|
||||
return this._sum(this._partialSumC1, x1, y1, x2, y2) / N;
|
||||
}
|
||||
meanC2(x1, y1, x2, y2) {
|
||||
const N = (y2 - y1 + 1) * (x2 - x1 + 1);
|
||||
return this._sum(this._partialSumC2, x1, y1, x2, y2) / N;
|
||||
}
|
||||
varianceC1(x1, y1, x2, y2) {
|
||||
const N = (y2 - y1 + 1) * (x2 - x1 + 1);
|
||||
return (this._sum(this._partialSumSq1, x1, y1, x2, y2) - this._sum(this._partialSumC1, x1, y1, x2, y2) ** 2 / N) / N;
|
||||
}
|
||||
varianceC2(x1, y1, x2, y2) {
|
||||
const N = (y2 - y1 + 1) * (x2 - x1 + 1);
|
||||
return (this._sum(this._partialSumSq2, x1, y1, x2, y2) - this._sum(this._partialSumC2, x1, y1, x2, y2) ** 2 / N) / N;
|
||||
}
|
||||
covariance(x1, y1, x2, y2) {
|
||||
const N = (y2 - y1 + 1) * (x2 - x1 + 1);
|
||||
return (this._sum(this._partialSumMult, x1, y1, x2, y2) - this._sum(this._partialSumC1, x1, y1, x2, y2) * this._sum(this._partialSumC2, x1, y1, x2, y2) / N) / N;
|
||||
}
|
||||
}
|
||||
exports.FastStats = FastStats;
|
||||
58
node_modules/playwright-core/lib/server/utils/linuxUtils.js
generated
vendored
Normal file
58
node_modules/playwright-core/lib/server/utils/linuxUtils.js
generated
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.getLinuxDistributionInfoSync = getLinuxDistributionInfoSync;
|
||||
var _fs = _interopRequireDefault(require("fs"));
|
||||
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
||||
/**
|
||||
* 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;
|
||||
function getLinuxDistributionInfoSync() {
|
||||
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 = _fs.default.readFileSync('/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 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;
|
||||
}
|
||||
160
node_modules/playwright-core/lib/server/utils/network.js
generated
vendored
Normal file
160
node_modules/playwright-core/lib/server/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 _http2 = _interopRequireDefault(require("http2"));
|
||||
var _https = _interopRequireDefault(require("https"));
|
||||
var _url = _interopRequireDefault(require("url"));
|
||||
var _utilsBundle = require("../../utilsBundle");
|
||||
var _happyEyeballs = require("./happyEyeballs");
|
||||
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
||||
/**
|
||||
* 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 = _url.default.parse(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);
|
||||
};
|
||||
}
|
||||
140
node_modules/playwright-core/lib/server/utils/nodePlatform.js
generated
vendored
Normal file
140
node_modules/playwright-core/lib/server/utils/nodePlatform.js
generated
vendored
Normal file
@@ -0,0 +1,140 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.nodePlatform = void 0;
|
||||
exports.setBoxedStackPrefixes = setBoxedStackPrefixes;
|
||||
var _crypto = _interopRequireDefault(require("crypto"));
|
||||
var _fs = _interopRequireDefault(require("fs"));
|
||||
var _path = _interopRequireDefault(require("path"));
|
||||
var util = _interopRequireWildcard(require("util"));
|
||||
var _stream = require("stream");
|
||||
var _events = require("events");
|
||||
var _utilsBundle = require("../../utilsBundle");
|
||||
var _debugLogger = require("./debugLogger");
|
||||
var _zones = require("./zones");
|
||||
var _debug = require("./debug");
|
||||
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 && {}.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(e) { return e && e.__esModule ? e : { default: e }; }
|
||||
/**
|
||||
* 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 pipelineAsync = util.promisify(_stream.pipeline);
|
||||
class NodeZone {
|
||||
constructor(zone) {
|
||||
this._zone = void 0;
|
||||
this._zone = zone;
|
||||
}
|
||||
push(data) {
|
||||
return new NodeZone(this._zone.with('apiZone', data));
|
||||
}
|
||||
pop() {
|
||||
return new NodeZone(this._zone.without('apiZone'));
|
||||
}
|
||||
run(func) {
|
||||
return this._zone.run(func);
|
||||
}
|
||||
data() {
|
||||
return this._zone.data('apiZone');
|
||||
}
|
||||
}
|
||||
let boxedStackPrefixes = [];
|
||||
function setBoxedStackPrefixes(prefixes) {
|
||||
boxedStackPrefixes = prefixes;
|
||||
}
|
||||
const coreDir = _path.default.dirname(require.resolve('../../../package.json'));
|
||||
const nodePlatform = exports.nodePlatform = {
|
||||
name: 'node',
|
||||
boxedStackPrefixes: () => {
|
||||
if (process.env.PWDEBUGIMPL) return [];
|
||||
return [coreDir, ...boxedStackPrefixes];
|
||||
},
|
||||
calculateSha1: text => {
|
||||
const sha1 = _crypto.default.createHash('sha1');
|
||||
sha1.update(text);
|
||||
return Promise.resolve(sha1.digest('hex'));
|
||||
},
|
||||
colors: _utilsBundle.colors,
|
||||
coreDir,
|
||||
createGuid: () => _crypto.default.randomBytes(16).toString('hex'),
|
||||
defaultMaxListeners: () => _events.EventEmitter.defaultMaxListeners,
|
||||
fs: () => _fs.default,
|
||||
env: process.env,
|
||||
inspectCustom: util.inspect.custom,
|
||||
isDebugMode: () => !!(0, _debug.debugMode)(),
|
||||
isJSDebuggerAttached: () => !!require('inspector').url(),
|
||||
isLogEnabled(name) {
|
||||
return _debugLogger.debugLogger.isEnabled(name);
|
||||
},
|
||||
isUnderTest: () => (0, _debug.isUnderTest)(),
|
||||
log(name, message) {
|
||||
_debugLogger.debugLogger.log(name, message);
|
||||
},
|
||||
path: () => _path.default,
|
||||
pathSeparator: _path.default.sep,
|
||||
showInternalStackFrames: () => !!process.env.PWDEBUGIMPL,
|
||||
async streamFile(path, stream) {
|
||||
await pipelineAsync(_fs.default.createReadStream(path), stream);
|
||||
},
|
||||
streamReadable: channel => {
|
||||
return new ReadableStreamImpl(channel);
|
||||
},
|
||||
streamWritable: channel => {
|
||||
return new WritableStreamImpl(channel);
|
||||
},
|
||||
zones: {
|
||||
current: () => new NodeZone((0, _zones.currentZone)()),
|
||||
empty: new NodeZone(_zones.emptyZone)
|
||||
}
|
||||
};
|
||||
class ReadableStreamImpl extends _stream.Readable {
|
||||
constructor(channel) {
|
||||
super();
|
||||
this._channel = void 0;
|
||||
this._channel = channel;
|
||||
}
|
||||
async _read() {
|
||||
const result = await this._channel.read({
|
||||
size: 1024 * 1024
|
||||
});
|
||||
if (result.binary.byteLength) this.push(result.binary);else this.push(null);
|
||||
}
|
||||
_destroy(error, callback) {
|
||||
// Stream might be destroyed after the connection was closed.
|
||||
this._channel.close().catch(e => null);
|
||||
super._destroy(error, callback);
|
||||
}
|
||||
}
|
||||
class WritableStreamImpl extends _stream.Writable {
|
||||
constructor(channel) {
|
||||
super();
|
||||
this._channel = void 0;
|
||||
this._channel = channel;
|
||||
}
|
||||
async _write(chunk, encoding, callback) {
|
||||
const error = await this._channel.write({
|
||||
binary: typeof chunk === 'string' ? Buffer.from(chunk) : chunk
|
||||
}).catch(e => e);
|
||||
callback(error || null);
|
||||
}
|
||||
async _final(callback) {
|
||||
// Stream might be destroyed after the connection was closed.
|
||||
const error = await this._channel.close().catch(e => e);
|
||||
callback(error || null);
|
||||
}
|
||||
}
|
||||
82
node_modules/playwright-core/lib/server/utils/pipeTransport.js
generated
vendored
Normal file
82
node_modules/playwright-core/lib/server/utils/pipeTransport.js
generated
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.PipeTransport = void 0;
|
||||
var _task = require("./task");
|
||||
/**
|
||||
* 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 PipeTransport {
|
||||
constructor(pipeWrite, pipeRead, closeable, endian = 'le') {
|
||||
this._pipeWrite = void 0;
|
||||
this._data = Buffer.from([]);
|
||||
this._waitForNextTask = (0, _task.makeWaitForNextTask)();
|
||||
this._closed = false;
|
||||
this._bytesLeft = 0;
|
||||
this.onmessage = void 0;
|
||||
this.onclose = void 0;
|
||||
this._endian = void 0;
|
||||
this._closeableStream = void 0;
|
||||
this._pipeWrite = pipeWrite;
|
||||
this._endian = endian;
|
||||
this._closeableStream = closeable;
|
||||
pipeRead.on('data', buffer => this._dispatch(buffer));
|
||||
pipeRead.on('close', () => {
|
||||
this._closed = true;
|
||||
if (this.onclose) this.onclose();
|
||||
});
|
||||
this.onmessage = undefined;
|
||||
this.onclose = undefined;
|
||||
}
|
||||
send(message) {
|
||||
if (this._closed) throw new Error('Pipe has been closed');
|
||||
const data = Buffer.from(message, 'utf-8');
|
||||
const dataLength = Buffer.alloc(4);
|
||||
if (this._endian === 'be') dataLength.writeUInt32BE(data.length, 0);else dataLength.writeUInt32LE(data.length, 0);
|
||||
this._pipeWrite.write(dataLength);
|
||||
this._pipeWrite.write(data);
|
||||
}
|
||||
close() {
|
||||
// Let it throw.
|
||||
this._closeableStream.close();
|
||||
}
|
||||
_dispatch(buffer) {
|
||||
this._data = Buffer.concat([this._data, buffer]);
|
||||
while (true) {
|
||||
if (!this._bytesLeft && this._data.length < 4) {
|
||||
// Need more data.
|
||||
break;
|
||||
}
|
||||
if (!this._bytesLeft) {
|
||||
this._bytesLeft = this._endian === 'be' ? this._data.readUInt32BE(0) : this._data.readUInt32LE(0);
|
||||
this._data = this._data.slice(4);
|
||||
}
|
||||
if (!this._bytesLeft || this._data.length < this._bytesLeft) {
|
||||
// Need more data.
|
||||
break;
|
||||
}
|
||||
const message = this._data.slice(0, this._bytesLeft);
|
||||
this._data = this._data.slice(this._bytesLeft);
|
||||
this._bytesLeft = 0;
|
||||
this._waitForNextTask(() => {
|
||||
if (this.onmessage) this.onmessage(message.toString('utf-8'));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.PipeTransport = PipeTransport;
|
||||
248
node_modules/playwright-core/lib/server/utils/processLauncher.js
generated
vendored
Normal file
248
node_modules/playwright-core/lib/server/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 childProcess = _interopRequireWildcard(require("child_process"));
|
||||
var _fs = _interopRequireDefault(require("fs"));
|
||||
var readline = _interopRequireWildcard(require("readline"));
|
||||
var _fileUtils = require("./fileUtils");
|
||||
var _utils = require("../../utils");
|
||||
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
||||
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 && {}.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 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, _utils.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('close', (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;
|
||||
}
|
||||
52
node_modules/playwright-core/lib/server/utils/profiler.js
generated
vendored
Normal file
52
node_modules/playwright-core/lib/server/utils/profiler.js
generated
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.startProfiling = startProfiling;
|
||||
exports.stopProfiling = stopProfiling;
|
||||
var _fs = _interopRequireDefault(require("fs"));
|
||||
var _path = _interopRequireDefault(require("path"));
|
||||
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
||||
/**
|
||||
* 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.default.mkdirSync(profileDir, {
|
||||
recursive: true
|
||||
});
|
||||
_fs.default.writeFileSync(_path.default.join(profileDir, profileName + '.json'), JSON.stringify(profile));
|
||||
}
|
||||
f();
|
||||
}));
|
||||
}
|
||||
570
node_modules/playwright-core/lib/server/utils/socksProxy.js
generated
vendored
Normal file
570
node_modules/playwright-core/lib/server/utils/socksProxy.js
generated
vendored
Normal file
@@ -0,0 +1,570 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.SocksProxyHandler = exports.SocksProxy = void 0;
|
||||
exports.parsePattern = parsePattern;
|
||||
var _events = _interopRequireDefault(require("events"));
|
||||
var _net = _interopRequireDefault(require("net"));
|
||||
var _assert = require("../../utils/isomorphic/assert");
|
||||
var _crypto = require("./crypto");
|
||||
var _debugLogger = require("./debugLogger");
|
||||
var _happyEyeballs = require("./happyEyeballs");
|
||||
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
||||
/**
|
||||
* 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://tools.ietf.org/html/rfc1928
|
||||
var SocksAuth = /*#__PURE__*/function (SocksAuth) {
|
||||
SocksAuth[SocksAuth["NO_AUTHENTICATION_REQUIRED"] = 0] = "NO_AUTHENTICATION_REQUIRED";
|
||||
SocksAuth[SocksAuth["GSSAPI"] = 1] = "GSSAPI";
|
||||
SocksAuth[SocksAuth["USERNAME_PASSWORD"] = 2] = "USERNAME_PASSWORD";
|
||||
SocksAuth[SocksAuth["NO_ACCEPTABLE_METHODS"] = 255] = "NO_ACCEPTABLE_METHODS";
|
||||
return SocksAuth;
|
||||
}(SocksAuth || {});
|
||||
var SocksAddressType = /*#__PURE__*/function (SocksAddressType) {
|
||||
SocksAddressType[SocksAddressType["IPv4"] = 1] = "IPv4";
|
||||
SocksAddressType[SocksAddressType["FqName"] = 3] = "FqName";
|
||||
SocksAddressType[SocksAddressType["IPv6"] = 4] = "IPv6";
|
||||
return SocksAddressType;
|
||||
}(SocksAddressType || {});
|
||||
var SocksCommand = /*#__PURE__*/function (SocksCommand) {
|
||||
SocksCommand[SocksCommand["CONNECT"] = 1] = "CONNECT";
|
||||
SocksCommand[SocksCommand["BIND"] = 2] = "BIND";
|
||||
SocksCommand[SocksCommand["UDP_ASSOCIATE"] = 3] = "UDP_ASSOCIATE";
|
||||
return SocksCommand;
|
||||
}(SocksCommand || {});
|
||||
var SocksReply = /*#__PURE__*/function (SocksReply) {
|
||||
SocksReply[SocksReply["Succeeded"] = 0] = "Succeeded";
|
||||
SocksReply[SocksReply["GeneralServerFailure"] = 1] = "GeneralServerFailure";
|
||||
SocksReply[SocksReply["NotAllowedByRuleSet"] = 2] = "NotAllowedByRuleSet";
|
||||
SocksReply[SocksReply["NetworkUnreachable"] = 3] = "NetworkUnreachable";
|
||||
SocksReply[SocksReply["HostUnreachable"] = 4] = "HostUnreachable";
|
||||
SocksReply[SocksReply["ConnectionRefused"] = 5] = "ConnectionRefused";
|
||||
SocksReply[SocksReply["TtlExpired"] = 6] = "TtlExpired";
|
||||
SocksReply[SocksReply["CommandNotSupported"] = 7] = "CommandNotSupported";
|
||||
SocksReply[SocksReply["AddressTypeNotSupported"] = 8] = "AddressTypeNotSupported";
|
||||
return SocksReply;
|
||||
}(SocksReply || {});
|
||||
class SocksConnection {
|
||||
constructor(uid, socket, client) {
|
||||
this._buffer = Buffer.from([]);
|
||||
this._offset = 0;
|
||||
this._fence = 0;
|
||||
this._fenceCallback = void 0;
|
||||
this._socket = void 0;
|
||||
this._boundOnData = void 0;
|
||||
this._uid = void 0;
|
||||
this._client = void 0;
|
||||
this._uid = uid;
|
||||
this._socket = socket;
|
||||
this._client = client;
|
||||
this._boundOnData = this._onData.bind(this);
|
||||
socket.on('data', this._boundOnData);
|
||||
socket.on('close', () => this._onClose());
|
||||
socket.on('end', () => this._onClose());
|
||||
socket.on('error', () => this._onClose());
|
||||
this._run().catch(() => this._socket.end());
|
||||
}
|
||||
async _run() {
|
||||
(0, _assert.assert)(await this._authenticate());
|
||||
const {
|
||||
command,
|
||||
host,
|
||||
port
|
||||
} = await this._parseRequest();
|
||||
if (command !== SocksCommand.CONNECT) {
|
||||
this._writeBytes(Buffer.from([0x05, SocksReply.CommandNotSupported, 0x00,
|
||||
// RSV
|
||||
0x01,
|
||||
// IPv4
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
// Address
|
||||
0x00, 0x00 // Port
|
||||
]));
|
||||
return;
|
||||
}
|
||||
this._socket.off('data', this._boundOnData);
|
||||
this._client.onSocketRequested({
|
||||
uid: this._uid,
|
||||
host,
|
||||
port
|
||||
});
|
||||
}
|
||||
async _authenticate() {
|
||||
// Request:
|
||||
// +----+----------+----------+
|
||||
// |VER | NMETHODS | METHODS |
|
||||
// +----+----------+----------+
|
||||
// | 1 | 1 | 1 to 255 |
|
||||
// +----+----------+----------+
|
||||
|
||||
// Response:
|
||||
// +----+--------+
|
||||
// |VER | METHOD |
|
||||
// +----+--------+
|
||||
// | 1 | 1 |
|
||||
// +----+--------+
|
||||
|
||||
const version = await this._readByte();
|
||||
(0, _assert.assert)(version === 0x05, 'The VER field must be set to x05 for this version of the protocol, was ' + version);
|
||||
const nMethods = await this._readByte();
|
||||
(0, _assert.assert)(nMethods, 'No authentication methods specified');
|
||||
const methods = await this._readBytes(nMethods);
|
||||
for (const method of methods) {
|
||||
if (method === 0) {
|
||||
this._writeBytes(Buffer.from([version, method]));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
this._writeBytes(Buffer.from([version, SocksAuth.NO_ACCEPTABLE_METHODS]));
|
||||
return false;
|
||||
}
|
||||
async _parseRequest() {
|
||||
// Request.
|
||||
// +----+-----+-------+------+----------+----------+
|
||||
// |VER | CMD | RSV | ATYP | DST.ADDR | DST.PORT |
|
||||
// +----+-----+-------+------+----------+----------+
|
||||
// | 1 | 1 | X'00' | 1 | Variable | 2 |
|
||||
// +----+-----+-------+------+----------+----------+
|
||||
|
||||
// Response.
|
||||
// +----+-----+-------+------+----------+----------+
|
||||
// |VER | REP | RSV | ATYP | BND.ADDR | BND.PORT |
|
||||
// +----+-----+-------+------+----------+----------+
|
||||
// | 1 | 1 | X'00' | 1 | Variable | 2 |
|
||||
// +----+-----+-------+------+----------+----------+
|
||||
|
||||
const version = await this._readByte();
|
||||
(0, _assert.assert)(version === 0x05, 'The VER field must be set to x05 for this version of the protocol, was ' + version);
|
||||
const command = await this._readByte();
|
||||
await this._readByte(); // skip reserved.
|
||||
const addressType = await this._readByte();
|
||||
let host = '';
|
||||
switch (addressType) {
|
||||
case SocksAddressType.IPv4:
|
||||
host = (await this._readBytes(4)).join('.');
|
||||
break;
|
||||
case SocksAddressType.FqName:
|
||||
const length = await this._readByte();
|
||||
host = (await this._readBytes(length)).toString();
|
||||
break;
|
||||
case SocksAddressType.IPv6:
|
||||
const bytes = await this._readBytes(16);
|
||||
const tokens = [];
|
||||
for (let i = 0; i < 8; ++i) tokens.push(bytes.readUInt16BE(i * 2).toString(16));
|
||||
host = tokens.join(':');
|
||||
break;
|
||||
}
|
||||
const port = (await this._readBytes(2)).readUInt16BE(0);
|
||||
this._buffer = Buffer.from([]);
|
||||
this._offset = 0;
|
||||
this._fence = 0;
|
||||
return {
|
||||
command,
|
||||
host,
|
||||
port
|
||||
};
|
||||
}
|
||||
async _readByte() {
|
||||
const buffer = await this._readBytes(1);
|
||||
return buffer[0];
|
||||
}
|
||||
async _readBytes(length) {
|
||||
this._fence = this._offset + length;
|
||||
if (!this._buffer || this._buffer.length < this._fence) await new Promise(f => this._fenceCallback = f);
|
||||
this._offset += length;
|
||||
return this._buffer.slice(this._offset - length, this._offset);
|
||||
}
|
||||
_writeBytes(buffer) {
|
||||
if (this._socket.writable) this._socket.write(buffer);
|
||||
}
|
||||
_onClose() {
|
||||
this._client.onSocketClosed({
|
||||
uid: this._uid
|
||||
});
|
||||
}
|
||||
_onData(buffer) {
|
||||
this._buffer = Buffer.concat([this._buffer, buffer]);
|
||||
if (this._fenceCallback && this._buffer.length >= this._fence) {
|
||||
const callback = this._fenceCallback;
|
||||
this._fenceCallback = undefined;
|
||||
callback();
|
||||
}
|
||||
}
|
||||
socketConnected(host, port) {
|
||||
this._writeBytes(Buffer.from([0x05, SocksReply.Succeeded, 0x00,
|
||||
// RSV
|
||||
...ipToSocksAddress(host),
|
||||
// ATYP, Address
|
||||
port >> 8, port & 0xFF // Port
|
||||
]));
|
||||
this._socket.on('data', data => this._client.onSocketData({
|
||||
uid: this._uid,
|
||||
data
|
||||
}));
|
||||
}
|
||||
socketFailed(errorCode) {
|
||||
const buffer = Buffer.from([0x05, 0, 0x00,
|
||||
// RSV
|
||||
...ipToSocksAddress('0.0.0.0'),
|
||||
// ATYP, Address
|
||||
0, 0 // Port
|
||||
]);
|
||||
switch (errorCode) {
|
||||
case 'ENOENT':
|
||||
case 'ENOTFOUND':
|
||||
case 'ETIMEDOUT':
|
||||
case 'EHOSTUNREACH':
|
||||
buffer[1] = SocksReply.HostUnreachable;
|
||||
break;
|
||||
case 'ENETUNREACH':
|
||||
buffer[1] = SocksReply.NetworkUnreachable;
|
||||
break;
|
||||
case 'ECONNREFUSED':
|
||||
buffer[1] = SocksReply.ConnectionRefused;
|
||||
break;
|
||||
case 'ERULESET':
|
||||
buffer[1] = SocksReply.NotAllowedByRuleSet;
|
||||
break;
|
||||
}
|
||||
this._writeBytes(buffer);
|
||||
this._socket.end();
|
||||
}
|
||||
sendData(data) {
|
||||
this._socket.write(data);
|
||||
}
|
||||
end() {
|
||||
this._socket.end();
|
||||
}
|
||||
error(error) {
|
||||
this._socket.destroy(new Error(error));
|
||||
}
|
||||
}
|
||||
function hexToNumber(hex) {
|
||||
// Note: parseInt has a few issues including ignoring trailing characters and allowing leading 0x.
|
||||
return [...hex].reduce((value, digit) => {
|
||||
const code = digit.charCodeAt(0);
|
||||
if (code >= 48 && code <= 57)
|
||||
// 0..9
|
||||
return value + code;
|
||||
if (code >= 97 && code <= 102)
|
||||
// a..f
|
||||
return value + (code - 97) + 10;
|
||||
if (code >= 65 && code <= 70)
|
||||
// A..F
|
||||
return value + (code - 65) + 10;
|
||||
throw new Error('Invalid IPv6 token ' + hex);
|
||||
}, 0);
|
||||
}
|
||||
function ipToSocksAddress(address) {
|
||||
if (_net.default.isIPv4(address)) {
|
||||
return [0x01,
|
||||
// IPv4
|
||||
...address.split('.', 4).map(t => +t & 0xFF) // Address
|
||||
];
|
||||
}
|
||||
if (_net.default.isIPv6(address)) {
|
||||
const result = [0x04]; // IPv6
|
||||
const tokens = address.split(':', 8);
|
||||
while (tokens.length < 8) tokens.unshift('');
|
||||
for (const token of tokens) {
|
||||
const value = hexToNumber(token);
|
||||
result.push(value >> 8 & 0xFF, value & 0xFF); // Big-endian
|
||||
}
|
||||
return result;
|
||||
}
|
||||
throw new Error('Only IPv4 and IPv6 addresses are supported');
|
||||
}
|
||||
function starMatchToRegex(pattern) {
|
||||
const source = pattern.split('*').map(s => {
|
||||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping
|
||||
return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||
}).join('.*');
|
||||
return new RegExp('^' + source + '$');
|
||||
}
|
||||
|
||||
// This follows "Proxy bypass rules" syntax without implicit and negative rules.
|
||||
// https://source.chromium.org/chromium/chromium/src/+/main:net/docs/proxy.md;l=331
|
||||
function parsePattern(pattern) {
|
||||
if (!pattern) return () => false;
|
||||
const matchers = pattern.split(',').map(token => {
|
||||
const match = token.match(/^(.*?)(?::(\d+))?$/);
|
||||
if (!match) throw new Error(`Unsupported token "${token}" in pattern "${pattern}"`);
|
||||
const tokenPort = match[2] ? +match[2] : undefined;
|
||||
const portMatches = port => tokenPort === undefined || tokenPort === port;
|
||||
let tokenHost = match[1];
|
||||
if (tokenHost === '<loopback>') {
|
||||
return (host, port) => {
|
||||
if (!portMatches(port)) return false;
|
||||
return host === 'localhost' || host.endsWith('.localhost') || host === '127.0.0.1' || host === '[::1]';
|
||||
};
|
||||
}
|
||||
if (tokenHost === '*') return (host, port) => portMatches(port);
|
||||
if (_net.default.isIPv4(tokenHost) || _net.default.isIPv6(tokenHost)) return (host, port) => host === tokenHost && portMatches(port);
|
||||
if (tokenHost[0] === '.') tokenHost = '*' + tokenHost;
|
||||
const tokenRegex = starMatchToRegex(tokenHost);
|
||||
return (host, port) => {
|
||||
if (!portMatches(port)) return false;
|
||||
if (_net.default.isIPv4(host) || _net.default.isIPv6(host)) return false;
|
||||
return !!host.match(tokenRegex);
|
||||
};
|
||||
});
|
||||
return (host, port) => matchers.some(matcher => matcher(host, port));
|
||||
}
|
||||
class SocksProxy extends _events.default {
|
||||
constructor() {
|
||||
super();
|
||||
this._server = void 0;
|
||||
this._connections = new Map();
|
||||
this._sockets = new Set();
|
||||
this._closed = false;
|
||||
this._port = void 0;
|
||||
this._patternMatcher = () => false;
|
||||
this._directSockets = new Map();
|
||||
this._server = new _net.default.Server(socket => {
|
||||
const uid = (0, _crypto.createGuid)();
|
||||
const connection = new SocksConnection(uid, socket, this);
|
||||
this._connections.set(uid, connection);
|
||||
});
|
||||
this._server.on('connection', socket => {
|
||||
if (this._closed) {
|
||||
socket.destroy();
|
||||
return;
|
||||
}
|
||||
this._sockets.add(socket);
|
||||
socket.once('close', () => this._sockets.delete(socket));
|
||||
});
|
||||
}
|
||||
setPattern(pattern) {
|
||||
try {
|
||||
this._patternMatcher = parsePattern(pattern);
|
||||
} catch (e) {
|
||||
this._patternMatcher = () => false;
|
||||
}
|
||||
}
|
||||
async _handleDirect(request) {
|
||||
try {
|
||||
var _this$_connections$ge4;
|
||||
const socket = await (0, _happyEyeballs.createSocket)(request.host, request.port);
|
||||
socket.on('data', data => {
|
||||
var _this$_connections$ge;
|
||||
return (_this$_connections$ge = this._connections.get(request.uid)) === null || _this$_connections$ge === void 0 ? void 0 : _this$_connections$ge.sendData(data);
|
||||
});
|
||||
socket.on('error', error => {
|
||||
var _this$_connections$ge2;
|
||||
(_this$_connections$ge2 = this._connections.get(request.uid)) === null || _this$_connections$ge2 === void 0 || _this$_connections$ge2.error(error.message);
|
||||
this._directSockets.delete(request.uid);
|
||||
});
|
||||
socket.on('end', () => {
|
||||
var _this$_connections$ge3;
|
||||
(_this$_connections$ge3 = this._connections.get(request.uid)) === null || _this$_connections$ge3 === void 0 || _this$_connections$ge3.end();
|
||||
this._directSockets.delete(request.uid);
|
||||
});
|
||||
const localAddress = socket.localAddress;
|
||||
const localPort = socket.localPort;
|
||||
this._directSockets.set(request.uid, socket);
|
||||
(_this$_connections$ge4 = this._connections.get(request.uid)) === null || _this$_connections$ge4 === void 0 || _this$_connections$ge4.socketConnected(localAddress, localPort);
|
||||
} catch (error) {
|
||||
var _this$_connections$ge5;
|
||||
(_this$_connections$ge5 = this._connections.get(request.uid)) === null || _this$_connections$ge5 === void 0 || _this$_connections$ge5.socketFailed(error.code);
|
||||
}
|
||||
}
|
||||
port() {
|
||||
return this._port;
|
||||
}
|
||||
async listen(port, hostname) {
|
||||
return new Promise(f => {
|
||||
this._server.listen(port, hostname, () => {
|
||||
const port = this._server.address().port;
|
||||
this._port = port;
|
||||
f(port);
|
||||
});
|
||||
});
|
||||
}
|
||||
async close() {
|
||||
if (this._closed) return;
|
||||
this._closed = true;
|
||||
for (const socket of this._sockets) socket.destroy();
|
||||
this._sockets.clear();
|
||||
await new Promise(f => this._server.close(f));
|
||||
}
|
||||
onSocketRequested(payload) {
|
||||
if (!this._patternMatcher(payload.host, payload.port)) {
|
||||
this._handleDirect(payload);
|
||||
return;
|
||||
}
|
||||
this.emit(SocksProxy.Events.SocksRequested, payload);
|
||||
}
|
||||
onSocketData(payload) {
|
||||
const direct = this._directSockets.get(payload.uid);
|
||||
if (direct) {
|
||||
direct.write(payload.data);
|
||||
return;
|
||||
}
|
||||
this.emit(SocksProxy.Events.SocksData, payload);
|
||||
}
|
||||
onSocketClosed(payload) {
|
||||
const direct = this._directSockets.get(payload.uid);
|
||||
if (direct) {
|
||||
direct.destroy();
|
||||
this._directSockets.delete(payload.uid);
|
||||
return;
|
||||
}
|
||||
this.emit(SocksProxy.Events.SocksClosed, payload);
|
||||
}
|
||||
socketConnected({
|
||||
uid,
|
||||
host,
|
||||
port
|
||||
}) {
|
||||
var _this$_connections$ge6;
|
||||
(_this$_connections$ge6 = this._connections.get(uid)) === null || _this$_connections$ge6 === void 0 || _this$_connections$ge6.socketConnected(host, port);
|
||||
}
|
||||
socketFailed({
|
||||
uid,
|
||||
errorCode
|
||||
}) {
|
||||
var _this$_connections$ge7;
|
||||
(_this$_connections$ge7 = this._connections.get(uid)) === null || _this$_connections$ge7 === void 0 || _this$_connections$ge7.socketFailed(errorCode);
|
||||
}
|
||||
sendSocketData({
|
||||
uid,
|
||||
data
|
||||
}) {
|
||||
var _this$_connections$ge8;
|
||||
(_this$_connections$ge8 = this._connections.get(uid)) === null || _this$_connections$ge8 === void 0 || _this$_connections$ge8.sendData(data);
|
||||
}
|
||||
sendSocketEnd({
|
||||
uid
|
||||
}) {
|
||||
var _this$_connections$ge9;
|
||||
(_this$_connections$ge9 = this._connections.get(uid)) === null || _this$_connections$ge9 === void 0 || _this$_connections$ge9.end();
|
||||
}
|
||||
sendSocketError({
|
||||
uid,
|
||||
error
|
||||
}) {
|
||||
var _this$_connections$ge10;
|
||||
(_this$_connections$ge10 = this._connections.get(uid)) === null || _this$_connections$ge10 === void 0 || _this$_connections$ge10.error(error);
|
||||
}
|
||||
}
|
||||
exports.SocksProxy = SocksProxy;
|
||||
SocksProxy.Events = {
|
||||
SocksRequested: 'socksRequested',
|
||||
SocksData: 'socksData',
|
||||
SocksClosed: 'socksClosed'
|
||||
};
|
||||
class SocksProxyHandler extends _events.default {
|
||||
constructor(pattern, redirectPortForTest) {
|
||||
super();
|
||||
this._sockets = new Map();
|
||||
this._patternMatcher = () => false;
|
||||
this._redirectPortForTest = void 0;
|
||||
this._patternMatcher = parsePattern(pattern);
|
||||
this._redirectPortForTest = redirectPortForTest;
|
||||
}
|
||||
cleanup() {
|
||||
for (const uid of this._sockets.keys()) this.socketClosed({
|
||||
uid
|
||||
});
|
||||
}
|
||||
async socketRequested({
|
||||
uid,
|
||||
host,
|
||||
port
|
||||
}) {
|
||||
_debugLogger.debugLogger.log('socks', `[${uid}] => request ${host}:${port}`);
|
||||
if (!this._patternMatcher(host, port)) {
|
||||
const payload = {
|
||||
uid,
|
||||
errorCode: 'ERULESET'
|
||||
};
|
||||
_debugLogger.debugLogger.log('socks', `[${uid}] <= pattern error ${payload.errorCode}`);
|
||||
this.emit(SocksProxyHandler.Events.SocksFailed, payload);
|
||||
return;
|
||||
}
|
||||
if (host === 'local.playwright') host = 'localhost';
|
||||
try {
|
||||
if (this._redirectPortForTest) port = this._redirectPortForTest;
|
||||
const socket = await (0, _happyEyeballs.createSocket)(host, port);
|
||||
socket.on('data', data => {
|
||||
const payload = {
|
||||
uid,
|
||||
data
|
||||
};
|
||||
this.emit(SocksProxyHandler.Events.SocksData, payload);
|
||||
});
|
||||
socket.on('error', error => {
|
||||
const payload = {
|
||||
uid,
|
||||
error: error.message
|
||||
};
|
||||
_debugLogger.debugLogger.log('socks', `[${uid}] <= network socket error ${payload.error}`);
|
||||
this.emit(SocksProxyHandler.Events.SocksError, payload);
|
||||
this._sockets.delete(uid);
|
||||
});
|
||||
socket.on('end', () => {
|
||||
const payload = {
|
||||
uid
|
||||
};
|
||||
_debugLogger.debugLogger.log('socks', `[${uid}] <= network socket closed`);
|
||||
this.emit(SocksProxyHandler.Events.SocksEnd, payload);
|
||||
this._sockets.delete(uid);
|
||||
});
|
||||
const localAddress = socket.localAddress;
|
||||
const localPort = socket.localPort;
|
||||
this._sockets.set(uid, socket);
|
||||
const payload = {
|
||||
uid,
|
||||
host: localAddress,
|
||||
port: localPort
|
||||
};
|
||||
_debugLogger.debugLogger.log('socks', `[${uid}] <= connected to network ${payload.host}:${payload.port}`);
|
||||
this.emit(SocksProxyHandler.Events.SocksConnected, payload);
|
||||
} catch (error) {
|
||||
const payload = {
|
||||
uid,
|
||||
errorCode: error.code
|
||||
};
|
||||
_debugLogger.debugLogger.log('socks', `[${uid}] <= connect error ${payload.errorCode}`);
|
||||
this.emit(SocksProxyHandler.Events.SocksFailed, payload);
|
||||
}
|
||||
}
|
||||
sendSocketData({
|
||||
uid,
|
||||
data
|
||||
}) {
|
||||
var _this$_sockets$get;
|
||||
(_this$_sockets$get = this._sockets.get(uid)) === null || _this$_sockets$get === void 0 || _this$_sockets$get.write(data);
|
||||
}
|
||||
socketClosed({
|
||||
uid
|
||||
}) {
|
||||
var _this$_sockets$get2;
|
||||
_debugLogger.debugLogger.log('socks', `[${uid}] <= browser socket closed`);
|
||||
(_this$_sockets$get2 = this._sockets.get(uid)) === null || _this$_sockets$get2 === void 0 || _this$_sockets$get2.destroy();
|
||||
this._sockets.delete(uid);
|
||||
}
|
||||
}
|
||||
exports.SocksProxyHandler = SocksProxyHandler;
|
||||
SocksProxyHandler.Events = {
|
||||
SocksConnected: 'socksConnected',
|
||||
SocksData: 'socksData',
|
||||
SocksError: 'socksError',
|
||||
SocksFailed: 'socksFailed',
|
||||
SocksEnd: 'socksEnd'
|
||||
};
|
||||
45
node_modules/playwright-core/lib/server/utils/spawnAsync.js
generated
vendored
Normal file
45
node_modules/playwright-core/lib/server/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
|
||||
}));
|
||||
});
|
||||
}
|
||||
58
node_modules/playwright-core/lib/server/utils/task.js
generated
vendored
Normal file
58
node_modules/playwright-core/lib/server/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);
|
||||
}
|
||||
};
|
||||
}
|
||||
91
node_modules/playwright-core/lib/server/utils/userAgent.js
generated
vendored
Normal file
91
node_modules/playwright-core/lib/server/utils/userAgent.js
generated
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.getEmbedderName = getEmbedderName;
|
||||
exports.getPlaywrightVersion = getPlaywrightVersion;
|
||||
exports.getUserAgent = getUserAgent;
|
||||
var _child_process = require("child_process");
|
||||
var _os = _interopRequireDefault(require("os"));
|
||||
var _linuxUtils = require("../utils/linuxUtils");
|
||||
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
128
node_modules/playwright-core/lib/server/utils/wsServer.js
generated
vendored
Normal file
128
node_modules/playwright-core/lib/server/utils/wsServer.js
generated
vendored
Normal file
@@ -0,0 +1,128 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.perMessageDeflate = exports.WSServer = void 0;
|
||||
var _network = require("./network");
|
||||
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 = {
|
||||
serverNoContextTakeover: true,
|
||||
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, _network.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/server/utils/zipFile.js
generated
vendored
Normal file
75
node_modules/playwright-core/lib/server/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;
|
||||
54
node_modules/playwright-core/lib/server/utils/zones.js
generated
vendored
Normal file
54
node_modules/playwright-core/lib/server/utils/zones.js
generated
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.Zone = void 0;
|
||||
exports.currentZone = currentZone;
|
||||
exports.emptyZone = 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.
|
||||
*/
|
||||
|
||||
const asyncLocalStorage = new _async_hooks.AsyncLocalStorage();
|
||||
class Zone {
|
||||
constructor(asyncLocalStorage, store) {
|
||||
this._asyncLocalStorage = void 0;
|
||||
this._data = void 0;
|
||||
this._asyncLocalStorage = asyncLocalStorage;
|
||||
this._data = store;
|
||||
}
|
||||
with(type, data) {
|
||||
return new Zone(this._asyncLocalStorage, new Map(this._data).set(type, data));
|
||||
}
|
||||
without(type) {
|
||||
const data = type ? new Map(this._data) : new Map();
|
||||
data.delete(type);
|
||||
return new Zone(this._asyncLocalStorage, data);
|
||||
}
|
||||
run(func) {
|
||||
return this._asyncLocalStorage.run(this, func);
|
||||
}
|
||||
data(type) {
|
||||
return this._data.get(type);
|
||||
}
|
||||
}
|
||||
exports.Zone = Zone;
|
||||
const emptyZone = exports.emptyZone = new Zone(asyncLocalStorage, new Map());
|
||||
function currentZone() {
|
||||
var _asyncLocalStorage$ge;
|
||||
return (_asyncLocalStorage$ge = asyncLocalStorage.getStore()) !== null && _asyncLocalStorage$ge !== void 0 ? _asyncLocalStorage$ge : emptyZone;
|
||||
}
|
||||
Reference in New Issue
Block a user