nativescript
Version:
Command-line interface for building NativeScript projects
201 lines • 8.12 kB
JavaScript
;
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Errors = void 0;
exports.installUncaughtExceptionListener = installUncaughtExceptionListener;
const util = require("util");
const path = require("path");
const _ = require("lodash");
const source_map_1 = require("source-map");
const helpers_1 = require("./helpers");
const decorators_1 = require("./decorators");
const yok_1 = require("./yok");
// we need this to overwrite .stack property (read-only in Error)
function Exception() {
/* intentionally left blank */
}
Exception.prototype = new Error();
async function resolveCallStack(error) {
const stackLines = error.stack.split("\n");
const parsed = _.map(stackLines, (line) => {
let match = line.match(/^\s*at ([^(]*) \((.*?):([0-9]+):([0-9]+)\)$/);
if (match) {
return match;
}
match = line.match(/^\s*at (.*?):([0-9]+):([0-9]+)$/);
if (match) {
match.splice(1, 0, "<anonymous>");
return match;
}
return line;
});
const fs = require("fs");
const remapped = await Promise.all(_.map(parsed, async (parsedLine) => {
if (_.isString(parsedLine)) {
return parsedLine;
}
const functionName = parsedLine[1];
const fileName = parsedLine[2];
const line = +parsedLine[3];
const column = +parsedLine[4];
const mapFileName = fileName + ".map";
if (!fs.existsSync(mapFileName)) {
return parsedLine.input;
}
const mapData = JSON.parse(fs.readFileSync(mapFileName).toString());
return await source_map_1.SourceMapConsumer.with(mapData, null, (consumer) => {
const sourcePos = consumer.originalPositionFor({
line: line,
column: column,
});
if (sourcePos && sourcePos.source) {
const source = path.join(path.dirname(fileName), sourcePos.source);
return util.format(" at %s (%s:%s:%s)", functionName, source, sourcePos.line, sourcePos.column);
}
return util.format(" at %s (%s:%s:%s)", functionName, fileName, line, column);
});
}));
let outputMessage = remapped.join("\n");
if (outputMessage.indexOf(error.message) === -1) {
// when fibers throw error in node 0.12.x, the stack does NOT contain the message
outputMessage = outputMessage.replace(/Error/, "Error: " + error.message);
}
return outputMessage;
}
function installUncaughtExceptionListener(actionOnException) {
const handler = async (err) => {
try {
let callstack = err.stack;
if (callstack) {
try {
callstack = await resolveCallStack(err);
}
catch (err) {
console.error("Error while resolving callStack:", err);
}
}
console.error(callstack || err.toString());
await tryTrackException(err, yok_1.injector);
if (actionOnException) {
actionOnException();
}
}
catch (err) {
// In case the handler throws error and we do not catch it, we'll go in infinite loop of unhandled rejections.
// We cannot do anything here as even `console.error` may fail. So just exit the process.
process.exit(131 /* ErrorCodes.UNHANDLED_REJECTION_FAILURE */);
}
};
process.on("uncaughtException", handler);
process.on("unhandledRejection", handler);
}
async function tryTrackException(error, localInjector) {
let disableAnalytics;
try {
disableAnalytics = localInjector.resolve("staticConfig").disableAnalytics;
}
catch (err) {
// We should get here only in our unit tests.
disableAnalytics = true;
}
if (!disableAnalytics) {
try {
const analyticsService = localInjector.resolve("analyticsService");
await analyticsService.trackException(error, error.message);
}
catch (e) {
// Do not replace with logger due to cyclic dependency
console.error("Error while reporting exception: " + e);
}
}
}
class Errors {
constructor($injector) {
this.$injector = $injector;
this.printCallStack = false;
}
fail(optsOrFormatStr, ...args) {
const opts = this.getFailOptions(optsOrFormatStr);
return this.failWithOptions(opts, false, ...args);
}
failWithoutHelp(optsOrFormatStr, ...args) {
return this.fail(optsOrFormatStr, ...args);
}
failWithHelp(optsOrFormatStr, ...args) {
const opts = this.getFailOptions(optsOrFormatStr);
return this.failWithOptions(opts, true, ...args);
}
getFailOptions(optsOrFormatStr) {
let opts = optsOrFormatStr;
if (_.isString(opts)) {
opts = { formatStr: opts };
}
return opts;
}
failWithOptions(opts, suggestCommandHelp, ...args) {
const argsArray = args || [];
const exception = new Exception();
exception.name = opts.name || "Exception";
exception.message = util.format.apply(null, [opts.formatStr].concat(argsArray));
try {
const $messagesService = this.$injector.resolve("messagesService");
exception.message = $messagesService.getMessage.apply($messagesService, [opts.formatStr].concat(argsArray));
}
catch (err) {
// Ignore
}
exception.stack = new Error(exception.message).stack;
exception.errorCode = opts.errorCode || 127 /* ErrorCodes.UNKNOWN */;
exception.suggestCommandHelp = suggestCommandHelp;
exception.proxyAuthenticationRequired = !!opts.proxyAuthenticationRequired;
exception.printOnStdout = opts.printOnStdout;
this.$injector.resolve("logger").trace(opts.formatStr);
throw exception;
}
async beginCommand(action, printCommandHelpSuggestion) {
try {
return await action();
}
catch (ex) {
const logger = this.$injector.resolve("logger");
const loggerLevel = logger.getLevel().toUpperCase();
const printCallStack = this.printCallStack ||
loggerLevel === "TRACE" ||
loggerLevel === "DEBUG";
const message = printCallStack
? await resolveCallStack(ex)
: (0, helpers_1.isInteractive)()
? `\x1B[31;1m${ex.message}\x1B[0m`
: ex.message;
if (ex.printOnStdout) {
logger.info(message);
}
else {
logger.error(message);
}
if (ex.suggestCommandHelp) {
await printCommandHelpSuggestion();
}
await tryTrackException(ex, this.$injector);
process.exit(_.isNumber(ex.errorCode) ? ex.errorCode : 127 /* ErrorCodes.UNKNOWN */);
}
}
// If you want to activate this function, start Node with flags --nouse_idle_notification and --expose_gc
verifyHeap(message) {
if (global.gc) {
console.log("verifyHeap: '%s'", message);
global.gc();
}
}
}
exports.Errors = Errors;
__decorate([
(0, decorators_1.deprecated)("Use `fail` instead.")
], Errors.prototype, "failWithoutHelp", null);
yok_1.injector.register("errors", Errors);
//# sourceMappingURL=errors.js.map