<commit_before>var Promise = require('rsvp').Promise;

var System = require('systemjs');
var fs = require('fs');

var asp = require('rsvp').denodeify;

var es6Compiler = require('./compilers/es6');
var registerCompiler = require('./compilers/register');
var amdCompiler = require('./compilers/amd');
var cjsCompiler = require('./compilers/cjs');
var globalCompiler = require('./compilers/global');
var builder = require('./lib/builder');

var path = require('path');

function Builder(cfg) {
  this.System = System;
  this.loader = null;
  this.reset();
  if (typeof cfg == "string")
    this.loadConfigSync(cfg);
  else if (typeof cfg == "object")
    this.config(cfg);
}

Builder.prototype.reset = function() {
  var loader = this.loader = new Loader(System);
  loader.baseURL = System.baseURL;
  loader.paths = { '*': '*.js' };
  loader.config = System.config;

  var pluginLoader = new Loader(System);
  pluginLoader.baseURL = System.baseURL;
  pluginLoader.paths = { '*': '*.js' };
  pluginLoader.config = System.config;
  pluginLoader.trace = true;
  pluginLoader.import = loader.import = System.import;

  pluginLoader._nodeRequire = loader._nodeRequire = require;

  loader.trace = true;
  loader.execute = false;
  loader.pluginLoader = pluginLoader;

  loader.set('@empty', loader.newModule({}));
  pluginLoader.set('@empty', loader.newModule({}));

  amdCompiler.attach(loader);
  amdCompiler.attach(pluginLoader);
};

Builder.prototype.build = function(moduleName, outFile, opts) {
  var self = this;
  opts = opts || {};

  return this.trace(moduleName, opts.config)
  .then(function(trace) {
    return self.buildTree(trace.tree, outFile, opts);
  });
};

var compilerMap = {
  'amd':      amdCompiler,
  'cjs':      cjsCompiler,
  'es6':      es6Compiler,
  'global':   globalCompiler,
  'register': registerCompiler
};

function compileLoad(loader, load, opts, compilers) {
  return Promise.resolve()
  .then(function() {
    // note which compilers we used
    compilers = compilers || {};
    var format = load.metadata.format;
    if (load.metadata.build === false) {
      return {};
    }
    else if (format in compilerMap) {
      compilers[format] = true;
      return compilerMap[format].compile(load, opts, loader);
    }
    else if (format == 'defined') {
      return {source: ''};
    }
    else {
      throw "unknown format " + format;
    }
  });
}

function buildOutputs(loader, tree, opts, sfxCompilers) {
  var names = Object.keys(tree);
  // store plugins with a bundle hook to allow post-processing
  var plugins = {};
  var outputs = [];

  return Promise.all(names.map(function(name) {
    var load = tree[name];

    if (sfxCompilers && load.metadata.plugin && (load.metadata.build === false || load.metadata.plugin.build === false))
      outputs.push('System.register("' + load.name + '", [], false, function() { console.log("SystemJS Builder - Plugin for ' + load.name + ' does not support sfx builds"); });\n');

    // support plugin "bundle" reduction hook
    var plugin = load.metadata.plugin;
    if (plugin && load.metadata.build !== false) {
      var entry = plugins[load.metadata.pluginName] = plugins[load.metadata.pluginName] || {
        loads: [],
        bundle: plugin.bundle
      };
      entry.loads.push(load);
    }

    return Promise.resolve(compileLoad(loader, load, opts, sfxCompilers))
    .then(outputs.push.bind(outputs));
  }))
  .then(function() {
    // apply plugin "bundle" hook
    return Promise.all(Object.keys(plugins).map(function(pluginName) {
      var entry = plugins[pluginName];
      if (entry.bundle)
      return Promise.resolve(entry.bundle.call(loader.pluginLoader, entry.loads, opts))
      .then(outputs.push.bind(outputs));
    }));
  })
  .then(function() {
    return outputs;
  });
}

