Skip to content

保存avalon v6的parser #64

@RubyLouvre

Description

@RubyLouvre

新的版本将不支持严格模式

//将绑定属性的值或插值表达式里面部分转换一个函数compileFn,里面或包含ViewModel的某些属性
    //而它们分分种都是setter, getter,成为双向绑定链的一部分
    var regEscape = /([-.*+?^${}()|[\]\/\\])/g;

    function escapeRegExp(target) {
        //将字符串安全格式化为正则表达式的源码
        return target.replace(regEscape, "\\$1");
    }
    var isStrict = (function() {
        return !this;
    })();

    function insertScopeNameBeforeVariableName(e, text, scopes, names, args, random) {
        var ok = false;
        if (W3C) { //判定是否IE9-11或者为标准浏览器
            ok = e instanceof ReferenceError;
        } else {
            ok = e instanceof TypeError;
        }
        //opera9.61
        //message: Statement on line 810: Undefined variable: nickName
        //opera12
        //Undefined variable: nickName
        //safari 5
        //Can't find variable: nickName
        //firefox3-20  chrome
        //ReferenceError: nickName is not defined
        //IE10
        //“nickName”未定义 
        //IE6 
        //'eee' 未定义 
        if (ok) {
            if (window.opera) {
                var varName = e.message.split("Undefined variable: ")[1];
            } else {
                varName = e.message.replace("Can't find variable: ", "")
                        .replace("“", "").replace("'", "");
            }
            varName = (varName.match(/^[\w$]+/) || [""])[0]; //取得未定义的变量名
            for (var i = 0, scope; scope = scopes[i++]; ) {
                if (scope.hasOwnProperty(varName)) {
                    var scopeName = scope.$id + random;
                    if (names.indexOf(scopeName) === -1) {
                        names.push(scopeName);
                        args.push(scope);
                    }
                    //这里实际还要做更严格的处理
                    var reg = new RegExp("(^|[^\\w\\u00c0-\\uFFFF_])(" + escapeRegExp(varName) + ")($|[^\\w\\u00c0-\\uFFFF_])", "g");
                    return text.replace(reg, function(a, b, c, d) {
                        return b + scopeName + "." + c + d; //添加作用域
                    });
                }
            }

        }
    }
    var doubleQuotedString = /"([^\\"\n]|\\.)*"/g;
    var singleQuotedString = /'([^\\'\n]|\\.)*'/g;

    function parseExpr(text, scopeList, data) {
        var names = [],
                args = [],
                random = new Date - 0,
                val;
        if (!isStrict) { //如果不是严格模式
            //取得ViewModel的名字
            scopeList.forEach(function(scope) {
                var scopeName = scope.$id + "" + random;
                if (names.indexOf(scopeName) === -1) {
                    names.push(scopeName);
                    args.push(scope);
                }
            });
            text = "var ret" + random + " = " + text + "\r\n";
            for (var i = 0, name; name = names[i++]; ) {
                text = "with(" + name + "){\r\n" + text + "\r\n}\r\n";
            }
        } else {
            var singleFix = random + 1;
            var doubleFix = singleFix + 1;
            var singleHolder = [];
            var doubleHolder = [];
            var loop = true;
            //抽取掉所有字符串
            text = text.replace(singleQuotedString, function(a) {
                singleHolder.push(a);
                return singleFix;
            }).replace(doubleQuotedString, function(b) {
                doubleHolder.push(b);
                return doubleFix;
            });
            do { //开始循环
                try {
                    var fn = Function.apply(Function, names.concat("return " + text));
                    var val = fn.apply(fn, args);
                    loop = false;
                } catch (e) {
                    text = insertScopeNameBeforeVariableName(e, text, scopeList, names, args, random);
                    loop = typeof text === "string";
                }
            } while (loop);
            if (text) {
                if (singleHolder.length) {
                    text = text.replace(new RegExp(singleFix, "g"), function() {
                        return singleHolder.shift();
                    });
                }
                if (doubleHolder.length) {
                    text = text.replace(new RegExp(doubleFix, "g"), function() {
                        return doubleHolder.shift();
                    });
                }
                text = "var ret" + random + " = " + text;
            } else {
                data.compileFn = function() {
                    return "";
                };
                return "";
            }
        }
        if (data.filters) {
            var textBuffer = [],
                    fargs;
            textBuffer.push(text, "\r\n");
            for (var i = 0, f; f = data.filters[i++]; ) {
                var start = f.indexOf("(");
                if (start !== -1) {
                    fargs = f.slice(start + 1, f.lastIndexOf(")")).trim();
                    fargs = "," + fargs;
                    f = f.slice(0, start).trim();
                } else {
                    fargs = "";
                }
                textBuffer.push(" if(filters", random, ".", f, "){\r\n\ttry{ret", random,
                        " = filters", random, ".", f, "(ret", random, fargs, ")}catch(e){};\r\n}\r\n");
            }
            text = textBuffer.join("");
            names.push("filters" + random);
            args.push(avalon.filters);
            delete data.filters; //释放内存
        }
        data.compileArgs = args;
        try {
            text += "\r\nreturn ret" + random;
            var fn = Function.apply(Function, names.concat(text));
            val = fn.apply(fn, args);
            data.compileFn = fn; //缓存,防止二次编译
        } catch (e) {
            data.remove = false;
            data.compileFn = function() {
                return "";
            };
            val = "";
        }
        textBuffer = names = null; //释放内存
        return val;
    }

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions