UNPKG

nativescript

Version:

Command-line interface for building NativeScript projects

201 lines • 8.12 kB
"use strict"; 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