Builder.prototype.buildTree = function(tree, outFile, opts) {
  var loader = this.loader;

  opts = opts || {};
  opts.outFile = outFile;

  return buildOutputs(loader, tree, opts, false)
  .then(function(outputs) {
    outputs.unshift('"format register";\n');
    return builder.writeOutput(opts, outputs, loader.baseURL);
  });
};

Builder.prototype.buildSFX = function(moduleName, outFile, opts) {
  var loader = this.loader;

  opts = opts || {};
  var config = opts.config;

  opts.outFile = outFile;

  var outputs;

  var compilers = {};
  opts.normalize = true;
  return this.trace(moduleName, config)
  .then(function(trace) {
    moduleName = trace.moduleName;
    return buildOutputs(loader, trace.tree, opts, compilers);
  })
  .then(function(_outputs) {
    outputs = _outputs;
  })
  // next add sfx headers for formats at the beginning
  .then(function() {
    Object.keys(compilers).forEach(function(format) {
      compiler = compilerMap[format];
      if (compiler.sfx)  {
        var sfx = compiler.sfx(loader);
        if (sfx) outputs.push(sfx);
      }
    });
  })
  // next wrap with the core code
  .then(function() {
    return asp(fs.readFile)(path.resolve(__dirname, './sfx/sfx-core.js'));
  })
  .then(function(sfxcore) {
    outputs.unshift("('" + moduleName + "', function(System) {\n");
    outputs.unshift(sfxcore.toString());
  })
  .then(function() {
    outputs.push("});");
  })
  .then(function() {
    return builder.writeOutput(opts, outputs, loader.baseURL);
  });
};

function executeConfigFile(loader, source) {
  var curSystem = global.System;
  global.System = {
    config: function(cfg) {
      loader.config(cfg);
      loader.pluginLoader.config(cfg);
    }
  };
  // jshint evil:true
  new Function(source.toString()).call(global);
  global.System = curSystem;
}

var resolvePath = path.resolve.bind(path, process.cwd());

Builder.prototype.loadConfig = function(configFile) {
  var self = this;
  return asp(fs.readFile)(resolvePath(configFile))
    .then(executeConfigFile.bind(null, this.loader))
    .then(function() { return self; });
};

Builder.prototype.loadConfigSync = function(configFile) {
  var source = fs.readFileSync(resolvePath(configFile));
  executeConfigFile(this.loader, source);
};

Builder.prototype.config = function(config) {
  var loader = this.loader;
  var pluginLoader = loader.pluginLoader;

  var cfg = {};
  for (var p in config) {
    if (p != 'bundles')
      cfg[p] = config[p];
  }
  loader.config(cfg);
  pluginLoader.config(cfg);
};

// returns a new tree containing tree1 n tree2
Builder.prototype.intersectTrees = function(tree1, tree2) {
  var name;
  var intersectTree = {};

  var tree1Names = [];
  for (name in tree1)
    tree1Names.push(name);

  for (name in tree2) {
    if (tree1Names.indexOf(name) == -1)
      continue;

    intersectTree[name] = tree1[name];
  }

  return intersectTree;
};

// returns a new tree containing tree1 + tree2
Builder.prototype.addTrees = function(tree1, tree2) {
  var name;
  var unionTree = {};

  for (name in tree2)
    unionTree[name] = tree2[name];

  for (name in tree1)
    unionTree[name] = tree1[name];

  return unionTree;
};

// returns a new tree containing tree1 - tree2
Builder.prototype.subtractTrees = function(tree1, tree2) {
  var name;
  var subtractTree = {};

  for (name in tree1)
    subtractTree[name] = tree1[name];

  for (name in tree2)
    delete subtractTree[name];

  return subtractTree;
};

// copies a subtree out of the tree
Builder.prototype.extractTree = function(tree, moduleName) {
  var outTree = {};
  return visitTree(tree, moduleName, null, function(load) {
    outTree[load.name] = load;
  })
  .then(function() {
    return outTree;
  });
};

