diff --git a/CHANGELOG.md b/CHANGELOG.md index 25ecbfb..007c6e2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,16 @@ # Changes for jscc +### v0.3.2 @ 2016-10-22 + +- Fixes an issue with losing location in sourceMap after replacing memvars. +- Now JSCC always returns an object, even if there were no changes. +- Updated `devDependencies`. + ### v0.3.1 @ 2016-10-14 - Source map includes the source filename (needed by jscc-brunch). - Removed jscc own source maps from the distribution. -- The CommonJS version validated by Coverty Scan. +- The CommonJS version is validated by Coverty Scan. ### v0.3.0 @ 2016-10-06 diff --git a/lib/jscc.es.js b/lib/jscc.es.js index fdf14a8..4310082 100644 --- a/lib/jscc.es.js +++ b/lib/jscc.es.js @@ -6,22 +6,22 @@ import { join, relative } from 'path'; */ // name=value in directives - $1:name, $2:value (including any comment) -var VARPAIR = /^\s*(_[0-9A-Z][_0-9A-Z]*)\s*=?(.*)/ +var VARPAIR = /^\s*(_[0-9A-Z][_0-9A-Z]*)\s*=?(.*)/; // to verify valid varnames and for #unset -var VARNAME = /^_[0-9A-Z][_0-9A-Z]*$/ +var VARNAME = /^_[0-9A-Z][_0-9A-Z]*$/; // prefixing varnames inside expression with `this.` or `global.` -var EVLVARS = /(^|[^$\w\.])(_[0-9A-Z][_0-9A-Z]*)\b(?=[^$\w]|$)/g +var EVLVARS = /(^|[^$\w\.])(_[0-9A-Z][_0-9A-Z]*)\b(?=[^$\w]|$)/g; // replace varnames inside the code from $_VAR.prop to value -var REPVARS = /(?:(\$_[0-9A-Z][_0-9A-Z]*)(\.[\w]+)?)(?=[\W]|$)/g +var REPVARS = /(?:(\$_[0-9A-Z][_0-9A-Z]*)(\.[\w]+)?)(?=[\W]|$)/g; // matches single and double quoted strings, take care about embedded eols -var STRINGS = /"[^"\n\r\\]*(?:\\(?:\r\n?|[\S\s])[^"\n\r\\]*)*"|'[^'\n\r\\]*(?:\\(?:\r\n?|[\S\s])[^'\n\r\\]*)*'/g +var STRINGS = /"[^"\n\r\\]*(?:\\(?:\r\n?|[\S\s])[^"\n\r\\]*)*"|'[^'\n\r\\]*(?:\\(?:\r\n?|[\S\s])[^'\n\r\\]*)*'/g; // For replacing of jspreproc variables ($1 = prefix, $2 = varname) -var _REPVARS = RegExp(((STRINGS.source) + "|" + (EVLVARS.source)), 'g') +var _REPVARS = RegExp(((STRINGS.source) + "|" + (EVLVARS.source)), 'g'); /** * Method to perform the evaluation of the received string using @@ -32,29 +32,29 @@ var _REPVARS = RegExp(((STRINGS.source) + "|" + (EVLVARS.source)), 'g') * @returns {any} The result. */ function evalExpr (ctx, str) { - var values = ctx.options.values + var values = ctx.options.values; // var replacement var _repVars = function (m, p, v) { return v ? p + (v in values ? ("this." + v) : v in global ? ("global." + v) : 'undefined') : m - } + }; var expr = str .replace(/\n/g, '\\n') .replace(/\r/g, '\\r') - .replace(_REPVARS, _repVars) + .replace(_REPVARS, _repVars); - var result + var result; try { // eslint-disable-next-line no-new-func - var fn = new Function('', ("return (" + expr + ");")) - result = fn.call(values) + var fn = new Function('', ("return (" + expr + ");")); + result = fn.call(values); } catch (e) { - result = false - ctx._emitError(((e.message) + " in expression \"" + expr + "\"")) + result = false; + ctx._emitError(((e.message) + " in expression \"" + expr + "\"")); } return result @@ -64,24 +64,24 @@ function evalExpr (ctx, str) { Parser for conditional comments */ // branch type -var NONE = 0 -var IF = 1 -var ELSE = 2 +var NONE = 0; +var IF = 1; +var ELSE = 2; // status -var WORKING = 0 -var TESTING = 1 -var ENDING = 2 -var ERROR = 3 +var WORKING = 0; +var TESTING = 1; +var ENDING = 2; +var ERROR = 3; // These characters have to be escaped. -var R_ESCAPED = /(?=[-[{()*+?.^$|\\])/g +var R_ESCAPED = /(?=[-[{()*+?.^$|\\])/g; // Matches a line with a directive, not including line-ending -var S_RE_BASE = /^[ \t\f\v]*(?:@)#(if|ifn?set|el(?:if|se)|endif|set|unset|error)(?:(?=[ \t])(.*)|\/\/.*)?$/.source +var S_RE_BASE = /^[ \t\f\v]*(?:@)#(if|ifn?set|el(?:if|se)|endif|set|unset|error)(?:(?=[ \t])(.*)|\/\/.*)?$/.source; // Match a substring that includes the first unquoted `//` -var R_LASTCMT = new RegExp(((STRINGS.source) + "|(//)"), 'g') +var R_LASTCMT = new RegExp(((STRINGS.source) + "|(//)"), 'g'); /** @@ -91,11 +91,11 @@ var R_LASTCMT = new RegExp(((STRINGS.source) + "|(//)"), 'g') * @class */ function Parser (options) { - this.options = options + this.options = options; this.cc = [{ state: WORKING, block: NONE - }] + }]; } @@ -107,17 +107,17 @@ Parser.prototype = { * @returns {boolean} Output state, `false` to hide the output. */ parse: function parse (match) { //eslint-disable-line complexity - var self = this - var cc = self.cc - var ccInfo = cc[cc.length - 1] - var state = ccInfo.state + var self = this; + var cc = self.cc; + var ccInfo = cc[cc.length - 1]; + var state = ccInfo.state; if (state === ERROR) { return false } - var key = match[1] - var expr = self._normalize(key, match[2]) + var key = match[1]; + var expr = self._normalize(key, match[2]); switch (key) { // Conditional blocks -- `#if-ifset-ifnset` pushes the state and `#endif` pop it @@ -125,33 +125,33 @@ Parser.prototype = { case 'ifset': case 'ifnset': if (state !== ENDING) { - state = self._getValue(key, expr) ? WORKING : TESTING + state = self._getValue(key, expr) ? WORKING : TESTING; } - ccInfo = { state: state, block: IF } - cc.push(ccInfo) + ccInfo = { state: state, block: IF }; + cc.push(ccInfo); break case 'elif': if (_checkBlock(IF)) { if (state === TESTING && self._getValue('if', expr)) { - ccInfo.state = WORKING + ccInfo.state = WORKING; } else if (state === WORKING) { - ccInfo.state = ENDING + ccInfo.state = ENDING; } } break case 'else': if (_checkBlock(IF)) { - ccInfo.block = ELSE - ccInfo.state = state === TESTING ? WORKING : ENDING + ccInfo.block = ELSE; + ccInfo.state = state === TESTING ? WORKING : ENDING; } break case 'endif': if (_checkBlock(IF | ELSE)) { - cc.pop() - ccInfo = cc[cc.length - 1] + cc.pop(); + ccInfo = cc[cc.length - 1]; } break @@ -160,13 +160,13 @@ Parser.prototype = { if (state === WORKING) { switch (key) { case 'set': - self._set(expr) + self._set(expr); break case 'unset': - self._unset(expr) + self._unset(expr); break case 'error': - self._error(expr) + self._error(expr); //_error throws } } @@ -177,12 +177,12 @@ Parser.prototype = { // Inner helper - throws if the current block is not of the expected type function _checkBlock (mask) { - var block = ccInfo.block + var block = ccInfo.block; if (block !== NONE && block === (block & mask)) { return true } - self._emitError(("Unexpected #" + key)) + self._emitError(("Unexpected #" + key)); return false } }, @@ -193,14 +193,14 @@ Parser.prototype = { * @returns {boolean} `true` if no error. */ close: function close () { - var cc = this.cc - var len = cc.length - var err = len !== 1 || cc[0].state !== WORKING + var cc = this.cc; + var len = cc.length; + var err = len !== 1 || cc[0].state !== WORKING; if (err && cc[0].state !== ERROR) { - this._emitError('Unexpected end of file') + this._emitError('Unexpected end of file'); } - this.options = false + this.options = false; return !err }, @@ -212,7 +212,7 @@ Parser.prototype = { getRegex: function getRegex () { var list = this.options.prefixes .map(function (s) { return s.replace(R_ESCAPED, '\\'); }) - .join('|') + .join('|'); return RegExp(S_RE_BASE.replace('@', list), 'gm') }, @@ -224,13 +224,13 @@ Parser.prototype = { * @param {string} message - Error description */ _emitError: function _emitError (message) { - var errFn = this.options.errorHandler + var errFn = this.options.errorHandler; //message = `jspp [${this.cc.fname || 'input'}] : ${message}` - this.cc[this.cc.length - 1].state = this.cc[0].state = ERROR + this.cc[this.cc.length - 1].state = this.cc[0].state = ERROR; if (typeof errFn == 'function') { - errFn(message) + errFn(message); } else { throw new Error(message) } @@ -252,13 +252,13 @@ Parser.prototype = { } // ...other keywords must have an expression if (!expr) { - this._emitError(("Expression expected for #" + ckey)) + this._emitError(("Expression expected for #" + ckey)); } - var match - R_LASTCMT.lastIndex = 0 + var match; + R_LASTCMT.lastIndex = 0; while ((match = R_LASTCMT.exec(expr))) { if (match[1]) { - expr = expr.slice(0, match.index) + expr = expr.slice(0, match.index); break } } @@ -274,7 +274,7 @@ Parser.prototype = { */ _getValue: function _getValue (ckey, expr) { if (ckey !== 'if') { - var yes = expr in this.options.values ? 1 : 0 + var yes = expr in this.options.values ? 1 : 0; return ckey === 'ifnset' ? yes ^ 1 : yes } @@ -283,36 +283,36 @@ Parser.prototype = { }, _set: function _set (s) { - var m = s.match(VARPAIR) + var m = s.match(VARPAIR); if (m) { - var k = m[1] - var v = m[2] + var k = m[1]; + var v = m[2]; - this.options.values[k] = v ? evalExpr(this, v.trim()) : undefined + this.options.values[k] = v ? evalExpr(this, v.trim()) : undefined; } else { - this._emitError(("Invalid memvar assignment \"" + s + "\"")) + this._emitError(("Invalid memvar assignment \"" + s + "\"")); } }, _unset: function _unset (s) { - var def = s.match(VARNAME) + var def = s.match(VARNAME); if (def) { - delete this.options.values[s] + delete this.options.values[s]; } else { - this._emitError(("Invalid memvar name \"" + s + "\"")) + this._emitError(("Invalid memvar name \"" + s + "\"")); } }, _error: function _error (s) { - s = evalExpr(this, s) + s = evalExpr(this, s); throw new Error(s) } -} +}; function checkOptions (opts) { - if (!opts) { opts = {} } + if (!opts) { opts = {}; } - var values = opts.values || (opts.values = {}) + var values = opts.values || (opts.values = {}); if (typeof opts.values != 'object') { throw new Error('jscc values must be a plain object') @@ -320,32 +320,32 @@ function checkOptions (opts) { // set _VERSION once in the options if (values._VERSION == null) { - var path$$1 = process.cwd().replace(/\\/g, '/') - var pack, version = '?' + var path$$1 = process.cwd().replace(/\\/g, '/'); + var pack, version = '?'; while (~path$$1.indexOf('/')) { - pack = join(path$$1, 'package.json') + pack = join(path$$1, 'package.json'); try { - version = require(pack).version + version = require(pack).version; break } catch (_) {/**/} - path$$1 = path$$1.replace(/\/[^/]*$/, '') + path$$1 = path$$1.replace(/\/[^/]*$/, ''); } - values._VERSION = version + values._VERSION = version; } Object.keys(opts.values).forEach(function (v) { if (!VARNAME.test(v)) { throw new Error(("Invalid memvar name: " + v)) } - }) + }); // sequence starting a directive - var prefixes = opts.prefixes + var prefixes = opts.prefixes; if (!prefixes) { - opts.prefixes = ['//', '/*', '