├── .gitattributes ├── .gitignore ├── lib ├── source-map.js ├── ModuleError.js ├── ModuleWarning.js ├── Source.js ├── SourceAndMapMixin.js ├── RawSource.js ├── ModuleBuildError.js ├── LineToLineMappedSource.js ├── ConcatSource.js ├── OptionsDefaulter.js ├── CachedSource.js ├── SourceMapSource.js ├── PrefixSource.js ├── OriginalSource.js ├── LoadersList.js ├── ReplaceSource.js └── NormalModuleMixin.js ├── .editorconfig ├── README.md └── package.json /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | -------------------------------------------------------------------------------- /lib/source-map.js: -------------------------------------------------------------------------------- 1 | /* 2 | MIT License http://www.opensource.org/licenses/mit-license.php 3 | Author Tobias Koppers @sokra 4 | */ 5 | module.exports = require("source-map"); -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # This file is for unifying the coding style for different editors and IDEs 2 | # editorconfig.org 3 | 4 | root = true 5 | 6 | [*] 7 | indent_style = tab 8 | end_of_line = lf 9 | charset = utf-8 10 | trim_trailing_whitespace = true 11 | insert_final_newline = true 12 | 13 | [package.json] 14 | indent_style = space 15 | indent_size = 2 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # webpack-core 2 | 3 | The shared core of [webpack](https://github.com/webpack/webpack) and [enhanced-require](https://github.com/webpack/enhanced-require). 4 | 5 | It mainly encapsulate 6 | 7 | * the loader stuff 8 | * SourceMap stuff 9 | 10 | Not useable as standalone module, but this may change in the future. 11 | 12 | # License 13 | 14 | Copyright (c) 2012 - 2013 Tobias Koppers 15 | 16 | MIT (http://www.opensource.org/licenses/mit-license.php) -------------------------------------------------------------------------------- /lib/ModuleError.js: -------------------------------------------------------------------------------- 1 | /* 2 | MIT License http://www.opensource.org/licenses/mit-license.php 3 | Author Tobias Koppers @sokra 4 | */ 5 | function ModuleError(module, err) { 6 | Error.call(this); 7 | Error.captureStackTrace(this, ModuleError); 8 | this.name = "ModuleError"; 9 | this.module = module; 10 | this.message = err; 11 | this.error = err; 12 | } 13 | module.exports = ModuleError; 14 | 15 | ModuleError.prototype = Object.create(Error.prototype); 16 | -------------------------------------------------------------------------------- /lib/ModuleWarning.js: -------------------------------------------------------------------------------- 1 | /* 2 | MIT License http://www.opensource.org/licenses/mit-license.php 3 | Author Tobias Koppers @sokra 4 | */ 5 | function ModuleWarning(module, warning) { 6 | Error.call(this); 7 | Error.captureStackTrace(this, ModuleWarning); 8 | this.name = "ModuleWarning"; 9 | this.module = module; 10 | this.message = warning; 11 | this.warning = warning; 12 | } 13 | module.exports = ModuleWarning; 14 | 15 | ModuleWarning.prototype = Object.create(Error.prototype); 16 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "webpack-core", 3 | "version": "0.6.9", 4 | "author": "Tobias Koppers @sokra", 5 | "description": "The core of webpack and enhanced-require.", 6 | "dependencies": { 7 | "source-map": "~0.4.1", 8 | "source-list-map": "~0.1.7" 9 | }, 10 | "licenses": [ 11 | { 12 | "type": "MIT", 13 | "url": "http://www.opensource.org/licenses/mit-license.php" 14 | } 15 | ], 16 | "devDependencies": { 17 | "mocha": "1.3.x", 18 | "should": "1.1.x" 19 | }, 20 | "engines": { 21 | "node": ">=0.6" 22 | }, 23 | "homepage": "http://github.com/webpack/core", 24 | "repository": { 25 | "type": "git", 26 | "url": "https://github.com/webpack/core.git" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /lib/Source.js: -------------------------------------------------------------------------------- 1 | /* 2 | MIT License http://www.opensource.org/licenses/mit-license.php 3 | Author Tobias Koppers @sokra 4 | */ 5 | var SourceNode = require("source-map").SourceNode; 6 | var SourceMapConsumer = require("source-map").SourceMapConsumer; 7 | 8 | function Source() {} 9 | 10 | module.exports = Source; 11 | 12 | Source.prototype.source = null; 13 | 14 | Source.prototype.size = function() { 15 | return this.source().length; 16 | }; 17 | 18 | Source.prototype.map = function(options) { 19 | return null; 20 | }; 21 | 22 | Source.prototype.sourceAndMap = function(options) { 23 | return { 24 | source: this.source(), 25 | map: this.map() 26 | }; 27 | }; 28 | 29 | Source.prototype.node = null; 30 | 31 | Source.prototype.listNode = null; 32 | 33 | Source.prototype.updateHash = function(hash) { 34 | var source = this.source(); 35 | hash.update(source || ""); 36 | }; 37 | -------------------------------------------------------------------------------- /lib/SourceAndMapMixin.js: -------------------------------------------------------------------------------- 1 | /* 2 | MIT License http://www.opensource.org/licenses/mit-license.php 3 | Author Tobias Koppers @sokra 4 | */ 5 | module.exports = function mixinSourceAndMap(proto) { 6 | proto.map = function(options) { 7 | options = options || {}; 8 | if(options.columns === false) { 9 | return this.listMap(options).toStringWithSourceMap().map; 10 | } 11 | 12 | return this.node(options).toStringWithSourceMap({file:"x"}).map.toJSON(); 13 | }; 14 | 15 | proto.sourceAndMap = function(options) { 16 | options = options || {}; 17 | if(options.columns === false) { 18 | //console.log(this.listMap(options).debugInfo()); 19 | return this.listMap(options).toStringWithSourceMap(); 20 | } 21 | 22 | var res = this.node(options).toStringWithSourceMap({file:"x"}); 23 | return { 24 | source: res.code, 25 | map: res.map.toJSON() 26 | }; 27 | }; 28 | } 29 | -------------------------------------------------------------------------------- /lib/RawSource.js: -------------------------------------------------------------------------------- 1 | /* 2 | MIT License http://www.opensource.org/licenses/mit-license.php 3 | Author Tobias Koppers @sokra 4 | */ 5 | var Source = require("./Source"); 6 | var SourceNode = require("source-map").SourceNode; 7 | var SourceListMap = require("source-list-map").SourceListMap; 8 | 9 | function RawSource(value) { 10 | Source.call(this); 11 | this._value = value; 12 | } 13 | module.exports = RawSource; 14 | 15 | RawSource.prototype = Object.create(Source.prototype); 16 | RawSource.prototype.constructor = RawSource; 17 | 18 | RawSource.prototype.source = function() { 19 | return this._value; 20 | }; 21 | 22 | RawSource.prototype.map = function(options) { 23 | return null; 24 | }; 25 | 26 | RawSource.prototype.node = function(options) { 27 | return new SourceNode(null, null, null, this._value); 28 | }; 29 | 30 | RawSource.prototype.listMap = function(options) { 31 | return new SourceListMap(this._value); 32 | }; 33 | 34 | RawSource.prototype.updateHash = function(hash) { 35 | hash.update(this._value); 36 | }; 37 | -------------------------------------------------------------------------------- /lib/ModuleBuildError.js: -------------------------------------------------------------------------------- 1 | /* 2 | MIT License http://www.opensource.org/licenses/mit-license.php 3 | Author Tobias Koppers @sokra 4 | */ 5 | var loaderFlag = "WEBPACK_CORE_LOADER_EXECUTION"; 6 | function ModuleBuildError(module, err) { 7 | Error.call(this); 8 | Error.captureStackTrace(this, ModuleBuildError); 9 | this.name = "ModuleBuildError"; 10 | this.message = "Module build failed: "; 11 | if(err !== null && typeof err === "object") { 12 | if(typeof err.stack === "string" && err.stack) { 13 | var stack = err.stack.split("\n"); 14 | for(var i = 0; i < stack.length; i++) 15 | if(stack[i].indexOf(loaderFlag) >= 0) 16 | stack.length = i; 17 | stack = stack.join("\n"); 18 | if(!err.hideStack) { 19 | this.message += stack; 20 | } else { 21 | this.details = stack; 22 | if(typeof err.message === "string" && err.message) { 23 | this.message += err.message; 24 | } else { 25 | this.message += err; 26 | } 27 | } 28 | } else if(typeof err.message === "string" && err.message) { 29 | this.message += err.message; 30 | } else { 31 | this.message += err; 32 | } 33 | } 34 | this.module = module; 35 | this.error = err; 36 | } 37 | module.exports = ModuleBuildError; 38 | 39 | ModuleBuildError.prototype = Object.create(Error.prototype); 40 | -------------------------------------------------------------------------------- /lib/LineToLineMappedSource.js: -------------------------------------------------------------------------------- 1 | /* 2 | MIT License http://www.opensource.org/licenses/mit-license.php 3 | Author Tobias Koppers @sokra 4 | */ 5 | var SourceNode = require("source-map").SourceNode; 6 | var SourceListMap = require("source-list-map").SourceListMap; 7 | var Source = require("./Source"); 8 | 9 | function LineToLineMappedSource(value, name, originalSource) { 10 | Source.call(this); 11 | this._value = value; 12 | this._name = name; 13 | this._originalSource = originalSource; 14 | } 15 | 16 | module.exports = LineToLineMappedSource; 17 | 18 | LineToLineMappedSource.prototype = Object.create(Source.prototype); 19 | LineToLineMappedSource.prototype.constructor = LineToLineMappedSource; 20 | 21 | LineToLineMappedSource.prototype.source = function() { 22 | return this._value; 23 | }; 24 | 25 | require("./SourceAndMapMixin")(LineToLineMappedSource.prototype); 26 | 27 | LineToLineMappedSource.prototype.node = function(options) { 28 | var value = this._value; 29 | var name = this._name; 30 | var lines = value.split("\n"); 31 | var node = new SourceNode(null, null, null, 32 | lines.map(function(line, idx) { 33 | return new SourceNode(idx+1, 0, name, 34 | (line + (idx != lines.length-1 ? "\n" : "")) 35 | ); 36 | }) 37 | ); 38 | node.setSourceContent(name, this._originalSource); 39 | return node; 40 | }; 41 | 42 | LineToLineMappedSource.prototype.listMap = function(options) { 43 | return new SourceListMap(this._value, this._name, this._originalSource) 44 | }; 45 | 46 | LineToLineMappedSource.prototype.updateHash = function(hash) { 47 | hash.update(this._value); 48 | hash.update(this._originalSource); 49 | }; 50 | -------------------------------------------------------------------------------- /lib/ConcatSource.js: -------------------------------------------------------------------------------- 1 | /* 2 | MIT License http://www.opensource.org/licenses/mit-license.php 3 | Author Tobias Koppers @sokra 4 | */ 5 | var SourceNode = require("source-map").SourceNode; 6 | var SourceListMap = require("source-list-map").SourceListMap; 7 | var Source = require("./Source"); 8 | 9 | function ConcatSource() { 10 | Source.call(this); 11 | this.children = Array.prototype.slice.call(arguments); 12 | } 13 | module.exports = ConcatSource; 14 | 15 | ConcatSource.prototype = Object.create(Source.prototype); 16 | ConcatSource.prototype.constructor = ConcatSource; 17 | 18 | ConcatSource.prototype.add = function(item) { 19 | this.children.push(item); 20 | }; 21 | 22 | ConcatSource.prototype.source = function() { 23 | return this.children.map(function(item) { 24 | return typeof item === "string" ? item : item.source(); 25 | }).join(""); 26 | }; 27 | 28 | ConcatSource.prototype.size = function() { 29 | return this.children.map(function(item) { 30 | return typeof item === "string" ? item.length : item.size(); 31 | }).reduce(function(sum, s) { return sum + s; }, 0); 32 | }; 33 | 34 | require("./SourceAndMapMixin")(ConcatSource.prototype); 35 | 36 | ConcatSource.prototype.node = function(options) { 37 | var node = new SourceNode(null, null, null, this.children.map(function(item) { 38 | return typeof item === "string" ? item : item.node(options); 39 | })); 40 | return node; 41 | }; 42 | 43 | ConcatSource.prototype.listMap = function(options) { 44 | var map = new SourceListMap(); 45 | this.children.forEach(function(item) { 46 | if(typeof item === "string") 47 | map.add(item); 48 | else 49 | map.add(item.listMap(options)); 50 | }); 51 | return map; 52 | }; 53 | 54 | ConcatSource.prototype.updateHash = function(hash) { 55 | this.children.forEach(function(item) { 56 | if (typeof item === "string") { 57 | hash.update(item) 58 | } else { 59 | item.updateHash(hash); 60 | } 61 | }); 62 | }; 63 | -------------------------------------------------------------------------------- /lib/OptionsDefaulter.js: -------------------------------------------------------------------------------- 1 | /* 2 | MIT License http://www.opensource.org/licenses/mit-license.php 3 | Author Tobias Koppers @sokra 4 | */ 5 | function OptionsDefaulter() { 6 | this.defaults = {}; 7 | this.config = {}; 8 | } 9 | module.exports = OptionsDefaulter; 10 | 11 | function getProperty(obj, name) { 12 | name = name.split("."); 13 | for(var i = 0; i < name.length - 1; i++) { 14 | obj = obj[name[i]]; 15 | if(typeof obj != "object" || !obj) return; 16 | } 17 | return obj[name.pop()]; 18 | } 19 | 20 | function setProperty(obj, name, value) { 21 | name = name.split("."); 22 | for(var i = 0; i < name.length - 1; i++) { 23 | if(typeof (obj[name[i]]) !== "object" || !obj[name[i]]) obj[name[i]] = {}; 24 | obj = obj[name[i]]; 25 | } 26 | obj[name.pop()] = value; 27 | } 28 | 29 | function hasProperty(obj, name, value) { 30 | name = name.split("."); 31 | for(var i = 0; i < name.length - 1; i++) { 32 | obj = obj[name[i]]; 33 | if(typeof obj != "object" || !obj) return false; 34 | } 35 | return Object.prototype.hasOwnProperty.call(obj, name.pop()); 36 | } 37 | 38 | OptionsDefaulter.prototype.process = function(options) { 39 | for(var name in this.defaults) { 40 | switch(this.config[name]) { 41 | case undefined: 42 | if(getProperty(options, name) === undefined) 43 | setProperty(options, name, this.defaults[name]); 44 | break; 45 | case "call": 46 | setProperty(options, name, this.defaults[name].call(this, getProperty(options, name)), options); 47 | break; 48 | case "append": 49 | var oldValue = getProperty(options, name); 50 | if(!Array.isArray(oldValue)) oldValue = []; 51 | this.defaults[name].forEach(function(item) { 52 | oldValue.push(item); 53 | }); 54 | setProperty(options, name, oldValue); 55 | break; 56 | default: 57 | throw new Error("OptionsDefaulter cannot process " + this.config[name]); 58 | } 59 | } 60 | }; 61 | 62 | OptionsDefaulter.prototype.set = function(name, config, def) { 63 | if(arguments.length === 3) { 64 | this.defaults[name] = def; 65 | this.config[name] = config; 66 | } else { 67 | this.defaults[name] = config; 68 | delete this.config[name]; 69 | } 70 | } -------------------------------------------------------------------------------- /lib/CachedSource.js: -------------------------------------------------------------------------------- 1 | /* 2 | MIT License http://www.opensource.org/licenses/mit-license.php 3 | Author Tobias Koppers @sokra 4 | */ 5 | function CachedSource(source) { 6 | this._source = source; 7 | this._cachedSource = undefined; 8 | this._cachedSize = undefined; 9 | this._cachedMaps = {}; 10 | } 11 | module.exports = CachedSource; 12 | 13 | CachedSource.prototype.source = function() { 14 | if(typeof this._cachedSource !== "undefined") return this._cachedSource; 15 | return this._cachedSource = this._source.source(); 16 | }; 17 | 18 | CachedSource.prototype.size = function() { 19 | if(typeof this._cachedSize !== "undefined") return this._cachedSize; 20 | if(typeof this._cachedSource !== "undefined") 21 | return this._cachedSize = this._cachedSource.length; 22 | return this._cachedSize = this._source.size(); 23 | }; 24 | 25 | CachedSource.prototype.sourceAndMap = function(options) { 26 | var key = JSON.stringify(options); 27 | if(typeof this._cachedSource !== "undefined" && key in this._cachedMaps) 28 | return { source: this._cachedSource, map: this._cachedMaps[key] }; 29 | else if(typeof this._cachedSource !== "undefined") { 30 | return { source: this._cachedSource, map: this._cachedMaps[key] = this._source.map(options) }; 31 | } else if(key in this._cachedMaps) { 32 | return { source: this._cachedSource = this._source.source(), map: this._cachedMaps[key] }; 33 | } 34 | var result = this._source.sourceAndMap(options); 35 | this._cachedSource = result.source; 36 | this._cachedMaps[key] = result.map; 37 | return { source: this._cachedSource, map: this._cachedMaps[key] }; 38 | }; 39 | 40 | CachedSource.prototype.node = function(options) { 41 | return this._source.node(options); 42 | }; 43 | 44 | CachedSource.prototype.listMap = function(options) { 45 | return this._source.listMap(options); 46 | } 47 | 48 | CachedSource.prototype.map = function(options) { 49 | if(!options) options = {}; 50 | var key = JSON.stringify(options); 51 | if(key in this._cachedMaps) 52 | return this._cachedMaps[key]; 53 | return this._cachedMaps[key] = this._source.map(); 54 | }; 55 | 56 | CachedSource.prototype.updateHash = function(hash) { 57 | this._source.updateHash(hash); 58 | }; 59 | -------------------------------------------------------------------------------- /lib/SourceMapSource.js: -------------------------------------------------------------------------------- 1 | /* 2 | MIT License http://www.opensource.org/licenses/mit-license.php 3 | Author Tobias Koppers @sokra 4 | */ 5 | var SourceNode = require("source-map").SourceNode; 6 | var SourceMapConsumer = require("source-map").SourceMapConsumer; 7 | var SourceMapGenerator = require("source-map").SourceMapGenerator; 8 | var SourceListMap = require("source-list-map").SourceListMap; 9 | var fromStringWithSourceMap = require("source-list-map").fromStringWithSourceMap; 10 | var Source = require("./Source"); 11 | 12 | function SourceMapSource(value, name, sourceMap, originalSource, innerSourceMap) { 13 | Source.call(this); 14 | this._value = value; 15 | this._name = name; 16 | this._sourceMap = sourceMap; 17 | this._originalSource = originalSource; 18 | this._innerSourceMap = innerSourceMap; 19 | } 20 | module.exports = SourceMapSource; 21 | 22 | SourceMapSource.prototype = Object.create(Source.prototype); 23 | SourceMapSource.prototype.constructor = SourceMapSource; 24 | 25 | SourceMapSource.prototype.source = function() { 26 | return this._value; 27 | }; 28 | 29 | require("./SourceAndMapMixin")(SourceMapSource.prototype); 30 | 31 | SourceMapSource.prototype.node = function(options) { 32 | var innerSourceMap = this._innerSourceMap; 33 | var sourceMap = this._sourceMap; 34 | if(innerSourceMap) { 35 | innerSourceMap = new SourceMapConsumer(innerSourceMap); 36 | sourceMap = SourceMapGenerator.fromSourceMap(new SourceMapConsumer(sourceMap)); 37 | sourceMap.setSourceContent(this._name, this._originalSource); 38 | sourceMap.applySourceMap(innerSourceMap, this._name); 39 | sourceMap = sourceMap.toJSON(); 40 | } 41 | return SourceNode.fromStringWithSourceMap(this._value, new SourceMapConsumer(sourceMap)); 42 | }; 43 | 44 | SourceMapSource.prototype.listMap = function(options) { 45 | if(options.module === false) 46 | return new SourceListMap(this._value, this._name, this._value); 47 | return fromStringWithSourceMap(this._value, typeof this._sourceMap === "string" ? JSON.parse(this._sourceMap) : this._sourceMap); 48 | }; 49 | 50 | SourceMapSource.prototype.updateHash = function(hash) { 51 | hash.update(this._value); 52 | if(this._originalSource) 53 | hash.update(this._originalSource); 54 | }; 55 | -------------------------------------------------------------------------------- /lib/PrefixSource.js: -------------------------------------------------------------------------------- 1 | /* 2 | MIT License http://www.opensource.org/licenses/mit-license.php 3 | Author Tobias Koppers @sokra 4 | */ 5 | var Source = require("./Source"); 6 | var SourceNode = require("source-map").SourceNode; 7 | 8 | function PrefixSource(prefix, source) { 9 | Source.call(this); 10 | this._source = source; 11 | this._prefix = prefix; 12 | } 13 | module.exports = PrefixSource; 14 | 15 | PrefixSource.prototype = Object.create(Source.prototype); 16 | PrefixSource.prototype.constructor = PrefixSource; 17 | 18 | PrefixSource.prototype.source = function() { 19 | var node = typeof this._source === "string" ? this._source : this._source.source(); 20 | var prefix = this._prefix; 21 | return prefix + node.replace(/\n(.)/g, "\n" + prefix + "$1"); 22 | }; 23 | 24 | require("./SourceAndMapMixin")(PrefixSource.prototype); 25 | 26 | PrefixSource.prototype.node = function(options) { 27 | var node = this._source.node(options); 28 | var append = [this._prefix]; 29 | return new SourceNode(null, null, null, [ 30 | cloneAndPrefix(node, this._prefix, append) 31 | ]); 32 | }; 33 | 34 | PrefixSource.prototype.listMap = function(options) { 35 | var prefix = this._prefix; 36 | var map = this._source.listMap(options); 37 | map.mapGeneratedCode(function(code) { 38 | return prefix + code.replace(/\n(.)/g, "\n" + prefix + "$1"); 39 | }); 40 | return map; 41 | }; 42 | 43 | PrefixSource.prototype.updateHash = function(hash) { 44 | if(typeof this._source === "string") 45 | hash.update(this._source); 46 | else 47 | this._source.updateHash(hash); 48 | if(typeof this._prefix === "string") 49 | hash.update(this._prefix); 50 | else 51 | this._prefix.updateHash(hash); 52 | }; 53 | 54 | function cloneAndPrefix(node, prefix, append) { 55 | if(typeof node === "string") { 56 | var result = node.replace(/\n(.)/g, "\n" + prefix + "$1"); 57 | if(append.length > 0) result = append.pop() + result; 58 | if(/\n$/.test(node)) append.push(prefix); 59 | return result; 60 | } else { 61 | var newNode = new SourceNode( 62 | node.line, 63 | node.column, 64 | node.source, 65 | node.children.map(function(node) { 66 | return cloneAndPrefix(node, prefix, append); 67 | }), 68 | node.name 69 | ); 70 | newNode.sourceContents = node.sourceContents; 71 | return newNode; 72 | } 73 | }; 74 | -------------------------------------------------------------------------------- /lib/OriginalSource.js: -------------------------------------------------------------------------------- 1 | /* 2 | MIT License http://www.opensource.org/licenses/mit-license.php 3 | Author Tobias Koppers @sokra 4 | */ 5 | var SourceNode = require("source-map").SourceNode; 6 | var SourceMapConsumer = require("source-map").SourceMapConsumer; 7 | var SourceListMap = require("source-list-map").SourceListMap; 8 | var Source = require("./Source"); 9 | 10 | function isSplitter(c) { 11 | switch(c) { 12 | case 10: // \n 13 | case 13: // \r 14 | case 59: // ; 15 | case 123: // { 16 | case 125: // } 17 | return true; 18 | } 19 | return false; 20 | } 21 | function _splitCode(code) { 22 | var result = []; 23 | var i = 0, j = 0; 24 | for(; i < code.length; i++) { 25 | if(isSplitter(code.charCodeAt(i))) { 26 | while(isSplitter(code.charCodeAt(++i))); 27 | result.push(code.substring(j, i)); 28 | j = i; 29 | } 30 | } 31 | if(j < code.length) 32 | result.push(code.substr(j)); 33 | return result; 34 | } 35 | 36 | function OriginalSource(value, name) { 37 | Source.call(this); 38 | this._value = value; 39 | this._name = name; 40 | } 41 | 42 | module.exports = OriginalSource; 43 | 44 | OriginalSource.prototype = Object.create(Source.prototype); 45 | OriginalSource.prototype.constructor = OriginalSource; 46 | 47 | OriginalSource.prototype.source = function() { 48 | return this._value; 49 | }; 50 | 51 | require("./SourceAndMapMixin")(OriginalSource.prototype); 52 | 53 | OriginalSource.prototype.node = function(options) { 54 | options = options || {}; 55 | var sourceMap = this._sourceMap; 56 | var value = this._value; 57 | var name = this._name; 58 | var lines = value.split("\n"); 59 | var node = new SourceNode(null, null, null, 60 | lines.map(function(line, idx) { 61 | var pos = 0; 62 | if(options.columns === false) { 63 | return new SourceNode(idx+1, 0, name, 64 | (line + (idx != lines.length-1 ? "\n" : "")) 65 | ); 66 | } 67 | return new SourceNode(null, null, null, 68 | _splitCode(line + (idx != lines.length-1 ? "\n" : "")).map(function(item) { 69 | if(/^\s*$/.test(item)) return item; 70 | var res = new SourceNode(idx+1, pos, name, item); 71 | pos += item.length; 72 | return res; 73 | }) 74 | ); 75 | }) 76 | ); 77 | node.setSourceContent(name, value); 78 | return node; 79 | }; 80 | 81 | OriginalSource.prototype.listMap = function(options) { 82 | return new SourceListMap(this._value, this._name, this._value) 83 | }; 84 | 85 | OriginalSource.prototype.updateHash = function(hash) { 86 | hash.update(this._value); 87 | }; 88 | -------------------------------------------------------------------------------- /lib/LoadersList.js: -------------------------------------------------------------------------------- 1 | /* 2 | MIT License http://www.opensource.org/licenses/mit-license.php 3 | Author Tobias Koppers @sokra 4 | */ 5 | function LoadersList(list) { 6 | this.list = list || []; 7 | this.list.forEach(function(element) { 8 | if(element === null || typeof element !== "object") 9 | throw new Error("Each element of the loaders list must be an object or array"); 10 | }); 11 | } 12 | module.exports = LoadersList; 13 | 14 | function regExpAsMatcher(regExp) { 15 | return function(str) { 16 | return regExp.test(str); 17 | } 18 | } 19 | 20 | function asMatcher(test) { 21 | if(typeof test === "string") { 22 | return regExpAsMatcher(new RegExp("^"+test.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"))); 23 | } else if(typeof test === "function") { 24 | return test; 25 | } else if(test instanceof RegExp) { 26 | return regExpAsMatcher(test); 27 | } else if(Array.isArray(test)) { 28 | var matchers = test.map(function(item) { 29 | if(Array.isArray(item)) { 30 | var matchers = item.map(asMatcher); 31 | return function(str) { 32 | return matchers.every(function(matcher) { 33 | return matcher(str); 34 | }); 35 | }; 36 | } else { 37 | return asMatcher(item); 38 | } 39 | }); 40 | return function(str) { 41 | for(var i = 0; i < test.length; i++) { 42 | if(matchers[i](str)) 43 | return true; 44 | } 45 | return false; 46 | }; 47 | } else { 48 | throw new Error(test + " is not a valid test"); 49 | } 50 | } 51 | 52 | function getLoadersFromObject(element) { 53 | if(element.query) { 54 | if(!element.loader || element.loader.indexOf("!") >= 0) throw new Error("Cannot define 'query' and multiple loaders in loaders list"); 55 | if(typeof element.query === "string") return [element.loader + "?" + element.query]; 56 | return [element.loader + "?" + JSON.stringify(element.query)]; 57 | } 58 | if(element.loader) return element.loader.split("!"); 59 | if(element.loaders) return element.loaders; 60 | throw new Error("Element from loaders list should have one of the fields 'loader' or 'loaders'"); 61 | } 62 | 63 | LoadersList.prototype.matchPart = function matchPart(str, test) { 64 | if(!test) return true; 65 | var matcher = asMatcher(test); 66 | return matcher(str); 67 | }; 68 | 69 | LoadersList.prototype.match = function match(str) { 70 | return this.list.map(function(element) { 71 | if(Array.isArray(element)) { 72 | for(var i = 0; i < element.length; i++) { 73 | if(this.matchObject(str, element[i])) 74 | return getLoadersFromObject(element[i]); 75 | } 76 | } else { 77 | if(this.matchObject(str, element)) 78 | return getLoadersFromObject(element); 79 | } 80 | }, this).filter(Boolean).reduce(function(array, r) { 81 | r.forEach(function(r) { 82 | array.push(r); 83 | }); 84 | return array; 85 | }, []) || []; 86 | }; 87 | 88 | LoadersList.prototype.matchObject = function matchObject(str, obj) { 89 | if(obj.test) 90 | if(!this.matchPart(str, obj.test)) return false; 91 | if(obj.include) 92 | if(!this.matchPart(str, obj.include)) return false; 93 | if(obj.exclude) 94 | if(this.matchPart(str, obj.exclude)) return false; 95 | return true; 96 | }; -------------------------------------------------------------------------------- /lib/ReplaceSource.js: -------------------------------------------------------------------------------- 1 | /* 2 | MIT License http://www.opensource.org/licenses/mit-license.php 3 | Author Tobias Koppers @sokra 4 | */ 5 | var Source = require("./Source"); 6 | var SourceNode = require("source-map").SourceNode; 7 | var SourceListMap = require("source-list-map").SourceListMap; 8 | var fromStringWithSourceMap = require("source-list-map").fromStringWithSourceMap; 9 | var SourceMapConsumer = require("source-map").SourceMapConsumer; 10 | 11 | function ReplaceSource(source, name) { 12 | Source.call(this); 13 | this._source = source; 14 | this._name = name; 15 | this.replacements = []; 16 | } 17 | module.exports = ReplaceSource; 18 | 19 | ReplaceSource.prototype = Object.create(Source.prototype); 20 | ReplaceSource.prototype.constructor = ReplaceSource; 21 | 22 | ReplaceSource.prototype.replace = function(start, end, newValue) { 23 | this.replacements.push([start, end, newValue]); 24 | }; 25 | 26 | ReplaceSource.prototype.insert = function(pos, newValue) { 27 | this.replacements.push([pos, pos-1, newValue]); 28 | }; 29 | 30 | ReplaceSource.prototype.source = function(options) { 31 | return this._replaceString(this._source.source()); 32 | }; 33 | 34 | ReplaceSource.prototype._sortReplacements = function() { 35 | this.replacements.forEach(function(item, idx) { 36 | item[3] = idx; 37 | }); 38 | this.replacements.sort(function(a, b) { 39 | var diff = b[1] - a[1]; 40 | if(diff !== 0) 41 | return diff; 42 | return b[3] - a[3]; 43 | }); 44 | 45 | }; 46 | 47 | ReplaceSource.prototype._replaceString = function(str) { 48 | this._sortReplacements(); 49 | var result = [str]; 50 | this.replacements.forEach(function(repl) { 51 | var remSource = result.pop(); 52 | var splitted1 = this._splitString(remSource, Math.floor(repl[1]+1)); 53 | var splitted2 = this._splitString(splitted1[0], Math.floor(repl[0])); 54 | result.push(splitted1[1], repl[2], splitted2[0]); 55 | }, this); 56 | result = result.reverse(); 57 | return result.join(""); 58 | }; 59 | 60 | require("./SourceAndMapMixin")(ReplaceSource.prototype); 61 | 62 | ReplaceSource.prototype.node = function(options) { 63 | this._sortReplacements(); 64 | var result = [this._source.node(options)]; 65 | this.replacements.forEach(function(repl) { 66 | var remSource = result.pop(); 67 | var splitted1 = this._splitSourceNode(remSource, Math.floor(repl[1]+1)); 68 | if(Array.isArray(splitted1)) { 69 | var splitted2 = this._splitSourceNode(splitted1[0], Math.floor(repl[0])); 70 | if(Array.isArray(splitted2)) { 71 | result.push(splitted1[1], this._replacementToSourceNode(splitted2[1], repl[2]), splitted2[0]); 72 | } else { 73 | result.push(splitted1[1], this._replacementToSourceNode(splitted1[1], repl[2]), splitted1[0]); 74 | } 75 | } else { 76 | var splitted2 = this._splitSourceNode(remSource, Math.floor(repl[0])); 77 | if(Array.isArray(splitted2)) { 78 | result.push(this._replacementToSourceNode(splitted2[1], repl[2]), splitted2[0]); 79 | } else { 80 | result.push(repl[2], remSource); 81 | } 82 | } 83 | }, this); 84 | result = result.reverse(); 85 | return new SourceNode(null, null, null, result); 86 | }; 87 | 88 | ReplaceSource.prototype.listMap = function(options) { 89 | var map = this._source.listMap(options); 90 | if(map.children.length !== 1) { 91 | var code = map.toString(); 92 | code = this._replaceString(code).split("\n"); 93 | var currentIndex = 0; 94 | map.mapGeneratedCode(function(str) { 95 | var idx = -1; 96 | var count = -1; 97 | do { 98 | count++; 99 | idx = str.indexOf("\n", idx + 1); 100 | } while(idx >= 0); 101 | if(!count) return ""; 102 | var result = code.slice(currentIndex, currentIndex + count).join("\n") + "\n"; 103 | currentIndex += count; 104 | return result; 105 | }); 106 | map.add(code.slice(currentIndex).join("\n")); 107 | } else { 108 | map.mapGeneratedCode(this._replaceString.bind(this)); 109 | } 110 | return map; 111 | }; 112 | 113 | ReplaceSource.prototype._replacementToSourceNode = function(oldNode, newString) { 114 | var map = oldNode.toStringWithSourceMap({ file: "?" }).map; 115 | var original = new SourceMapConsumer(map.toJSON()).originalPositionFor({ line: 1, column: 0 }); 116 | if(original) { 117 | return new SourceNode(original.line, original.column, original.source, newString); 118 | } else { 119 | return newString; 120 | } 121 | }; 122 | 123 | ReplaceSource.prototype._splitSourceNode = function(node, position) { 124 | if(typeof node === "string") { 125 | if(node.length <= position) return position - node.length; 126 | return [node.substr(0, position), node.substr(position)]; 127 | } else { 128 | for(var i = 0; i < node.children.length; i++) { 129 | position = this._splitSourceNode(node.children[i], position); 130 | if(Array.isArray(position)) { 131 | var leftNode = new SourceNode( 132 | node.line, 133 | node.column, 134 | node.source, 135 | node.children.slice(0, i).concat([position[0]]), 136 | node.name 137 | ); 138 | var rightNode = new SourceNode( 139 | node.line, 140 | node.column, 141 | node.source, 142 | [position[1]].concat(node.children.slice(i+1)), 143 | node.name 144 | ); 145 | leftNode.sourceContents = node.sourceContents; 146 | return [leftNode, rightNode]; 147 | } 148 | } 149 | return position; 150 | } 151 | }; 152 | 153 | ReplaceSource.prototype._splitString = function(str, position) { 154 | return [str.substr(0, position), str.substr(position)]; 155 | }; 156 | -------------------------------------------------------------------------------- /lib/NormalModuleMixin.js: -------------------------------------------------------------------------------- 1 | /* 2 | MIT License http://www.opensource.org/licenses/mit-license.php 3 | Author Tobias Koppers @sokra 4 | */ 5 | var RawSource = require("./RawSource"); 6 | var OriginalSource = require("./OriginalSource"); 7 | var SourceMapSource = require("./SourceMapSource"); 8 | var LineToLineMappedSource = require("./LineToLineMappedSource"); 9 | var path = require("path"); // TODO refactor 10 | 11 | var ModuleBuildError = require("./ModuleBuildError"); 12 | var ModuleError = require("./ModuleError"); 13 | var ModuleWarning = require("./ModuleWarning"); 14 | 15 | function utf8BufferToString(buf) { 16 | var str = buf.toString("utf-8"); 17 | if(str.charCodeAt(0) === 0xFEFF) { 18 | return str.substr(1); 19 | } else { 20 | return str; 21 | } 22 | } 23 | 24 | function NormalModuleMixin(loaders, resource) { 25 | this.resource = resource; 26 | this.loaders = loaders; 27 | var resourcePath = this.splitQuery(this.resource)[0]; 28 | this.context = resourcePath ? path.dirname(resourcePath) : null; 29 | this.fileDependencies = []; 30 | this.contextDependencies = []; 31 | this.warnings = []; 32 | this.errors = []; 33 | this.error = null; 34 | this._source = null; 35 | } 36 | module.exports = NormalModuleMixin; 37 | 38 | NormalModuleMixin.mixin = function(pt) { 39 | for(var name in NormalModuleMixin.prototype) 40 | pt[name] = NormalModuleMixin.prototype[name]; 41 | }; 42 | 43 | NormalModuleMixin.prototype.splitQuery = function splitQuery(req) { 44 | var i = req.indexOf("?"); 45 | if(i < 0) return [req, ""]; 46 | return [req.substr(0, i), req.substr(i)]; 47 | }; 48 | 49 | NormalModuleMixin.prototype.doBuild = function doBuild(options, moduleContext, resolver, fs, callback) { 50 | var splitQuery = this.splitQuery.bind(this); 51 | var module = this; 52 | this.cacheable = true; 53 | 54 | // Prepare context 55 | var loaders = []; 56 | function addLoaderToList(loader) { 57 | var l = splitQuery(loader); 58 | loaders.push({ 59 | request: loader, 60 | path: l[0], 61 | query: l[1], 62 | module: null 63 | }); 64 | } 65 | this.loaders.forEach(addLoaderToList); 66 | var loaderContextCacheable; 67 | var loaderContext = { 68 | version: 1, 69 | context: this.context, 70 | loaders: loaders, 71 | loaderIndex: 0, 72 | resource: this.resource, 73 | resourcePath: splitQuery(this.resource)[0], 74 | resourceQuery: this.resource ? splitQuery(this.resource)[1] || null : undefined, 75 | emitWarning: function(warning) { 76 | this.warnings.push(new ModuleWarning(this, warning)); 77 | }.bind(this), 78 | emitError: function(error) { 79 | this.errors.push(new ModuleError(this, error)); 80 | }.bind(this), 81 | exec: function(code, filename) { 82 | if(typeof __webpack_modules__ === "undefined") { 83 | // TODO: check if in enhanced-require 84 | var Module = require("module"); 85 | var m = new Module(filename, module); 86 | m.paths = Module._nodeModulePaths(loaderContext.context); 87 | m.filename = filename; 88 | m._compile(code, filename); 89 | return m.exports; 90 | } else { 91 | throw new Error("loaderContext.exec is not supported"); 92 | } 93 | }, 94 | resolve: function(context, request, callback) { 95 | resolver.resolve(context, request, callback); 96 | }, 97 | resolveSync: function(context, request) { 98 | return resolver.resolveSync(context, request); 99 | }, 100 | cacheable: function(flag) { 101 | loaderContextCacheable = flag !== false; 102 | }, 103 | dependency: function(file) { 104 | this.fileDependencies.push(file); 105 | }.bind(this), 106 | addDependency: function(file) { 107 | this.fileDependencies.push(file); 108 | }.bind(this), 109 | addContextDependency: function(context) { 110 | this.contextDependencies.push(context); 111 | }.bind(this), 112 | clearDependencies: function() { 113 | this.fileDependencies.length = 0; 114 | this.contextDependencies.length = 0; 115 | module.cacheable = true; 116 | }.bind(this), 117 | inputValue: undefined, 118 | value: null, 119 | options: options, 120 | debug: options.debug 121 | }; 122 | this.fillLoaderContext(loaderContext, options, moduleContext); 123 | if(options.loader) for(var key in options.loader) 124 | loaderContext[key] = options.loader[key]; 125 | 126 | 127 | function runSyncOrAsync(fn, context, args, callback) { 128 | var isSync = true; 129 | var isDone = false; 130 | var isError = false; // internal error 131 | var reportedError = false; 132 | if(!context.async) context.async = function async() { 133 | if(isDone) { 134 | if(reportedError) return; // ignore 135 | throw new Error("async(): The callback was already called."); 136 | } 137 | isSync = false; 138 | return context.callback; 139 | }; 140 | context.callback = function() { 141 | if(isDone) { 142 | if(reportedError) return; // ignore 143 | throw new Error("callback(): The callback was already called."); 144 | } 145 | isDone = true; 146 | isSync = false; 147 | try { 148 | callback.apply(null, arguments); 149 | } catch(e) { 150 | isError = true; 151 | throw e; 152 | } 153 | }; 154 | try { 155 | var result = (function WEBPACK_CORE_LOADER_EXECUTION() { return fn.apply(context, args) }()); 156 | if(isSync) { 157 | isDone = true; 158 | if(result === undefined) 159 | return callback(); 160 | return callback(null, result); 161 | } 162 | } catch(e) { 163 | if(isError) throw e; 164 | if(isDone) { 165 | // loader is already "done", so we cannot use the callback function 166 | // for better debugging we print the error on the console 167 | if(typeof e === "object" && e.stack) console.error(e.stack); 168 | else console.error(e); 169 | return; 170 | } 171 | isDone = true; 172 | reportedError = true; 173 | callback(e); 174 | } 175 | 176 | } 177 | 178 | // Load and pitch loaders 179 | (function loadPitch() { 180 | var l = loaderContext.loaders[loaderContext.loaderIndex]; 181 | if(!l) { 182 | return onLoadPitchDone.call(this); 183 | } 184 | if(l.module) { 185 | loaderContext.loaderIndex++; 186 | return loadPitch.call(this); 187 | } 188 | if(typeof __webpack_modules__ === "undefined") { 189 | if(require.supportQuery) { 190 | l.module = require(l.request); 191 | } else { 192 | try { 193 | l.module = require(l.path); 194 | } catch (e) { 195 | // it is possible for node to choke on a require if the FD descriptor 196 | // limit has been reached. give it a chance to recover. 197 | if (e instanceof Error && e.code === 'EMFILE') { 198 | if (typeof setImmediate === 'function') { 199 | // node >= 0.9.0 200 | return setImmediate(loadPitch.bind(this)); 201 | } else { 202 | // node < 0.9.0 203 | return process.nextTick(loadPitch.bind(this)); 204 | } 205 | } 206 | return callback(e) 207 | } 208 | } 209 | } else if(typeof __webpack_require_loader__ === "function") { 210 | l.module = __webpack_require_loader__(l.request); 211 | } else { 212 | return callback(new Error("Cannot load loader, __webpack_require_loader__ not provided.")); 213 | } 214 | if(typeof l.module !== "function") 215 | return callback(new Error("Loader " + l.request + " didn't return a function")); 216 | var pitchedLoaders = []; 217 | var remaining = []; 218 | for(var i = 0; i < loaderContext.loaderIndex; i++) 219 | pitchedLoaders.push(loaderContext.loaders[i].request); 220 | for(i = loaderContext.loaderIndex + 1; i < loaderContext.loaders.length; i++) 221 | remaining.push(loaderContext.loaders[i].request); 222 | remaining.push(loaderContext.resource); 223 | if(typeof l.module.pitch !== "function") return loadPitch.call(this); 224 | loaderContextCacheable = false; 225 | var privateLoaderContext = Object.create(loaderContext); 226 | privateLoaderContext.query = l.query; 227 | runSyncOrAsync(l.module.pitch, privateLoaderContext, [remaining.join("!"), pitchedLoaders.join("!"), l.data = {}], function(err) { 228 | if(err) return onModuleBuildFailed.call(this, err); 229 | if(!loaderContextCacheable) this.cacheable = false; 230 | var args = Array.prototype.slice.call(arguments, 1); 231 | loaderContext.resourcePath = privateLoaderContext.resourcePath; 232 | loaderContext.resourceQuery = privateLoaderContext.resourceQuery; 233 | loaderContext.resource = privateLoaderContext.resource; 234 | loaderContext.loaderIndex = privateLoaderContext.loaderIndex; 235 | if(args.length > 0) { 236 | nextLoader.apply(this, [null].concat(args)); 237 | } else { 238 | loadPitch.call(this); 239 | } 240 | }.bind(this)); 241 | }.call(this)); 242 | 243 | var resourceBuffer; 244 | function onLoadPitchDone() { 245 | loaderContext.loaderIndex = loaderContext.loaders.length; 246 | var request = []; 247 | for(var i = 0; i < loaderContext.loaders.length; i++) 248 | request.push(loaderContext.loaders[i].request); 249 | request.push(loaderContext.resource); 250 | loaderContext.request = request.join("!"); 251 | var resourcePath = loaderContext.resourcePath; 252 | loaderContextCacheable = true; 253 | if(resourcePath) { 254 | loaderContext.addDependency(resourcePath); 255 | fs.readFile(resourcePath, function(err, buffer) { 256 | if(err) return nextLoader(err); 257 | if(module.lineToLine) 258 | resourceBuffer = buffer; 259 | nextLoader(null, buffer); 260 | }); 261 | } else 262 | nextLoader(null, null); 263 | } 264 | 265 | function nextLoader(err/*, paramBuffer1, param2, ...*/) { 266 | if(!loaderContextCacheable) module.cacheable = false; 267 | var args = Array.prototype.slice.call(arguments, 1); 268 | if(err) { 269 | // a loader emitted an error 270 | return onModuleBuildFailed.call(module, err); 271 | } 272 | if(loaderContext.loaderIndex === 0) { 273 | if(Buffer.isBuffer(args[0])) 274 | args[0] = utf8BufferToString(args[0]); 275 | return onModuleBuild.apply(module, args); 276 | } 277 | loaderContext.loaderIndex--; 278 | var l = loaderContext.loaders[loaderContext.loaderIndex]; 279 | if(!l.module) return nextLoader.apply(null, [null].concat(args)); 280 | var privateLoaderContext = Object.create(loaderContext); 281 | privateLoaderContext.data = l.data; 282 | privateLoaderContext.inputValue = loaderContext.inputValue; 283 | privateLoaderContext.query = l.query; 284 | if(!l.module.raw && Buffer.isBuffer(args[0])) { 285 | args[0] = utf8BufferToString(args[0]); 286 | } else if(l.module.raw && typeof args[0] === "string") { 287 | args[0] = new Buffer(args[0], "utf-8"); 288 | } 289 | loaderContextCacheable = false; 290 | runSyncOrAsync(l.module, privateLoaderContext, args, function() { 291 | loaderContext.inputValue = privateLoaderContext.value; 292 | nextLoader.apply(null, arguments); 293 | }); 294 | } 295 | 296 | 297 | function onModuleBuild(source, sourceMap) { 298 | if(!Buffer.isBuffer(source) && typeof source !== "string") 299 | return onModuleBuildFailed.call(this, new Error("Final loader didn't return a Buffer or String")); 300 | if(this.identifier && this.lineToLine && resourceBuffer) { 301 | this._source = new LineToLineMappedSource(source, this.identifier(), 302 | resourceBuffer.toString("utf-8")); 303 | } else if(this.identifier && this.useSourceMap && sourceMap) { 304 | this._source = new SourceMapSource(source, this.identifier(), sourceMap); 305 | } else if(this.identifier) { 306 | this._source = new OriginalSource(source, this.identifier()); 307 | } else { 308 | this._source = new RawSource(source); 309 | } 310 | return callback(); 311 | } 312 | 313 | function onModuleBuildFailed(err) { 314 | this.error = err; 315 | return callback(new ModuleBuildError(this, err)); 316 | } 317 | }; 318 | 319 | NormalModuleMixin.prototype.fillLoaderContext = function fillLoaderContext() {}; 320 | --------------------------------------------------------------------------------