Builder.prototype.trace = function(moduleName, config, includePlugins) {
  var loader = this.loader;
  var pluginLoader = loader.pluginLoader;

  if (config) {
    this.config(config);
  }

  var System = loader.global.System;
  loader.global.System = loader;

  var traceTree = {};

  return loader.import(moduleName)
  .then(function() {
    return loader.normalize(moduleName);
  })
  .then(function(_moduleName) {
    moduleName = _moduleName;
    loader.global.System = System;
    return visitTree(loader.loads, moduleName, includePlugins && pluginLoader, function(load) {
      traceTree[load.name] = load;
    });
  })
  .then(function() {
    return {
      moduleName: moduleName,
      tree: traceTree
    };
  })
  .catch(function(e) {
    loader.global.System = System;
    throw e;
  });
};

function visitTree(tree, moduleName, pluginLoader, visit, seen) {
  seen = seen || [];

  if (seen.indexOf(moduleName) != -1)
    return;

  seen.push(moduleName);

  var load = tree[moduleName];

  if (!load)
    return Promise.resolve();

  // visit the deps first
  return Promise.all(load.deps.map(function(dep) {
    return visitTree(tree, load.depMap[dep], pluginLoader, visit, seen);
  })).then(function() {
    if (!pluginLoader)
      return;

    var pluginName = load.metadata.pluginName;
    if (pluginName) {
      return visitTree(pluginLoader.loads, pluginName, pluginLoader, visit, seen);
    }
  })
  .then(function() {
    // if we are the bottom of the tree, visit
    return visit(load);
  });
}

Builder.legacy = new Builder();

module.exports = Builder;
<commit_msg>Defensive copying of config objects passed to pubic API<commit_after>var Promise = require('rsvp').Promise;

var System = require('systemjs');
var fs = require('fs');

var asp = require('rsvp').denodeify;

var es6Compiler = require('./compilers/es6');
var registerCompiler = require('./compilers/register');
var amdCompiler = require('./compilers/amd');
var cjsCompiler = require('./compilers/cjs');
var globalCompiler = require('./compilers/global');
var builder = require('./lib/builder');

var path = require('path');

/* Very basic, null-friendly, shallow clone for object attributes only */
function clone(obj) {
  obj = obj || {};
  var copy = {};
  for (var key in obj) {
    copy[key] = obj[key];
  }
  return copy;
}

function Builder(cfg) {
  this.System = System;
  this.loader = null;
  this.reset();
  if (typeof cfg == "string")
    this.loadConfigSync(cfg);
  else if (typeof cfg == "object")
    this.config(cfg);
}

Builder.prototype.reset = function() {
  var loader = this.loader = new Loader(System);
  loader.baseURL = System.baseURL;
  loader.paths = { '*': '*.js' };
  loader.config = System.config;

  var pluginLoader = new Loader(System);
  pluginLoader.baseURL = System.baseURL;
  pluginLoader.paths = { '*': '*.js' };
  pluginLoader.config = System.config;
  pluginLoader.trace = true;
  pluginLoader.import = loader.import = System.import;

  pluginLoader._nodeRequire = loader._nodeRequire = require;

  loader.trace = true;
  loader.execute = false;
  loader.pluginLoader = pluginLoader;

  loader.set('@empty', loader.newModule({}));
  pluginLoader.set('@empty', loader.newModule({}));

  amdCompiler.attach(loader);
  amdCompiler.attach(pluginLoader);
};

Builder.prototype.build = function(moduleName, outFile, opts) {
  var self = this;
  opts = opts || {};

  return this.trace(moduleName, opts.config)
  .then(function(trace) {
    return self.buildTree(trace.tree, outFile, opts);
  });
};

var compilerMap = {
  'amd':      amdCompiler,
  'cjs':      cjsCompiler,
  'es6':      es6Compiler,
  'global':   globalCompiler,
  'register': registerCompiler
};

