JezK
Edit File: parse.js
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports["default"] = _default; function _typeof2() { var data = _interopRequireDefault(require("@babel/runtime/helpers/typeof")); _typeof2 = function _typeof2() { return data; }; return data; } function _classCallCheck2() { var data = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck")); _classCallCheck2 = function _classCallCheck2() { return data; }; return data; } function _createClass2() { var data = _interopRequireDefault(require("@babel/runtime/helpers/createClass")); _createClass2 = function _createClass2() { return data; }; return data; } function _defineProperty2() { var data = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); _defineProperty2 = function _defineProperty2() { return data; }; return data; } function _regenerator() { var data = _interopRequireDefault(require("@babel/runtime/regenerator")); _regenerator = function _regenerator() { return data; }; return data; } function _util() { var data = _interopRequireDefault(require("util")); _util = function _util() { return data; }; return data; } function _invariant() { var data = _interopRequireDefault(require("invariant")); _invariant = function _invariant() { return data; }; return data; } function _stripBom() { var data = _interopRequireDefault(require("strip-bom")); _stripBom = function _stripBom() { return data; }; return data; } function _constants() { var data = require("../constants.js"); _constants = function _constants() { return data; }; return data; } function _errors() { var data = require("../errors.js"); _errors = function _errors() { return data; }; return data; } function _map() { var data = _interopRequireDefault(require("../util/map.js")); _map = function _map() { return data; }; return data; } function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; } var _marked = /*#__PURE__*/_regenerator()["default"].mark(tokenise); var _require = require('js-yaml'), load = _require.load, FAILSAFE_SCHEMA = _require.FAILSAFE_SCHEMA; var VERSION_REGEX = /^yarn lockfile v(\d+)$/; var TOKEN_TYPES = { "boolean": 'BOOLEAN', string: 'STRING', identifier: 'IDENTIFIER', eof: 'EOF', colon: 'COLON', newline: 'NEWLINE', comment: 'COMMENT', indent: 'INDENT', invalid: 'INVALID', number: 'NUMBER', comma: 'COMMA' }; var VALID_PROP_VALUE_TOKENS = [TOKEN_TYPES["boolean"], TOKEN_TYPES.string, TOKEN_TYPES.number]; function isValidPropValueToken(token) { return VALID_PROP_VALUE_TOKENS.indexOf(token.type) >= 0; } function tokenise(input) { var lastNewline, line, col, buildToken, chop, nextNewline, val, indentSize, i, _i, isEscaped, _val, _val2, _i2, _char, name; return _regenerator()["default"].wrap(function tokenise$(_context) { while (1) switch (_context.prev = _context.next) { case 0: buildToken = function _buildToken(type, value) { return { line: line, col: col, type: type, value: value }; }; lastNewline = false; line = 1; col = 0; case 4: if (!input.length) { _context.next = 125; break; } chop = 0; if (!(input[0] === '\n' || input[0] === '\r')) { _context.next = 15; break; } chop++; // If this is a \r\n line, ignore both chars but only add one new line if (input[1] === '\n') { chop++; } line++; col = 0; _context.next = 13; return buildToken(TOKEN_TYPES.newline); case 13: _context.next = 117; break; case 15: if (!(input[0] === '#')) { _context.next = 25; break; } chop++; nextNewline = input.indexOf('\n', chop); if (nextNewline === -1) { nextNewline = input.length; } val = input.substring(chop, nextNewline); chop = nextNewline; _context.next = 23; return buildToken(TOKEN_TYPES.comment, val); case 23: _context.next = 117; break; case 25: if (!(input[0] === ' ')) { _context.next = 41; break; } if (!lastNewline) { _context.next = 38; break; } indentSize = 1; for (i = 1; input[i] === ' '; i++) { indentSize++; } if (!(indentSize % 2)) { _context.next = 33; break; } throw new TypeError('Invalid number of spaces'); case 33: chop = indentSize; _context.next = 36; return buildToken(TOKEN_TYPES.indent, indentSize / 2); case 36: _context.next = 39; break; case 38: chop++; case 39: _context.next = 117; break; case 41: if (!(input[0] === '"')) { _context.next = 69; break; } _i = 1; case 43: if (!(_i < input.length)) { _context.next = 52; break; } if (!(input[_i] === '"')) { _context.next = 49; break; } isEscaped = input[_i - 1] === '\\' && input[_i - 2] !== '\\'; if (isEscaped) { _context.next = 49; break; } _i++; return _context.abrupt("break", 52); case 49: _i++; _context.next = 43; break; case 52: _val = input.substring(0, _i); chop = _i; _context.prev = 54; _context.next = 57; return buildToken(TOKEN_TYPES.string, JSON.parse(_val)); case 57: _context.next = 67; break; case 59: _context.prev = 59; _context.t0 = _context["catch"](54); if (!(_context.t0 instanceof SyntaxError)) { _context.next = 66; break; } _context.next = 64; return buildToken(TOKEN_TYPES.invalid); case 64: _context.next = 67; break; case 66: throw _context.t0; case 67: _context.next = 117; break; case 69: if (!/^[0-9]/.test(input)) { _context.next = 76; break; } _val2 = /^[0-9]+/.exec(input)[0]; chop = _val2.length; _context.next = 74; return buildToken(TOKEN_TYPES.number, +_val2); case 74: _context.next = 117; break; case 76: if (!/^true/.test(input)) { _context.next = 82; break; } _context.next = 79; return buildToken(TOKEN_TYPES["boolean"], true); case 79: chop = 4; _context.next = 117; break; case 82: if (!/^false/.test(input)) { _context.next = 88; break; } _context.next = 85; return buildToken(TOKEN_TYPES["boolean"], false); case 85: chop = 5; _context.next = 117; break; case 88: if (!(input[0] === ':')) { _context.next = 94; break; } _context.next = 91; return buildToken(TOKEN_TYPES.colon); case 91: chop++; _context.next = 117; break; case 94: if (!(input[0] === ',')) { _context.next = 100; break; } _context.next = 97; return buildToken(TOKEN_TYPES.comma); case 97: chop++; _context.next = 117; break; case 100: if (!/^[a-zA-Z\/.-]/g.test(input)) { _context.next = 115; break; } _i2 = 0; case 102: if (!(_i2 < input.length)) { _context.next = 109; break; } _char = input[_i2]; if (!(_char === ':' || _char === ' ' || _char === '\n' || _char === '\r' || _char === ',')) { _context.next = 106; break; } return _context.abrupt("break", 109); case 106: _i2++; _context.next = 102; break; case 109: name = input.substring(0, _i2); chop = _i2; _context.next = 113; return buildToken(TOKEN_TYPES.string, name); case 113: _context.next = 117; break; case 115: _context.next = 117; return buildToken(TOKEN_TYPES.invalid); case 117: if (chop) { _context.next = 120; break; } _context.next = 120; return buildToken(TOKEN_TYPES.invalid); case 120: col += chop; lastNewline = input[0] === '\n' || input[0] === '\r' && input[1] === '\n'; input = input.slice(chop); _context.next = 4; break; case 125: _context.next = 127; return buildToken(TOKEN_TYPES.eof); case 127: case "end": return _context.stop(); } }, _marked, null, [[54, 59]]); } var Parser = /*#__PURE__*/function () { function Parser(input) { var fileLoc = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'lockfile'; (0, _classCallCheck2()["default"])(this, Parser); (0, _defineProperty2()["default"])(this, "fileLoc", void 0); (0, _defineProperty2()["default"])(this, "token", void 0); (0, _defineProperty2()["default"])(this, "tokens", void 0); (0, _defineProperty2()["default"])(this, "comments", void 0); this.comments = []; this.tokens = tokenise(input); this.fileLoc = fileLoc; } (0, _createClass2()["default"])(Parser, [{ key: "onComment", value: function onComment(token) { var value = token.value; (0, _invariant()["default"])(typeof value === 'string', 'expected token value to be a string'); var comment = value.trim(); var versionMatch = comment.match(VERSION_REGEX); if (versionMatch) { var version = +versionMatch[1]; if (version > _constants().LOCKFILE_VERSION) { throw new (_errors().MessageError)("Can't install from a lockfile of version ".concat(version, " as you're on an old yarn version that only supports ") + "versions up to ".concat(_constants().LOCKFILE_VERSION, ". Run `$ yarn self-update` to upgrade to the latest version.")); } } this.comments.push(comment); } }, { key: "next", value: function next() { var item = this.tokens.next(); (0, _invariant()["default"])(item, 'expected a token'); var done = item.done, value = item.value; if (done || !value) { throw new Error('No more tokens'); } else if (value.type === TOKEN_TYPES.comment) { this.onComment(value); return this.next(); } else { return this.token = value; } } }, { key: "unexpected", value: function unexpected() { var msg = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'Unexpected token'; throw new SyntaxError("".concat(msg, " ").concat(this.token.line, ":").concat(this.token.col, " in ").concat(this.fileLoc)); } }, { key: "expect", value: function expect(tokType) { if (this.token.type === tokType) { this.next(); } else { this.unexpected(); } } }, { key: "eat", value: function eat(tokType) { if (this.token.type === tokType) { this.next(); return true; } else { return false; } } }, { key: "parse", value: function parse() { var indent = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; var obj = (0, _map()["default"])(); while (true) { var propToken = this.token; if (propToken.type === TOKEN_TYPES.newline) { var nextToken = this.next(); if (!indent) { // if we have 0 indentation then the next token doesn't matter continue; } if (nextToken.type !== TOKEN_TYPES.indent) { // if we have no indentation after a newline then we've gone down a level break; } if (nextToken.value === indent) { // all is good, the indent is on our level this.next(); } else { // the indentation is less than our level break; } } else if (propToken.type === TOKEN_TYPES.indent) { if (propToken.value === indent) { this.next(); } else { break; } } else if (propToken.type === TOKEN_TYPES.eof) { break; } else if (propToken.type === TOKEN_TYPES.string) { // property key var key = propToken.value; (0, _invariant()["default"])(key, 'Expected a key'); var keys = [key]; this.next(); // support multiple keys while (this.token.type === TOKEN_TYPES.comma) { this.next(); // skip comma var keyToken = this.token; if (keyToken.type !== TOKEN_TYPES.string) { this.unexpected('Expected string'); } var _key = keyToken.value; (0, _invariant()["default"])(_key, 'Expected a key'); keys.push(_key); this.next(); } var wasColon = this.token.type === TOKEN_TYPES.colon; if (wasColon) { this.next(); } if (isValidPropValueToken(this.token)) { // plain value var _iterator = _createForOfIteratorHelper(keys), _step; try { for (_iterator.s(); !(_step = _iterator.n()).done;) { var _key2 = _step.value; obj[_key2] = this.token.value; } } catch (err) { _iterator.e(err); } finally { _iterator.f(); } this.next(); } else if (wasColon) { // parse object var val = this.parse(indent + 1); var _iterator2 = _createForOfIteratorHelper(keys), _step2; try { for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) { var _key3 = _step2.value; obj[_key3] = val; } } catch (err) { _iterator2.e(err); } finally { _iterator2.f(); } if (indent && this.token.type !== TOKEN_TYPES.indent) { break; } } else { this.unexpected('Invalid value type'); } } else { this.unexpected("Unknown token: ".concat(_util()["default"].inspect(propToken))); } } return obj; } }]); return Parser; }(); var MERGE_CONFLICT_ANCESTOR = '|||||||'; var MERGE_CONFLICT_END = '>>>>>>>'; var MERGE_CONFLICT_SEP = '======='; var MERGE_CONFLICT_START = '<<<<<<<'; /** * Extract the two versions of the lockfile from a merge conflict. */ function extractConflictVariants(str) { var variants = [[], []]; var lines = str.split(/\r?\n/g); var skip = false; while (lines.length) { var _line = lines.shift(); if (_line.startsWith(MERGE_CONFLICT_START)) { // get the first variant while (lines.length) { var conflictLine = lines.shift(); if (conflictLine === MERGE_CONFLICT_SEP) { skip = false; break; } else if (skip || conflictLine.startsWith(MERGE_CONFLICT_ANCESTOR)) { skip = true; continue; } else { variants[0].push(conflictLine); } } // get the second variant while (lines.length) { var _conflictLine = lines.shift(); if (_conflictLine.startsWith(MERGE_CONFLICT_END)) { break; } else { variants[1].push(_conflictLine); } } } else { variants[0].push(_line); variants[1].push(_line); } } return [variants[0].join('\n'), variants[1].join('\n')]; } /** * Check if a lockfile has merge conflicts. */ function hasMergeConflicts(str) { return str.includes(MERGE_CONFLICT_START) && str.includes(MERGE_CONFLICT_SEP) && str.includes(MERGE_CONFLICT_END); } /** * Parse the lockfile. */ function parse(str, fileLoc) { var parser = new Parser(str, fileLoc); parser.next(); if (!fileLoc.endsWith(".yml")) { try { return parser.parse(); } catch (error1) { try { return load(str, { schema: FAILSAFE_SCHEMA }); } catch (error2) { throw error1; } } } else { var result = load(str, { schema: FAILSAFE_SCHEMA }); if ((0, _typeof2()["default"])(result) === 'object') { return result; } else { return {}; } } } /** * Parse and merge the two variants in a conflicted lockfile. */ function parseWithConflict(str, fileLoc) { var variants = extractConflictVariants(str); try { return { type: 'merge', object: Object.assign({}, parse(variants[0], fileLoc), parse(variants[1], fileLoc)) }; } catch (err) { if (err instanceof SyntaxError) { return { type: 'conflict', object: {} }; } else { throw err; } } } function _default(str) { var fileLoc = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'lockfile'; str = (0, _stripBom()["default"])(str); return hasMergeConflicts(str) ? parseWithConflict(str, fileLoc) : { type: 'success', object: parse(str, fileLoc) }; } //# sourceMappingURL=parse.js.map