代码重构 java 脚本编译器

code refactoring a java script compiler

我试图理解一个 JavaScript 包编译器并重新设计了基本结构。 每次编译字符串时,都会将其添加到 SrcTable 数组中。并扔到输出端。 但是,要获得输出,必须将 SrcTable 声明为全局。 but the example from which i am building this code has that variable declared as local。 我想了解:- 1.Why 我不能在这里声明变量为本地变量吗? 2. 我需要更改什么才能使其像本地一样工作?

srcTablepreprocessors.compiler 变量中。

function resolveRequest(request) {
  var match = request.match(/^\s*import\s+(.*)$/),
    imports = {};

  if (match) {
    match[1].replace(/\s*([\w.\-$]+)(?:\s+as\s+([\w.\-$]+))?,?/g, function(_, from, as) {
      imports = {
        from: from,
        as: as || from
      };
    });
  }
  return imports;
}

var preprocessors = {
  import: "var importExpr = /^(\s*)(import\s+[^=+*\"'\r\n;\/]+|from\s+[^=+\"'\r\n;\/ ]+\s+import\s+[^=+\"'\r\n;\/]+)(;|\/|$)/gm;" +
    "function replace(raw, p1, p2, p3) {" +
    "  return p1 + 'jsio(\"' + p2 + '\")' + p3;" +
    "};" +
    "exports = function(src) {" +
    "  return src.replace(importExpr, replace);" +
    "};",
  compiler: "srcTable = [];" + // this array needs to be local
    "        exports = function (src) {" +
    "          var jsioNormal = " + /^(.*)jsio\s*\(\s*(['"].+?['"])\s*(,\s*\{[^}]+\})?\)/gm + "\n;" +
    "          var match = jsioNormal.exec(src);\n" +
    "          if(match) {" +
    "            var request = eval(match[2]);\n" +
    "            jsio(request, ['import', 'compiler']);\n" +
    "          } \n" +
    "          srcTable.push(src);"+
    "          return '';\n" +
    "        };" +
    "        exports.compile = function(request) {" +
    "          jsio(request, ['import', 'compiler']);" +
    "        };" + 
    "        exports.generateSrc = function (callback) {"+
    "          callback(srcTable);"+
    "        };"
};

function _require(previousCtx, request, p) {
  var p = p || ['import'];
  var request = resolveRequest(request);
  var src = eval(request.from);

  p.forEach(function(name, index) {
    var args = name == 'import' ? [] : null;
    var preprocessor = jsio('import preprocessors.' + name, args);

    src = preprocessor(src);
  });

  var code = "(function (__) { with (__) {" + src + "}});";
  var fn = eval(code);
  var context = makeContext();
  fn(context);
  previousCtx[request.as] = context.exports;
  return context.exports;
}

function makeContext() {
  return {
    jsio: function(request, p) {
      return _require(this, request, p);
    },
    exports: {}
  };
}

var jsio = makeContext().jsio;

var example = {
  app: "import example.calculator as calculator;" +
    "   calculator.add(2, 3);",

  calculator: "import example.print as print;" +
    "          exports = {" +
    "            add: function (a, b) {" +
    "              print(a+b);" +
    "            }" +
    "          }",

  print: "exports = function(res) {" +
    "       console.log(res);" +
    "     }"
};

var compiler = jsio('import preprocessors.compiler;');
compiler.compile('import example.app;');
compiler.generateSrc(function(src) {
  console.log(src);
});

由于代码是使用 java-script with 上下文编译的,因此,评估代码的函数需要缓存,否则每次都会编译相同的代码,将重新创建实例。 所以解决方案是

function resolveRequest(request) {
  var match = request.match(/^\s*import\s+(.*)$/),
    imports = {};

  if (match) {
    match[1].replace(/\s*([\w.\-$]+)(?:\s+as\s+([\w.\-$]+))?,?/g, function(_, from, as) {
      imports = {
        from: from,
        as: as || from
      };
    });
  }
  return imports;
}

var preprocessors = {
  import: "var importExpr = /^(\s*)(import\s+[^=+*\"'\r\n;\/]+|from\s+[^=+\"'\r\n;\/ ]+\s+import\s+[^=+\"'\r\n;\/]+)(;|\/|$)/gm;" +
    "function replace(raw, p1, p2, p3) {" +
    "  return p1 + 'jsio(\"' + p2 + '\")' + p3;" +
    "};" +
    "exports = function(src) {" +
    "  return src.replace(importExpr, replace);" +
    "};",
  compiler: "var srcTable = [];\n" +
    "        exports = function (src) {\n" +
    "          var jsioNormal = " + /^(.*)jsio\s*\(\s*(['"].+?['"])\s*(,\s*\{[^}]+\})?\)/gm + "\n;" +
    "          var match = jsioNormal.exec(src);\n" +
    "          if(match) {\n" +
    "            var request = eval(match[2]);\n" +
    "            jsio(request, ['import', 'compiler']);\n" +
    "          } \n" +
    "          srcTable.push(src);\n" +
    "          return '';\n" +
    "        };\n" +
    "        exports.compile = function(request) {\n" +
    "          jsio(request, ['import', 'compiler']);\n" +
    "        };\n" +
    "        exports.generateSrc = function (callback) {\n" +
    "          callback(srcTable);\n" +
    "        };\n"
};

var _cache_context = [];

function _require(previousCtx, request, p) {
  var p = p || ['import'];
  var request = resolveRequest(request);
  var src = loadModule(request).src;

  p.forEach(function(name, index) {
    var args = name == 'import' ? [] : null;
    var preprocessor = jsio('import preprocessors.' + name, args);
    src = preprocessor(src);
  });

  if (src) {
    if (!_cache_context[request.from]) {
      var code = "(function (__) { with (__) {\n" + src + "\n}});";
      var fn = eval(code);
      var context = makeContext();
      fn(context);
      _cache_context[request.from] = context.exports;
    }
    previousCtx[request.as] = _cache_context[request.from];
    return previousCtx[request.as];
  }
}

function loadModule(request){
 var src = eval(request.from);

 return {
   src: src,
   path: request.from
 } 
}

function makeContext() {
  return {
    jsio: function(request, p) {
      return _require(this, request, p);
    },
    exports: {}
  };
}

var jsio = makeContext().jsio;

var example = {
  app: "import example.calculator as calculator;" +
    "   calculator.add(2, 3);",

  calculator: "import example.print as print;" +
    "          exports = {" +
    "            add: function (a, b) {" +
    "              print(a+b);" +
    "            }" +
    "          }",

  print: "exports = function(res) {" +
    "       console.log(res);" +
    "     }"
};

var compiler = jsio('import preprocessors.compiler;');
compiler.compile('import example.app;');
compiler.generateSrc(function(src) {
  console.log(src);
});