function compileLoad(loader, load, opts, compilers) {
  return Promise.resolve()
  .then(function() {
    // note which compilers we used
    compilers = compilers || {};
    var format = load.metadata.format;
    if (load.metadata.build === false) {
      return {};
    }
    else if (format in compilerMap) {
      compilers[format] = true;
      return compilerMap[format].compile(load, opts, loader);
    }
    else if (format == 'defined') {
      return {source: ''};
    }
    else {
      throw "unknown format " + format;
    }
  });
}

function buildOutputs(loader, tree, opts, sfxCompilers) {
  var names = Object.keys(tree);
  // store plugins with a bundle hook to allow post-processing
  var plugins = {};
  var outputs = [];

  return Promise.all(names.map(function(name) {
    var load = tree[name];

    if (sfxCompilers && load.metadata.plugin && (load.metadata.build === false || load.metadata.plugin.build === false))
      outputs.push('System.register("' + load.name + '", [], false, function() { console.log("SystemJS Builder - Plugin for ' + load.name + ' does not support sfx builds"); });\n');

    // support plugin "bundle" reduction hook
    var plugin = load.metadata.plugin;
    if (plugin && load.metadata.build !== false) {
      var entry = plugins[load.metadata.pluginName] = plugins[load.metadata.pluginName] || {
        loads: [],
        bundle: plugin.bundle
      };
      entry.loads.push(load);
    }

    return Promise.resolve(compileLoad(loader, load, opts, sfxCompilers))
    .then(outputs.push.bind(outputs));
  }))
  .then(function() {
    // apply plugin "bundle" hook
    return Promise.all(Object.keys(plugins).map(function(pluginName) {
      var entry = plugins[pluginName];
      if (entry.bundle)
      return Promise.resolve(entry.bundle.call(loader.pluginLoader, entry.loads, opts))
      .then(outputs.push.bind(outputs));
    }));
  })
  .then(function() {
    return outputs;
  });
}

Builder.prototype.buildTree = function(tree, outFile, opts) {
  var loader = this.loader;

  opts = clone(opts);
  opts.outFile = outFile;

  return buildOutputs(loader, tree, opts, false)
  .then(function(outputs) {
    outputs.unshift('"format register";\n');
    return builder.writeOutput(opts, outputs, loader.baseURL);
  });
};

Builder.prototype.buildSFX = function(moduleName, outFile, opts) {
  var loader = this.loader;

  opts = clone(opts);
  opts.outFile = outFile;

  var config = opts.config;

  var outputs;

  var compilers = {};
  opts.normalize = true;
  return this.trace(moduleName, config)
  .then(function(trace) {
    moduleName = trace.moduleName;
    return buildOutputs(loader, trace.tree, opts, compilers);
  })
  .then(function(_outputs) {
    outputs = _outputs;
  })
  // next add sfx headers for formats at the beginning
  .then(function() {
    Object.keys(compilers).forEach(function(format) {
      compiler = compilerMap[format];
      if (compiler.sfx)  {
        var sfx = compiler.sfx(loader);
        if (sfx) outputs.push(sfx);
      }
    });
  })
  // next wrap with the core code
  .then(function() {
    return asp(fs.readFile)(path.resolve(__dirname, './sfx/sfx-core.js'));
  })
  .then(function(sfxcore) {
    outputs.unshift("('" + moduleName + "', function(System) {\n");
    outputs.unshift(sfxcore.toString());
  })
  .then(function() {
    outputs.push("});");
  })
  .then(function() {
    return builder.writeOutput(opts, outputs, loader.baseURL);
  });
};

function executeConfigFile(loader, source) {
  var curSystem = global.System;
  global.System = {
    config: function(cfg) {
      loader.config(cfg);
      loader.pluginLoader.config(cfg);
    }
  };
  // jshint evil:true
  new Function(source.toString()).call(global);
  global.System = curSystem;
}

var resolvePath = path.resolve.bind(path, process.cwd());

