Skip to content

Commit

Permalink
v3.2.4
Browse files Browse the repository at this point in the history
  • Loading branch information
aMarCruz committed Jun 22, 2017
1 parent 472572b commit 883c0ce
Show file tree
Hide file tree
Showing 23 changed files with 512 additions and 212 deletions.
12 changes: 6 additions & 6 deletions .eslintrc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@ root: true

env:
node: true
#es6: true

ecmaFeatures:
modules: true
es6: true

parserOptions:
sourceType: "module"
sourceType: "module"
ecmaVersion: 6
ecmaFeatures:
impliedStrict: true

###########################################################################
# GLOBALS #
Expand Down Expand Up @@ -142,7 +142,7 @@ rules:
new-parens: 2 # disallow the omission of parentheses when invoking a constructor with no arguments (Default: 0)
no-array-constructor: 2 # disallow use of the Array constructor (Default: 0)
no-lonely-if: 2 # disallow if as the only statement in an else block
no-multiple-empty-lines: [2, {"max": 1}]
no-multiple-empty-lines: [2, {"max": 2}]
# disallow multiple empty lines
no-new-object: 2 # disallow use of the Object constructor (Default: 0)
no-restricted-syntax: [2, "WithStatement"] # disallow use of `with` statements in code
Expand Down
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Compiler Changes

