8000 javascript 代码变量静态分析 · Issue #27 · goofychris/art-template · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content
javascript 代码变量静态分析 #27
Closed
@aui

Description

@aui

2013-09-06 更新

上一版本的分析器包含两个BUG,导致模板逻辑语法中出现地雷:

  1. 无法正确处理特殊情况下的字符串 "\"" 或者 '\''
  2. 无法解析$号开头且后面为数字的变量,如 $0

以下是新的解析器实现,完善字符串与数字判断的正则,解决上述两个BUG:

// 静态分析模板变量
var KEYWORDS =
    // 关键字
    'break,case,catch,continue,debugger,default,delete,do,else,false'
    + ',finally,for,function,if,in,instanceof,new,null,return,switch,this'
    + ',throw,true,try,typeof,var,void,while,with'

    // 保留字
    + ',abstract,boolean,byte,char,class,const,double,enum,export,extends'
    + ',final,float,goto,implements,import,int,interface,long,native'
    + ',package,private,protected,public,short,static,super,synchronized'
    + ',throws,transient,volatile'

    // ECMA 5 - use strict
    + ',arguments,let,yield'

    + ',undefined';

var REMOVE_RE = /\/\*[\w\W]*?\*\/|\/\/[^\n]*\n|\/\/[^\n]*$|"(?:[^"\\]|\\[\w\W])*"|'(?:[^'\\]|\\[\w\W])*'|[\s\t\n]*\.[\s\t\n]*[$\w\.]+/g;
var SPLIT_RE = /[^\w$]+/g;
var KEYWORDS_RE = new RegExp(["\\b" + KEYWORDS.replace(/,/g, '\\b|\\b') + "\\b"].join('|'), 'g');
var NUMBER_RE = /^\d[^,]*|,\d[^,]*/g;
var BOUNDARY_RE = /^,+|,+$/g;

var getVariable = function (code) {

    code = code
    .replace(REMOVE_RE, '')
    .replace(SPLIT_RE, ',')
    .replace(KEYWORDS_RE, '')
    .replace(NUMBER_RE, '')
    .replace(BOUNDARY_RE, '');

    code = code ? code.split(/,+/) : [];

    return code;
};

测试代码:

// test
var test = function () {
    /*tang bin*/
    // hello
    var $1, $1$, a$0, a$$, a0;
    var str = c$0 + 'fdsf\'hello';//word
    var $ = 7;
    var x = {};
    x.toString();

    var _me; _2, _;

    var $test = _2 > 399  || _3 < -235;

    return false;
}.toString();

console.log(getVariable(test))

算法采用过滤的思路实现:

  1. 删除注释、字符串、方法名,这一步是为了排除干扰
  2. 删除可组成变量的字符,只保留字母、数字、美元符号与下划线,并进行分组
  3. 删除分组中的 js 关键字与保留字成员
  4. 删除分组中的数字成员

经过四轮过滤后,剩下来的就是模板变量列表了,且不会有漏网之鱼,从而避免编译后的函数出现未定义的变量。当然,出于使用场景考虑,忽略了下面的两个问题:

  1. 没有排除对象字面量
  2. 没有排除正则表达式

关于第2点,有个现实的问题是是:要完美区分正则与除法在不使用语法分析的情况下是无法实现的,引入 ast 成本过大。

最后,默念一遍:没有完美的方案,只有最适合的方案。如有问题欢迎提出

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      0