Builder.prototype.loadConfig = function(configFile) {
  var self = this;
  return asp(fs.readFile)(resolvePath(configFile))
    .then(executeConfigFile.bind(null, this.loader))
    .then(function() { return self; });
};

Builder.prototype.loadConfigSync = function(configFile) {
  var source = fs.readFileSync(resolvePath(configFile));
  executeConfigFile(this.loader, source);
};

Builder.prototype.config = function(config) {
  var loader = this.loader;
  var pluginLoader = loader.pluginLoader;

  var cfg = {};
  for (var p in config) {
    if (p != 'bundles')
      cfg[p] = config[p];
  }
  loader.config(cfg);
  pluginLoader.config(cfg);
};

// returns a new tree containing tree1 n tree2
Builder.prototype.intersectTrees = function(tree1, tree2) {
  var name;
  var intersectTree = {};

  var tree1Names = [];
  for (name in tree1)
    tree1Names.push(name);

  for (name in tree2) {
    if (tree1Names.indexOf(name) == -1)
      continue;

    intersectTree[name] = tree1[name];
  }

  return intersectTree;
};

// returns a new tree containing tree1 + tree2
Builder.prototype.addTrees = function(tree1, tree2) {
  var name;
  var unionTree = {};

  for (name in tree2)
    unionTree[name] = tree2[name];

  for (name in tree1)
    unionTree[name] = tree1[name];

  return unionTree;
};

// returns a new tree containing tree1 - tree2
Builder.prototype.subtractTrees = function(tree1, tree2) {
  var name;
  var subtractTree = {};

  for (name in tree1)
    subtractTree[name] = tree1[name];

  for (name in tree2)
    delete subtractTree[name];

  return subtractTree;
};

// copies a subtree out of the tree
Builder.prototype.extractTree = function(tree, moduleName) {
  var outTree = {};
  return visitTree(tree, moduleName, null, function(load) {
    outTree[load.name] = load;
  })
  .then(function() {
    return outTree;
  });
};

Builder.prototype.trace = function(moduleName, config, includePlugins) {
  var loader = this.loader;
  var pluginLoader = loader.pluginLoader;

  if (config) {
    this.config(config);
  }

  var System = loader.global.System;
  loader.global.System = loader;

  var traceTree = {};

  return loader.import(moduleName)
  .then(function() {
    return loader.normalize(moduleName);
  })
  .then(function(_moduleName) {
    moduleName = _moduleName;
    loader.global.System = System;
    return visitTree(loader.loads, moduleName, includePlugins && pluginLoader, function(load) {
      traceTree[load.name] = load;
    });
  })
  .then(function() {
    return {
      moduleName: moduleName,
      tree: traceTree
    };
  })
  .catch(function(e) {
    loader.global.System = System;
    throw e;
  });
};

function visitTree(tree, moduleName, pluginLoader, visit, seen) {
  seen = seen || [];

  if (seen.indexOf(moduleName) != -1)
    return;

  seen.push(moduleName);

  var load = tree[moduleName];

  if (!load)
    return Promise.resolve();

  // visit the deps first
  return Promise.all(load.deps.map(function(dep) {
    return visitTree(tree, load.depMap[dep], pluginLoader, visit, seen);
  })).then(function() {
    if (!pluginLoader)
      return;

    var pluginName = load.metadata.pluginName;
    if (pluginName) {
      return visitTree(pluginLoader.loads, pluginName, pluginLoader, visit, seen);
    }
  })
  .then(function() {
    // if we are the bottom of the tree, visit
    return visit(load);
  });
}

Builder.legacy = new Builder();

module.exports = Builder;

{'fraction_non_alphanumeric': 0.14867429376999403, 'fraction_numerical': 0.0033617090495038767, 'mean_word_length': 3.4647785039941903, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4162331', 'n_tokens_mistral': 5908, 'n_tokens_neox': 5822, 'n_words': 1330}