### v3.2.4
- Fix [riot#2369](https://github.com/riot/riot/issues/2369) : Possible bug involving compilation of tags containing regex.
- Using the `skip-regex` function from npm for sharing bwteen modules (at future).
- Using the `jsSplitter` function for safer replacement of JS code, part of the next compiler.

### v3.2.3
- Fixes various issues with literal regexes.

Expand Down
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ LIB = "./lib/"
# default job
test: build test-mocha

build: clean eslint pre-build
build: clean pre-build eslint
# build riot and es6 versions
@ mkdir -p $(DIST)
@ $(JSPP) $(JSPP_RIOT_FLAGS) src/_riot.js > $(DIST)riot.compiler.js
Expand All @@ -35,6 +35,7 @@ pre-build:
# build the node version
@ $(JSPP) $(JSPP_NODE_FLAGS) src/core.js > $(LIB)compiler.js
@ $(JSPP) $(JSPP_NODE_FLAGS) src/safe-regex.js > $(LIB)safe-regex.js
@ $(JSPP) $(JSPP_NODE_FLAGS) src/js-splitter.js > $(LIB)js-splitter.js

eslint:
# check code style
Expand Down
4 changes: 2 additions & 2 deletions lib/brackets.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*/

var safeRegex = require('./safe-regex')
var skipRegex = require('./skip-regex')
var skipRegex = require('skip-regex')

/**
* Matches valid, multiline JavaScript comments in almost all its forms.
Expand Down Expand Up @@ -39,7 +39,7 @@ var S_QBLOCKS = R_STRINGS.source + '|' +
/*
JS/ES6 quoted strings and start of regex (basic ES6 does not supports nested backquotes).
*/
var S_QBLOCK2 = R_STRINGS.source + '|' + /(\/)(?![*\/])/.source
var S_QBLOCK2 = R_STRINGS.source + '|(/)(?![*/])'

/**
* Hash of regexes for matching JavaScript brackets out of quoted strings and literal
Expand Down
62 changes: 22 additions & 40 deletions lib/compiler.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
/**
* The riot-compiler v3.2.3
* The riot-compiler v3.2.4
*
* @module compiler
* @version v3.2.3
* @version v3.2.4
* @license MIT
* @copyright Muut Inc. + contributors
*/
Expand All @@ -11,6 +11,7 @@
var brackets = require('./brackets')
var parsers = require('./parsers')
var safeRegex = require('./safe-regex')
var jsSplitter = require('./js-splitter')
var path = require('path')

var extend = require('./parsers/_utils').mixobj
Expand Down Expand Up @@ -339,23 +340,6 @@ function compileHTML (html, opts, pcex) {
*/
var JS_ES6SIGN = /^[ \t]*(((?:async|\*)\s*)?([$_A-Za-z][$\w]*))\s*\([^()]*\)\s*{/m

/**
* Regex for remotion of multiline and single-line JavaScript comments, merged with
* {@link module:brackets.S_QBLOCKS|brackets.S_QBLOCKS} to skip literal string and regexes.
* Used by the {@link module:compiler~riotjs|riotjs} parser.
*
* 2016-01-18: rewritten to not capture the brackets (reduces 9 steps)
* @const {RegExp}
*/
var JS_ES6END = RegExp('[{}]|' + brackets.S_QBLOCKS, 'g')

/**
* Regex for remotion of multiline and single-line JavaScript comments, merged with
* {@link module:brackets.S_QBLOCKS|brackets.S_QBLOCKS} to skip literal string and regexes.
* @const {RegExp}
*/
var JS_COMMS = RegExp(brackets.R_MLCOMMS.source + '|//[^\r\n]*|' + brackets.S_QBLOCK2, 'g')

/**
* Default parser for JavaScript, supports ES6-like method syntax
*
Expand All @@ -373,13 +357,14 @@ function riotjs (js) {
name,
RE = RegExp

if (~js.indexOf('/')) js = rmComms(js, JS_COMMS)
const src = jsSplitter(js)
js = src.shift().join('<%>')

while ((match = js.match(JS_ES6SIGN))) {

parts.push(RE.leftContext)
js = RE.rightContext
pos = skipBody(js, JS_ES6END)
pos = skipBody(js)

method = match[1]
prefix = match[2] || ''
Expand All @@ -399,28 +384,25 @@ function riotjs (js) {
if (toes5 && !/^\s*.\s*bind\b/.test(js)) parts.push('.bind(this)')
}

return parts.length ? parts.join('') + js : js
if (parts.length) {
js = parts.join('') + js
}

function rmComms (s, r, m) {
r.lastIndex = 0
while ((m = r.exec(s))) {
if (m[1]) {
r.lastIndex = brackets.skipRegex(s, m.index)
} else if (m[0][0] === '/') {
s = s.slice(0, m.index) + ' ' + s.slice(r.lastIndex)
r.lastIndex = m.index + 1
}
}
return s
if (src.length) {
js = js.replace(/<%>/g, function () {
return src.shift()
})
}

function skipBody (s, r) {
var m, i = 1
return js

function skipBody (s) {
var r = /[{}]/g
var i = 1

r.lastIndex = 0
while (i && (m = r.exec(s))) {
if (m[0] === '{') ++i
else if (m[0] === '}') --i
while (i && r.exec(s)) {
if (s[r.lastIndex - 1] === '{') ++i
else --i
}
return i ? s.length : r.lastIndex
}
Expand Down Expand Up @@ -1010,5 +992,5 @@ module.exports = {
css: compileCSS,
js: compileJS,
parsers: parsers,
version: 'v3.2.3'
version: 'v3.2.4'
}
135 changes: 135 additions & 0 deletions lib/js-splitter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@

var skipRegex = require('skip-regex')

var S_SQ_STR = /'[^'\n\r\\]*(?:\\(?:\r\n?|[\S\s])[^'\n\r\\]*)*'/.source

var S_R_SRC1 = [
/\/\*[^*]*\*+(?:[^*\/][^*]*\*+)*\//.source,
'//.*',
S_SQ_STR,
S_SQ_STR.replace(/'/g, '"'),
'([/`])'
].join('|')

var S_R_SRC2 = `${S_R_SRC1.slice(0, -2)}{}])`

/**
* Simple ES6 Template Literal parser, it searches the next back-quote that
* signals the end of the ES6TL or the `${` sequence that starts a JS expression,
* skipping any escaped character.
*
* @param {string} code - Whole code
* @param {number} start - The start position of the template
* @param {number} stack - To save nested ES6 TL count
* @returns {number} The end of the string (-1 if not found)
*/
function skipES6str (code, start, stack) {

var re = /[`$\\]/g

re.lastIndex = start
while (re.exec(code)) {
var end = re.lastIndex
var c = code[end - 1]

if (c === '`') {
return end
}
if (c === '$' && code[end] === '{') {
stack.push('`', '}')
return end + 1
}
re.lastIndex++
}

throw new Error('Unclosed ES6 template')
}

/**
* Parses the code string searching the end of the expression.
* @param {string} code - Buffer to parse
* @param {number} [start=0] - Start position of the parsing
* @returns {Array} Expression's end (after the closing brace) or -1 if it is not an expr.
* @class
*/
function jsSplitter (code, start) {

var re1 = new RegExp(S_R_SRC1, 'g')
var re2

var offset = start |= 0
var result = [[]]
var stack = []
var re = re1

var lastPos = re.lastIndex = offset
var str, ch, idx, end, match

while ((match = re.exec(code))) {
idx = match.index
end = re.lastIndex
str = ''
ch = match[1]

if (ch) {

if (ch === '{') {
stack.push('}')

} else if (ch === '}') {
if (stack.pop() !== ch) {
throw new Error("Unexpected '}'")

} else if (stack[stack.length - 1] === '`') {
ch = stack.pop()
}

} else if (ch === '/') {
end = skipRegex(code, idx)

if (end > idx + 1) {
str = code.slice(idx, end)
}
}

if (ch === '`') {
end = skipES6str(code, end, stack)
str = code.slice(idx, end)

if (stack.length) {
re = re2 || (re2 = new RegExp(S_R_SRC2, 'g'))
} else {
re = re1
}
}

} else {

str = match[0]

if (str[0] === '/') {
str = str[1] === '*' ? ' ' : ''
code = code.slice(offset, idx) + str + code.slice(end)
end = idx + str.length
str = ''

} else if (str.length === 2) {
str = ''
}
}

if (str) {
result[0].push(code.slice(lastPos, idx))
result.push(str)
lastPos = end
}

re.lastIndex = end
}

result[0].push(code.slice(lastPos))

return result
}

module.exports = jsSplitter
Loading

0 comments on commit 883c0ce

Please sign in to comment.