Compare commits
24 Commits
Author | SHA1 | Date | |
---|---|---|---|
b4d51739f9 | |||
ad43dccb4d | |||
c2f9cef04d | |||
b67934cbcf | |||
ef83023339 | |||
671dc9c9e0 | |||
ddab646771 | |||
3f9dbd5a76 | |||
171dd555b9 | |||
6e59b075e0 | |||
9c5916f06d | |||
33434f1c62 | |||
9ca978d38e | |||
8e154b2a92 | |||
18f90432be | |||
2721abb4d0 | |||
20dac2ed48 | |||
8557470a68 | |||
10db75894f | |||
5a6b15373e | |||
923ad837f1 | |||
f094b77505 | |||
af7c021bb9 | |||
97872c4843 |
1
.github/FUNDING.yml
vendored
Normal file
1
.github/FUNDING.yml
vendored
Normal file
@ -0,0 +1 @@
|
||||
github: peter-evans
|
7
.github/dependabot.yml
vendored
7
.github/dependabot.yml
vendored
@ -6,3 +6,10 @@ updates:
|
||||
interval: "weekly"
|
||||
labels:
|
||||
- "dependencies"
|
||||
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
allow:
|
||||
- dependency-name: "@actions/*"
|
||||
|
5
.github/workflows/ci.yml
vendored
5
.github/workflows/ci.yml
vendored
@ -10,6 +10,11 @@ on:
|
||||
paths-ignore:
|
||||
- 'README.md'
|
||||
- 'docs/**'
|
||||
|
||||
permissions:
|
||||
pull-requests: write
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
@ -36,6 +36,13 @@ Create Pull Request action will:
|
||||
|
||||
You can also pin to a [specific release](https://github.com/peter-evans/create-pull-request/releases) version in the format `@v4.x.x`
|
||||
|
||||
### Workflow permissions
|
||||
|
||||
For this action to work you must explicitly allow GitHub Actions to create pull requests.
|
||||
This setting can be found in a repository's settings under Actions > General > Workflow permissions.
|
||||
|
||||
For repositories belonging to an organization, this setting can be managed by admins in organization settings under Actions > General > Workflow permissions.
|
||||
|
||||
### Action inputs
|
||||
|
||||
All inputs are **optional**. If not set, sensible defaults will be used.
|
||||
@ -106,7 +113,7 @@ How the action behaves:
|
||||
|
||||
- If there are changes (i.e. a diff exists with the checked-out base branch), the changes will be pushed to a new `branch` and a pull request created.
|
||||
- If there are no changes (i.e. no diff exists with the checked-out base branch), no pull request will be created and the action exits silently.
|
||||
- If a pull request already exists and there are no further changes (i.e. no diff with the current pull request branch) then the action exits silently.
|
||||
- If a pull request already exists it will be updated if necessary. Local changes in the Actions workspace, or changes on the base branch, can cause an update. If no update is required the action exits silently.
|
||||
- If a pull request exists and new changes on the base branch make the pull request unnecessary (i.e. there is no longer a diff between the pull request branch and the base), the pull request is automatically closed. Additionally, if `delete-branch` is set to `true` the `branch` will be deleted.
|
||||
|
||||
For further details about how the action works and usage guidelines, see [Concepts, guidelines and advanced usage](docs/concepts-guidelines.md).
|
||||
|
@ -8,9 +8,9 @@ if [[ "$(docker images -q $IMAGE 2> /dev/null)" == "" || $ARG1 == "build" ]]; th
|
||||
echo "Building Docker image $IMAGE ..."
|
||||
|
||||
cat > Dockerfile << EOF
|
||||
FROM node:12-alpine
|
||||
FROM node:16-alpine
|
||||
RUN apk --no-cache add git git-daemon
|
||||
RUN npm install jest --global
|
||||
RUN npm install jest jest-environment-jsdom --global
|
||||
WORKDIR /cpr
|
||||
COPY __test__/entrypoint.sh /entrypoint.sh
|
||||
ENTRYPOINT ["/entrypoint.sh"]
|
||||
|
@ -56,6 +56,24 @@ describe('utils tests', () => {
|
||||
)
|
||||
expect(remote4.protocol).toEqual('HTTPS')
|
||||
expect(remote4.repository).toEqual('peter-evans/create-pull-request')
|
||||
|
||||
const remote5 = utils.getRemoteDetail(
|
||||
'https://github.com/peter-evans/ungit'
|
||||
)
|
||||
expect(remote5.protocol).toEqual('HTTPS')
|
||||
expect(remote5.repository).toEqual('peter-evans/ungit')
|
||||
|
||||
const remote6 = utils.getRemoteDetail(
|
||||
'https://github.com/peter-evans/ungit.git'
|
||||
)
|
||||
expect(remote6.protocol).toEqual('HTTPS')
|
||||
expect(remote6.repository).toEqual('peter-evans/ungit')
|
||||
|
||||
const remote7 = utils.getRemoteDetail(
|
||||
'git@github.com:peter-evans/ungit.git'
|
||||
)
|
||||
expect(remote7.protocol).toEqual('SSH')
|
||||
expect(remote7.repository).toEqual('peter-evans/ungit')
|
||||
})
|
||||
|
||||
test('getRemoteDetail fails to parse a remote URL', async () => {
|
||||
|
1010
dist/bridge.js
vendored
Normal file
1010
dist/bridge.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
977
dist/events.js
vendored
Normal file
977
dist/events.js
vendored
Normal file
@ -0,0 +1,977 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
// Modified by the vm2 team to make this a standalone module to be loaded into the sandbox.
|
||||
|
||||
'use strict';
|
||||
|
||||
const host = fromhost;
|
||||
|
||||
const {
|
||||
Boolean,
|
||||
Error,
|
||||
String,
|
||||
Symbol
|
||||
} = globalThis;
|
||||
|
||||
const ReflectApply = Reflect.apply;
|
||||
const ReflectOwnKeys = Reflect.ownKeys;
|
||||
|
||||
const ErrorCaptureStackTrace = Error.captureStackTrace;
|
||||
|
||||
const NumberIsNaN = Number.isNaN;
|
||||
|
||||
const ObjectCreate = Object.create;
|
||||
const ObjectDefineProperty = Object.defineProperty;
|
||||
const ObjectDefineProperties = Object.defineProperties;
|
||||
const ObjectGetPrototypeOf = Object.getPrototypeOf;
|
||||
|
||||
const SymbolFor = Symbol.for;
|
||||
|
||||
function uncurryThis(func) {
|
||||
return (thiz, ...args) => ReflectApply(func, thiz, args);
|
||||
}
|
||||
|
||||
const ArrayPrototypeIndexOf = uncurryThis(Array.prototype.indexOf);
|
||||
const ArrayPrototypeJoin = uncurryThis(Array.prototype.join);
|
||||
const ArrayPrototypeSlice = uncurryThis(Array.prototype.slice);
|
||||
const ArrayPrototypeSplice = uncurryThis(Array.prototype.splice);
|
||||
const ArrayPrototypeUnshift = uncurryThis(Array.prototype.unshift);
|
||||
|
||||
const kRejection = SymbolFor('nodejs.rejection');
|
||||
|
||||
function inspect(obj) {
|
||||
return typeof obj === 'symbol' ? obj.toString() : `${obj}`;
|
||||
}
|
||||
|
||||
function spliceOne(list, index) {
|
||||
for (; index + 1 < list.length; index++)
|
||||
list[index] = list[index + 1];
|
||||
list.pop();
|
||||
}
|
||||
|
||||
function assert(what, message) {
|
||||
if (!what) throw new Error(message);
|
||||
}
|
||||
|
||||
function E(key, msg, Base) {
|
||||
return function NodeError(...args) {
|
||||
const error = new Base();
|
||||
const message = ReflectApply(msg, error, args);
|
||||
ObjectDefineProperties(error, {
|
||||
message: {
|
||||
value: message,
|
||||
enumerable: false,
|
||||
writable: true,
|
||||
configurable: true,
|
||||
},
|
||||
toString: {
|
||||
value() {
|
||||
return `${this.name} [${key}]: ${this.message}`;
|
||||
},
|
||||
enumerable: false,
|
||||
writable: true,
|
||||
configurable: true,
|
||||
},
|
||||
});
|
||||
error.code = key;
|
||||
return error;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
const ERR_INVALID_ARG_TYPE = E('ERR_INVALID_ARG_TYPE',
|
||||
(name, expected, actual) => {
|
||||
assert(typeof name === 'string', "'name' must be a string");
|
||||
if (!ArrayIsArray(expected)) {
|
||||
expected = [expected];
|
||||
}
|
||||
|
||||
let msg = 'The ';
|
||||
if (StringPrototypeEndsWith(name, ' argument')) {
|
||||
// For cases like 'first argument'
|
||||
msg += `${name} `;
|
||||
} else {
|
||||
const type = StringPrototypeIncludes(name, '.') ? 'property' : 'argument';
|
||||
msg += `"${name}" ${type} `;
|
||||
}
|
||||
msg += 'must be ';
|
||||
|
||||
const types = [];
|
||||
const instances = [];
|
||||
const other = [];
|
||||
|
||||
for (const value of expected) {
|
||||
assert(typeof value === 'string',
|
||||
'All expected entries have to be of type string');
|
||||
if (ArrayPrototypeIncludes(kTypes, value)) {
|
||||
ArrayPrototypePush(types, StringPrototypeToLowerCase(value));
|
||||
} else if (RegExpPrototypeTest(classRegExp, value)) {
|
||||
ArrayPrototypePush(instances, value);
|
||||
} else {
|
||||
assert(value !== 'object',
|
||||
'The value "object" should be written as "Object"');
|
||||
ArrayPrototypePush(other, value);
|
||||
}
|
||||
}
|
||||
|
||||
// Special handle `object` in case other instances are allowed to outline
|
||||
// the differences between each other.
|
||||
if (instances.length > 0) {
|
||||
const pos = ArrayPrototypeIndexOf(types, 'object');
|
||||
if (pos !== -1) {
|
||||
ArrayPrototypeSplice(types, pos, 1);
|
||||
ArrayPrototypePush(instances, 'Object');
|
||||
}
|
||||
}
|
||||
|
||||
if (types.length > 0) {
|
||||
if (types.length > 2) {
|
||||
const last = ArrayPrototypePop(types);
|
||||
msg += `one of type ${ArrayPrototypeJoin(types, ', ')}, or ${last}`;
|
||||
} else if (types.length === 2) {
|
||||
msg += `one of type ${types[0]} or ${types[1]}`;
|
||||
} else {
|
||||
msg += `of type ${types[0]}`;
|
||||
}
|
||||
if (instances.length > 0 || other.length > 0)
|
||||
msg += ' or ';
|
||||
}
|
||||
|
||||
if (instances.length > 0) {
|
||||
if (instances.length > 2) {
|
||||
const last = ArrayPrototypePop(instances);
|
||||
msg +=
|
||||
`an instance of ${ArrayPrototypeJoin(instances, ', ')}, or ${last}`;
|
||||
} else {
|
||||
msg += `an instance of ${instances[0]}`;
|
||||
if (instances.length === 2) {
|
||||
msg += ` or ${instances[1]}`;
|
||||
}
|
||||
}
|
||||
if (other.length > 0)
|
||||
msg += ' or ';
|
||||
}
|
||||
|
||||
if (other.length > 0) {
|
||||
if (other.length > 2) {
|
||||
const last = ArrayPrototypePop(other);
|
||||
msg += `one of ${ArrayPrototypeJoin(other, ', ')}, or ${last}`;
|
||||
} else if (other.length === 2) {
|
||||
msg += `one of ${other[0]} or ${other[1]}`;
|
||||
} else {
|
||||
if (StringPrototypeToLowerCase(other[0]) !== other[0])
|
||||
msg += 'an ';
|
||||
msg += `${other[0]}`;
|
||||
}
|
||||
}
|
||||
|
||||
if (actual == null) {
|
||||
msg += `. Received ${actual}`;
|
||||
} else if (typeof actual === 'function' && actual.name) {
|
||||
msg += `. Received function ${actual.name}`;
|
||||
} else if (typeof actual === 'object') {
|
||||
if (actual.constructor && actual.constructor.name) {
|
||||
msg += `. Received an instance of ${actual.constructor.name}`;
|
||||
} else {
|
||||
const inspected = inspect(actual, { depth: -1 });
|
||||
msg += `. Received ${inspected}`;
|
||||
}
|
||||
} else {
|
||||
let inspected = inspect(actual, { colors: false });
|
||||
if (inspected.length > 25)
|
||||
inspected = `${StringPrototypeSlice(inspected, 0, 25)}...`;
|
||||
msg += `. Received type ${typeof actual} (${inspected})`;
|
||||
}
|
||||
return msg;
|
||||
}, TypeError);
|
||||
|
||||
const ERR_INVALID_THIS = E('ERR_INVALID_THIS', s => `Value of "this" must be of type ${s}`, TypeError);
|
||||
|
||||
const ERR_OUT_OF_RANGE = E('ERR_OUT_OF_RANGE',
|
||||
(str, range, input, replaceDefaultBoolean = false) => {
|
||||
assert(range, 'Missing "range" argument');
|
||||
let msg = replaceDefaultBoolean ? str :
|
||||
`The value of "${str}" is out of range.`;
|
||||
const received = inspect(input);
|
||||
msg += ` It must be ${range}. Received ${received}`;
|
||||
return msg;
|
||||
}, RangeError);
|
||||
|
||||
const ERR_UNHANDLED_ERROR = E('ERR_UNHANDLED_ERROR',
|
||||
err => {
|
||||
const msg = 'Unhandled error.';
|
||||
if (err === undefined) return msg;
|
||||
return `${msg} (${err})`;
|
||||
}, Error);
|
||||
|
||||
function validateBoolean(value, name) {
|
||||
if (typeof value !== 'boolean')
|
||||
throw new ERR_INVALID_ARG_TYPE(name, 'boolean', value);
|
||||
}
|
||||
|
||||
function validateFunction(value, name) {
|
||||
if (typeof value !== 'function')
|
||||
throw new ERR_INVALID_ARG_TYPE(name, 'Function', value);
|
||||
}
|
||||
|
||||
function validateString(value, name) {
|
||||
if (typeof value !== 'string')
|
||||
throw new ERR_INVALID_ARG_TYPE(name, 'string', value);
|
||||
}
|
||||
|
||||
function nc(cond, e) {
|
||||
return cond === undefined || cond === null ? e : cond;
|
||||
}
|
||||
|
||||
function oc(base, key) {
|
||||
return base === undefined || base === null ? undefined : base[key];
|
||||
}
|
||||
|
||||
const kCapture = Symbol('kCapture');
|
||||
const kErrorMonitor = host.kErrorMonitor || Symbol('events.errorMonitor');
|
||||
const kMaxEventTargetListeners = Symbol('events.maxEventTargetListeners');
|
||||
const kMaxEventTargetListenersWarned =
|
||||
Symbol('events.maxEventTargetListenersWarned');
|
||||
|
||||
const kIsEventTarget = SymbolFor('nodejs.event_target');
|
||||
|
||||
function isEventTarget(obj) {
|
||||
return oc(oc(obj, 'constructor'), kIsEventTarget);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new `EventEmitter` instance.
|
||||
* @param {{ captureRejections?: boolean; }} [opts]
|
||||
* @constructs {EventEmitter}
|
||||
*/
|
||||
function EventEmitter(opts) {
|
||||
EventEmitter.init.call(this, opts);
|
||||
}
|
||||
module.exports = EventEmitter;
|
||||
if (host.once) module.exports.once = host.once;
|
||||
if (host.on) module.exports.on = host.on;
|
||||
if (host.getEventListeners) module.exports.getEventListeners = host.getEventListeners;
|
||||
// Backwards-compat with node 0.10.x
|
||||
EventEmitter.EventEmitter = EventEmitter;
|
||||
|
||||
EventEmitter.usingDomains = false;
|
||||
|
||||
EventEmitter.captureRejectionSymbol = kRejection;
|
||||
ObjectDefineProperty(EventEmitter, 'captureRejections', {
|
||||
get() {
|
||||
return EventEmitter.prototype[kCapture];
|
||||
},
|
||||
set(value) {
|
||||
validateBoolean(value, 'EventEmitter.captureRejections');
|
||||
|
||||
EventEmitter.prototype[kCapture] = value;
|
||||
},
|
||||
enumerable: true
|
||||
});
|
||||
|
||||
if (host.EventEmitterReferencingAsyncResource) {
|
||||
const kAsyncResource = Symbol('kAsyncResource');
|
||||
const EventEmitterReferencingAsyncResource = host.EventEmitterReferencingAsyncResource;
|
||||
|
||||
class EventEmitterAsyncResource extends EventEmitter {
|
||||
/**
|
||||
* @param {{
|
||||
* name?: string,
|
||||
* triggerAsyncId?: number,
|
||||
* requireManualDestroy?: boolean,
|
||||
* }} [options]
|
||||
*/
|
||||
constructor(options = undefined) {
|
||||
let name;
|
||||
if (typeof options === 'string') {
|
||||
name = options;
|
||||
options = undefined;
|
||||
} else {
|
||||
if (new.target === EventEmitterAsyncResource) {
|
||||
validateString(oc(options, 'name'), 'options.name');
|
||||
}
|
||||
name = oc(options, 'name') || new.target.name;
|
||||
}
|
||||
super(options);
|
||||
|
||||
this[kAsyncResource] =
|
||||
new EventEmitterReferencingAsyncResource(this, name, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {symbol,string} event
|
||||
* @param {...any} args
|
||||
* @returns {boolean}
|
||||
*/
|
||||
emit(event, ...args) {
|
||||
if (this[kAsyncResource] === undefined)
|
||||
throw new ERR_INVALID_THIS('EventEmitterAsyncResource');
|
||||
const { asyncResource } = this;
|
||||
ArrayPrototypeUnshift(args, super.emit, this, event);
|
||||
return ReflectApply(asyncResource.runInAsyncScope, asyncResource,
|
||||
args);
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {void}
|
||||
*/
|
||||
emitDestroy() {
|
||||
if (this[kAsyncResource] === undefined)
|
||||
throw new ERR_INVALID_THIS('EventEmitterAsyncResource');
|
||||
this.asyncResource.emitDestroy();
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
get asyncId() {
|
||||
if (this[kAsyncResource] === undefined)
|
||||
throw new ERR_INVALID_THIS('EventEmitterAsyncResource');
|
||||
return this.asyncResource.asyncId();
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
get triggerAsyncId() {
|
||||
if (this[kAsyncResource] === undefined)
|
||||
throw new ERR_INVALID_THIS('EventEmitterAsyncResource');
|
||||
return this.asyncResource.triggerAsyncId();
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {EventEmitterReferencingAsyncResource}
|
||||
*/
|
||||
get asyncResource() {
|
||||
if (this[kAsyncResource] === undefined)
|
||||
throw new ERR_INVALID_THIS('EventEmitterAsyncResource');
|
||||
return this[kAsyncResource];
|
||||
}
|
||||
}
|
||||
EventEmitter.EventEmitterAsyncResource = EventEmitterAsyncResource;
|
||||
}
|
||||
|
||||
EventEmitter.errorMonitor = kErrorMonitor;
|
||||
|
||||
// The default for captureRejections is false
|
||||
ObjectDefineProperty(EventEmitter.prototype, kCapture, {
|
||||
value: false,
|
||||
writable: true,
|
||||
enumerable: false
|
||||
});
|
||||
|
||||
EventEmitter.prototype._events = undefined;
|
||||
EventEmitter.prototype._eventsCount = 0;
|
||||
EventEmitter.prototype._maxListeners = undefined;
|
||||
|
||||
// By default EventEmitters will print a warning if more than 10 listeners are
|
||||
// added to it. This is a useful default which helps finding memory leaks.
|
||||
let defaultMaxListeners = 10;
|
||||
|
||||
function checkListener(listener) {
|
||||
validateFunction(listener, 'listener');
|
||||
}
|
||||
|
||||
ObjectDefineProperty(EventEmitter, 'defaultMaxListeners', {
|
||||
enumerable: true,
|
||||
get: function() {
|
||||
return defaultMaxListeners;
|
||||
},
|
||||
set: function(arg) {
|
||||
if (typeof arg !== 'number' || arg < 0 || NumberIsNaN(arg)) {
|
||||
throw new ERR_OUT_OF_RANGE('defaultMaxListeners',
|
||||
'a non-negative number',
|
||||
arg);
|
||||
}
|
||||
defaultMaxListeners = arg;
|
||||
}
|
||||
});
|
||||
|
||||
ObjectDefineProperties(EventEmitter, {
|
||||
kMaxEventTargetListeners: {
|
||||
value: kMaxEventTargetListeners,
|
||||
enumerable: false,
|
||||
configurable: false,
|
||||
writable: false,
|
||||
},
|
||||
kMaxEventTargetListenersWarned: {
|
||||
value: kMaxEventTargetListenersWarned,
|
||||
enumerable: false,
|
||||
configurable: false,
|
||||
writable: false,
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Sets the max listeners.
|
||||
* @param {number} n
|
||||
* @param {EventTarget[] | EventEmitter[]} [eventTargets]
|
||||
* @returns {void}
|
||||
*/
|
||||
EventEmitter.setMaxListeners =
|
||||
function(n = defaultMaxListeners, ...eventTargets) {
|
||||
if (typeof n !== 'number' || n < 0 || NumberIsNaN(n))
|
||||
throw new ERR_OUT_OF_RANGE('n', 'a non-negative number', n);
|
||||
if (eventTargets.length === 0) {
|
||||
defaultMaxListeners = n;
|
||||
} else {
|
||||
for (let i = 0; i < eventTargets.length; i++) {
|
||||
const target = eventTargets[i];
|
||||
if (isEventTarget(target)) {
|
||||
target[kMaxEventTargetListeners] = n;
|
||||
target[kMaxEventTargetListenersWarned] = false;
|
||||
} else if (typeof target.setMaxListeners === 'function') {
|
||||
target.setMaxListeners(n);
|
||||
} else {
|
||||
throw new ERR_INVALID_ARG_TYPE(
|
||||
'eventTargets',
|
||||
['EventEmitter', 'EventTarget'],
|
||||
target);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// If you're updating this function definition, please also update any
|
||||
// re-definitions, such as the one in the Domain module (lib/domain.js).
|
||||
EventEmitter.init = function(opts) {
|
||||
|
||||
if (this._events === undefined ||
|
||||
this._events === ObjectGetPrototypeOf(this)._events) {
|
||||
this._events = ObjectCreate(null);
|
||||
this._eventsCount = 0;
|
||||
}
|
||||
|
||||
this._maxListeners = this._maxListeners || undefined;
|
||||
|
||||
|
||||
if (oc(opts, 'captureRejections')) {
|
||||
validateBoolean(opts.captureRejections, 'options.captureRejections');
|
||||
this[kCapture] = Boolean(opts.captureRejections);
|
||||
} else {
|
||||
// Assigning the kCapture property directly saves an expensive
|
||||
// prototype lookup in a very sensitive hot path.
|
||||
this[kCapture] = EventEmitter.prototype[kCapture];
|
||||
}
|
||||
};
|
||||
|
||||
function addCatch(that, promise, type, args) {
|
||||
if (!that[kCapture]) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle Promises/A+ spec, then could be a getter
|
||||
// that throws on second use.
|
||||
try {
|
||||
const then = promise.then;
|
||||
|
||||
if (typeof then === 'function') {
|
||||
then.call(promise, undefined, function(err) {
|
||||
// The callback is called with nextTick to avoid a follow-up
|
||||
// rejection from this promise.
|
||||
process.nextTick(emitUnhandledRejectionOrErr, that, err, type, args);
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
that.emit('error', err);
|
||||
}
|
||||
}
|
||||
|
||||
function emitUnhandledRejectionOrErr(ee, err, type, args) {
|
||||
if (typeof ee[kRejection] === 'function') {
|
||||
ee[kRejection](err, type, ...args);
|
||||
} else {
|
||||
// We have to disable the capture rejections mechanism, otherwise
|
||||
// we might end up in an infinite loop.
|
||||
const prev = ee[kCapture];
|
||||
|
||||
// If the error handler throws, it is not catchable and it
|
||||
// will end up in 'uncaughtException'. We restore the previous
|
||||
// value of kCapture in case the uncaughtException is present
|
||||
// and the exception is handled.
|
||||
try {
|
||||
ee[kCapture] = false;
|
||||
ee.emit('error', err);
|
||||
} finally {
|
||||
ee[kCapture] = prev;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Increases the max listeners of the event emitter.
|
||||
* @param {number} n
|
||||
* @returns {EventEmitter}
|
||||
*/
|
||||
EventEmitter.prototype.setMaxListeners = function setMaxListeners(n) {
|
||||
if (typeof n !== 'number' || n < 0 || NumberIsNaN(n)) {
|
||||
throw new ERR_OUT_OF_RANGE('n', 'a non-negative number', n);
|
||||
}
|
||||
this._maxListeners = n;
|
||||
return this;
|
||||
};
|
||||
|
||||
function _getMaxListeners(that) {
|
||||
if (that._maxListeners === undefined)
|
||||
return EventEmitter.defaultMaxListeners;
|
||||
return that._maxListeners;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current max listener value for the event emitter.
|
||||
* @returns {number}
|
||||
*/
|
||||
EventEmitter.prototype.getMaxListeners = function getMaxListeners() {
|
||||
return _getMaxListeners(this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Synchronously calls each of the listeners registered
|
||||
* for the event.
|
||||
* @param {string | symbol} type
|
||||
* @param {...any} [args]
|
||||
* @returns {boolean}
|
||||
*/
|
||||
EventEmitter.prototype.emit = function emit(type, ...args) {
|
||||
let doError = (type === 'error');
|
||||
|
||||
const events = this._events;
|
||||
if (events !== undefined) {
|
||||
if (doError && events[kErrorMonitor] !== undefined)
|
||||
this.emit(kErrorMonitor, ...args);
|
||||
doError = (doError && events.error === undefined);
|
||||
} else if (!doError)
|
||||
return false;
|
||||
|
||||
// If there is no 'error' event listener then throw.
|
||||
if (doError) {
|
||||
let er;
|
||||
if (args.length > 0)
|
||||
er = args[0];
|
||||
if (er instanceof Error) {
|
||||
try {
|
||||
const capture = {};
|
||||
ErrorCaptureStackTrace(capture, EventEmitter.prototype.emit);
|
||||
} catch (e) {}
|
||||
|
||||
// Note: The comments on the `throw` lines are intentional, they show
|
||||
// up in Node's output if this results in an unhandled exception.
|
||||
throw er; // Unhandled 'error' event
|
||||
}
|
||||
|
||||
let stringifiedEr;
|
||||
try {
|
||||
stringifiedEr = inspect(er);
|
||||
} catch (e) {
|
||||
stringifiedEr = er;
|
||||
}
|
||||
|
||||
// At least give some kind of context to the user
|
||||
const err = new ERR_UNHANDLED_ERROR(stringifiedEr);
|
||||
err.context = er;
|
||||
throw err; // Unhandled 'error' event
|
||||
}
|
||||
|
||||
const handler = events[type];
|
||||
|
||||
if (handler === undefined)
|
||||
return false;
|
||||
|
||||
if (typeof handler === 'function') {
|
||||
const result = handler.apply(this, args);
|
||||
|
||||
// We check if result is undefined first because that
|
||||
// is the most common case so we do not pay any perf
|
||||
// penalty
|
||||
if (result !== undefined && result !== null) {
|
||||
addCatch(this, result, type, args);
|
||||
}
|
||||
} else {
|
||||
const len = handler.length;
|
||||
const listeners = arrayClone(handler);
|
||||
for (let i = 0; i < len; ++i) {
|
||||
const result = listeners[i].apply(this, args);
|
||||
|
||||
// We check if result is undefined first because that
|
||||
// is the most common case so we do not pay any perf
|
||||
// penalty.
|
||||
// This code is duplicated because extracting it away
|
||||
// would make it non-inlineable.
|
||||
if (result !== undefined && result !== null) {
|
||||
addCatch(this, result, type, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
function _addListener(target, type, listener, prepend) {
|
||||
let m;
|
||||
let events;
|
||||
let existing;
|
||||
|
||||
checkListener(listener);
|
||||
|
||||
events = target._events;
|
||||
if (events === undefined) {
|
||||
events = target._events = ObjectCreate(null);
|
||||
target._eventsCount = 0;
|
||||
} else {
|
||||
// To avoid recursion in the case that type === "newListener"! Before
|
||||
// adding it to the listeners, first emit "newListener".
|
||||
if (events.newListener !== undefined) {
|
||||
target.emit('newListener', type,
|
||||
nc(listener.listener, listener));
|
||||
|
||||
// Re-assign `events` because a newListener handler could have caused the
|
||||
// this._events to be assigned to a new object
|
||||
events = target._events;
|
||||
}
|
||||
existing = events[type];
|
||||
}
|
||||
|
||||
if (existing === undefined) {
|
||||
// Optimize the case of one listener. Don't need the extra array object.
|
||||
events[type] = listener;
|
||||
++target._eventsCount;
|
||||
} else {
|
||||
if (typeof existing === 'function') {
|
||||
// Adding the second element, need to change to array.
|
||||
existing = events[type] =
|
||||
prepend ? [listener, existing] : [existing, listener];
|
||||
// If we've already got an array, just append.
|
||||
} else if (prepend) {
|
||||
existing.unshift(listener);
|
||||
} else {
|
||||
existing.push(listener);
|
||||
}
|
||||
|
||||
// Check for listener leak
|
||||
m = _getMaxListeners(target);
|
||||
if (m > 0 && existing.length > m && !existing.warned) {
|
||||
existing.warned = true;
|
||||
// No error code for this since it is a Warning
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
const w = new Error('Possible EventEmitter memory leak detected. ' +
|
||||
`${existing.length} ${String(type)} listeners ` +
|
||||
`added to ${inspect(target, { depth: -1 })}. Use ` +
|
||||
'emitter.setMaxListeners() to increase limit');
|
||||
w.name = 'MaxListenersExceededWarning';
|
||||
w.emitter = target;
|
||||
w.type = type;
|
||||
w.count = existing.length;
|
||||
process.emitWarning(w);
|
||||
}
|
||||
}
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a listener to the event emitter.
|
||||
* @param {string | symbol} type
|
||||
* @param {Function} listener
|
||||
* @returns {EventEmitter}
|
||||
*/
|
||||
EventEmitter.prototype.addListener = function addListener(type, listener) {
|
||||
return _addListener(this, type, listener, false);
|
||||
};
|
||||
|
||||
EventEmitter.prototype.on = EventEmitter.prototype.addListener;
|
||||
|
||||
/**
|
||||
* Adds the `listener` function to the beginning of
|
||||
* the listeners array.
|
||||
* @param {string | symbol} type
|
||||
* @param {Function} listener
|
||||
* @returns {EventEmitter}
|
||||
*/
|
||||
EventEmitter.prototype.prependListener =
|
||||
function prependListener(type, listener) {
|
||||
return _addListener(this, type, listener, true);
|
||||
};
|
||||
|
||||
function onceWrapper() {
|
||||
if (!this.fired) {
|
||||
this.target.removeListener(this.type, this.wrapFn);
|
||||
this.fired = true;
|
||||
if (arguments.length === 0)
|
||||
return this.listener.call(this.target);
|
||||
return this.listener.apply(this.target, arguments);
|
||||
}
|
||||
}
|
||||
|
||||
function _onceWrap(target, type, listener) {
|
||||
const state = { fired: false, wrapFn: undefined, target, type, listener };
|
||||
const wrapped = onceWrapper.bind(state);
|
||||
wrapped.listener = listener;
|
||||
state.wrapFn = wrapped;
|
||||
return wrapped;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a one-time `listener` function to the event emitter.
|
||||
* @param {string | symbol} type
|
||||
* @param {Function} listener
|
||||
* @returns {EventEmitter}
|
||||
*/
|
||||
EventEmitter.prototype.once = function once(type, listener) {
|
||||
checkListener(listener);
|
||||
|
||||
this.on(type, _onceWrap(this, type, listener));
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds a one-time `listener` function to the beginning of
|
||||
* the listeners array.
|
||||
* @param {string | symbol} type
|
||||
* @param {Function} listener
|
||||
* @returns {EventEmitter}
|
||||
*/
|
||||
EventEmitter.prototype.prependOnceListener =
|
||||
function prependOnceListener(type, listener) {
|
||||
checkListener(listener);
|
||||
|
||||
this.prependListener(type, _onceWrap(this, type, listener));
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Removes the specified `listener` from the listeners array.
|
||||
* @param {string | symbol} type
|
||||
* @param {Function} listener
|
||||
* @returns {EventEmitter}
|
||||
*/
|
||||
EventEmitter.prototype.removeListener =
|
||||
function removeListener(type, listener) {
|
||||
checkListener(listener);
|
||||
|
||||
const events = this._events;
|
||||
if (events === undefined)
|
||||
return this;
|
||||
|
||||
const list = events[type];
|
||||
if (list === undefined)
|
||||
return this;
|
||||
|
||||
if (list === listener || list.listener === listener) {
|
||||
if (--this._eventsCount === 0)
|
||||
this._events = ObjectCreate(null);
|
||||
else {
|
||||
delete events[type];
|
||||
if (events.removeListener)
|
||||
this.emit('removeListener', type, list.listener || listener);
|
||||
}
|
||||
} else if (typeof list !== 'function') {
|
||||
let position = -1;
|
||||
|
||||
for (let i = list.length - 1; i >= 0; i--) {
|
||||
if (list[i] === listener || list[i].listener === listener) {
|
||||
position = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (position < 0)
|
||||
return this;
|
||||
|
||||
if (position === 0)
|
||||
list.shift();
|
||||
else {
|
||||
spliceOne(list, position);
|
||||
}
|
||||
|
||||
if (list.length === 1)
|
||||
events[type] = list[0];
|
||||
|
||||
if (events.removeListener !== undefined)
|
||||
this.emit('removeListener', type, listener);
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
EventEmitter.prototype.off = EventEmitter.prototype.removeListener;
|
||||
|
||||
/**
|
||||
* Removes all listeners from the event emitter. (Only
|
||||
* removes listeners for a specific event name if specified
|
||||
* as `type`).
|
||||
* @param {string | symbol} [type]
|
||||
* @returns {EventEmitter}
|
||||
*/
|
||||
EventEmitter.prototype.removeAllListeners =
|
||||
function removeAllListeners(type) {
|
||||
const events = this._events;
|
||||
if (events === undefined)
|
||||
return this;
|
||||
|
||||
// Not listening for removeListener, no need to emit
|
||||
if (events.removeListener === undefined) {
|
||||
if (arguments.length === 0) {
|
||||
this._events = ObjectCreate(null);
|
||||
this._eventsCount = 0;
|
||||
} else if (events[type] !== undefined) {
|
||||
if (--this._eventsCount === 0)
|
||||
this._events = ObjectCreate(null);
|
||||
else
|
||||
delete events[type];
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
// Emit removeListener for all listeners on all events
|
||||
if (arguments.length === 0) {
|
||||
for (const key of ReflectOwnKeys(events)) {
|
||||
if (key === 'removeListener') continue;
|
||||
this.removeAllListeners(key);
|
||||
}
|
||||
this.removeAllListeners('removeListener');
|
||||
this._events = ObjectCreate(null);
|
||||
this._eventsCount = 0;
|
||||
return this;
|
||||
}
|
||||
|
||||
const listeners = events[type];
|
||||
|
||||
if (typeof listeners === 'function') {
|
||||
this.removeListener(type, listeners);
|
||||
} else if (listeners !== undefined) {
|
||||
// LIFO order
|
||||
for (let i = listeners.length - 1; i >= 0; i--) {
|
||||
this.removeListener(type, listeners[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
function _listeners(target, type, unwrap) {
|
||||
const events = target._events;
|
||||
|
||||
if (events === undefined)
|
||||
return [];
|
||||
|
||||
const evlistener = events[type];
|
||||
if (evlistener === undefined)
|
||||
return [];
|
||||
|
||||
if (typeof evlistener === 'function')
|
||||
return unwrap ? [evlistener.listener || evlistener] : [evlistener];
|
||||
|
||||
return unwrap ?
|
||||
unwrapListeners(evlistener) : arrayClone(evlistener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of the array of listeners for the event name
|
||||
* specified as `type`.
|
||||
* @param {string | symbol} type
|
||||
* @returns {Function[]}
|
||||
*/
|
||||
EventEmitter.prototype.listeners = function listeners(type) {
|
||||
return _listeners(this, type, true);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a copy of the array of listeners and wrappers for
|
||||
* the event name specified as `type`.
|
||||
* @param {string | symbol} type
|
||||
* @returns {Function[]}
|
||||
*/
|
||||
EventEmitter.prototype.rawListeners = function rawListeners(type) {
|
||||
return _listeners(this, type, false);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the number of listeners listening to the event name
|
||||
* specified as `type`.
|
||||
* @deprecated since v3.2.0
|
||||
* @param {EventEmitter} emitter
|
||||
* @param {string | symbol} type
|
||||
* @returns {number}
|
||||
*/
|
||||
EventEmitter.listenerCount = function(emitter, type) {
|
||||
if (typeof emitter.listenerCount === 'function') {
|
||||
return emitter.listenerCount(type);
|
||||
}
|
||||
return emitter.listenerCount(type);
|
||||
};
|
||||
|
||||
EventEmitter.prototype.listenerCount = listenerCount;
|
||||
|
||||
/**
|
||||
* Returns the number of listeners listening to event name
|
||||
* specified as `type`.
|
||||
* @param {string | symbol} type
|
||||
* @returns {number}
|
||||
*/
|
||||
function listenerCount(type) {
|
||||
const events = this._events;
|
||||
|
||||
if (events !== undefined) {
|
||||
const evlistener = events[type];
|
||||
|
||||
if (typeof evlistener === 'function') {
|
||||
return 1;
|
||||
} else if (evlistener !== undefined) {
|
||||
return evlistener.length;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array listing the events for which
|
||||
* the emitter has registered listeners.
|
||||
* @returns {any[]}
|
||||
*/
|
||||
EventEmitter.prototype.eventNames = function eventNames() {
|
||||
return this._eventsCount > 0 ? ReflectOwnKeys(this._events) : [];
|
||||
};
|
||||
|
||||
function arrayClone(arr) {
|
||||
// At least since V8 8.3, this implementation is faster than the previous
|
||||
// which always used a simple for-loop
|
||||
switch (arr.length) {
|
||||
case 2: return [arr[0], arr[1]];
|
||||
case 3: return [arr[0], arr[1], arr[2]];
|
||||
case 4: return [arr[0], arr[1], arr[2], arr[3]];
|
||||
case 5: return [arr[0], arr[1], arr[2], arr[3], arr[4]];
|
||||
case 6: return [arr[0], arr[1], arr[2], arr[3], arr[4], arr[5]];
|
||||
}
|
||||
return ArrayPrototypeSlice(arr);
|
||||
}
|
||||
|
||||
function unwrapListeners(arr) {
|
||||
const ret = arrayClone(arr);
|
||||
for (let i = 0; i < ret.length; ++i) {
|
||||
const orig = ret[i].listener;
|
||||
if (typeof orig === 'function')
|
||||
ret[i] = orig;
|
||||
}
|
||||
return ret;
|
||||
}
|
50650
dist/index.js
vendored
50650
dist/index.js
vendored
File diff suppressed because it is too large
Load Diff
469
dist/setup-node-sandbox.js
vendored
Normal file
469
dist/setup-node-sandbox.js
vendored
Normal file
@ -0,0 +1,469 @@
|
||||
/* global host, data, VMError */
|
||||
|
||||
'use strict';
|
||||
|
||||
const LocalError = Error;
|
||||
const LocalTypeError = TypeError;
|
||||
const LocalWeakMap = WeakMap;
|
||||
|
||||
const {
|
||||
apply: localReflectApply,
|
||||
defineProperty: localReflectDefineProperty
|
||||
} = Reflect;
|
||||
|
||||
const {
|
||||
set: localWeakMapSet,
|
||||
get: localWeakMapGet
|
||||
} = LocalWeakMap.prototype;
|
||||
|
||||
const {
|
||||
isArray: localArrayIsArray
|
||||
} = Array;
|
||||
|
||||
function uncurryThis(func) {
|
||||
return (thiz, ...args) => localReflectApply(func, thiz, args);
|
||||
}
|
||||
|
||||
const localArrayPrototypeSlice = uncurryThis(Array.prototype.slice);
|
||||
const localArrayPrototypeIncludes = uncurryThis(Array.prototype.includes);
|
||||
const localArrayPrototypePush = uncurryThis(Array.prototype.push);
|
||||
const localArrayPrototypeIndexOf = uncurryThis(Array.prototype.indexOf);
|
||||
const localArrayPrototypeSplice = uncurryThis(Array.prototype.splice);
|
||||
const localStringPrototypeStartsWith = uncurryThis(String.prototype.startsWith);
|
||||
const localStringPrototypeSlice = uncurryThis(String.prototype.slice);
|
||||
const localStringPrototypeIndexOf = uncurryThis(String.prototype.indexOf);
|
||||
|
||||
const {
|
||||
argv: optionArgv,
|
||||
env: optionEnv,
|
||||
console: optionConsole,
|
||||
vm,
|
||||
resolver,
|
||||
extensions
|
||||
} = data;
|
||||
|
||||
function ensureSandboxArray(a) {
|
||||
return localArrayPrototypeSlice(a);
|
||||
}
|
||||
|
||||
const globalPaths = ensureSandboxArray(resolver.globalPaths);
|
||||
|
||||
class Module {
|
||||
|
||||
constructor(id, path, parent) {
|
||||
this.id = id;
|
||||
this.filename = id;
|
||||
this.path = path;
|
||||
this.parent = parent;
|
||||
this.loaded = false;
|
||||
this.paths = path ? ensureSandboxArray(resolver.genLookupPaths(path)) : [];
|
||||
this.children = [];
|
||||
this.exports = {};
|
||||
}
|
||||
|
||||
_updateChildren(child, isNew) {
|
||||
const children = this.children;
|
||||
if (children && (isNew || !localArrayPrototypeIncludes(children, child))) {
|
||||
localArrayPrototypePush(children, child);
|
||||
}
|
||||
}
|
||||
|
||||
require(id) {
|
||||
return requireImpl(this, id, false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const originalRequire = Module.prototype.require;
|
||||
const cacheBuiltins = {__proto__: null};
|
||||
|
||||
function requireImpl(mod, id, direct) {
|
||||
if (direct && mod.require !== originalRequire) {
|
||||
return mod.require(id);
|
||||
}
|
||||
const filename = resolver.resolve(mod, id, undefined, Module._extensions, direct);
|
||||
if (localStringPrototypeStartsWith(filename, 'node:')) {
|
||||
id = localStringPrototypeSlice(filename, 5);
|
||||
let nmod = cacheBuiltins[id];
|
||||
if (!nmod) {
|
||||
nmod = resolver.loadBuiltinModule(vm, id);
|
||||
if (!nmod) throw new VMError(`Cannot find module '${filename}'`, 'ENOTFOUND');
|
||||
cacheBuiltins[id] = nmod;
|
||||
}
|
||||
return nmod;
|
||||
}
|
||||
|
||||
const cachedModule = Module._cache[filename];
|
||||
if (cachedModule !== undefined) {
|
||||
mod._updateChildren(cachedModule, false);
|
||||
return cachedModule.exports;
|
||||
}
|
||||
|
||||
let nmod = cacheBuiltins[id];
|
||||
if (nmod) return nmod;
|
||||
nmod = resolver.loadBuiltinModule(vm, id);
|
||||
if (nmod) {
|
||||
cacheBuiltins[id] = nmod;
|
||||
return nmod;
|
||||
}
|
||||
|
||||
const path = resolver.pathDirname(filename);
|
||||
const module = new Module(filename, path, mod);
|
||||
resolver.registerModule(module, filename, path, mod, direct);
|
||||
mod._updateChildren(module, true);
|
||||
try {
|
||||
Module._cache[filename] = module;
|
||||
const handler = findBestExtensionHandler(filename);
|
||||
handler(module, filename);
|
||||
module.loaded = true;
|
||||
} catch (e) {
|
||||
delete Module._cache[filename];
|
||||
const children = mod.children;
|
||||
if (localArrayIsArray(children)) {
|
||||
const index = localArrayPrototypeIndexOf(children, module);
|
||||
if (index !== -1) {
|
||||
localArrayPrototypeSplice(children, index, 1);
|
||||
}
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
|
||||
return module.exports;
|
||||
}
|
||||
|
||||
Module.builtinModules = ensureSandboxArray(resolver.getBuiltinModulesList());
|
||||
Module.globalPaths = globalPaths;
|
||||
Module._extensions = {__proto__: null};
|
||||
Module._cache = {__proto__: null};
|
||||
|
||||
{
|
||||
const keys = Object.getOwnPropertyNames(extensions);
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
const key = keys[i];
|
||||
const handler = extensions[key];
|
||||
Module._extensions[key] = (mod, filename) => handler(mod, filename);
|
||||
}
|
||||
}
|
||||
|
||||
function findBestExtensionHandler(filename) {
|
||||
const name = resolver.pathBasename(filename);
|
||||
for (let i = 0; (i = localStringPrototypeIndexOf(name, '.', i + 1)) !== -1;) {
|
||||
const ext = localStringPrototypeSlice(name, i);
|
||||
const handler = Module._extensions[ext];
|
||||
if (handler) return handler;
|
||||
}
|
||||
const js = Module._extensions['.js'];
|
||||
if (js) return js;
|
||||
const keys = Object.getOwnPropertyNames(Module._extensions);
|
||||
if (keys.length === 0) throw new VMError(`Failed to load '${filename}': Unknown type.`, 'ELOADFAIL');
|
||||
return Module._extensions[keys[0]];
|
||||
}
|
||||
|
||||
function createRequireForModule(mod) {
|
||||
// eslint-disable-next-line no-shadow
|
||||
function require(id) {
|
||||
return requireImpl(mod, id, true);
|
||||
}
|
||||
function resolve(id, options) {
|
||||
return resolver.resolve(mod, id, options, Module._extensions, true);
|
||||
}
|
||||
require.resolve = resolve;
|
||||
function paths(id) {
|
||||
return ensureSandboxArray(resolver.lookupPaths(mod, id));
|
||||
}
|
||||
resolve.paths = paths;
|
||||
|
||||
require.extensions = Module._extensions;
|
||||
|
||||
require.cache = Module._cache;
|
||||
|
||||
return require;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare sandbox.
|
||||
*/
|
||||
|
||||
const TIMERS = new LocalWeakMap();
|
||||
|
||||
class Timeout {
|
||||
}
|
||||
|
||||
class Interval {
|
||||
}
|
||||
|
||||
class Immediate {
|
||||
}
|
||||
|
||||
function clearTimer(timer) {
|
||||
const obj = localReflectApply(localWeakMapGet, TIMERS, [timer]);
|
||||
if (obj) {
|
||||
obj.clear(obj.value);
|
||||
}
|
||||
}
|
||||
|
||||
// This is a function and not an arrow function, since the original is also a function
|
||||
// eslint-disable-next-line no-shadow
|
||||
global.setTimeout = function setTimeout(callback, delay, ...args) {
|
||||
if (typeof callback !== 'function') throw new LocalTypeError('"callback" argument must be a function');
|
||||
const obj = new Timeout(callback, args);
|
||||
const cb = () => {
|
||||
localReflectApply(callback, null, args);
|
||||
};
|
||||
const tmr = host.setTimeout(cb, delay);
|
||||
|
||||
const ref = {
|
||||
__proto__: null,
|
||||
clear: host.clearTimeout,
|
||||
value: tmr
|
||||
};
|
||||
|
||||
localReflectApply(localWeakMapSet, TIMERS, [obj, ref]);
|
||||
return obj;
|
||||
};
|
||||
|
||||
// eslint-disable-next-line no-shadow
|
||||
global.setInterval = function setInterval(callback, interval, ...args) {
|
||||
if (typeof callback !== 'function') throw new LocalTypeError('"callback" argument must be a function');
|
||||
const obj = new Interval();
|
||||
const cb = () => {
|
||||
localReflectApply(callback, null, args);
|
||||
};
|
||||
const tmr = host.setInterval(cb, interval);
|
||||
|
||||
const ref = {
|
||||
__proto__: null,
|
||||
clear: host.clearInterval,
|
||||
value: tmr
|
||||
};
|
||||
|
||||
localReflectApply(localWeakMapSet, TIMERS, [obj, ref]);
|
||||
return obj;
|
||||
};
|
||||
|
||||
// eslint-disable-next-line no-shadow
|
||||
global.setImmediate = function setImmediate(callback, ...args) {
|
||||
if (typeof callback !== 'function') throw new LocalTypeError('"callback" argument must be a function');
|
||||
const obj = new Immediate();
|
||||
const cb = () => {
|
||||
localReflectApply(callback, null, args);
|
||||
};
|
||||
const tmr = host.setImmediate(cb);
|
||||
|
||||
const ref = {
|
||||
__proto__: null,
|
||||
clear: host.clearImmediate,
|
||||
value: tmr
|
||||
};
|
||||
|
||||
localReflectApply(localWeakMapSet, TIMERS, [obj, ref]);
|
||||
return obj;
|
||||
};
|
||||
|
||||
// eslint-disable-next-line no-shadow
|
||||
global.clearTimeout = function clearTimeout(timeout) {
|
||||
clearTimer(timeout);
|
||||
};
|
||||
|
||||
// eslint-disable-next-line no-shadow
|
||||
global.clearInterval = function clearInterval(interval) {
|
||||
clearTimer(interval);
|
||||
};
|
||||
|
||||
// eslint-disable-next-line no-shadow
|
||||
global.clearImmediate = function clearImmediate(immediate) {
|
||||
clearTimer(immediate);
|
||||
};
|
||||
|
||||
const localProcess = host.process;
|
||||
|
||||
function vmEmitArgs(event, args) {
|
||||
const allargs = [event];
|
||||
for (let i = 0; i < args.length; i++) {
|
||||
if (!localReflectDefineProperty(allargs, i + 1, {
|
||||
__proto__: null,
|
||||
value: args[i],
|
||||
writable: true,
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
})) throw new LocalError('Unexpected');
|
||||
}
|
||||
return localReflectApply(vm.emit, vm, allargs);
|
||||
}
|
||||
|
||||
const LISTENERS = new LocalWeakMap();
|
||||
const LISTENER_HANDLER = new LocalWeakMap();
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {*} name
|
||||
* @param {*} handler
|
||||
* @this process
|
||||
* @return {this}
|
||||
*/
|
||||
function addListener(name, handler) {
|
||||
if (name !== 'beforeExit' && name !== 'exit') {
|
||||
throw new LocalError(`Access denied to listen for '${name}' event.`);
|
||||
}
|
||||
|
||||
let cb = localReflectApply(localWeakMapGet, LISTENERS, [handler]);
|
||||
if (!cb) {
|
||||
cb = () => {
|
||||
handler();
|
||||
};
|
||||
localReflectApply(localWeakMapSet, LISTENER_HANDLER, [cb, handler]);
|
||||
localReflectApply(localWeakMapSet, LISTENERS, [handler, cb]);
|
||||
}
|
||||
|
||||
localProcess.on(name, cb);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @this process
|
||||
* @return {this}
|
||||
*/
|
||||
// eslint-disable-next-line no-shadow
|
||||
function process() {
|
||||
return this;
|
||||
}
|
||||
|
||||
const baseUptime = localProcess.uptime();
|
||||
|
||||
// FIXME wrong class structure
|
||||
global.process = {
|
||||
__proto__: process.prototype,
|
||||
argv: optionArgv !== undefined ? optionArgv : [],
|
||||
title: localProcess.title,
|
||||
version: localProcess.version,
|
||||
versions: localProcess.versions,
|
||||
arch: localProcess.arch,
|
||||
platform: localProcess.platform,
|
||||
env: optionEnv !== undefined ? optionEnv : {},
|
||||
pid: localProcess.pid,
|
||||
features: localProcess.features,
|
||||
nextTick: function nextTick(callback, ...args) {
|
||||
if (typeof callback !== 'function') {
|
||||
throw new LocalError('Callback must be a function.');
|
||||
}
|
||||
|
||||
localProcess.nextTick(()=>{
|
||||
localReflectApply(callback, null, args);
|
||||
});
|
||||
},
|
||||
hrtime: function hrtime(time) {
|
||||
return localProcess.hrtime(time);
|
||||
},
|
||||
uptime: function uptime() {
|
||||
return localProcess.uptime() - baseUptime;
|
||||
},
|
||||
cwd: function cwd() {
|
||||
return localProcess.cwd();
|
||||
},
|
||||
addListener,
|
||||
on: addListener,
|
||||
|
||||
once: function once(name, handler) {
|
||||
if (name !== 'beforeExit' && name !== 'exit') {
|
||||
throw new LocalError(`Access denied to listen for '${name}' event.`);
|
||||
}
|
||||
|
||||
let triggered = false;
|
||||
const cb = () => {
|
||||
if (triggered) return;
|
||||
triggered = true;
|
||||
localProcess.removeListener(name, cb);
|
||||
handler();
|
||||
};
|
||||
localReflectApply(localWeakMapSet, LISTENER_HANDLER, [cb, handler]);
|
||||
|
||||
localProcess.on(name, cb);
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
listeners: function listeners(name) {
|
||||
if (name !== 'beforeExit' && name !== 'exit') {
|
||||
// Maybe add ({__proto__:null})[name] to throw when name fails in https://tc39.es/ecma262/#sec-topropertykey.
|
||||
return [];
|
||||
}
|
||||
|
||||
// Filter out listeners, which were not created in this sandbox
|
||||
const all = localProcess.listeners(name);
|
||||
const filtered = [];
|
||||
let j = 0;
|
||||
for (let i = 0; i < all.length; i++) {
|
||||
const h = localReflectApply(localWeakMapGet, LISTENER_HANDLER, [all[i]]);
|
||||
if (h) {
|
||||
if (!localReflectDefineProperty(filtered, j, {
|
||||
__proto__: null,
|
||||
value: h,
|
||||
writable: true,
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
})) throw new LocalError('Unexpected');
|
||||
j++;
|
||||
}
|
||||
}
|
||||
return filtered;
|
||||
},
|
||||
|
||||
removeListener: function removeListener(name, handler) {
|
||||
if (name !== 'beforeExit' && name !== 'exit') {
|
||||
return this;
|
||||
}
|
||||
|
||||
const cb = localReflectApply(localWeakMapGet, LISTENERS, [handler]);
|
||||
if (cb) localProcess.removeListener(name, cb);
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
umask: function umask() {
|
||||
if (arguments.length) {
|
||||
throw new LocalError('Access denied to set umask.');
|
||||
}
|
||||
|
||||
return localProcess.umask();
|
||||
}
|
||||
};
|
||||
|
||||
if (optionConsole === 'inherit') {
|
||||
global.console = host.console;
|
||||
} else if (optionConsole === 'redirect') {
|
||||
global.console = {
|
||||
debug(...args) {
|
||||
vmEmitArgs('console.debug', args);
|
||||
},
|
||||
log(...args) {
|
||||
vmEmitArgs('console.log', args);
|
||||
},
|
||||
info(...args) {
|
||||
vmEmitArgs('console.info', args);
|
||||
},
|
||||
warn(...args) {
|
||||
vmEmitArgs('console.warn', args);
|
||||
},
|
||||
error(...args) {
|
||||
vmEmitArgs('console.error', args);
|
||||
},
|
||||
dir(...args) {
|
||||
vmEmitArgs('console.dir', args);
|
||||
},
|
||||
time() {},
|
||||
timeEnd() {},
|
||||
trace(...args) {
|
||||
vmEmitArgs('console.trace', args);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
__proto__: null,
|
||||
Module,
|
||||
jsonParse: JSON.parse,
|
||||
createRequireForModule,
|
||||
requireImpl
|
||||
};
|
457
dist/setup-sandbox.js
vendored
Normal file
457
dist/setup-sandbox.js
vendored
Normal file
@ -0,0 +1,457 @@
|
||||
/* global host, bridge, data, context */
|
||||
|
||||
'use strict';
|
||||
|
||||
const {
|
||||
Object: localObject,
|
||||
Array: localArray,
|
||||
Error: LocalError,
|
||||
Reflect: localReflect,
|
||||
Proxy: LocalProxy,
|
||||
WeakMap: LocalWeakMap,
|
||||
Function: localFunction,
|
||||
Promise: localPromise,
|
||||
eval: localEval
|
||||
} = global;
|
||||
|
||||
const {
|
||||
freeze: localObjectFreeze
|
||||
} = localObject;
|
||||
|
||||
const {
|
||||
getPrototypeOf: localReflectGetPrototypeOf,
|
||||
apply: localReflectApply,
|
||||
deleteProperty: localReflectDeleteProperty,
|
||||
has: localReflectHas,
|
||||
defineProperty: localReflectDefineProperty,
|
||||
setPrototypeOf: localReflectSetPrototypeOf,
|
||||
getOwnPropertyDescriptor: localReflectGetOwnPropertyDescriptor
|
||||
} = localReflect;
|
||||
|
||||
const {
|
||||
isArray: localArrayIsArray
|
||||
} = localArray;
|
||||
|
||||
const {
|
||||
ensureThis,
|
||||
ReadOnlyHandler,
|
||||
from,
|
||||
fromWithFactory,
|
||||
readonlyFactory,
|
||||
connect,
|
||||
addProtoMapping,
|
||||
VMError,
|
||||
ReadOnlyMockHandler
|
||||
} = bridge;
|
||||
|
||||
const {
|
||||
allowAsync,
|
||||
GeneratorFunction,
|
||||
AsyncFunction,
|
||||
AsyncGeneratorFunction
|
||||
} = data;
|
||||
|
||||
const {
|
||||
get: localWeakMapGet,
|
||||
set: localWeakMapSet
|
||||
} = LocalWeakMap.prototype;
|
||||
|
||||
function localUnexpected() {
|
||||
return new VMError('Should not happen');
|
||||
}
|
||||
|
||||
// global is originally prototype of host.Object so it can be used to climb up from the sandbox.
|
||||
if (!localReflectSetPrototypeOf(context, localObject.prototype)) throw localUnexpected();
|
||||
|
||||
Object.defineProperties(global, {
|
||||
global: {value: global, writable: true, configurable: true, enumerable: true},
|
||||
globalThis: {value: global, writable: true, configurable: true},
|
||||
GLOBAL: {value: global, writable: true, configurable: true},
|
||||
root: {value: global, writable: true, configurable: true},
|
||||
Error: {value: LocalError}
|
||||
});
|
||||
|
||||
if (!localReflectDefineProperty(global, 'VMError', {
|
||||
__proto__: null,
|
||||
value: VMError,
|
||||
writable: true,
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
})) throw localUnexpected();
|
||||
|
||||
// Fixes buffer unsafe allocation
|
||||
/* eslint-disable no-use-before-define */
|
||||
class BufferHandler extends ReadOnlyHandler {
|
||||
|
||||
apply(target, thiz, args) {
|
||||
if (args.length > 0 && typeof args[0] === 'number') {
|
||||
return LocalBuffer.alloc(args[0]);
|
||||
}
|
||||
return localReflectApply(LocalBuffer.from, LocalBuffer, args);
|
||||
}
|
||||
|
||||
construct(target, args, newTarget) {
|
||||
if (args.length > 0 && typeof args[0] === 'number') {
|
||||
return LocalBuffer.alloc(args[0]);
|
||||
}
|
||||
return localReflectApply(LocalBuffer.from, LocalBuffer, args);
|
||||
}
|
||||
|
||||
}
|
||||
/* eslint-enable no-use-before-define */
|
||||
|
||||
const LocalBuffer = fromWithFactory(obj => new BufferHandler(obj), host.Buffer);
|
||||
|
||||
|
||||
if (!localReflectDefineProperty(global, 'Buffer', {
|
||||
__proto__: null,
|
||||
value: LocalBuffer,
|
||||
writable: true,
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
})) throw localUnexpected();
|
||||
|
||||
addProtoMapping(LocalBuffer.prototype, host.Buffer.prototype, 'Uint8Array');
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {*} size Size of new buffer
|
||||
* @this LocalBuffer
|
||||
* @return {LocalBuffer}
|
||||
*/
|
||||
function allocUnsafe(size) {
|
||||
return LocalBuffer.alloc(size);
|
||||
}
|
||||
|
||||
connect(allocUnsafe, host.Buffer.allocUnsafe);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {*} size Size of new buffer
|
||||
* @this LocalBuffer
|
||||
* @return {LocalBuffer}
|
||||
*/
|
||||
function allocUnsafeSlow(size) {
|
||||
return LocalBuffer.alloc(size);
|
||||
}
|
||||
|
||||
connect(allocUnsafeSlow, host.Buffer.allocUnsafeSlow);
|
||||
|
||||
/**
|
||||
* Replacement for Buffer inspect
|
||||
*
|
||||
* @param {*} recurseTimes
|
||||
* @param {*} ctx
|
||||
* @this LocalBuffer
|
||||
* @return {string}
|
||||
*/
|
||||
function inspect(recurseTimes, ctx) {
|
||||
// Mimic old behavior, could throw but didn't pass a test.
|
||||
const max = host.INSPECT_MAX_BYTES;
|
||||
const actualMax = Math.min(max, this.length);
|
||||
const remaining = this.length - max;
|
||||
let str = this.hexSlice(0, actualMax).replace(/(.{2})/g, '$1 ').trim();
|
||||
if (remaining > 0) str += ` ... ${remaining} more byte${remaining > 1 ? 's' : ''}`;
|
||||
return `<${this.constructor.name} ${str}>`;
|
||||
}
|
||||
|
||||
connect(inspect, host.Buffer.prototype.inspect);
|
||||
|
||||
connect(localFunction.prototype.bind, host.Function.prototype.bind);
|
||||
|
||||
connect(localObject.prototype.__defineGetter__, host.Object.prototype.__defineGetter__);
|
||||
connect(localObject.prototype.__defineSetter__, host.Object.prototype.__defineSetter__);
|
||||
connect(localObject.prototype.__lookupGetter__, host.Object.prototype.__lookupGetter__);
|
||||
connect(localObject.prototype.__lookupSetter__, host.Object.prototype.__lookupSetter__);
|
||||
|
||||
/*
|
||||
* PrepareStackTrace sanitization
|
||||
*/
|
||||
|
||||
const oldPrepareStackTraceDesc = localReflectGetOwnPropertyDescriptor(LocalError, 'prepareStackTrace');
|
||||
|
||||
let currentPrepareStackTrace = LocalError.prepareStackTrace;
|
||||
const wrappedPrepareStackTrace = new LocalWeakMap();
|
||||
if (typeof currentPrepareStackTrace === 'function') {
|
||||
wrappedPrepareStackTrace.set(currentPrepareStackTrace, currentPrepareStackTrace);
|
||||
}
|
||||
|
||||
let OriginalCallSite;
|
||||
LocalError.prepareStackTrace = (e, sst) => {
|
||||
OriginalCallSite = sst[0].constructor;
|
||||
};
|
||||
new LocalError().stack;
|
||||
if (typeof OriginalCallSite === 'function') {
|
||||
LocalError.prepareStackTrace = undefined;
|
||||
|
||||
function makeCallSiteGetters(list) {
|
||||
const callSiteGetters = [];
|
||||
for (let i=0; i<list.length; i++) {
|
||||
const name = list[i];
|
||||
const func = OriginalCallSite.prototype[name];
|
||||
callSiteGetters[i] = {__proto__: null,
|
||||
name,
|
||||
propName: '_' + name,
|
||||
func: (thiz) => {
|
||||
return localReflectApply(func, thiz, []);
|
||||
}
|
||||
};
|
||||
}
|
||||
return callSiteGetters;
|
||||
}
|
||||
|
||||
function applyCallSiteGetters(thiz, callSite, getters) {
|
||||
for (let i=0; i<getters.length; i++) {
|
||||
const getter = getters[i];
|
||||
localReflectDefineProperty(thiz, getter.propName, {
|
||||
__proto__: null,
|
||||
value: getter.func(callSite)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const callSiteGetters = makeCallSiteGetters([
|
||||
'getTypeName',
|
||||
'getFunctionName',
|
||||
'getMethodName',
|
||||
'getFileName',
|
||||
'getLineNumber',
|
||||
'getColumnNumber',
|
||||
'getEvalOrigin',
|
||||
'isToplevel',
|
||||
'isEval',
|
||||
'isNative',
|
||||
'isConstructor',
|
||||
'isAsync',
|
||||
'isPromiseAll',
|
||||
'getPromiseIndex'
|
||||
]);
|
||||
|
||||
class CallSite {
|
||||
constructor(callSite) {
|
||||
applyCallSiteGetters(this, callSite, callSiteGetters);
|
||||
}
|
||||
getThis() {
|
||||
return undefined;
|
||||
}
|
||||
getFunction() {
|
||||
return undefined;
|
||||
}
|
||||
toString() {
|
||||
return 'CallSite {}';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (let i=0; i<callSiteGetters.length; i++) {
|
||||
const name = callSiteGetters[i].name;
|
||||
const funcProp = localReflectGetOwnPropertyDescriptor(OriginalCallSite.prototype, name);
|
||||
if (!funcProp) continue;
|
||||
const propertyName = callSiteGetters[i].propName;
|
||||
const func = {func() {
|
||||
return this[propertyName];
|
||||
}}.func;
|
||||
const nameProp = localReflectGetOwnPropertyDescriptor(func, 'name');
|
||||
if (!nameProp) throw localUnexpected();
|
||||
nameProp.value = name;
|
||||
if (!localReflectDefineProperty(func, 'name', nameProp)) throw localUnexpected();
|
||||
funcProp.value = func;
|
||||
if (!localReflectDefineProperty(CallSite.prototype, name, funcProp)) throw localUnexpected();
|
||||
}
|
||||
|
||||
if (!localReflectDefineProperty(LocalError, 'prepareStackTrace', {
|
||||
configurable: false,
|
||||
enumerable: false,
|
||||
get() {
|
||||
return currentPrepareStackTrace;
|
||||
},
|
||||
set(value) {
|
||||
if (typeof(value) !== 'function') {
|
||||
currentPrepareStackTrace = value;
|
||||
return;
|
||||
}
|
||||
const wrapped = localReflectApply(localWeakMapGet, wrappedPrepareStackTrace, [value]);
|
||||
if (wrapped) {
|
||||
currentPrepareStackTrace = wrapped;
|
||||
return;
|
||||
}
|
||||
const newWrapped = (error, sst) => {
|
||||
if (localArrayIsArray(sst)) {
|
||||
for (let i=0; i < sst.length; i++) {
|
||||
const cs = sst[i];
|
||||
if (typeof cs === 'object' && localReflectGetPrototypeOf(cs) === OriginalCallSite.prototype) {
|
||||
sst[i] = new CallSite(cs);
|
||||
}
|
||||
}
|
||||
}
|
||||
return value(error, sst);
|
||||
};
|
||||
localReflectApply(localWeakMapSet, wrappedPrepareStackTrace, [value, newWrapped]);
|
||||
localReflectApply(localWeakMapSet, wrappedPrepareStackTrace, [newWrapped, newWrapped]);
|
||||
currentPrepareStackTrace = newWrapped;
|
||||
}
|
||||
})) throw localUnexpected();
|
||||
} else if (oldPrepareStackTraceDesc) {
|
||||
localReflectDefineProperty(LocalError, 'prepareStackTrace', oldPrepareStackTraceDesc);
|
||||
} else {
|
||||
localReflectDeleteProperty(LocalError, 'prepareStackTrace');
|
||||
}
|
||||
|
||||
/*
|
||||
* Exception sanitization
|
||||
*/
|
||||
|
||||
const withProxy = localObjectFreeze({
|
||||
__proto__: null,
|
||||
has(target, key) {
|
||||
if (key === host.INTERNAL_STATE_NAME) return false;
|
||||
return localReflectHas(target, key);
|
||||
}
|
||||
});
|
||||
|
||||
const interanState = localObjectFreeze({
|
||||
__proto__: null,
|
||||
wrapWith(x) {
|
||||
if (x === null || x === undefined) return x;
|
||||
return new LocalProxy(localObject(x), withProxy);
|
||||
},
|
||||
handleException: ensureThis,
|
||||
import(what) {
|
||||
throw new VMError('Dynamic Import not supported');
|
||||
}
|
||||
});
|
||||
|
||||
if (!localReflectDefineProperty(global, host.INTERNAL_STATE_NAME, {
|
||||
__proto__: null,
|
||||
configurable: false,
|
||||
enumerable: false,
|
||||
writable: false,
|
||||
value: interanState
|
||||
})) throw localUnexpected();
|
||||
|
||||
/*
|
||||
* Eval sanitization
|
||||
*/
|
||||
|
||||
function throwAsync() {
|
||||
return new VMError('Async not available');
|
||||
}
|
||||
|
||||
function makeFunction(inputArgs, isAsync, isGenerator) {
|
||||
const lastArgs = inputArgs.length - 1;
|
||||
let code = lastArgs >= 0 ? `${inputArgs[lastArgs]}` : '';
|
||||
let args = lastArgs > 0 ? `${inputArgs[0]}` : '';
|
||||
for (let i = 1; i < lastArgs; i++) {
|
||||
args += `,${inputArgs[i]}`;
|
||||
}
|
||||
try {
|
||||
code = host.transformAndCheck(args, code, isAsync, isGenerator, allowAsync);
|
||||
} catch (e) {
|
||||
throw bridge.from(e);
|
||||
}
|
||||
return localEval(code);
|
||||
}
|
||||
|
||||
const FunctionHandler = {
|
||||
__proto__: null,
|
||||
apply(target, thiz, args) {
|
||||
return makeFunction(args, this.isAsync, this.isGenerator);
|
||||
},
|
||||
construct(target, args, newTarget) {
|
||||
return makeFunction(args, this.isAsync, this.isGenerator);
|
||||
}
|
||||
};
|
||||
|
||||
const EvalHandler = {
|
||||
__proto__: null,
|
||||
apply(target, thiz, args) {
|
||||
if (args.length === 0) return undefined;
|
||||
let code = `${args[0]}`;
|
||||
try {
|
||||
code = host.transformAndCheck(null, code, false, false, allowAsync);
|
||||
} catch (e) {
|
||||
throw bridge.from(e);
|
||||
}
|
||||
return localEval(code);
|
||||
}
|
||||
};
|
||||
|
||||
const AsyncErrorHandler = {
|
||||
__proto__: null,
|
||||
apply(target, thiz, args) {
|
||||
throw throwAsync();
|
||||
},
|
||||
construct(target, args, newTarget) {
|
||||
throw throwAsync();
|
||||
}
|
||||
};
|
||||
|
||||
function makeCheckFunction(isAsync, isGenerator) {
|
||||
if (isAsync && !allowAsync) return AsyncErrorHandler;
|
||||
return {
|
||||
__proto__: FunctionHandler,
|
||||
isAsync,
|
||||
isGenerator
|
||||
};
|
||||
}
|
||||
|
||||
function overrideWithProxy(obj, prop, value, handler) {
|
||||
const proxy = new LocalProxy(value, handler);
|
||||
if (!localReflectDefineProperty(obj, prop, {__proto__: null, value: proxy})) throw localUnexpected();
|
||||
return proxy;
|
||||
}
|
||||
|
||||
const proxiedFunction = overrideWithProxy(localFunction.prototype, 'constructor', localFunction, makeCheckFunction(false, false));
|
||||
if (GeneratorFunction) {
|
||||
if (!localReflectSetPrototypeOf(GeneratorFunction, proxiedFunction)) throw localUnexpected();
|
||||
overrideWithProxy(GeneratorFunction.prototype, 'constructor', GeneratorFunction, makeCheckFunction(false, true));
|
||||
}
|
||||
if (AsyncFunction) {
|
||||
if (!localReflectSetPrototypeOf(AsyncFunction, proxiedFunction)) throw localUnexpected();
|
||||
overrideWithProxy(AsyncFunction.prototype, 'constructor', AsyncFunction, makeCheckFunction(true, false));
|
||||
}
|
||||
if (AsyncGeneratorFunction) {
|
||||
if (!localReflectSetPrototypeOf(AsyncGeneratorFunction, proxiedFunction)) throw localUnexpected();
|
||||
overrideWithProxy(AsyncGeneratorFunction.prototype, 'constructor', AsyncGeneratorFunction, makeCheckFunction(true, true));
|
||||
}
|
||||
|
||||
global.Function = proxiedFunction;
|
||||
global.eval = new LocalProxy(localEval, EvalHandler);
|
||||
|
||||
/*
|
||||
* Promise sanitization
|
||||
*/
|
||||
|
||||
if (localPromise && !allowAsync) {
|
||||
|
||||
const PromisePrototype = localPromise.prototype;
|
||||
|
||||
overrideWithProxy(PromisePrototype, 'then', PromisePrototype.then, AsyncErrorHandler);
|
||||
// This seems not to work, and will produce
|
||||
// UnhandledPromiseRejectionWarning: TypeError: Method Promise.prototype.then called on incompatible receiver [object Object].
|
||||
// This is likely caused since the host.Promise.prototype.then cannot use the VM Proxy object.
|
||||
// Contextify.connect(host.Promise.prototype.then, Promise.prototype.then);
|
||||
|
||||
if (PromisePrototype.finally) {
|
||||
overrideWithProxy(PromisePrototype, 'finally', PromisePrototype.finally, AsyncErrorHandler);
|
||||
// Contextify.connect(host.Promise.prototype.finally, Promise.prototype.finally);
|
||||
}
|
||||
if (Promise.prototype.catch) {
|
||||
overrideWithProxy(PromisePrototype, 'catch', PromisePrototype.catch, AsyncErrorHandler);
|
||||
// Contextify.connect(host.Promise.prototype.catch, Promise.prototype.catch);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function readonly(other, mock) {
|
||||
// Note: other@other(unsafe) mock@other(unsafe) returns@this(unsafe) throws@this(unsafe)
|
||||
if (!mock) return fromWithFactory(readonlyFactory, other);
|
||||
const tmock = from(mock);
|
||||
return fromWithFactory(obj=>new ReadOnlyMockHandler(obj, tmock), other);
|
||||
}
|
||||
|
||||
return {
|
||||
__proto__: null,
|
||||
readonly,
|
||||
global
|
||||
};
|
@ -136,9 +136,9 @@ For further reading regarding the security of pull requests, see this GitHub blo
|
||||
|
||||
Pull requests created by the action using the default `GITHUB_TOKEN` cannot trigger other workflows. If you have `on: pull_request` or `on: push` workflows acting as checks on pull requests, they will not run.
|
||||
|
||||
> When you use the repository's GITHUB_TOKEN to perform tasks on behalf of the GitHub Actions app, events triggered by the GITHUB_TOKEN will not create a new workflow run.
|
||||
> When you use the repository's `GITHUB_TOKEN` to perform tasks, events triggered by the `GITHUB_TOKEN` will not create a new workflow run. This prevents you from accidentally creating recursive workflow runs. For example, if a workflow run pushes code using the repository's `GITHUB_TOKEN`, a new workflow will not run even when the repository contains a workflow configured to run when `push` events occur.
|
||||
|
||||
[GitHub Actions: Events that trigger workflows](https://docs.github.com/en/actions/reference/events-that-trigger-workflows#triggering-new-workflows-using-a-personal-access-token)
|
||||
[GitHub Actions: Triggering a workflow from a workflow](https://docs.github.com/en/actions/using-workflows/triggering-a-workflow#triggering-a-workflow-from-a-workflow)
|
||||
|
||||
#### Workarounds to trigger further workflow runs
|
||||
|
||||
|
6571
package-lock.json
generated
6571
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
17
package.json
17
package.json
@ -29,16 +29,16 @@
|
||||
},
|
||||
"homepage": "https://github.com/peter-evans/create-pull-request",
|
||||
"dependencies": {
|
||||
"@actions/core": "^1.6.0",
|
||||
"@actions/exec": "^1.1.0",
|
||||
"@actions/core": "^1.10.0",
|
||||
"@actions/exec": "^1.1.1",
|
||||
"@octokit/core": "^3.5.1",
|
||||
"@octokit/plugin-paginate-rest": "^2.17.0",
|
||||
"@octokit/plugin-rest-endpoint-methods": "^5.13.0",
|
||||
"https-proxy-agent": "^5.0.0",
|
||||
"proxy-agent": "^5.0.0",
|
||||
"uuid": "^8.3.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "^27.0.3",
|
||||
"@types/jest": "^27.5.0",
|
||||
"@types/node": "^16.11.11",
|
||||
"@typescript-eslint/parser": "^5.5.0",
|
||||
"@vercel/ncc": "^0.32.0",
|
||||
@ -46,12 +46,13 @@
|
||||
"eslint-import-resolver-typescript": "^2.5.0",
|
||||
"eslint-plugin-github": "^4.3.5",
|
||||
"eslint-plugin-import": "^2.25.3",
|
||||
"eslint-plugin-jest": "^25.3.0",
|
||||
"jest": "^27.4.3",
|
||||
"jest-circus": "^27.4.2",
|
||||
"eslint-plugin-jest": "^26.1.5",
|
||||
"jest": "^28.1.0",
|
||||
"jest-circus": "^28.1.0",
|
||||
"jest-environment-jsdom": "^28.1.0",
|
||||
"js-yaml": "^4.1.0",
|
||||
"prettier": "^2.5.0",
|
||||
"ts-jest": "^27.0.7",
|
||||
"ts-jest": "^28.0.2",
|
||||
"typescript": "^4.5.2"
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import {v4 as uuidv4} from 'uuid'
|
||||
|
||||
const CHERRYPICK_EMPTY =
|
||||
'The previous cherry-pick is now empty, possibly due to conflict resolution.'
|
||||
const NOTHING_TO_COMMIT = 'nothing to commit, working tree clean'
|
||||
|
||||
export enum WorkingBaseType {
|
||||
Branch = 'branch',
|
||||
@ -33,7 +34,9 @@ export async function tryFetch(
|
||||
branch: string
|
||||
): Promise<boolean> {
|
||||
try {
|
||||
await git.fetch([`${branch}:refs/remotes/${remote}/${branch}`], remote)
|
||||
await git.fetch([`${branch}:refs/remotes/${remote}/${branch}`], remote, [
|
||||
'--force'
|
||||
])
|
||||
return true
|
||||
} catch {
|
||||
return false
|
||||
@ -132,7 +135,14 @@ export async function createOrUpdateBranch(
|
||||
if (signoff) {
|
||||
popts.push('--signoff')
|
||||
}
|
||||
await git.commit(popts)
|
||||
const commitResult = await git.commit(popts, true)
|
||||
// 'nothing to commit' can occur when core.autocrlf is set to true
|
||||
if (
|
||||
commitResult.exitCode != 0 &&
|
||||
!commitResult.stdout.includes(NOTHING_TO_COMMIT)
|
||||
) {
|
||||
throw new Error(`Unexpected error: ${commitResult.stderr}`)
|
||||
}
|
||||
}
|
||||
|
||||
// Remove uncommitted tracked and untracked changes
|
||||
|
@ -60,6 +60,9 @@ export async function createPullRequest(inputs: Inputs): Promise<void> {
|
||||
: baseRemote.repository
|
||||
if (inputs.pushToFork) {
|
||||
// Check if the supplied fork is really a fork of the base
|
||||
core.info(
|
||||
`Checking if '${branchRepository}' is a fork of '${baseRemote.repository}'`
|
||||
)
|
||||
const parentRepository = await githubHelper.getRepositoryParent(
|
||||
branchRepository
|
||||
)
|
||||
@ -240,8 +243,8 @@ export async function createPullRequest(inputs: Inputs): Promise<void> {
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error: any) {
|
||||
core.setFailed(error.message)
|
||||
} catch (error) {
|
||||
core.setFailed(utils.getErrorMessage(error))
|
||||
} finally {
|
||||
// Remove auth and restore persisted auth config if it existed
|
||||
core.startGroup('Restore persisted git credentials')
|
||||
|
@ -3,6 +3,7 @@ import * as fs from 'fs'
|
||||
import {GitCommandManager} from './git-command-manager'
|
||||
import * as path from 'path'
|
||||
import {URL} from 'url'
|
||||
import * as utils from './utils'
|
||||
|
||||
export class GitAuthHelper {
|
||||
private git: GitCommandManager
|
||||
@ -33,8 +34,8 @@ export class GitAuthHelper {
|
||||
try {
|
||||
await this.setExtraheaderConfig(this.persistedExtraheaderConfigValue)
|
||||
core.info('Persisted git credentials restored')
|
||||
} catch (e: any) {
|
||||
core.warning(e)
|
||||
} catch (e) {
|
||||
core.warning(utils.getErrorMessage(e))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -53,7 +53,10 @@ export class GitCommandManager {
|
||||
return await this.exec(args, allowAllExitCodes)
|
||||
}
|
||||
|
||||
async commit(options?: string[]): Promise<void> {
|
||||
async commit(
|
||||
options?: string[],
|
||||
allowAllExitCodes = false
|
||||
): Promise<GitOutput> {
|
||||
const args = ['commit']
|
||||
if (this.identityGitOptions) {
|
||||
args.unshift(...this.identityGitOptions)
|
||||
@ -63,7 +66,7 @@ export class GitCommandManager {
|
||||
args.push(...options)
|
||||
}
|
||||
|
||||
await this.exec(args)
|
||||
return await this.exec(args, allowAllExitCodes)
|
||||
}
|
||||
|
||||
async config(
|
||||
|
@ -1,6 +1,7 @@
|
||||
import * as core from '@actions/core'
|
||||
import {Inputs} from './create-pull-request'
|
||||
import {Octokit, OctokitOptions} from './octokit-client'
|
||||
import * as utils from './utils'
|
||||
|
||||
const ERROR_PR_REVIEW_FROM_AUTHOR =
|
||||
'Review cannot be requested from pull request author'
|
||||
@ -64,10 +65,9 @@ export class GitHubHelper {
|
||||
html_url: pull.html_url,
|
||||
created: true
|
||||
}
|
||||
} catch (e: any) {
|
||||
} catch (e) {
|
||||
if (
|
||||
e.message &&
|
||||
e.message.includes(`A pull request already exists for ${headBranch}`)
|
||||
utils.getErrorMessage(e).includes(`A pull request already exists for`)
|
||||
) {
|
||||
core.info(`A pull request already exists for ${headBranch}`)
|
||||
} else {
|
||||
@ -169,8 +169,8 @@ export class GitHubHelper {
|
||||
pull_number: pull.number,
|
||||
...requestReviewersParams
|
||||
})
|
||||
} catch (e: any) {
|
||||
if (e.message && e.message.includes(ERROR_PR_REVIEW_FROM_AUTHOR)) {
|
||||
} catch (e) {
|
||||
if (utils.getErrorMessage(e).includes(ERROR_PR_REVIEW_FROM_AUTHOR)) {
|
||||
core.warning(ERROR_PR_REVIEW_FROM_AUTHOR)
|
||||
} else {
|
||||
throw e
|
||||
|
@ -30,8 +30,8 @@ async function run(): Promise<void> {
|
||||
core.debug(`Inputs: ${inspect(inputs)}`)
|
||||
|
||||
await createPullRequest(inputs)
|
||||
} catch (error: any) {
|
||||
core.setFailed(error.message)
|
||||
} catch (error) {
|
||||
core.setFailed(utils.getErrorMessage(error))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import {Octokit as Core} from '@octokit/core'
|
||||
import {paginateRest} from '@octokit/plugin-paginate-rest'
|
||||
import {restEndpointMethods} from '@octokit/plugin-rest-endpoint-methods'
|
||||
import {HttpsProxyAgent} from 'https-proxy-agent'
|
||||
import ProxyAgent from 'proxy-agent'
|
||||
export {RestEndpointMethodTypes} from '@octokit/plugin-rest-endpoint-methods'
|
||||
export {OctokitOptions} from '@octokit/core/dist-types/types'
|
||||
|
||||
@ -11,12 +11,17 @@ export const Octokit = Core.plugin(
|
||||
autoProxyAgent
|
||||
)
|
||||
|
||||
// Octokit plugin to support the https_proxy environment variable
|
||||
// Octokit plugin to support the standard environment variables http_proxy, https_proxy and no_proxy
|
||||
function autoProxyAgent(octokit: Core) {
|
||||
const proxy = process.env.https_proxy || process.env.HTTPS_PROXY
|
||||
const proxy =
|
||||
process.env.https_proxy ||
|
||||
process.env.HTTPS_PROXY ||
|
||||
process.env.http_proxy ||
|
||||
process.env.HTTP_PROXY
|
||||
|
||||
if (!proxy) return
|
||||
|
||||
const agent = new HttpsProxyAgent(proxy)
|
||||
const agent = new ProxyAgent()
|
||||
octokit.hook.before('request', options => {
|
||||
options.request.agent = agent
|
||||
})
|
||||
|
22
src/utils.ts
22
src/utils.ts
@ -47,11 +47,11 @@ export function getRemoteDetail(remoteUrl: string): RemoteDetail {
|
||||
}
|
||||
|
||||
const httpsUrlPattern = new RegExp(
|
||||
'^https?://.*@?' + githubServerMatch[1] + '/(.+/.+?)(.git)?$',
|
||||
'^https?://.*@?' + githubServerMatch[1] + '/(.+/.+?)(\\.git)?$',
|
||||
'i'
|
||||
)
|
||||
const sshUrlPattern = new RegExp(
|
||||
'^git@' + githubServerMatch[1] + ':(.+/.+).git$',
|
||||
'^git@' + githubServerMatch[1] + ':(.+/.+)\\.git$',
|
||||
'i'
|
||||
)
|
||||
|
||||
@ -134,13 +134,15 @@ export function fileExistsSync(path: string): boolean {
|
||||
let stats: fs.Stats
|
||||
try {
|
||||
stats = fs.statSync(path)
|
||||
} catch (error: any) {
|
||||
if (error.code === 'ENOENT') {
|
||||
} catch (error) {
|
||||
if (hasErrorCode(error) && error.code === 'ENOENT') {
|
||||
return false
|
||||
}
|
||||
|
||||
throw new Error(
|
||||
`Encountered an error when checking whether path '${path}' exists: ${error.message}`
|
||||
`Encountered an error when checking whether path '${path}' exists: ${getErrorMessage(
|
||||
error
|
||||
)}`
|
||||
)
|
||||
}
|
||||
|
||||
@ -150,3 +152,13 @@ export function fileExistsSync(path: string): boolean {
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
function hasErrorCode(error: any): error is {code: string} {
|
||||
return typeof (error && error.code) === 'string'
|
||||
}
|
||||
|
||||
export function getErrorMessage(error: unknown) {
|
||||
if (error instanceof Error) return error.message
|
||||
return String(error)
|
||||
}
|
||||
|
Reference in New Issue
Block a user