bug描述
require('tmpl', '<%var a=12/3;%><div><%=a%></div>');
require('page', function(require, exports, module){
console.log('page');
})
如上代码,如果使用seajs 2.2.1版本,将会出现模块解析的错误。原因是require(‘tmpl’),模板字符串中有算数表达式12/3。而seajs在计算模块依赖时,使用的正则表达式未处理到这种情况。
seajs 2.2.1版本
var REQUIRE_RE = /"(?:\\"|[^"])*"|'(?:\\'|[^'])*'|\/\*[\S\s]*?\*\/|\/(?:\\\/|[^\/\r\n])+\/(?=[^\/])|\/\/.*|\.\s*require|(?:^|[^$])\brequire\s*\(\s*(["'])(.+?)\1\s*\)/g
var SLASH_RE = /\\\\/g
function parseDependencies(code) {
var ret = []
code.replace(SLASH_RE, "")
.replace(REQUIRE_RE, function(m, m1, m2) {
if (m2) {
ret.push(m2)
}
})
return ret
}
新版本seajs改进之后,bug得以解决
function parseDependencies(s) {
if(s.indexOf('require') == -1) {
return []
}
var index = 0, peek, length = s.length, isReg = 1, modName = 0, parentheseState = 0, parentheseStack = [], res = []
while(index < length) {
readch()
if(isBlank()) {
}
else if(isQuote()) {
dealQuote()
isReg = 1
}
else if(peek == '/') {
readch()
if(peek == '/') {
index = s.indexOf('\n', index)
if(index == -1) {
index = s.length
}
}
else if(peek == '*') {
index = s.indexOf('*/', index)
if(index == -1) {
index = length
}
else {
index += 2
}
}
else if(isReg) {
dealReg()
isReg = 0
}
else {
index--
isReg = 1
}
}
else if(isWord()) {
dealWord()
}
else if(isNumber()) {
dealNumber()
}
else if(peek == '(') {
parentheseStack.push(parentheseState)
isReg = 1
}
else if(peek == ')') {
isReg = parentheseStack.pop()
}
else {
isReg = peek != ']'
modName = 0
}
}
return res
function readch() {
peek = s.charAt(index++)
}
function isBlank() {
return /\s/.test(peek)
}
function isQuote() {
return peek == '"' || peek == "'"
}
function dealQuote() {
var start = index
var c = peek
var end = s.indexOf(c, start)
if(end == -1) {
index = length
}
else if(s.charAt(end - 1) != '\\') {
index = end + 1
}
else {
while(index < length) {
readch()
if(peek == '\\') {
index++
}
else if(peek == c) {
break
}
}
}
if(modName) {
res.push(s.slice(start, index - 1))
modName = 0
}
}
function dealReg() {
index--
while(index < length) {
readch()
if(peek == '\\') {
index++
}
else if(peek == '/') {
break
}
else if(peek == '[') {
while(index < length) {
readch()
if(peek == '\\') {
index++
}
else if(peek == ']') {
break
}
}
}
}
}
function isWord() {
return /[a-z_$]/i.test(peek)
}
function dealWord() {
var s2 = s.slice(index - 1)
var r = /^[\w$]+/.exec(s2)[0]
parentheseState = {
'if': 1,
'for': 1,
'while': 1,
'with': 1
}[r]
isReg = {
'break': 1,
'case': 1,
'continue': 1,
'debugger': 1,
'delete': 1,
'do': 1,
'else': 1,
'false': 1,
'if': 1,
'in': 1,
'instanceof': 1,
'return': 1,
'typeof': 1,
'void': 1
}[r]
modName = /^require\s*\(\s*(['"]).+?\1\s*\)/.test(s2)
if(modName) {
r = /^require\s*\(\s*['"]/.exec(s2)[0]
index += r.length - 2
}
else {
index += /^[\w$]+(?:\s*\.\s*[\w$]+)*/.exec(s2)[0].length - 1
}
}
function isNumber() {
return /\d/.test(peek)
|| peek == '.' && /\d/.test(s.charAt(index))
}
function dealNumber() {
var s2 = s.slice(index - 1)
var r
if(peek == '.') {
r = /^\.\d+(?:E[+-]?\d*)?\s*/i.exec(s2)[0]
}
else if(/^0x[\da-f]*/i.test(s2)) {
r = /^0x[\da-f]*\s*/i.exec(s2)[0]
}
else {
r = /^\d+\.?\d*(?:E[+-]?\d*)?\s*/i.exec(s2)[0]
}
index += r.length - 1
isReg = 0
}
}