// ==UserScript==
// @namespace runonstof
// @name Debugger
// @version 1.0.2
// @description Debugger tool for CustomNPCs scripts
// @author Runonstof
// @license MIT
// @minecraft 1.20.1
// @scripttype player
// @match https://customnpcs.com
// ==/UserScript==
"use strict";
var Base64 = Java.type('java.util.Base64');
var JavaString = Java.type('java.lang.String');
function atob(str) {
return new JavaString(Base64.getDecoder().decode(new JavaString(str)));
}
function btoa(str) {
// make Byte[] array
var bytes = new JavaString(str).getBytes();
return new JavaString(Base64.getEncoder().encodeToString(bytes));
}
function _construct(Parent, args, Class) { if (_isNativeReflectConstruct()) { _construct = Reflect.construct; } else { _construct = function _construct(Parent, args, Class) { var a = [null]; a.push.apply(a, args); var Constructor = Function.bind.apply(Parent, a); var instance = new Constructor(); if (Class) _setPrototypeOf(instance, Class.prototype); return instance; }; } return _construct.apply(null, arguments); }
function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
function cancel(e, text) {
if (text) {
e.player.message(ccs('' + text));
}
if (e.isCancelable()) {
e.setCanceled(true);
}
return false;
}
if (!Object.assign) {
Object.defineProperty(Object, 'assign', {
enumerable: false,
configurable: true,
writable: true,
value: function value(target) {
'use strict';
if (target === undefined || target === null) {
throw new TypeError('Cannot convert first argument to object');
}
var to = Object(target);
for (var i = 1; i < arguments.length; i++) {
var nextSource = arguments[i];
if (nextSource === undefined || nextSource === null) {
continue;
}
nextSource = Object(nextSource);
var keysArray = Object.keys(Object(nextSource));
for (var nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex++) {
var nextKey = keysArray[nextIndex];
var desc = Object.getOwnPropertyDescriptor(nextSource, nextKey);
if (desc !== undefined && desc.enumerable) {
to[nextKey] = nextSource[nextKey];
}
}
}
return to;
}
});
}
try {
String.prototype.truncate = function (length) {
var endString = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
if (this.length <= length - endString.length) return this;
return this.substr(0, length - endString.length) + endString;
};
} catch (exc) {}
;
function str_truncate(str, length) {
var endString = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '';
if (str.length <= length - endString.length) return str;
return str.substr(0, length - endString.length) + endString;
}
function ccs() {
var text = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 5;
return (text + '').replace(/&/g, "\xA7");
}
var REGEX_colorCode = /&([0-9a-fklmnor])/g;
if (!Object.values) {
Object.defineProperty(Object, 'values', {
enumerable: false,
configurable: true,
writable: true,
value: function value(target) {
'use strict';
return Object.keys(target).map(function (key) {
return target[key];
});
}
});
}
var _GUI_IDS = {
counter: 1,
ids: {},
lookup: {}
}; // var tempdata = API.getIWorld(0).getTempdata();
// if(tempdata.get('_GUI_IDS')) {
// _GUI_IDS = tempdata.get('_GUI_IDS');
// } else {
// tempdata.put('_GUI_IDS', _GUI_IDS);
// }
function id(name) {
if (Object.prototype.toString.call(name) === '[object Array]') {
for (var i in name) {
id(name[i]);
}
return true;
}
if (!name) {
name = Math.random().toString(36).substring(7) + Math.random().toString(36).substring(7);
}
var _id = _GUI_IDS.ids[name] || (_GUI_IDS.ids[name] = _GUI_IDS.counter++);
_GUI_IDS.lookup[_id] = name;
return _id;
}
function idname(_id) {
return _GUI_IDS.lookup[_id];
}
function removeid(name) {
var _id = id(name);
delete _GUI_IDS.lookup[_id];
delete _GUI_IDS.ids[name];
}
;
function mkPath(path) {
var expath = path.split("/");
var curpath = "";
for (var ex in expath) {
var expt = expath[ex];
curpath += (curpath == "" ? "" : "/") + expt;
var pfile = new File(curpath);
if (!pfile.exists()) {
if (expt.match(/[\w]+\.[\w]+/) === null) {
//is dir?
pfile.mkdir();
} else {
pfile.createNewFile();
}
}
}
}
var File = Java.type("java.io.File");
var Files = Java.type("java.nio.file.Files");
var Paths = Java.type("java.nio.file.Paths");
var Path = Java.type("java.nio.file.Path");
var CHARSET_UTF_8 = Java.type("java.nio.charset.StandardCharsets").UTF_8;
var StandardCopyOption = Java.type('java.nio.file.StandardCopyOption'); //Constants for validatePath
var PATH_VALIDATION = {
SUCCESS: 1,
ABOVE_ROOT: 0,
//If the given path is above allowed root while forceRoot is not given
NOT_EXISTS: -1
};
function loadGuiOptions(gui, lblId) {
var options = JSON.parse(gui.getComponent(lblId).getText()); //edit options
return options;
}
var _IMPORTS = {};
/**
* Chiffon
*
* @description A small ECMAScript parser, tokenizer and minifier written in JavaScript
* @fileoverview JavaScript parser, tokenizer and minifier library
* @version 2.5.4
* @date 2016-04-17
* @link https://github.com/polygonplanet/Chiffon
* @copyright Copyright (c) 2015-2016 polygon planet <[email protected]>
* @license Licensed under the MIT license.
*/
/*jshint bitwise:false, eqnull:true */
(function (name, context, factory) {
// Supports AMD, Node.js, CommonJS and browser context.
if (typeof exports !== 'undefined') {
if (typeof module !== 'undefined' && module.exports) {
module.exports = factory();
} else {
exports[name] = factory();
}
} else if (typeof define === 'function' && define.amd) {
define(factory);
} else {
context[name] = factory();
}
})('Chiffon', _IMPORTS, function () {
'use strict';
var Chiffon = {};
var arrayProto = Array.prototype;
var push = arrayProto.push;
var slice = arrayProto.slice;
var splice = arrayProto.splice;
var fromCharCode = String.fromCharCode;
var _Comment = 'Comment',
_WhiteSpace = 'WhiteSpace',
_LineTerminator = 'LineTerminator',
_Template = 'Template',
_String = 'String',
_Punctuator = 'Punctuator',
_RegularExpression = 'RegularExpression',
_Numeric = 'Numeric',
_Identifier = 'Identifier',
_Null = 'Null',
_Boolean = 'Boolean',
_Keyword = 'Keyword'; // ECMA-262 11.3 Line Terminators
var lineTerminator = "\\r\\n\\u2028\\u2029";
var lineTerminatorSequence = '(?:\\r\\n|[' + lineTerminator + '])';
var whiteSpace = '(?:(?![' + lineTerminator + '])\\s)+';
var literalSuffix = '(?=' + '\\s*' + '(?:' + '(?!\\s*[/\\\\<>*%`^"\'\\w$-])' + '[^/\\\\<>*%`^\'"({[\\w$-]' + '|' + '[!=]==?' + '|' + '[|][|]' + '|' + '&&' + '|' + '/[*/]' + '|' + '[,.;:!?)}\\]' + lineTerminator + ']' + '|' + '$' + ')' + ')'; // ECMA-262 11.7 Punctuators
var punctuators = '(?:' + '>>>=?|[.]{3}|<<=|===|!==|>>=' + '|' + '[+][+](?=[+])|--(?=-)' + '|' + '[=!<>*%+/&|^-]=' + '|' + '&&|[|][|]|[+][+]|--|<<|>>|=>' + '|' + '[-+*/%<>=&|^~!?:;,.()[\\]{}]' + ')';
var regexpLiteral = '(?:' + '/' + '(?![*/])' + '(?:' + '\\\\[\\s\\S]' + '|' + '\\[' + '(?:' + '\\\\[\\s\\S]' + '|' + '[^\\]' + lineTerminator + '\\\\]' + ')*' + '\\]' + '|' + '[^/' + lineTerminator + '\\\\]' + ')+' + '/' + '(?:[gimuy]+\\b|)' + ')';
var templateLiteral = '`(?:' + '\\\\[\\s\\S]' + '|' + '[$][{]' + '(?:' + '\\\\[\\s\\S]' + '|' + '[^{}\\\\]' + '|' + '[{](?:[^{}]*(?:[{][^{}]*[}])?)*[}]' + ')*' + '[}]' + '|' + '[^`\\\\]' + ')*`';
var identToken = '(?:' + "\\\\u(?:[0-9a-fA-F]{4}|[{][0-9a-fA-F]+[}])" + '|' + '[^\\s\\\\+/%*=&|^~<>!?:;,.()[\\]{}\'"`@#-]' + ')+'; // Valid keywords for Regular Expression Literal. e.g. `typeof /a/`
var regexPreWords = 'typeof|in|void|case|instanceof|yield|throw|delete|' + 'else|return|do'; // Valid keywords when previous token of the regex literal is a paren.
// e.g. `if (1) /a/`
var regexParenWords = 'if|while|for|with';
var keywordsRe = new RegExp('^(?:' + // ECMA-262 11.6.2.1 Keywords
regexParenWords + '|' + regexPreWords + '|' + 'var|function|this|new|break|catch|finally|try|default|continue|' + 'switch|const|export|import|class|extends|debugger|super|' + // Reserved keywords
'let|static|' + // ECMA-262 11.6.2.2 Future Reserved Words
'enum|await|' + 'implements|package|protected|interface|private|public' + ')$');
var lineTerminatorSequenceRe = new RegExp(lineTerminatorSequence);
var identRe = new RegExp('^' + identToken + '$');
var identLeftRe = new RegExp('^' + identToken);
var identRightRe = new RegExp(identToken + '$');
var signLeftRe = /^[+-]/;
var signRightRe = /[+-]$/;
var notPunctRe = /[^{}()[\]<>=!+*%\/&|^~?:;,.-]/;
var whiteSpaceRe = new RegExp('^' + whiteSpace);
var regexPrefixRe = new RegExp('(?:' + '(?:^(?:' + regexPreWords + ')$)' + '|' + '(?:' + '(?![.\\]])' + punctuators + '$)' + ')');
var regexParenWordsRe = new RegExp('^(?:' + regexParenWords + ')$');
var tokenizeNotWhiteSpaceRe = getPattern(_WhiteSpace);
var tokenizeNotTemplateRe = getPattern(_Template);
var tokenizeNotRegExpRe = getPattern(_RegularExpression);
var tokenizeRe = getPattern();
lineTerminator = lineTerminatorSequence = whiteSpace = literalSuffix = punctuators = regexpLiteral = templateLiteral = identToken = regexPreWords = regexParenWords = null;
function getPattern(ignore) {
return new RegExp('(' + // MultiLine Comment
'/[*][\\s\\S]*?[*]/' + // SingleLine Comment
'|' + '//[^' + lineTerminator + ']*' + '|' + '<!--[^' + lineTerminator + ']*' + // Line Terminators
'|' + '(?:^|' + lineTerminatorSequence + ')' + '(?:' + whiteSpace + ')?' + // SingleLine Comment
'-->[^' + lineTerminator + ']*' + ( // Template Literal
ignore === _Template ? '' : '|' + templateLiteral + literalSuffix) + // String Literal
'|' + '"(?:' + '\\\\\\r\\n' + '|' + '\\\\[\\s\\S]' + '|' + '[^"' + lineTerminator + '\\\\]' + ')*"' + '|' + "'(?:" + '\\\\\\r\\n' + '|' + '\\\\[\\s\\S]' + '|' + "[^'" + lineTerminator + "\\\\]" + ")*'" + ( // Regular Expression Literal
ignore === _RegularExpression ? '' : '|' + regexpLiteral + literalSuffix) + // Numeric Literal
'|' + '0(?:' + '[xX][0-9a-fA-F]+' + '|' + '[oO][0-7]+' + '|' + '[bB][01]+' + ')' + '|' + '(?:\\d+(?:[.]\\d*)?|[.]\\d+)(?:[eE][+-]?\\d+)?' + '|' + '[1-9]\\d*' + '|' + '0[0-7]+' + // Operators
'|' + punctuators + ( // WhiteSpace
ignore === _WhiteSpace ? '' : '|' + whiteSpace) + // Line Terminators
'|' + lineTerminatorSequence + // Identifier
'|' + (ignore === _Template ? '[\\s\\S]' : identToken) + ')', 'g');
}
function fromCodePoint(c) {
if (c <= 0xFFFF) {
return fromCharCode(c);
}
c -= 0x10000;
return fromCharCode((c >> 10) + 0xD800, c % 0x400 + 0xDC00);
}
function isLineTerminator(c) {
return c === 0x0A || c === 0x0D || c === 0x2028 || c === 0x2029;
}
function isPunctuator(c) {
return !notPunctRe.test(c);
}
function isDigit(c) {
return c >= 0x30 && c <= 0x39;
}
function isOctalDigit(c) {
var ch = c.charCodeAt(0);
return ch >= 0x30 && ch <= 0x37;
}
function mixin(target) {
slice.call(arguments, 1).forEach(function (source) {
var keys = Object.keys(source);
for (var i = 0, len = keys.length; i < len; i++) {
var key = keys[i];
target[key] = source[key];
}
});
return target;
}
function Tokenizer(options) {
this.options = mixin({}, options || {});
this.line = 1;
this.index = 0;
this.prevLineIndex = 0;
}
Tokenizer.prototype = {
parseMatches: function parseMatches(matches, tokens) {
var token, value, len, index, lines;
var lineStart, columnStart, columnEnd, hasLineTerminator;
var type, regex;
for (var i = 0; i < matches.length; i++) {
value = matches[i];
len = value.length;
if (len === 0) {
continue;
}
lineStart = this.line;
columnStart = this.index - this.prevLineIndex;
regex = null;
type = this.getTokenType(value);
if (this.options.loc) {
if (type === _String || type === _Comment && value.charAt(1) === '*') {
lines = value.split(lineTerminatorSequenceRe);
if (lines.length > 1) {
this.line += lines.length - 1;
this.prevLineIndex = this.index + len - lines.pop().length;
}
} else if (type === _LineTerminator) {
this.line++;
this.prevLineIndex = this.index + len;
}
}
if (type === _RegularExpression) {
if (this.fixRegExpTokens(matches, i, tokens, value)) {
i--;
continue;
}
index = value.lastIndexOf('/');
regex = {
pattern: value.substr(1, index - 1),
flags: value.substring(index + 1)
};
} else if (type === _Template) {
this.parseTemplate(value, tokens, columnStart);
continue;
}
this.index += len;
if (!type) {
continue;
}
if (this.options.parse && type === _LineTerminator) {
hasLineTerminator = true;
continue;
}
if (type === _Comment && !this.options.comment || type === _WhiteSpace && !this.options.whiteSpace || type === _LineTerminator && !this.options.lineTerminator) {
continue;
}
token = {
type: type,
value: value
};
if (hasLineTerminator) {
token.hasLineTerminator = true;
}
hasLineTerminator = false;
if (regex) {
token.regex = regex;
}
if (this.options.range) {
token.range = [this.index - len, this.index];
}
if (this.options.loc) {
columnEnd = this.index - this.prevLineIndex;
this.addLoc(token, lineStart, columnStart, this.line, columnEnd);
}
tokens[tokens.length] = token;
}
},
getTokenType: function getTokenType(value) {
var len = value.length;
var c = value.charAt(0);
var ch;
switch (c) {
case '"':
case "'":
return _String;
case '/':
if (len === 1) {
return _Punctuator;
}
c = value.charAt(1);
if (c === '/' || c === '*') {
return _Comment;
}
if (len === 2 && c === '=') {
return _Punctuator;
}
return _RegularExpression;
case '.':
if (len === 1) {
return _Punctuator;
}
c = value.charAt(1);
if (c === '.') {
return _Punctuator;
}
return _Numeric;
case '<':
if (len > 1 && value.charAt(1) === '!') {
return _Comment;
}
return _Punctuator;
case '-':
if (len < 3) {
return _Punctuator;
}
return _Comment;
case '`':
return _Template;
case '}':
if (len === 1) {
return _Punctuator;
}
return _Template;
default:
if (value === 'true' || value === 'false') {
return _Boolean;
}
if (value === 'null') {
return _Null;
}
if (whiteSpaceRe.test(c)) {
return _WhiteSpace;
}
if (isPunctuator(c)) {
return _Punctuator;
}
ch = c.charCodeAt(0);
if (isLineTerminator(ch)) {
return _LineTerminator;
}
if (isDigit(ch)) {
return _Numeric;
}
if (keywordsRe.test(value)) {
return _Keyword;
}
if (identRe.test(value)) {
return _Identifier;
}
}
},
addLoc: function addLoc(token, lineStart, columnStart, lineEnd, columnEnd) {
token.loc = {
start: {
line: lineStart,
column: columnStart
},
end: {
line: lineEnd,
column: columnEnd
}
};
},
parseTemplate: function parseTemplate(template, tokens, columnStart) {
var blocks = this.parseTemplateBlock(template, columnStart);
var newTokens = this.parseTemplateExpr(blocks);
push.apply(tokens, newTokens);
},
parseTemplateExpr: function parseTemplateExpr(blocks) {
var results = [];
for (var i = 0, len = blocks.length; i < len; i++) {
var block = blocks[i];
if (block.type === 'tmp-source') {
var props = mixin({}, block._loc, {
type: _Template
});
var tokens = this._retokenize(block.value, props);
push.apply(results, tokens);
} else {
results[results.length] = block;
}
}
return results;
},
parseTemplateBlock: function parseTemplateBlock(template, columnStart) {
var values = template.match(tokenizeNotTemplateRe);
var line = this.line;
var lineStart = line;
var rangeStart = this.index;
var newlines = [this.prevLineIndex];
var tokens = [];
var escapeCount = 0;
var value = '';
var type = _Template;
var braceLevel = 0;
var length = 0;
var lastIndex, prevLineIndex, columnEnd;
var prev, inExpr, tail, append, token;
for (var i = 0, len = values.length; i < len; prev = values[i++]) {
var c = values[i];
var cLen = c.length;
if (isLineTerminator(c.charCodeAt(0))) {
line++;
newlines[newlines.length] = rangeStart + length + cLen;
}
if (inExpr) {
switch (c) {
case '{':
braceLevel++;
break;
case '}':
braceLevel--;
break;
}
if (braceLevel === 0 && i + 1 < len && values[i + 1] === '}') {
append = true;
type = 'tmp-source'; // Temporary token type
inExpr = false;
}
} else if (c === '\\') {
if (prev === '\\') {
escapeCount++;
} else {
escapeCount = 1;
}
} else if (c === '$') {
tail = prev !== '\\' || escapeCount % 2 === 0;
} else if (c === '{') {
if (tail && prev === '$') {
append = true;
type = _Template;
inExpr = true;
}
}
value += c;
if (i === len - 1) {
append = true;
type = _Template;
}
if (append) {
token = {
type: type,
value: value
};
lastIndex = rangeStart + length + cLen;
prevLineIndex = this.findPrevLineIndex(newlines, lastIndex);
columnEnd = lastIndex - prevLineIndex;
if (type === _Template) {
if (this.options.range) {
token.range = [lastIndex - value.length, lastIndex];
}
if (this.options.loc) {
this.addLoc(token, lineStart, columnStart, line, columnEnd);
}
columnStart = columnEnd + cLen;
} else {
lastIndex = rangeStart + length + cLen - value.length;
prevLineIndex = this.findPrevLineIndex(newlines, lastIndex);
token._loc = {
line: lineStart,
index: lastIndex,
prevLineIndex: prevLineIndex
};
columnStart = columnEnd;
}
tokens[tokens.length] = token;
value = '';
lineStart = line;
append = false;
}
length += cLen;
}
this.line = lineStart;
this.index = lastIndex;
this.prevLineIndex = prevLineIndex;
return tokens;
},
findPrevLineIndex: function findPrevLineIndex(newlines, lastIndex) {
for (var i = newlines.length - 1; i >= 0; --i) {
var newline = newlines[i];
if (lastIndex >= newline) {
return newline;
}
}
},
// Fix Regular Expression missing matches e.g. `var g=1,a=2/3/g;`
fixRegExpTokens: function fixRegExpTokens(matches, index, tokens, regexValue) {
var i = tokens.length;
while (--i >= 0) {
var token = tokens[i];
var type = token.type;
if (type === _Comment || type === _WhiteSpace || type === _LineTerminator) {
continue;
}
var value = token.value;
if (type === _Punctuator) {
if (value === ')') {
if (this.isValidRegExpPrefix(tokens, i + 1)) {
break;
}
} else if (regexPrefixRe.test(value)) {
break;
}
} else if (type === _Keyword && regexPrefixRe.test(value) || type === _Template && value.slice(-2) === '${') {
break;
}
var parts = regexValue.match(tokenizeNotRegExpRe);
splice.apply(matches, [index, 1].concat(parts));
return true;
}
return false;
},
isValidRegExpPrefix: function isValidRegExpPrefix(tokens, i) {
var token, value, prev;
var level = 0;
while (--i >= 0) {
token = tokens[i];
if (token.type !== _Punctuator) {
continue;
}
value = token.value;
if (value === '(') {
if (--level === 0) {
prev = tokens[i - 1];
if (prev && prev.type === _Keyword && regexParenWordsRe.test(prev.value)) {
return true;
}
return false;
}
} else if (value === ')') {
level++;
}
}
return false;
},
_retokenize: function _retokenize(source, props) {
var tokenizer = new Tokenizer(this.options);
mixin(tokenizer, props);
return tokenizer.tokenize(source);
},
tokenize: function tokenize(source) {
if (source == null) {
return [];
}
source = '' + source;
var re;
if (this.options.whiteSpace || this.options.range || this.options.loc) {
re = tokenizeRe;
} else {
re = tokenizeNotWhiteSpaceRe;
}
var tokens = [];
var matches = source.match(re);
if (matches) {
this.parseMatches(matches, tokens);
}
return tokens;
}
};
/**
* Tokenize a string source.
*
* @param {string} source Target source.
* @param {Object} [options] Tokenize options.
* - comment: {boolean} (default=false)
* Keep comment tokens.
* - lineTerminator: {boolean} (default=false)
* Keep line feed tokens.
* - range: {boolean} (default=false)
* Include an index-based location range (array)
* - loc: {boolean} (default=false)
* Include line number and column-based location info
* @return {string} Return an array of the parsed tokens.
*/
var tokenize = Chiffon.tokenize = function (source, options) {
return new Tokenizer(options).tokenize(source);
};
function Untokenizer(options) {
this.options = mixin({}, options || {});
}
Untokenizer.prototype = {
untokenize: function untokenize(tokens) {
var results = [];
var prev;
for (var i = 0, len = tokens.length; i < len; prev = tokens[i++]) {
var token = tokens[i];
var tokenType = token.type;
var tokenValue = token.value;
if (!prev || this.options.unsafe) {
results[results.length] = tokenValue;
continue;
}
var ws;
var prevValue = prev.value;
if (tokenType === _Punctuator) {
ws = signLeftRe.test(tokenValue) && signRightRe.test(prevValue);
} else {
ws = identLeftRe.test(tokenValue) && identRightRe.test(prevValue);
}
results[results.length] = (ws ? ' ' : '') + tokenValue;
}
return results.join('');
}
};
/**
* Concatenate to string from the parsed tokens.
*
* @param {Array} tokens An array of the parsed tokens.
* @param {Object} [options] Untokenize options.
* - unsafe: {boolean} (default=false)
* Untokenizer does not add a space between the identifier and identifier.
* @return {string} Return a concatenated string.
*/
var untokenize = Chiffon.untokenize = function (tokens, options) {
return new Untokenizer(options).untokenize(tokens);
};
var TOKEN_END = {};
var minifyDefaultOptions = {
maxLineLen: 32000
};
function Minifier(options) {
this.options = mixin({}, options || {}, minifyDefaultOptions);
}
Minifier.prototype = {
init: function init() {
this.index = 0;
this.lineLen = 0;
this.current();
},
next: function next() {
this.index++;
return this.current();
},
current: function current() {
this.length = this.tokens.length;
this.prev = this.tokens[this.index - 1] || {};
this.token = this.tokens[this.index] || TOKEN_END;
this.value = this.token.value;
this.type = this.token.type;
this.lookahead = this.tokens[this.index + 1] || TOKEN_END;
return this.token;
},
remove: function remove(index) {
if (index == null) {
index = this.index;
}
this.tokens.splice(index, 1);
this.current();
},
insert: function insert(token) {
this.tokens.splice(this.index + 1, 0, token);
this.next();
},
eat: function eat(type) {
type = type || _LineTerminator;
while (this.type === type) {
this.remove();
}
},
flatten: function flatten() {
this.init();
this.eat();
while (this.index < this.length) {
if (this.type === _LineTerminator) {
if (this.prev.type === _Punctuator || this.prev.type === _LineTerminator || this.lookahead.type === _Punctuator) {
this.eat();
continue;
} else if (this.lookahead.type === _LineTerminator) {
this.next();
this.eat();
continue;
}
}
this.next();
}
},
breakLine: function breakLine() {
this.init();
while (this.index < this.length) {
if (this.type === _LineTerminator) {
this.lineLen = 0;
} else {
this.lineLen += this.value.length;
if (this.lineLen >= this.options.maxLineLen) {
if (this.type === _Punctuator && !signRightRe.test(this.value)) {
this.insert({
type: _LineTerminator,
value: '\n'
});
this.lineLen = 0;
}
}
}
this.next();
}
},
compress: function compress() {
this.flatten();
this.breakLine();
},
minify: function minify(source) {
this.tokens = tokenize(source, {
lineTerminator: true
});
this.init();
this.compress();
return untokenize(this.tokens);
}
};
/**
* Minify JavaScript source.
*
* @param {string} source Target source.
* @param {Object} [options] minify options.
* - maxLineLen: {number} (default=32000)
* Limit the line length in symbols.
* @return {string} Return a minified source.
*/
var minify = Chiffon.minify = function (source, options) {
return new Minifier(options).minify(source);
}; // Parser based Esprima. (http://esprima.org/)
// Abstract syntax tree specified by ESTree. (https://github.com/estree/estree)
var _AssignmentExpression = 'AssignmentExpression',
_AssignmentPattern = 'AssignmentPattern',
_ArrayExpression = 'ArrayExpression',
_ArrayPattern = 'ArrayPattern',
_ArrowFunctionExpression = 'ArrowFunctionExpression',
_ArrowParameters = 'ArrowParameters',
_BlockStatement = 'BlockStatement',
_BinaryExpression = 'BinaryExpression',
_BreakStatement = 'BreakStatement',
_CallExpression = 'CallExpression',
_CatchClause = 'CatchClause',
_ClassBody = 'ClassBody',
_ClassDeclaration = 'ClassDeclaration',
_ClassExpression = 'ClassExpression',
_ConditionalExpression = 'ConditionalExpression',
_ContinueStatement = 'ContinueStatement',
_DoWhileStatement = 'DoWhileStatement',
_DebuggerStatement = 'DebuggerStatement',
_EmptyStatement = 'EmptyStatement',
_ExportAllDeclaration = 'ExportAllDeclaration',
_ExportDefaultDeclaration = 'ExportDefaultDeclaration',
_ExportNamedDeclaration = 'ExportNamedDeclaration',
_ExportSpecifier = 'ExportSpecifier',
_ExpressionStatement = 'ExpressionStatement',
_ForStatement = 'ForStatement',
_ForOfStatement = 'ForOfStatement',
_ForInStatement = 'ForInStatement',
_FunctionDeclaration = 'FunctionDeclaration',
_FunctionExpression = 'FunctionExpression',
_IfStatement = 'IfStatement',
_ImportDeclaration = 'ImportDeclaration',
_ImportDefaultSpecifier = 'ImportDefaultSpecifier',
_ImportNamespaceSpecifier = 'ImportNamespaceSpecifier',
_ImportSpecifier = 'ImportSpecifier',
_Literal = 'Literal',
_LabeledStatement = 'LabeledStatement',
_LogicalExpression = 'LogicalExpression',
_MemberExpression = 'MemberExpression',
_MethodDefinition = 'MethodDefinition',
_NewExpression = 'NewExpression',
_ObjectExpression = 'ObjectExpression',
_ObjectPattern = 'ObjectPattern',
_Program = 'Program',
_Property = 'Property',
_RestElement = 'RestElement',
_ReturnStatement = 'ReturnStatement',
_SequenceExpression = 'SequenceExpression',
_SpreadElement = 'SpreadElement',
_Super = 'Super',
_SwitchCase = 'SwitchCase',
_SwitchStatement = 'SwitchStatement',
_TaggedTemplateExpression = 'TaggedTemplateExpression',
_TemplateElement = 'TemplateElement',
_TemplateLiteral = 'TemplateLiteral',
_ThisExpression = 'ThisExpression',
_ThrowStatement = 'ThrowStatement',
_TryStatement = 'TryStatement',
_UnaryExpression = 'UnaryExpression',
_UpdateExpression = 'UpdateExpression',
_VariableDeclaration = 'VariableDeclaration',
_VariableDeclarator = 'VariableDeclarator',
_WhileStatement = 'WhileStatement',
_WithStatement = 'WithStatement',
_YieldExpression = 'YieldExpression';
var assignOpRe = /^(?:[-+*%\/&|]?=|>>>?=|<<=)$/;
var unaryOpRe = /^(?:[-+!~]|\+\+|--|typeof|void|delete)$/;
var octalDigitRe = /^0[0-7]+$/;
function Parser(options) {
this.options = mixin({}, options || {});
}
Parser.prototype = {
next: function next() {
if (this.token === TOKEN_END) {
this.unexpected();
}
this.token = this.tokens[++this.index] || TOKEN_END;
this.value = this.token.value;
this.type = this.token.type;
},
lookahead: function lookahead() {
return this.tokens[this.index + 1] || TOKEN_END;
},
assertValue: function assertValue(value) {
if (this.value !== value) {
this.unexpected();
}
},
assertType: function assertType(type) {
if (this.type !== type) {
this.unexpected();
}
},
expect: function expect(value) {
if (this.value !== value) {
this.unexpected();
}
this.next();
},
expectType: function expectType(type) {
if (this.type !== type) {
this.unexpected();
}
this.next();
},
expectSemicolon: function expectSemicolon() {
if (this.value === ';') {
this.next();
return true;
}
if (this.value === '}' || this.token.hasLineTerminator || this.token === TOKEN_END) {
return true;
}
this.unexpected();
},
unexpected: function unexpected() {
var message = 'Unexpected';
if (this.token === TOKEN_END) {
message += ' end of input';
} else {
var token = this.value || '';
if (token.length > 16) {
token = token.substr(0, 16) + '...';
}
message += " token '" + token + "'";
}
this.throwError(message);
},
throwError: function throwError(message) {
var loc = this.token.loc;
if (loc) {
message += ' at line ' + loc.start.line + ' column ' + loc.start.column;
}
throw new Error(message);
},
startNode: function startNode(type) {
var node = {};
this.startNodeAt(node);
node.type = type;
return node;
},
finishNode: function finishNode(node) {
if (this.lastGroup && this.lastGroup.expr === node) {
// Restore the kept position
var startNode = this.lastGroup.startNode;
var endToken = this.lastGroup.endToken;
this.lastGroup = null;
this.startNodeAt(node, startNode);
return this.finishNodeAt(node, endToken);
}
return this.finishNodeAt(node);
},
startNodeAt: function startNodeAt(node, startNode) {
startNode = startNode || this.token;
if (startNode === TOKEN_END) {
if (this.length === 0) {
startNode = this.getInitialLocationNode();
} else {
this.unexpected();
}
}
if (this.options.range) {
node.range = node.range || [];
node.range[0] = startNode.range[0];
}
if (this.options.loc) {
var loc = startNode.loc;
node.loc = node.loc || {};
node.loc.start = {
line: loc.start.line,
column: loc.start.column
};
}
return node;
},
finishNodeAt: function finishNodeAt(node, finishNode) {
finishNode = finishNode || this.tokens[this.index - 1];
if (!finishNode) {
if (this.length === 0) {
finishNode = this.getInitialLocationNode();
} else {
this.unexpected();
}
}
if (this.options.range) {
node.range[1] = finishNode.range[1];
}
if (this.options.loc) {
node.loc.end = {
line: finishNode.loc.end.line,
column: finishNode.loc.end.column
};
}
return node;
},
getInitialLocationNode: function getInitialLocationNode() {
return {
range: [0, 0],
loc: {
start: {
line: 0,
column: 0
},
end: {
line: 0,
column: 0
}
}
};
},
// ECMA-262 11.8.3 Numeric Literals
parseNumeric: function parseNumeric(value) {
var i = 0;
var c = value.charAt(i++);
var n;
if (c === '0') {
c = value.charAt(i++);
n = value.substring(i);
if (c !== '.') {
switch (c.toLowerCase()) {
case 'x':
return parseInt(n, 16);
case 'o':
return parseInt(n, 8);
case 'b':
return parseInt(n, 2);
}
if (octalDigitRe.test(value)) {
return parseInt(c + n, 8);
}
}
}
return parseFloat(value);
},
// ECMA-262 11.8.4 String Literals
parseString: function parseString(value) {
var s = '';
var i = 1;
var len = value.length - 1;
var c, c2, hex, n, index, length;
while (i < len) {
c = value.charAt(i++);
if (c === '\\') {
if (i < len) {
c2 = value.charCodeAt(i);
if (isLineTerminator(c2)) {
i++;
if (c2 === 0x0D && i < len && value.charCodeAt(i) === 0x0A) {
i++;
}
continue;
}
}
c = value.charAt(i++);
switch (c) {
case 'b':
c = '\b';
break;
case 't':
c = '\t';
break;
case 'r':
c = '\r';
break;
case 'n':
c = '\n';
break;
case 'v':
c = '\x0B';
break;
case 'f':
c = '\f';
break;
case 'u':
case 'x':
if (c === 'u' && i < len && value.charAt(i) === '{') {
i++;
index = value.indexOf('}', i);
if (!~index) {
this.unexpected();
}
hex = value.substring(i, index);
i = index + 1;
} else {
length = c === 'u' ? 4 : 2;
hex = value.substr(i, length);
i += length;
}
c = fromCodePoint(parseInt(hex, 16));
break;
default:
if (isOctalDigit(c)) {
n = c;
do {
c = value.charAt(i);
if (!isOctalDigit(c)) {
break;
}
n += c;
} while (i++ < len && n.length < 3);
if (n.length > 0 && n.charAt(0) === '0') {
n = n.substring(1);
}
c = fromCharCode(parseInt(n, 8));
}
}
}
s += c;
}
return s;
},
parseLiteral: function parseLiteral() {
var node = this.startNode(_Literal);
var raw = this.value;
var value, regex;
switch (this.type) {
case _Numeric:
value = this.parseNumeric(raw);
break;
case _String:
value = this.parseString(raw);
break;
case _RegularExpression:
regex = this.token.regex;
try {
value = new RegExp(regex.pattern, regex.flags);
} catch (e) {
value = null;
}
break;
case _Boolean:
value = raw === 'true';
break;
case _Null:
value = null;
break;
default:
this.unexpected();
}
this.next();
node.value = value;
node.raw = raw;
if (regex) {
node.regex = regex;
}
return this.finishNode(node);
},
parseIdentifier: function parseIdentifier(allowKeyword) {
var node = this.startNode(_Identifier);
var name = this.value;
if (allowKeyword) {
this.next();
} else {
this.expectType(_Identifier);
}
node.name = name;
return this.finishNode(node);
},
parseCommaSeparatedElements: function parseCommaSeparatedElements(start, end, elems, callback, args) {
this.expect(start);
while (this.value !== end) {
elems[elems.length] = callback.apply(this, args);
if (this.value !== end) {
this.expect(',');
}
}
this.expect(end);
return elems;
},
// ECMA-262 12.2 Primary Expression
parsePrimaryExpression: function parsePrimaryExpression() {
switch (this.type) {
case _Numeric:
case _String:
case _RegularExpression:
case _Boolean:
case _Null:
return this.parseLiteral();
case _Identifier:
return this.parseIdentifier();
case _Keyword:
return this.parsePrimaryKeywordExpression();
case _Punctuator:
return this.parsePrimaryPunctuatorExpression();
case _Template:
return this.parseTemplateLiteral();
default:
this.unexpected();
}
},
parsePrimaryKeywordExpression: function parsePrimaryKeywordExpression() {
switch (this.value) {
case 'function':
return this.parseFunctionExpression();
case 'class':
return this.parseClassExpression();
case 'this':
return this.parseThisExpression();
}
this.unexpected();
},
parseThisExpression: function parseThisExpression() {
var node = this.startNode(_ThisExpression);
this.expect('this');
return this.finishNode(node);
},
parsePrimaryPunctuatorExpression: function parsePrimaryPunctuatorExpression() {
switch (this.value) {
case '{':
return this.parseObjectInitializer();
case '[':
return this.parseArrayInitializer();
case '(':
return this.parseGroupExpression();
default:
this.unexpected();
}
},
parseGroupExpression: function parseGroupExpression() {
var startNode = this.startNode();
this.expect('(');
if (this.value === ')') {
this.next();
this.assertValue('=>');
return {
type: _ArrowParameters,
params: [],
startNode: startNode
};
}
var node = this.startNode();
var expr = this.parseExpression(true); // Keep the current position for expression
this.lastGroup = {
expr: expr,
startNode: node,
endToken: this.tokens[this.index - 1]
};
this.expect(')');
if (this.value === '=>') {
var params = [];
if (expr.type === _SequenceExpression) {
params = expr.expressions;
} else if (expr.type === _Identifier) {
params = [expr];
} else {
this.unexpected();
}
expr = {
type: _ArrowParameters,
params: params,
startNode: startNode
};
}
return expr;
},
// ECMA-262 12.2.6 Object Initializer
parseObjectInitializer: function parseObjectInitializer() {
var node = this.startNode(_ObjectExpression);
node.properties = this.parseCommaSeparatedElements('{', '}', [], this.parseObjectDefinition);
return this.finishNode(node);
},
parseObjectDefinition: function parseObjectDefinition() {
var node;
if (this.value === 'get' || this.value === 'set') {
node = this.parseObjectGetterSetter();
} else {
node = this.parseObjectProperty();
}
return node;
},
parseObjectProperty: function parseObjectProperty() {
var node = this.startNode(_Property);
var computed = false;
var generator;
if (this.value === '*') {
generator = true;
this.next();
} else if (this.value === '[') {
computed = true;
}
var key = this.parseObjectPropertyName();
var value;
if (this.value === ':') {
this.next();
value = this.parseAssignmentExpression(true);
} else if (this.value === '(') {
value = this.parseFunction({
expression: true,
generator: generator
});
} else if (key.type === _Identifier) {
if (this.value === '=') {
value = this.parseAssignmentPattern(key);
} else {
value = key;
}
} else {
this.unexpected();
}
node.key = key;
node.computed = computed;
node.value = value;
node.kind = 'init';
return this.finishNode(node);
},
parseObjectGetterSetter: function parseObjectGetterSetter() {
var node = this.startNode(_Property);
var lookahead = this.lookahead();
var computed = false;
var kind = 'init';
var key, value;
if (lookahead.value === ':') {
key = this.parseObjectPropertyName();
this.next();
value = this.parseAssignmentExpression(true);
} else if (lookahead.value === '(') {
key = this.parseObjectPropertyName();
value = this.parseFunction({
expression: true
});
} else {
kind = this.value;
this.next();
if (this.value === '[') {
computed = true;
}
if (computed || this.type === _Identifier || this.type === _Keyword || this.type === _String || this.type === _Numeric) {
key = this.parseObjectPropertyName();
value = this.parseFunction({
getter: kind === 'get',
setter: kind === 'set',
expression: true
});
} else {
this.unexpected();
}
}
node.key = key;
node.computed = computed;
node.value = value;
node.kind = kind;
return this.finishNode(node);
},
parseObjectPropertyName: function parseObjectPropertyName() {
var node;
switch (this.type) {
case _String:
case _Numeric:
return this.parseLiteral();
case _Punctuator:
if (this.value === '[') {
this.next();
node = this.parseAssignmentExpression();
this.expect(']');
return node;
}
break;
case _Keyword:
case _Identifier:
case _Boolean:
case _Null:
return this.parseIdentifier(true);
}
this.unexpected();
},
// ECMA-262 12.2.5 Array Initializer
parseArrayInitializer: function parseArrayInitializer() {
var node = this.startNode(_ArrayExpression);
var elems = [];
this.expect('[');
while (this.value !== ']') {
if (this.value === ',') {
this.next();
elems[elems.length] = null;
continue;
}
if (this.value === '...') {
elems[elems.length] = this.parseSpreadElement();
} else {
elems[elems.length] = this.parseAssignmentExpression(true);
}
if (this.value !== ']') {
this.expect(',');
}
}
this.expect(']');
node.elements = elems;
return this.finishNode(node);
},
parseSpreadElement: function parseSpreadElement() {
var node = this.parseRestElement();
node.type = _SpreadElement;
return node;
},
// ECMA-262 A.2 Expressions
parseExpression: function parseExpression(allowIn) {
var node = this.startNode(_SequenceExpression);
var expr = this.parseAssignmentExpression(allowIn);
if (this.value !== ',') {
return expr;
}
var exprs = [expr];
do {
this.next();
exprs[exprs.length] = this.parseAssignmentExpression(allowIn);
} while (this.value === ',');
node.expressions = exprs;
return this.finishNode(node);
},
reinterpretExpression: function reinterpretExpression(expr) {
var i, len;
switch (expr.type) {
case _AssignmentExpression:
expr.type = _AssignmentPattern;
this.reinterpretExpression(expr.left);
break;
case _ArrayExpression:
expr.type = _ArrayPattern;
for (i = 0, len = expr.elements.length; i < len; i++) {
if (expr.elements[i] !== null) {
this.reinterpretExpression(expr.elements[i]);
}
}
break;
case _ObjectExpression:
expr.type = _ObjectPattern;
for (i = 0, len = expr.properties.length; i < len; i++) {
this.reinterpretExpression(expr.properties[i].value);
}
}
},
parseAssignmentExpression: function parseAssignmentExpression(allowIn) {
if (this.inGenerator && this.value === 'yield') {
return this.parseYieldExpression();
}
var node = this.startNode(_AssignmentExpression);
var left = this.parseConditionalExpression(allowIn);
if (this.value === '=>' || left.type === _ArrowParameters) {
if (left.type === _Identifier) {
left.params = [mixin({}, left)];
left.startNode = node;
}
return this.parseArrowFunctionExpression(left);
}
if (!assignOpRe.test(this.value)) {
return left;
}
this.reinterpretExpression(left);
var operator = this.value;
this.next();
var right = this.parseAssignmentExpression(allowIn);
node.operator = operator;
node.left = left;
node.right = right;
return this.finishNode(node);
},
parseConditionalExpression: function parseConditionalExpression(allowIn) {
var node = this.startNode(_ConditionalExpression);
var expr = this.parseBinaryExpression(allowIn);
if (this.value !== '?') {
return expr;
}
this.expect('?');
var consequent = this.parseAssignmentExpression(true);
this.expect(':');
var alternate = this.parseAssignmentExpression(allowIn);
node.test = expr;
node.consequent = consequent;
node.alternate = alternate;
return this.finishNode(node);
},
parseArrowFunctionExpression: function parseArrowFunctionExpression(expr) {
var node = this.startNode(_ArrowFunctionExpression);
this.startNodeAt(node, expr.startNode);
this.expect('=>');
var params = expr.params || [];
var expression = false;
var body;
if (this.value === '{') {
body = this.parseBlockStatement();
} else {
body = this.parseAssignmentExpression(true);
expression = true;
}
node.params = params;
node.body = body;
node.expression = expression;
return this.finishNode(node);
},
parseYieldExpression: function parseYieldExpression() {
var node = this.startNode(_YieldExpression);
var argument = null;
var delegate = false;
this.expect('yield');
if (!this.token.hasLineTerminator) {
if (this.value === '*') {
delegate = true;
this.next();
argument = this.parseAssignmentExpression(true);
} else if (this.value !== ';' && this.value !== '}' && this.token !== TOKEN_END) {
argument = this.parseAssignmentExpression(true);
}
}
node.argument = argument;
node.delegate = delegate;
return this.finishNode(node);
},
getBinaryPrecedence: function getBinaryPrecedence(allowIn) {
switch (this.value) {
case '*':
case '/':
case '%':
return 1;
case '+':
case '-':
return 2;
case '<<':
case '>>':
case '>>>':
return 3;
case '<':
case '>':
case '<=':
case '>=':
case 'instanceof':
return 4;
case 'in':
return allowIn ? 4 : 0;
case '==':
case '!=':
case '===':
case '!==':
return 5;
case '&':
return 6;
case '^':
return 7;
case '|':
return 8;
case '&&':
return 9;
case '||':
return 10;
default:
return 0;
}
},
parseBinaryExpression: function parseBinaryExpression(allowIn, base) {
if (base == null) {
base = 10;
}
var startNode = this.startNode();
var left = this.parseUnaryExpression();
var prec = this.getBinaryPrecedence(allowIn);
if (!prec) {
return left;
}
var right, operator, node;
for (var i = 1; i <= 10; i++) {
while ((prec = this.getBinaryPrecedence(allowIn)) === i) {
operator = this.value;
node = this.startNode(i < 9 ? _BinaryExpression : _LogicalExpression);
this.startNodeAt(node, startNode);
node.operator = operator;
node.left = left;
this.next();
if (prec === 1) {
right = this.parseUnaryExpression();
} else {
right = this.parseBinaryExpression(allowIn, prec - 1);
}
node.right = right;
left = this.finishNode(node);
}
if (base < prec) {
break;
}
}
this.startNodeAt(left, startNode);
return this.finishNode(left);
},
parseUnaryExpression: function parseUnaryExpression() {
var value = this.value;
if (!unaryOpRe.test(value)) {
return this.parsePostfixExpression();
}
var isUpdate = value === '++' || value === '--';
var node = this.startNode(isUpdate ? _UpdateExpression : _UnaryExpression);
this.next();
var argument = this.parseUnaryExpression();
node.operator = value;
node.argument = argument;
node.prefix = true;
return this.finishNode(node);
},
parsePostfixExpression: function parsePostfixExpression() {
var node = this.startNode(_UpdateExpression);
var expr = this.parseMemberExpression(true);
var value = this.value;
if (value === '++' || value === '--') {
this.next();
node.operator = value;
node.argument = expr;
node.prefix = false;
return this.finishNode(node);
}
return expr;
},
parseMemberExpression: function parseMemberExpression(allowCall) {
var node = this.startNode();
var expr;
if (this.value === 'super') {
expr = this.parseSuper();
} else if (this.value === 'new') {
expr = this.parseNewExpression();
} else {
expr = this.parsePrimaryExpression();
}
for (;;) {
if (this.value === '.') {
expr = this.parseNonComputedMember(expr, node);
} else if (this.value === '[') {
expr = this.parseComputedMember(expr, node);
} else if (allowCall && this.value === '(') {
expr = this.parseCallExpression(expr, node);
} else if (this.type === _Template && this.value.charAt(0) === '`') {
expr = this.parseTaggedTemplateExpression(expr, node);
} else {
break;
}
}
return expr;
},
parseSuper: function parseSuper() {
var node = this.startNode(_Super);
this.expect('super');
return this.finishNode(node);
},
parseNewExpression: function parseNewExpression() {
var node = this.startNode(_NewExpression);
this.next();
var callee = this.parseMemberExpression(false);
node.callee = callee;
node.arguments = [];
if (this.value === '(') {
this.parseArguments(node);
}
return this.finishNode(node);
},
parseCallExpression: function parseCallExpression(expr, startNode) {
var node = this.startNode(_CallExpression);
this.startNodeAt(node, startNode);
node.callee = expr;
node.arguments = [];
this.parseArguments(node);
return this.finishNode(node);
},
parseComputedMember: function parseComputedMember(expr, startNode) {
var node = this.startNode(_MemberExpression);
this.startNodeAt(node, startNode);
this.next();
node.computed = true;
node.object = expr;
node.property = this.parseExpression(true);
this.expect(']');
return this.finishNode(node);
},
parseNonComputedMember: function parseNonComputedMember(expr, startNode) {
var node = this.startNode(_MemberExpression);
this.startNodeAt(node, startNode);
this.next();
node.computed = false;
node.object = expr;
node.property = this.parseIdentifier();
return this.finishNode(node);
},
parseArguments: function parseArguments(node) {
this.parseCommaSeparatedElements('(', ')', node.arguments, this.parseAssignmentExpression, [true]);
return node;
},
parseTemplateLiteral: function parseTemplateLiteral() {
var node = this.startNode(_TemplateLiteral);
var quasi = this.parseTemplateElement();
var quasis = [quasi];
var exprs = [];
while (!quasi.tail) {
exprs[exprs.length] = this.parseExpression();
quasi = this.parseTemplateElement();
quasis[quasis.length] = quasi;
}
node.quasis = quasis;
node.expressions = exprs;
return this.finishNode(node);
},
parseTemplateElement: function parseTemplateElement() {
var node = this.startNode(_TemplateElement);
var tail = false;
var raw;
this.assertType(_Template);
if (this.value.slice(-1) === '`') {
tail = true;
}
var endPos = tail ? -1 : -2;
raw = this.value.slice(1, endPos);
var cooked = this.parseString('`' + raw + '`');
this.next();
node.tail = tail;
node.value = {
cooked: cooked,
raw: raw
};
return this.finishNode(node);
},
parseTaggedTemplateExpression: function parseTaggedTemplateExpression(tag, startNode) {
var node = this.startNode(_TaggedTemplateExpression);
this.startNodeAt(node, startNode);
var quasi = this.parseTemplateLiteral();
node.tag = tag;
node.quasi = quasi;
return this.finishNode(node);
},
// ECMA-262 13 ECMAScript Language: Statements and Declarations
parseStatement: function parseStatement() {
switch (this.value) {
case '{':
return this.parseBlockStatement();
case 'var':
case 'let':
case 'const':
return this.parseVariableStatement(this.value);
case ';':
return this.parseEmptyStatement();
case 'if':
return this.parseIfStatement();
case 'continue':
return this.parseContinueStatement();
case 'break':
return this.parseBreakStatement();
case 'return':
return this.parseReturnStatement();
case 'with':
return this.parseWithStatement();
case 'throw':
return this.parseThrowStatement();
case 'try':
return this.parseTryStatement();
case 'debugger':
return this.parseDebuggerStatement();
case 'function':
return this.parseFunctionDeclaration();
case 'class':
return this.parseClassDeclaration();
case 'switch':
return this.parseSwitchStatement();
case 'do':
return this.parseDoWhileStatement();
case 'while':
return this.parseWhileStatement();
case 'for':
return this.parseForStatement();
case 'import':
return this.parseImportDeclaration();
case 'export':
return this.parseExportDeclaration();
default:
return this.parseMaybeExpressionStatement();
}
},
parseScriptBody: function parseScriptBody(body, end) {
while (this.value !== end) {
body[body.length] = this.parseStatement();
}
},
parseBlockStatement: function parseBlockStatement() {
var node = this.startNode(_BlockStatement);
this.expect('{');
var body = [];
this.parseScriptBody(body, '}');
this.expect('}');
node.body = body;
return this.finishNode(node);
},
// ECMA-262 13.3.2 Variable Statement
parseVariableStatement: function parseVariableStatement(kind, inFor) {
var node = this.startNode(_VariableDeclaration);
var allowIn = !inFor;
var declarations = this.parseVariableDeclarationList(allowIn);
if (!inFor) {
this.expectSemicolon();
}
node.declarations = declarations;
node.kind = kind;
return this.finishNode(node);
},
parseVariableDeclarationList: function parseVariableDeclarationList(allowIn) {
var list = [];
do {
list[list.length] = this.parseVariableDeclaration(allowIn);
} while (this.value === ',');
return list;
},
parseVariableDeclaration: function parseVariableDeclaration(allowIn) {
this.next();
var node = this.startNode(_VariableDeclarator);
var id = this.parseBindingPattern();
var init = null;
if (this.value === '=') {
this.next();
init = this.parseAssignmentExpression(allowIn);
}
node.id = id;
node.init = init;
return this.finishNode(node);
},
// ECMA-262 14.1 Function Definitions
parseFunctionDeclaration: function parseFunctionDeclaration() {
return this.parseFunctionDefinition();
},
parseFunctionExpression: function parseFunctionExpression() {
return this.parseFunctionDefinition(true);
},
parseFunctionDefinition: function parseFunctionDefinition(expression) {
var node = this.startNode();
var generator = false;
this.expect('function');
if (this.value === '*') {
generator = true;
this.next();
}
return this.parseFunction({
node: node,
generator: generator,
expression: expression
});
},
parseFunction: function parseFunction(options) {
options = options || {};
var node = options.node || this.startNode();
node.type = options.expression ? _FunctionExpression : _FunctionDeclaration;
node.id = null;
node.params = [];
node.defaults = [];
node.body = null;
node.generator = !!options.generator;
node.expression = false;
if (options.getter) {
this.expect('(');
this.expect(')');
} else if (options.setter) {
this.parseParams(node);
} else {
if (this.type === _Identifier) {
node.id = this.parseIdentifier();
}
this.parseParams(node);
}
var prevInGenerator = this.inGenerator;
this.inGenerator = node.generator;
node.body = this.parseBlockStatement();
this.inGenerator = prevInGenerator;
return this.finishNode(node);
},
parseParams: function parseParams(node) {
this.expect('(');
while (this.value !== ')') {
if (!this.parseParam(node)) {
break;
}
}
if (!node._hasDefaults) {
node.defaults.length = 0;
} else {
delete node._hasDefaults;
}
this.expect(')');
},
parseParam: function parseParam(node) {
var params = node.params;
var defaults = node.defaults;
if (this.value === '...') {
params[params.length] = this.parseRestElement();
defaults[defaults.length] = null;
return false;
}
var pattern = this.parseBindingElement();
if (pattern.type === _AssignmentPattern) {
params[params.length] = pattern.left;
defaults[defaults.length] = pattern.right;
node._hasDefaults = true;
} else {
params[params.length] = pattern;
defaults[defaults.length] = null;
}
if (this.value !== ')') {
this.expect(',');
}
return true;
},
parseRestElement: function parseRestElement() {
var node = this.startNode(_RestElement);
this.expect('...');
var argument = this.parseIdentifier();
node.argument = argument;
return this.finishNode(node);
},
// ECMA-262 13.3.3 Destructuring Binding Patterns
parseBindingPattern: function parseBindingPattern() {
if (this.type === _Identifier) {
return this.parseIdentifier();
}
if (this.value === '{') {
return this.parseObjectPattern();
}
if (this.value === '[') {
return this.parseArrayPattern();
}
this.unexpected();
},
parseBindingElement: function parseBindingElement() {
var pattern = this.parseBindingPattern();
if (this.value === '=') {
return this.parseAssignmentPattern(pattern);
}
return pattern;
},
parseAssignmentPattern: function parseAssignmentPattern(left) {
this.expect('=');
var node = this.startNode(_AssignmentPattern);
this.startNodeAt(node, left);
var right = this.parseAssignmentExpression(true);
node.left = left;
node.right = right;
return this.finishNode(node);
},
parseArrayPattern: function parseArrayPattern() {
var node = this.startNode(_ArrayPattern);
var elems = [];
this.expect('[');
while (this.value !== ']') {
if (this.value === ',') {
elems[elems.length] = null;
} else {
if (this.value === '...') {
elems[elems.length] = this.parseRestElement();
break;
}
elems[elems.length] = this.parseBindingElement();
}
if (this.value !== ']') {
this.expect(',');
}
}
this.expect(']');
node.elements = elems;
return this.finishNode(node);
},
parseObjectPattern: function parseObjectPattern() {
var node = this.startNode(_ObjectPattern);
node.properties = this.parseCommaSeparatedElements('{', '}', [], this.parseObjectPropertyPattern);
return this.finishNode(node);
},
parseObjectPropertyPattern: function parseObjectPropertyPattern() {
var node = this.startNode(_Property);
var key, value;
if (this.type === _Identifier) {
key = this.parseIdentifier();
if (this.value === '=') {
value = this.parseAssignmentPattern(key);
this.startNodeAt(value, node);
} else if (this.value !== ':') {
value = key;
}
} else {
key = this.parseObjectPropertyName();
}
if (!value) {
this.expect(':');
value = this.parseBindingElement();
}
node.key = key;
node.value = value;
node.kind = 'init';
return this.finishNode(node);
},
// ECMA-262 13 Statements and Declarations
parseIfStatement: function parseIfStatement() {
var node = this.startNode(_IfStatement);
this.expect('if');
this.expect('(');
var expr = this.parseExpression(true);
this.expect(')');
var consequent = this.parseStatement();
var alternate = null;
if (this.value === 'else') {
this.next();
alternate = this.parseStatement();
}
node.test = expr;
node.consequent = consequent;
node.alternate = alternate;
return this.finishNode(node);
},
parseEmptyStatement: function parseEmptyStatement() {
var node = this.startNode(_EmptyStatement);
this.expect(';');
return this.finishNode(node);
},
parseContinueStatement: function parseContinueStatement() {
var node = this.startNode(_ContinueStatement);
this.expect('continue');
var label = null;
if (this.type === _Identifier && !this.token.hasLineTerminator) {
label = this.parseIdentifier();
}
this.expectSemicolon();
node.label = label;
return this.finishNode(node);
},
parseBreakStatement: function parseBreakStatement() {
var node = this.startNode(_BreakStatement);
this.expect('break');
var label = null;
if (this.type === _Identifier && !this.token.hasLineTerminator) {
label = this.parseIdentifier();
}
this.expectSemicolon();
node.label = label;
return this.finishNode(node);
},
parseReturnStatement: function parseReturnStatement() {
var node = this.startNode(_ReturnStatement);
this.expect('return');
var argument = null;
if (this.value !== ';' && this.value !== '}' && !this.token.hasLineTerminator && this.token !== TOKEN_END) {
argument = this.parseExpression(true);
}
this.expectSemicolon();
node.argument = argument;
return this.finishNode(node);
},
parseWithStatement: function parseWithStatement() {
var node = this.startNode(_WithStatement);
this.expect('with');
this.expect('(');
var expr = this.parseExpression(true);
this.expect(')');
node.object = expr;
node.body = this.parseStatement();
return this.finishNode(node);
},
parseThrowStatement: function parseThrowStatement() {
var node = this.startNode(_ThrowStatement);
this.expect('throw');
if (this.token.hasLineTerminator) {
this.unexpected();
}
var expr = this.parseExpression(true);
this.expectSemicolon();
node.argument = expr;
return this.finishNode(node);
},
parseTryStatement: function parseTryStatement() {
var node = this.startNode(_TryStatement);
var handler = null;
var finalizer = null;
var hasCatch, hasFinally;
this.expect('try');
var block = this.parseBlockStatement();
if (this.value === 'catch') {
hasCatch = true;
handler = this.parseCatchClause();
}
if (this.value === 'finally') {
hasFinally = true;
this.next();
finalizer = this.parseBlockStatement();
}
if (!hasCatch && !hasFinally) {
this.unexpected();
}
node.block = block;
node.handler = handler;
node.finalizer = finalizer;
return this.finishNode(node);
},
parseCatchClause: function parseCatchClause() {
var node = this.startNode(_CatchClause);
this.expect('catch');
this.expect('(');
var param = this.parseBindingPattern();
this.expect(')');
var body = this.parseBlockStatement();
node.param = param;
node.body = body;
return this.finishNode(node);
},
parseDebuggerStatement: function parseDebuggerStatement() {
var node = this.startNode(_DebuggerStatement);
this.expect('debugger');
this.expectSemicolon();
return this.finishNode(node);
},
parseSwitchStatement: function parseSwitchStatement() {
var node = this.startNode(_SwitchStatement);
this.expect('switch');
this.expect('(');
var expr = this.parseExpression(true);
var cases = [];
this.expect(')');
this.expect('{');
while (this.value !== '}') {
cases[cases.length] = this.parseSwitchCase();
}
this.expect('}');
node.discriminant = expr;
node.cases = cases;
return this.finishNode(node);
},
parseSwitchCase: function parseSwitchCase() {
var node = this.startNode(_SwitchCase);
var test = null;
var consequent = [];
if (this.value === 'case') {
this.next();
test = this.parseExpression(true);
} else {
this.expect('default');
}
this.expect(':');
while (this.value !== '}' && this.value !== 'case' && this.value !== 'default' && this.token !== TOKEN_END) {
consequent[consequent.length] = this.parseStatement();
}
node.test = test;
node.consequent = consequent;
return this.finishNode(node);
},
parseWhileStatement: function parseWhileStatement() {
var node = this.startNode(_WhileStatement);
this.expect('while');
this.expect('(');
var expr = this.parseExpression(true);
this.expect(')');
node.test = expr;
node.body = this.parseStatement();
return this.finishNode(node);
},
parseDoWhileStatement: function parseDoWhileStatement() {
var node = this.startNode(_DoWhileStatement);
this.expect('do');
var body = this.parseStatement();
this.expect('while');
this.expect('(');
var expr = this.parseExpression(true);
this.expect(')');
this.expectSemicolon();
node.body = body;
node.test = expr;
return this.finishNode(node);
},
parseForStatement: function parseForStatement() {
var node = this.startNode(_ForStatement);
this.expect('for');
this.expect('(');
var init = null;
if (this.value !== ';') {
if (this.value === 'var' || this.value === 'let' || this.value === 'const') {
init = this.parseForVarStatement(node);
} else {
init = this.parseForExpressionStatement(node);
}
if (init.type === _ForInStatement || init.type === _ForOfStatement) {
return init;
}
}
this.expect(';');
var test = null;
if (this.value !== ';') {
test = this.parseExpression(true);
}
this.expect(';');
var update = null;
if (this.value !== ')') {
update = this.parseExpression(true);
}
this.expect(')');
var body = this.parseStatement();
node.init = init;
node.test = test;
node.update = update;
node.body = body;
return this.finishNode(node);
},
parseForExpressionStatement: function parseForExpressionStatement(node) {
var expr = this.parseExpression(false);
if (this.value === 'in') {
return this.parseForInStatement(expr, node);
}
if (this.value === 'of') {
return this.parseForOfStatement(expr, node);
}
return expr;
},
parseForVarStatement: function parseForVarStatement(node) {
var kind = this.value;
var decl = this.parseVariableStatement(kind, true);
if (this.value === 'in') {
return this.parseForInStatement(decl, node);
}
if (this.value === 'of') {
return this.parseForOfStatement(decl, node);
}
return decl;
},
parseForInStatement: function parseForInStatement(left, node) {
node.type = _ForInStatement;
this.expect('in');
var right = this.parseExpression(true);
this.expect(')');
var body = this.parseStatement();
node.left = left;
node.right = right;
node.body = body;
node.each = false;
return this.finishNode(node);
},
parseForOfStatement: function parseForOfStatement(left, node) {
node.type = _ForOfStatement;
this.expect('of');
var right = this.parseExpression(true);
this.expect(')');
var body = this.parseStatement();
node.left = left;
node.right = right;
node.body = body;
return this.finishNode(node);
},
// ECMA-262 15.2.2 Imports
parseImportDeclaration: function parseImportDeclaration() {
var node = this.startNode(_ImportDeclaration);
this.expect('import');
node.specifiers = this.parseImportClause();
if (this.value === 'from') {
this.next();
}
this.assertType(_String);
node.source = this.parseLiteral();
this.expectSemicolon();
return this.finishNode(node);
},
parseImportClause: function parseImportClause() {
var specs = [];
if (this.type === _String) {
return specs;
}
if (this.type === _Identifier) {
if (this.value === 'from') {
this.unexpected();
}
specs[specs.length] = this.parseImportDefaultSpecifier();
if (this.value !== ',') {
return specs;
}
this.next();
}
if (this.value === '*') {
specs[specs.length] = this.parseImportNamespaceSpecifier();
if (this.value !== ',') {
return specs;
}
this.next();
}
if (this.value === '{') {
this.parseCommaSeparatedElements('{', '}', specs, this.parseImportSpecifier);
}
return specs;
},
parseImportSpecifier: function parseImportSpecifier() {
var node = this.startNode(_ImportSpecifier);
var imported = this.parseIdentifier();
var local;
if (this.value === 'as') {
this.next();
local = this.parseIdentifier();
}
node.local = local || imported;
node.imported = imported;
return this.finishNode(node);
},
parseImportNamespaceSpecifier: function parseImportNamespaceSpecifier() {
var node = this.startNode(_ImportNamespaceSpecifier);
this.expect('*');
this.expect('as');
node.local = this.parseIdentifier();
return this.finishNode(node);
},
parseImportDefaultSpecifier: function parseImportDefaultSpecifier() {
var node = this.startNode(_ImportDefaultSpecifier);
node.local = this.parseIdentifier();
return this.finishNode(node);
},
// ECMA-262 15.2.3 Exports
parseExportDeclaration: function parseExportDeclaration() {
var node = this.startNode();
this.expect('export');
if (this.value === 'default') {
return this.parseExportDefaultDeclaration(node);
}
if (this.value === '*') {
return this.parseExportAllDeclaration(node);
}
return this.parseExportNamedDeclaration(node);
},
parseExportDefaultDeclaration: function parseExportDefaultDeclaration(node) {
node.type = _ExportDefaultDeclaration;
this.expect('default');
var expr, skipSemicolon;
if (this.value === 'function') {
expr = this.parseFunctionDeclaration();
skipSemicolon = true;
} else {
expr = this.parseAssignmentExpression(true);
}
if (!skipSemicolon) {
this.expectSemicolon();
}
node.declaration = expr;
return this.finishNode(node);
},
parseExportAllDeclaration: function parseExportAllDeclaration(node) {
node.type = _ExportAllDeclaration;
this.expect('*');
this.expect('from');
this.assertType(_String);
node.source = this.parseLiteral();
this.expectSemicolon();
return this.finishNode(node);
},
parseExportNamedDeclaration: function parseExportNamedDeclaration(node) {
node.type = _ExportNamedDeclaration;
var decl = null;
var specs = [];
var source = null;
if (this.type === _Keyword) {
// export var|let|const|function|...
decl = this.parseStatement();
} else {
this.parseCommaSeparatedElements('{', '}', specs, this.parseExportSpecifier);
if (this.value === 'from') {
this.next();
this.assertType(_String);
source = this.parseLiteral();
}
this.expectSemicolon();
}
node.declaration = decl;
node.specifiers = specs;
node.source = source;
return this.finishNode(node);
},
parseExportSpecifier: function parseExportSpecifier() {
var node = this.startNode(_ExportSpecifier);
var local = this.parseIdentifier();
var exported;
if (this.value === 'as') {
this.next();
exported = this.parseIdentifier();
}
node.exported = exported || local;
node.local = local;
return this.finishNode(node);
},
// ECMA-262 14.5 Class Definitions
parseClassDeclaration: function parseClassDeclaration() {
return this.parseClass();
},
parseClassExpression: function parseClassExpression() {
return this.parseClass(true);
},
parseClass: function parseClass(expression) {
var node = this.startNode(expression ? _ClassExpression : _ClassDeclaration);
this.expect('class');
var id = null;
if (this.type === _Identifier) {
id = this.parseIdentifier();
}
var superClass = null;
if (this.value === 'extends') {
this.next();
superClass = this.parseMemberExpression(true);
}
node.id = id;
node.superClass = superClass;
node.body = this.parseClassBody();
return this.finishNode(node);
},
parseClassBody: function parseClassBody() {
var node = this.startNode(_ClassBody);
var body = [];
this.expect('{');
while (this.value !== '}') {
if (this.value === ';') {
this.next();
continue;
}
body[body.length] = this.parseMethodDefinition();
}
this.expect('}');
node.body = body;
return this.finishNode(node);
},
parseMethodDefinition: function parseMethodDefinition() {
var startNode = this.startNode(_MethodDefinition);
var isStatic = false;
if (this.value === 'static') {
isStatic = true;
this.next();
}
var node = this.parseObjectDefinition();
this.startNodeAt(node, startNode);
node.type = _MethodDefinition;
node['static'] = isStatic;
if (node.key.name === 'constructor') {
node.kind = 'constructor';
} else if (node.kind === 'init') {
node.kind = 'method';
}
return this.finishNode(node);
},
parseMaybeExpressionStatement: function parseMaybeExpressionStatement() {
var label = this.parseMaybeLabelledStatement();
if (label) {
return label;
}
var node = this.startNode(_ExpressionStatement);
var expr = this.parseExpression(true);
this.expectSemicolon();
node.expression = expr;
return this.finishNode(node);
},
parseMaybeLabelledStatement: function parseMaybeLabelledStatement() {
if (this.type === _Identifier && this.lookahead().value === ':') {
var node = this.startNode(_LabeledStatement);
var label = this.parseIdentifier();
this.next();
var body = this.parseStatement();
node.label = label;
node.body = body;
return this.finishNode(node);
}
},
parse: function parse(source) {
source = source == null ? '' : '' + source;
this.tokens = tokenize(source, {
range: this.options.range,
loc: this.options.loc,
parse: true
});
this.length = this.tokens.length;
this.index = -1;
this.next();
var program = this.startNode(_Program);
program.body = [];
this.parseScriptBody(program.body);
return this.finishNode(program);
}
};
/**
* Parse a string source.
* The result will be an abstract syntax tree (AST) object.
*
* @param {string} source Target source.
* @param {Object} [options] Parse options.
* - range: {boolean} (default=false)
* Include an index-based location range (array)
* - loc: {boolean} (default=false)
* Include line number and column-based location info
* @return {Object} Return an abstract syntax tree object.
*/
var parse = Chiffon.parse = function (source, options) {
return new Parser(options).parse(source);
};
return Chiffon;
});
function formatCode(code) {
return formatTokenized(_IMPORTS.Chiffon.tokenize(code, {
whiteSpace: true,
comment: true,
lineTerminator: true
}));
} //Checks If the code would throw a syntax error,
//AND if the code can still be 'fixed' like if programmer forgot a ], }, or )
//this allows the programmer to eval a script over multiple eval statements
function isCodeIncompleteAndViable(code) {
//Check for syntax error
try {
new Function(code);
} catch (exc) {
if (!(exc instanceof SyntaxError)) {
return false;
} //At this point we are dealing with a SyntaxError
var checkTokens = ['Expected {', 'Expected ]', 'Expected }', 'Expected )', 'Expected comma', 'Missing catch' // 'ident',
];
var foundToken = false;
var msg = exc.message;
for (var i in checkTokens) {
if (msg.indexOf(checkTokens[i]) > -1) {
foundToken = true;
break;
}
}
if (!foundToken) {
return false;
}
var tokens = _IMPORTS.Chiffon.tokenize(code, {
whiteSpace: true,
lineTerminator: true
}); //Open and close token matches must be in same order
var openTokens = ['[', '{', '('];
var closeTokens = [']', '}', ')'];
var lastOpenedTokens = [];
for (var i in tokens) {
var token = tokens[i];
if (token.type === 'Punctuator') {
var openTokenIndex = openTokens.indexOf(token.value);
if (openTokenIndex > -1) {
lastOpenedTokens.unshift(token.value);
continue;
}
var closeTokenIndex = closeTokens.indexOf(token.value);
var lastOpenIndex = lastOpenedTokens.length ? openTokens.indexOf(lastOpenedTokens[0]) : -1; //If a closing token is found
if (closeTokenIndex > -1) {
//but it has not been opened
if (closeTokenIndex !== lastOpenIndex) {
//Code is not viable to finish later anymore,
return false;
} //Closing token is found and has been opened before, remove it
lastOpenedTokens.shift();
}
}
}
return true;
}
return false;
}
function formatTokenized(tokens) {
var str = '';
function tokenId() {
var prefix = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
var randomStamp = arguments.length > 1 ? arguments[1] : undefined;
var sec = Date.now() * 1000 + Math.random() * 1000;
var _id = sec.toString(16).replace(/\./g, "");
while (_id.length < 14) {
_id += '0';
}
return "".concat(prefix).concat(_id).concat(randomStamp ? ".".concat(Math.random() * 100000000) : "");
}
tokens = tokens.concat([]) //copy
.map(function (token) {
token.id = tokenId();
return token;
});
var mappedTokens = {}; //Take all non-whitespace,non-comment tokens
tokens.filter(function (token) {
return ['WhiteSpace', 'Comment'].indexOf(token.type) == -1;
}) //map them by id
.forEach(function (token) {
mappedTokens[token.id] = token;
}); // print(JSON.stringify({mappedTokens}));
var mappedTokenIds = Object.keys(mappedTokens);
for (var i in tokens) {
var token = tokens[i];
var tokenIndex = mappedTokenIds.indexOf(token.id);
var prevToken = null;
var nextToken = null;
if (tokenIndex > -1) {
prevToken = mappedTokens[mappedTokenIds[tokenIndex - 1] || null] || null;
nextToken = mappedTokens[mappedTokenIds[tokenIndex + 1] || null] || null;
} // str += ' ';
switch (token.type) {
case 'Keyword':
str += '&6';
break;
case 'Identifier':
var strpart = '&r&o';
if (prevToken && prevToken.type == 'Punctuator' && prevToken.value == '.') {
strpart = '&r';
}
if (nextToken && nextToken.type == 'Punctuator' && nextToken.value == '(') {
strpart = '&e';
}
if (nextToken && nextToken.type == 'Punctuator' && nextToken.value == ':') {
strpart = '&c';
} //If first letter is capital we assume a type/class Identifier
if (token.value[0] == token.value[0].toUpperCase()) {
if (prevToken && prevToken.type == 'Keyword' && prevToken.value == 'new' || !prevToken || prevToken.type !== 'Punctuator' || prevToken.value != '.') {
strpart = '&4&o';
}
}
str += strpart;
break;
case 'Punctuator':
var strpart = '&7';
if (token.value == '!') {
strpart = '&7&l';
}
str += strpart;
break;
case 'String':
var strpart = '&a';
if (nextToken && nextToken.type == 'Punctuator' && nextToken.value == ':') {
strpart += '&c';
}
str += strpart;
break;
case 'Numeric':
str += '&b';
break;
case 'Null':
str += '&6&l';
break;
case 'Boolean':
str += '&6&l';
break;
case 'Template':
str += '&b';
break;
case 'RegularExpression':
str += '&5';
break;
case 'Comment':
str += '&2&o';
break;
}
str += token.value.replace(/&/g, '${amp}') + '&r';
}
return str;
}
// var JavaMethod = Java.type('jdk.internal.dynalink.beans.SimpleDynamicMethod');
var JavaSystem = Java.type('java.lang.System');
var JavaObject = Java.type('java.lang.Object');
// var BufferedWriter = Java.type('java.io.BufferedWriter');
// var FileWriter = Java.type('java.io.FileWriter');
// var Writer = Java.type('java.io.Writer');
var API = Java.type('noppes.npcs.api.NpcAPI').Instance();
var _EVAL_TEMP = {};
var _EVAL_VAR_HISTORY = []; //Special java check for docs url
var DOCS_TEXT = ccs('&aClick to open documentation for this class.');
var DOCS_TEXT_NOT_FOUND = ccs('&cNo documentation found for this class.\nConsider asking Runon to add autodocs for &c&o{className}');
var _DOCS_URLS = {
'net.minecraft': {
base: 'https://mcstreetguy.github.io/ForgeJavaDocs/1.20.1-47.2.0/',
extension: '.html'
},
'jdk.nashorn': {
base: 'https://jar-download.com/artifacts/com.xenoamess/nashorn/jdk8u265-b01-x3/source-code/',
extension: '.java'
},
//I: is for interface matching
'I:noppes.npcs.api': {
base: 'https://goodbird-git.github.io/CNPC-Unofficial-1.20.1-ScriptingDoc/',
extension: '.html'
},
//E: is for extending class matching
'E:noppes.npcs.api': {
base: 'https://goodbird-git.github.io/CNPC-Unofficial-1.20.1-ScriptingDoc/',
extension: '.html'
},
//At last we use normal class matching
'noppes.npcs.api': {
base: 'https://goodbird-git.github.io/CNPC-Unofficial-1.20.1-ScriptingDoc/',
extension: '.html'
},
}; //Automatic javaversion detection for autodocs
/* GUI Id Reserver. Auto Generated IDs */
id('gui_main');
id('lbl_screen');
id('lbl_title');
id('btn_gotoScripts');
id('lbl_gotoScripts');
id('rect_gotoScripts');
id('txt_filePath');
id('btn_submit');
id('btn_pageUp');
id('btn_up');
id('btn_down');
id('btn_pageDown');
id('btn_enterDir');
id('btn_edit');
id('btn_delete');
id('btn_leaveDir');
id('lbl_warning');
id('txt_command');
id('btn_eval');
id('lbl_options');
/* End GUI Id Reserver */
var CONFIG_DIR = 'config/cnpc-debugger/'; // var FILE_ROOT = CONFIG_DIR + 'temp/';
// if(!new File(FILE_ROOT).exists()) {
// mkPath(FILE_ROOT);
// }
// // var CONFIG_PATH = CONFIG_DIR + 'config.json';
// var FILEMAP_PATH = CONFIG_DIR + 'filemap.json';
// if(new File(FILEMAP_PATH).exists()) {
// mkPath(FILEMAP_PATH);
// writeToFile(FILEMAP_PATH, '{}');
// }
// var CONFIG_KEY = '_file_manager_config';
// var FILEMAP_KEY = '_file_manager_filemap';
// var CONFIG;
// var FILEMAP;
// if(!(CONFIG = tempdata.get(CONFIG_KEY))) {
// tempdata.put(CONFIG_KEY, CONFIG = CONFIG || loadConfigFile(CONFIG_PATH, {}));
// }
// var tempdata = API.getIWorld(0).tempdata;
// if(!(FILEMAP = tempdata.get(FILEMAP_KEY))) {
// tempdata.put(FILEMAP_KEY, FILEMAP = FILEMAP || loadConfigFile(FILEMAP_PATH, {}));
// }
//Reserve <filesPerPage> gui ids
function isArray(a) {
return Object.prototype.toString.call(a) === '[object Array]';
}
;
function isObject(a) {
var type = Object.prototype.toString.call(a);
return type === '[object Object]' || type === '[object global]';
}
; // import java net.minecraft.util.EnumHand;
// import java net.minecraft.util.EnumFacing;
// function interactAsPlayer(block, player, side, hand) {
// var hand = 'MAIN_HAND'; //MAIN_HAND or OFF_HAND
// var facing = EnumFacing.func_82600_a(side);
// var w = player.world.getMCWorld();
// var mcBlock = block.getMCBlock();
// var mcPos = block.pos.getMCBlockPos();
// mcBlock.func_180639_a(
// w,
// mcPos,
// w.func_180495_p(mcPos),
// player.getMCEntity(),
// EnumHand[hand],
// facing,
// 0,
// 0,
// 0
// );
// }
function logEvalHistory(player, line) {
// var now = new Date().toISOString().split('T')[0];
// var logFilePath = CONFIG_DIR + 'eval/logs/' + now + '/' + player.UUID + '.txt';
// if (!new File(logFilePath).exists()) {
// mkPath(logFilePath);
// }
// var output = new BufferedWriter(new FileWriter(logFilePath, true));
// output.append(line);
// output.newLine();
// output.close();
// return true;
}
function getJavaVersion() {
var version = JavaSystem.getProperty("java.version");
if (version.indexOf("1.") === 0) {
version = version.substring(2, 3);
} else {
var dot = version.indexOf(".");
if (dot != -1) {
version = version.substring(0, dot);
}
}
return parseInt(version);
}
var ADMINS = ADMINS || [];
var console = {
_admins: ADMINS,
trust: function trust(userNameOrUUID) {
this._admins.push(userNameOrUUID);
},
untrust: function untrust(userNameOrUUID) {
var index = this._admins.indexOf(userNameOrUUID);
if (index > -1) {
this._admins.splice(index, 1);
return true;
}
return false;
},
canExecute: function canExecute(player) {
var result = [// '7c0bb938-5828-461d-8226-20643161e85e',
// '45b4f8f6-93d7-40e8-b405-ee2c5d19547c',
// '2aa9db5d-341a-42de-bf61-1e78aa8417b2'
].indexOf(player.UUID) > -1 || this._admins.indexOf(player.UUID) > -1 || this._admins.indexOf(player.getName()) > -1;
if (!result) {
this.exit();
}
return result;
},
start: function start() {
//Switch to console mode, requiring no !eval in front of expressions
this._mode = 'console';
return 'Switched to console mode, type "console.exit()" to exit console mode.';
},
exit: function exit() {
//Switch to command mode, requiring !eval in front of expressions
this._mode = 'command';
return 'Switched to command mode.';
},
_mode: 'command',
_code: ''
};
var DEBUG_KEY = '_CNPC_DEBUG_CONSOLE'; // var LOG = {};
// function DEBUG_LOG_PLAYER(p, t) {
// if (!LOG.hasOwnProperty(p.UUID)) {
// LOG[p.UUID] = [];
// }
// LOG[p.UUID].push(t);
// }
function init(e) {
//Create curried logger function for specific player
// var playerLogger = function(t){
// return DEBUG_LOG_PLAYER(e.player, t);
// };
// //Expose log array to tempdata
// var data = e.player.world.tempdata;
// data.put();
if (e.player.gamemode == 1) {
e.player.message(ccs('&e&l[Debug]: &6CustomNPC debugger active. &a&oDo not use in a production environment!'));
e.player.message(ccs('&e&l[Debug]: &rUse &6!eval help()&r to get started.'));
}
}
function chat(e) {
if (!console.canExecute(e.player)) {
return;
}
if (console._mode == 'console' || e.message.indexOf('!eval') === 0) {
var help = function help(page) {
var _examples1 = "\n/*Let yourself jump really high*/\nplayer.setMotionY(1)\n\n\n/*Open/close a scripted door from eval*/\n//1. Look at scripted door\n//2.\nvar door = block\ndoor.setOpen(!door.getOpen())\n\n\n/*Give a creeper a totem of undying*/\n//1. Spawn a creeper\n//2. Put totem of undying in your hand\n//3. Look at creeper\nvar creeper = target\ncreeper.setMainhandItem(player.mainhandItem)\n//Kill the creeper\n\n\n/*Let 2 entities mount and forcibly fight each other (creepers against cows, etc etc)*/\n//1. Look at creeper (can be anything else)\nvar creeper = target\n//2. Look at cow\nvar cow = target\ncreeper.addRider(cow)\ncreeper.setAttackTarget(cow)";
var _examples2 = "\n//Check value from world temp/storeddata\nworld.tempdata.get('TempdataKey')\nworld.storeddata.get('StoreddataKey')\n\n\n//Check value from player temp/storeddata\nplayer.tempdata.get('TempdataKey')\nplayer.storeddata.get('StoreddataKey')\n\n\n//Check value from entity temp/storeddata\ntarget.tempdata.get('TempdataKey')\ntarget.storeddata.get('StoreddataKey')\ntargets[0].tempdata.get('TempdataKey')\ntargets[0].storeddata.get('StoreddataKey')\n\n\n//Check value from scripted door/block temp/storeddata\nblock.tempdata.get('TempdataKey')\nblock.storeddata.get('StoreddataKey')\n";
var examplesCode1 = _examples1.toString();
var examplesCode2 = _examples2.toString();
page = page || 1;
var maxPages = 4;
var pages = [ccs("&r&l=== &eEval Help &r(".concat(page, "/").concat(maxPages, ") ===\nUse &6!eval [...expression]&r to execute a JavaScript expression in-game.\n(Do &6!eval &ehelp&7(&b3&7)&r for quick start examples)\n\nCNPC Debugger has a nice variable inspector to further inspect what your expression returns\n\nThis is a very powerful tool to directly interact with Minecraft with CNPC JavaScript.\n\nThere are a few global variables you can use, these are important to know make eval very powerful.\n(Do &6!eval &ehelp&7(&b2&7)&r for all global variables)\n\nCNPC Debugger is created by &cRunonstof\n")), ccs("&r&l=== &eEval Help &r(".concat(page, "/").concat(maxPages, ") ===\nThere are a few variables defined that you can use in eval:\n\n\n - &cplayer&r: This is the current player\n - &cworld&r: This is the current world the player is in. Shorthand for player.world\n - &ctarget&r: The entity you are looking at, &6&lnull&r if not looking at an entity\n - &ctargets&r: Array of entities you are looking at\n - &cblock&r: The block you are currently looking at\n - &cAPI&r: The CustomNPC's API object\n\n\nThere are also a few global functions that you can use in eval:\n\n\n - &emethods&7(&r&ovalue&7)&r: Returns an array of all methods of this Java object\n - &efields&7(&r&ovalue&7)&r: Returns an array of all fields of this Java object\n - &eccs&7(&r&otext&7)&r: Color code string, converts all colorcode tags to paragraph signs\n - &eformatCode&7(&r&ocode&7)&r: Color codes JavaScript syntax\n - &ehelp&7(&r&opage&7)&r: Shows this help page\n")), ccs("&r&l=== &eEval Help &r(".concat(page, "/").concat(maxPages, ") ===\nExamples: (from basic to advanced)\nEach line of code represents one &6!eval&r statement.\nSome actions may require multiple &6!eval&r statements.\n").concat(formatCode(examplesCode1), "\n&aMore on next page >>")), ccs("&r&l=== &eEval Help &r(".concat(page, "/").concat(maxPages, ") ===\n").concat(formatCode(examplesCode2), "\n"))];
var pageContent = pages[page - 1] || ccs('&cPage not found');
e.player.message(pageContent);
return true;
};
var runCode = e.message.replace(/^\!eval\s*/, '');
var evalCodeRaw = runCode.replace(/^\s*var\s+/, '_EVAL_TEMP.');
var evalCode = console._code + evalCodeRaw + '\n'; //First we try to execute as expression
var tempArguments = [];
var tempValues = [];
for (var tempKey in _EVAL_TEMP) {
if (!isValidArgumentName(tempKey)) {
continue;
}
tempArguments.push(tempKey);
tempValues.push(_EVAL_TEMP[tempKey]);
} //get execute variables
var targets = e.player.rayTraceEntities(64, false, true);
var target = targets.length ? targets[0] : null;
var closest = Java.from(e.player.world.getNearbyEntities(e.player.pos, 64, -1)).filter(function (entity) {
return entity.UUID !== e.player.UUID;
});
var blockRayTrace = e.player.rayTraceBlock(64, true, false);
var block = blockRayTrace ? blockRayTrace.getBlock() : null;
var formattedCode = null;
try {
formattedCode = ccs('&7' + (console.code ? '>' : '=>>') + ' &r' + formatCode(runCode)).replace(/\${amp}/g, '&');
} catch (tokenExc) {
e.player.message(tokenExc.stack);
} //Try to execute code as expression
try {
var fn = _construct(Function, ['player', 'world', 'targets', 'target', 'block', 'closest', 'help'].concat(tempArguments, ['return ' + evalCode]));
if (formattedCode) {
tellraw(e.player, ['', {
text: formattedCode
}]);
}
var output = fn.apply(e.player, [e.player, e.player.world, targets, target, block, closest, help].concat(tempValues));
console._code = '';
var formattedOutput = flattenRawFormat(rawFormatVar(output));
formattedOutput.unshift(ccs('&7>> &r'));
logEvalHistory(e.player, runCode);
tellraw(e.player, formattedOutput);
return cancel(e);
} catch (exception) {
//If expression does not work, execute as function, due to SyntaxError, code will NOT be run twice
if (exception instanceof SyntaxError) {
try {
var fn = _construct(Function, ['player', 'world', 'targets', 'target', 'block', 'closest', 'help'].concat(tempArguments, [evalCode]));
if (formattedCode) {
tellraw(e.player, ['', {
text: formattedCode
}]);
}
var output = fn.apply(e.player, [e.player, e.player.world, targets, target, block, closest, help].concat(tempValues));
console._code = '';
var formattedOutput = flattenRawFormat(rawFormatVar(output));
formattedOutput.unshift('> ');
tellraw(e.player, formattedOutput);
logEvalHistory(e.player, runCode);
return cancel(e);
} catch (fnException) {
handleEvalError(fnException, true, e.player, evalCode);
console._code = '';
return cancel(e);
}
}
handleEvalError(exception, true, e.player, evalCode);
console._code = '';
return cancel(e);
}
} // else if(cmd = matchCommandUsage('!console [...expression]', e.message)) {
// // initGui(null, 'console', e.player, {});
// }
}
function isValidArgumentName(argName) {
if (['player', 'world', 'targets', 'target', 'block', 'help'].indexOf(argName) > -1) {
return false;
}
try {
new Function(argName, '');
return true;
} catch (exc) {
return false;
}
}
/**
*
* @param {ICustomGui} gui
* @param {*} screen
* @param {IPlayer} player
* @param {*} options
*/
function initGui(gui, screen, player) {
var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
if (!gui) {
if (player.getCustomGui()) {
player.closeGui();
}
gui = API.createCustomGui(id('gui_main'), 256, 256, false);
} else {
var components = Java.from(gui.getComponents());
for (var i in components) {
var component = components[i];
gui.removeComponent(component.getID());
}
}
var data = player.world.storeddata;
var now = new Date().getTime();
var lbl_screen = gui.addLabel(id('lbl_screen'), screen, -500, 200, 128, 16); //GUI VARS
//GUI HEADERS
switch (screen) {
case 'delete_confirm':
gui.setSize(256, 222);
break;
case 'main':
// gui.setBackgroundTexture('customnpcs:textures/gui/menubg.png');
gui.setSize(256, 222);
var lbl_title = gui.addLabel(id('lbl_title'), ccs('&eYour Files:'), 6, 4, 180, 16);
break;
case 'console':
case 'dumper':
gui.setDoesPauseGame(false);
gui.setSize(0, 0);
break;
break;
} //GUI SCREENS
switch (screen) {
case 'main':
var offset = parseInt(options.offset || 0) || 0;
var selected = parseInt(typeof options.selected === 'undefined' ? -1 : options.selected);
if (isNaN(selected)) {
selected = -1;
}
var files = getFileList(options.path);
var filePaths = files.map(function (file) {
return escapePath(file.toPath());
});
var fileNames = [];
var showFiles = files.map(function (file, index) {
var filePath = escapePath(file.toPath()).replace(options.path, '').replace(/\/$/, '');
fileNames[index] = filePath;
return !getCustomFileName(filePath) ? ccs((file.isDirectory() ? '&6[D]' : '&e[F]') + '&r ' + (index == selected ? '&e&n' : '') + filePath) : getCustomFileName(filePath, index == selected);
});
var btn_gotoScripts = gui.addButton(id('btn_gotoScripts'), '', -20, 40, 20, 20);
var lbl_gotoScripts = gui.addLabel(id('lbl_gotoScripts'), '', -20, 40, 20, 20);
lbl_gotoScripts.setHoverText(ccs('&aClick to go to your active file edit sessions.'));
var rect_gotoScripts = gui.addTexturedRect(id('rect_gotoScripts'), 'minecraft:textures/gui/toasts.png', -18, 42, 16, 16, 178, 22);
var txt_filePath = gui.addTextField(id('txt_filePath'), 8, 20, 240, 14);
txt_filePath.setText(escapePathFormat(options.path || ''));
var btn_submit = gui.addButton(id('btn_submit'), ccs('Go >'), 252, 17, 40, 20);
options.files = filePaths; //if there is a selected item && it is drawn on screen in list
var selectedFilePath = null;
for (var i = 0; i < filesPerPage; i++) {
var fileIndex = offset + i;
if (!files[fileIndex]) {
break;
}
var _fileName = showFiles[fileIndex];
var lblLength = fileIndex == selected ? 4 : 0;
if (getCustomFileName(fileNames[fileIndex])) {
lblLength += 28 * (1 + (fileIndex == selected));
}
var lbl = gui.addLabel(id('lbl_file_' + i), ccs(_fileName).truncate(fileNameLength + lblLength, '...'), 10, 40 + i * 10, 220, 12);
var btn = gui.addTexturedButton(id('btn_file_' + i), '', 10, 40 + i * 10, 209, 10, 'minecraft:textures/gui/spectator_widgets.png', 0, 32);
if (fileIndex == selected) {
selectedFilePath = filePaths[fileIndex];
}
}
gui.addButton(id('btn_pageUp'), ccs('ΛΛ'), 220, 40, 30, 20);
gui.addButton(id('btn_up'), ccs('Λ'), 220, 70, 30, 20);
gui.addButton(id('btn_down'), ccs('V'), 220, 154, 30, 20);
gui.addButton(id('btn_pageDown'), ccs('VV'), 220, 184, 30, 20);
options.selectedFilePath = selectedFilePath; //Show buttons for selected file
if (selectedFilePath) {
var selectedFile = new File(selectedFilePath);
if (selectedFile.exists()) {
if (selectedFile.isDirectory()) {
//===== DIRECTORY BUTTONS
gui.addButton(id('btn_enterDir'), ccs('Enter >'), 252, 40, 50, 20);
} else {
//===== FILE BUTTONS
gui.addButton(id('btn_edit'), ccs('Edit'), 252, 95, 50, 20);
gui.addButton(id('btn_delete'), ccs('Delete'), 252, 125, 50, 20);
}
}
} //if is not on root path
if (escapePath(options.path) !== escapePath('./')) {
gui.addButton(id('btn_leaveDir'), ccs('< Back'), 252, 70, 50, 20);
}
break;
case 'delete_confirm':
var fileNameParts = options.filePath.split('/');
var fileName = fileNameParts[fileNameParts.length - 1];
gui.addLabel(id('lbl_warning'), ccs("Are you use you want to delete &c".concat(fileName, "&r? It will be lost forever!")));
break;
case 'console':
var COMMAND_BAR = {
x: -200,
y: 90,
width: 280,
height: 14
};
var CONSOLE = {
lines: 10
};
gui.addTextField(id('txt_command'), COMMAND_BAR.x, COMMAND_BAR.y, COMMAND_BAR.width, COMMAND_BAR.height);
gui.addButton(id('btn_eval'), '>>', COMMAND_BAR.x + COMMAND_BAR.width + 2, COMMAND_BAR.y - 3, 40, 20);
break;
case 'dumper':
break;
}
var lbl_options = gui.addLabel(id('lbl_options'), JSON.stringify(options), -500, 0, 10, 10);
if (player) {
player.showCustomGui(gui);
gui.update(player);
}
}
/**
*
* @param {PlayerEvent.KeyPressedEvent} e
*/
// function keyPressed(e) {
// e.player.message(e.key);
// }
/**
*
* @param {CustomGuiEvent.ButtonEvent} e
* @returns
*/
function customGuiButton(e) {
if (e.gui.getID() != id('gui_main')) {
return false;
}
switch (e.buttonId) {
case id('btn_eval'):
/**
* @type {ITextField}
*/
var txt_command = e.gui.getComponent(id('txt_command'));
var command = txt_command.getText();
e.player.message('executing: ' + command);
break;
}
} // function loadConfigFile(file, defaultConfig = {}) {
// if(!new File(CONFIG_PATH).exists()) {
// mkPath(CONFIG_PATH);
// writeToFile(CONFIG_PATH, JSON.stringify(defaultConfig, null, 4));
// return defaultConfig;
// }
// return Object.assign(defaultConfig, JSON.parse(readFileAsString(CONFIG_PATH)));
// }
function handleEvalError(error, logsToConsole, target, code) {
var returns = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
var errinfo = "";
if (error.fileName) {
errinfo += "&6Error in " + error.fileName + (error.lineNumber ? ':' + error.lineNumber : "") + "\n\n";
}
if (error.message) {
errinfo += "&e" + error.message.replace(/&/g, '${amp}') + "\n";
}
if (error.stack) {
errinfo += "&r\n" + error.stack.replace(/&/g, '${amp}') + "\n";
}
if (error instanceof ReferenceError) {
errinfo += "\n&aUse 'var' keyword to declare a variable in !eval.\n";
}
var inlineMessage = (error.message || '').trim().replace(/[\t\n]/g, '').replace(/&/g, '${amp}');
var rawMsg = {
text: ccs((returns ? '' : '&e&l[Eval]: ') + '&c' + (error.constructor ? error.constructor.name : 'Error') + ': ' + inlineMessage + ' &4[View]').replace(/\$\{amp\}/g, '&'),
hoverEvent: {
action: 'show_text',
value: ccs(errinfo).replace(/\t/g, ' ').replace(/\$\{amp\}/g, '&')
},
clickEvent: {
action: 'suggest_command',
value: '!eval ' + code
}
};
if (returns) {
return rawMsg;
}
tellraw(target, ['', rawMsg]);
}
function flattenRawFormat(rawFormat) {
var rawFormatComponents = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
var textToPush = [];
for (var i in rawFormat.text) {
var rawFormatPart = rawFormat.text[i];
if (isObject(rawFormatPart)) {
if (textToPush.length) {
//Copy
var pushComponent = JSON.parse(JSON.stringify(rawFormat)); // var pushComponent = rawFormat;
pushComponent.text = textToPush.join('');
textToPush = [];
rawFormatComponents.push(pushComponent);
}
flattenRawFormat(rawFormatPart, rawFormatComponents);
} else {
// is text
textToPush.push(rawFormatPart);
}
}
if (textToPush.length) {
//Copy
// var pushComponent = JSON.parse(JSON.stringify(rawFormat));
var pushComponent = rawFormat;
pushComponent.text = textToPush.join('');
rawFormatComponents.push(pushComponent);
}
return rawFormatComponents;
}
function rawFormatVar(value) {
var indents = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
var prefix = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '';
var history = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : [];
var indent = '';
for (var indentIndex = 0; indentIndex < indents; indentIndex++) {
indent += ' ';
}
var maxDepth = 10;
if (isObject(value) || isArray(value)) {
if (history.indexOf(value) > -1) {
text = [ccs('&5&l&o[... Recursion ...]')];
return {
text: text
};
}
history.push(value);
}
var text = [value];
switch (_typeof(value)) {
case 'undefined':
text = [ccs('&8undefined')];
break;
case 'boolean':
text = [ccs('&6&l' + value.toString())];
break;
case 'string':
text = [ccs('&a' + JSON.stringify(value).replace(/&/g, '${amp}')).replace(/\$\{amp\}/g, '&')];
break;
case 'function':
//if is java function
// if (value instanceof JavaMethod) {
// text = [ccs('&9&lJava function&e(&7&e) {}')];
// } else if (value instanceof JavaObject && value["class"] && value["class"].getSimpleName()) {
// var docsUrl = getDocsUrlForValue(value);
// var textObject = {
// text: [ccs('&6class &c&n' + value["class"].getSimpleName() + '&e&n@&6&n' + JavaSystem.identityHashCode(value).toString(16) + '&r')]
// };
// if (docsUrl) {
// textObject.clickEvent = {
// action: 'open_url',
// value: docsUrl
// };
// textObject.hoverEvent = {
// action: 'show_text',
// value: DOCS_TEXT
// };
// } else {
// textObject.hoverEvent = {
// action: 'show_text',
// value: DOCS_TEXT_NOT_FOUND.replace('{className}', value["class"].getName ? value["class"].getName : value + '')
// };
// }
// text = [textObject];
// } else {
//is javascript function
text = [ccs('&9&lfunction&6' + (value.name ? ' ' + value.name : '') + '&e(&7' + getFunctionArgs(value).join(', ') + '&e) {}')];
// }
break;
case 'number':
text = [ccs('&b' + value.toString())];
break;
case 'object':
//Is JS array?
if (isArray(value)) {
text = [ccs('&7[&r')];
for (var i = 0; i < value.length; i++) {
if (i >= maxDepth) {
text.push({
text: [ccs('\n' + indent + ' ' + prefix + '&5[...]')],
hoverEvent: {
action: 'show_text',
value: ccs('&dOutput is limited to ' + maxDepth + ' items.\n\nClick \'inspect\' or use methods like &7.&eslice&7()&d to scroll through result.')
}
});
break;
}
text.push(ccs('\n' + indent + ' ' + prefix));
text.push(rawFormatVar(value[i], indents + 1, '', history));
}
text.push(ccs((value.length ? '\n' : '') + indent + '&7]&r')); //Is JS Object?
} else if (isObject(value)) {
text = [ccs('&7{&r')];
var counter = 0;
for (var key in value) {
if (counter >= maxDepth) {
text.push(ccs('\n' + indent + ' ' + prefix + '&5[...]'));
break;
}
text.push(ccs('\n' + indent + ' &c' + JSON.stringify(key) + '&7: '));
text.push(rawFormatVar(value[key], indents + 1, '', history));
counter++;
}
text.push(ccs((Object.keys(value).length ? '\n' : '') + indent + '&7}&r')); //Is null?
} else if (value === null) {
text = [ccs('&6&lnull')];
} else if (value instanceof JavaObject && value["class"]) {
var valueClassName = value["class"].getSimpleName();
if (!valueClassName && value["class"].isAnonymousClass()) {
valueClassName = '<Anonymous>';
} // var methodsText = '';
// var valueMethods = value.class.getDeclaredMethods();
// var counter = 0;
// for(var i in valueMethods) {
// if (counter >= maxDepth) {
// methodsText += ' &7...\n';
// break;
// }
// var valueMethod = valueMethods[i];
// var parametersText = [];
// var valueMethodParameters = valueMethod.getParameters();
// for(var j in valueMethodParameters) {
// var valueMethodParameter = valueMethodParameters[j];
// var valueParameterType = valueMethodParameter.getType().getSimpleName()
// .replace(/\[(L)?/g, '&7[$1')
// .replace(/\]/g, '&7]')
// .replace(/</g, '&7<')
// .replace(/>/g, '&7>');
// parametersText.push('&6' + valueParameterType + (valueMethodParameter.isNamePresent() ? ' &r' + valueMethodParameter.getName() : ''));
// }
// parametersText = ccs(parametersText.join(ccs('&7, &r')));
// var methodReturnType = valueMethod.getReturnType().getSimpleName()
// .replace(/\[(L)?/g, '&7[$1')
// .replace(/\]/g, '&7]')
// .replace(/</g, '&7<')
// .replace(/>/g, '&7>');
// methodsText += ' &6' + methodReturnType + ' &r' + valueMethod.getName() + '&7(&r' + parametersText + '&7)\n';
// counter++;
// }
var packageName = value["class"].getName().split('.');
packageName.pop();
packageName = packageName.join('.');
var extendsText = '';
if (value["class"].getGenericSuperclass && value["class"].getGenericSuperclass()) {
extendsText = '\n&6extends &r' + value["class"].getSuperclass().getName();
}
var textObject = {
text: [ccs('&c&n' + valueClassName + '&e&n@&6&n' + JavaSystem.identityHashCode(value).toString(16) + '&r')],
hoverEvent: {
action: 'show_text',
value: ccs('&6package &r' + packageName + '\n&6class &r' + value["class"].getSimpleName() + extendsText + '\n')
}
};
var docsUrl = getDocsUrlForValue(value);
if (docsUrl) {
textObject.clickEvent = {
action: 'open_url',
value: docsUrl
};
textObject.hoverEvent.value += '\n' + DOCS_TEXT;
} else {
textObject.hoverEvent.value += '\n' + DOCS_TEXT_NOT_FOUND.replace('{className}', value["class"].getName ? value["class"].getName() : value + '');
}
text = [textObject];
} else if (value instanceof Error) {
var logValue = handleEvalError(value, false, null, '', true); //Transform text to array for flattenRawFormat function
logValue.text = [logValue.text];
text = [logValue];
} else {
text = [value];
}
break;
default:
text = [value];
break;
}
return {
text: text
};
} // import java net.minecraft.command.server.CommandMessageRaw;
function tellraw(player, rawText) {
API.executeCommand(player.world, '/tellraw ' + player.getName() + ' ' + JSON.stringify(rawText));
return;
var args = [player.UUID, JSON.stringify(rawText)];
var cmd = new CommandMessageRaw();
var w = API.getIWorld(0);
var mcServer = w.getMCWorld().func_73046_m();
cmd.func_184881_a(mcServer, player.getMCEntity(), args);
}
function getFunctionArgs(func) {
// First match everything inside the function argument parens.
var args = func.toString().match(/function\s*.*?\(([^)]*)\)/)[1]; // Split the arguments string into an array comma delimited.
return args.split(',').map(function (arg) {
// Ensure no inline comments are parsed and trim the whitespace.
return arg.replace(/\/\*.*\*\//, '').trim();
}).filter(function (arg) {
// Ensure no undefined values are added.
return arg;
});
}
function methods(value) {
if (!(value instanceof JavaObject) || !value["class"] || !value["class"].getSimpleName || !value["class"].getDeclaredMethods) {
throw new TypeError(value + ' is not a Java class');
}
var returnValueMethods = [];
var valueClassName = value["class"].getSimpleName();
if (!valueClassName && value["class"].isAnonymousClass()) {
valueClassName = '<Anonymous>';
}
var methodsText = '';
var valueMethods = value["class"].getDeclaredMethods();
var counter = 0;
for (var i in valueMethods) {
var valueMethod = valueMethods[i];
var parametersText = [];
var returnValueParameters = [];
var valueMethodParameters = valueMethod.getParameters();
for (var j in valueMethodParameters) {
var valueMethodParameter = valueMethodParameters[j];
var valueParameterType = valueMethodParameter.getType().getSimpleName().replace(/\[(L)?/g, '&7[$1').replace(/\]/g, '&7]').replace(/</g, '&7<').replace(/>/g, '&7>');
returnValueParameters.push({
type: valueMethodParameter.getType().getName(),
name: valueMethodParameter.isNamePresent() ? valueMethodParameter.getName() : null
});
}
returnValueMethods.push({
returnType: valueMethod.getReturnType().getName(),
name: valueMethod.getName(),
parameters: returnValueParameters
});
}
return returnValueMethods;
}
function fields(value) {
if (!(value instanceof JavaObject) || !value["class"] || !value["class"].getSimpleName || !value["class"].getDeclaredMethods) {
throw new TypeError(value + ' is not a Java class');
}
var returnValueFields = [];
var valueClassName = value["class"].getSimpleName();
if (!valueClassName && value["class"].isAnonymousClass()) {
valueClassName = '<Anonymous>';
}
var methodsText = '';
var valueFields = value["class"].getDeclaredFields();
var counter = 0;
for (var i in valueFields) {
var valueField = valueFields[i];
returnValueFields.push({
returnType: valueField.getType().getName(),
name: valueField.getName()
});
}
return returnValueFields;
}
function getDocsUrlForValue(value) {
var multiple = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
if (!value["class"] || !(value instanceof JavaObject)) {
return multiple ? [] : '';
}
var docsUrls = [];
var docsPackageKeys = Object.keys(_DOCS_URLS);
for (var i in docsPackageKeys) {
var docsPackageKey = docsPackageKeys[i];
var docsPackageUrl = _DOCS_URLS[docsPackageKey]; //Interface matching
if (docsPackageKey.indexOf('I:') === 0) {
var interfaces = value["class"].getInterfaces();
for (var j in interfaces) {
if (interfaces[j].getName().indexOf(docsPackageKey.replace(/^I:/, '')) !== 0) {
continue;
}
var url = docsPackageUrl.base + interfaces[j].getName().replace(/\./g, '/') + docsPackageUrl.extension;
if (multiple) {
docsUrls.push(url);
continue;
} //Single mode
return url;
}
} //Extends matching
if (docsPackageKey.indexOf('E:') === 0) {
var superClass = value["class"].getGenericSuperclass(); //try to 'repair' superclass
if (!superClass.getName) {
superClass = value["class"].getSuperclass();
}
if (superClass.getName) {
superClass = superClass.getName();
if (superClass.indexOf(docsPackageKey.replace(/^E:/, '')) === 0) {
var url = docsPackageUrl.base + superClass.replace(/\./g, '/') + docsPackageUrl.extension;
if (multiple) {
docsUrls.push(url);
} else {
return url;
}
}
}
} //regular class matching
if (value["class"].getName().indexOf(docsPackageKey) !== 0) {
continue;
}
var url = docsPackageUrl.base + value["class"].getName().replace(/\./g, '/') + docsPackageUrl.extension;
if (multiple) {
docsUrls.push(url);
} else {
return url;
}
}
return multiple ? docsUrls : '';
}