Sea.js:
var seajs = global.seajs = { // The current version of Sea.js being used version: "@VERSION" } var data = seajs.data = {}
代码定义了一个seajs变量并暴露给全局,变量现在只有一个值就是版本号变量
另外定义了一个data变量,后面会用到
util-lang.js
/** * util-lang.js - The minimal language enhancement */ function isType(type) { return function(obj) { return {}.toString.call(obj) == "[object " + type + "]" } } var isObject = isType("Object") var isString = isType("String") var isArray = Array.isArray || isType("Array") var isFunction = isType("Function") var isUndefined = isType("Undefined") var _cid = 0 function cid() { return _cid++ }
这里用一个函数来判断对象类型,这里有一个演变过程比较有意思,如果有兴趣可以参考下玉伯的github博客
cid方法用来产生一个唯一的ID,后面会用到
util-events.js
/** * util-events.js - The minimal events support */ var events = data.events = {} // Bind event seajs.on = function(name, callback) { var list = events[name] || (events[name] = []) list.push(callback) return seajs } // Remove event. If `callback` is undefined, remove all callbacks for the // event. If `event` and `callback` are both undefined, remove all callbacks // for all events seajs.off = function(name, callback) { // Remove *all* events if (!(name || callback)) { events = data.events = {} return seajs } var list = events[name] if (list) { if (callback) { for (var i = list.length - 1; i >= 0; i--) { if (list[i] === callback) { list.splice(i, 1) } } } else { delete events[name] } } return seajs } // Emit event, firing all bound callbacks. Callbacks receive the same // arguments as `emit` does, apart from the event name var emit = seajs.emit = function(name, data) { var list = events[name], fn if (list) { // Copy callback lists to prevent modification list = list.slice() // Execute event callbacks while ((fn = list.shift())) { fn(data) } } return seajs }
一个事件处理机制,on用来注册事件,为指定事件数组添加回调函数,off用来移除事件,如果没有指定事件名和回调函数,删除所有事件的回调函数,如果没有指定回调函数,则删除该事件的所有回调函数,emit用来触发事件以及事件绑定的函数
util-path.js
/** * util-path.js - The utilities for operating path such as id, uri */ var DIRNAME_RE = /[^?#]*\// var DOT_RE = /\/\.\//g var DOUBLE_DOT_RE = /\/[^/]+\/\.\.\// var DOUBLE_SLASH_RE = /([^:/])\/\//g // Extract the directory portion of a path // dirname("a/b/c.js?t=123#xx/zz") ==> "a/b/" // ref: http://jsperf.com/regex-vs-split/2 function dirname(path) { return path.match(DIRNAME_RE)[0] } // Canonicalize a path // realpath("http://test.com/a//./b/../c") ==> "http://test.com/a/c" function realpath(path) { // /a/b/./c/./d ==> /a/b/c/d path = path.replace(DOT_RE, "/") // a/b/c/../../d ==> a/b/../d ==> a/d while (path.match(DOUBLE_DOT_RE)) { path = path.replace(DOUBLE_DOT_RE, "/") } // a//b/c ==> a/b/c path = path.replace(DOUBLE_SLASH_RE, "$1/") return path } // Normalize an id // normalize("path/to/a") ==> "path/to/a.js" // NOTICE: substring is faster than negative slice and RegExp function normalize(path) { var last = path.length - 1 var lastC = path.charAt(last) // If the uri ends with `#`, just return it without ‘#‘ if (lastC === "#") { return path.substring(0, last) } return (path.substring(last - 2) === ".js" || path.indexOf("?") > 0 || path.substring(last - 3) === ".css" || lastC === "/") ? path : path + ".js" } var PATHS_RE = /^([^/:]+)(\/.+)$/ var VARS_RE = /{([^{]+)}/g function parseAlias(id) { var alias = data.alias return alias && isString(alias[id]) ? alias[id] : id } function parsePaths(id) { var paths = data.paths var m if (paths && (m = id.match(PATHS_RE)) && isString(paths[m[1]])) { id = paths[m[1]] + m[2] } return id } function parseVars(id) { var vars = data.vars if (vars && id.indexOf("{") > -1) { id = id.replace(VARS_RE, function(m, key) { return isString(vars[key]) ? vars[key] : m }) } return id } function parseMap(uri) { var map = data.map var ret = uri if (map) { for (var i = 0, len = map.length; i < len; i++) { var rule = map[i] ret = isFunction(rule) ? (rule(uri) || uri) : uri.replace(rule[0], rule[1]) // Only apply the first matched rule if (ret !== uri) break } } return ret } var ABSOLUTE_RE = /^\/\/.|:\// var ROOT_DIR_RE = /^.*?\/\/.*?\// function addBase(id, refUri) { var ret var first = id.charAt(0) // Absolute if (ABSOLUTE_RE.test(id)) { ret = id } // Relative else if (first === ".") { ret = realpath((refUri ? dirname(refUri) : data.cwd) + id) } // Root else if (first === "/") { var m = data.cwd.match(ROOT_DIR_RE) ret = m ? m[0] + id.substring(1) : id } // Top-level else { ret = data.base + id } // Add default protocol when uri begins with "//" if (ret.indexOf("//") === 0) { ret = location.protocol + ret } return ret } function id2Uri(id, refUri) { if (!id) return "" id = parseAlias(id) id = parsePaths(id) id = parseVars(id) id = normalize(id) var uri = addBase(id, refUri) uri = parseMap(uri) return uri } var doc = document var cwd = dirname(doc.URL) var scripts = doc.scripts // Recommend to add `seajsnode` id for the `sea.js` script element var loaderScript = doc.getElementById("seajsnode") || scripts[scripts.length - 1] // When `sea.js` is inline, set loaderDir to current working directory var loaderDir = dirname(getScriptAbsoluteSrc(loaderScript) || cwd) function getScriptAbsoluteSrc(node) { return node.hasAttribute ? // non-IE6/7 node.src : // see http://msdn.microsoft.com/en-us/library/ms536429(VS.85).aspx node.getAttribute("src", 4) } // For Developers seajs.resolve = id2Uri
这段代码是用来进行路径处理的:
首先定义了一组正则表达式用来路径分析
dirname函数:获得一组路径的目录部分,比如dirname("a/b/c.js?t=123#xx/zz") 获得的结果是a/b
realpath函数:规范一组路径,比如realpath("http://test.com/a//./b/../c") ==> "http://test.com/a/c",就是将./ ../ 和//转换成规范的路径
normalize函数:规范一组路径的后缀名,比如normalize("path/to/a") ==> "path/to/a.js".
parseAlias函数:路径别名处理,根据别名id返回别名
parsePaths:解析配置中的path,具体可以参考config用法
parseVars:解析配置中的变量
parseMap:解析配置中的map
addBase:将路径转换为完整路径
id2Uri:将模块id转换为真实完整路径
util-deps.js:
/** * util-deps.js - The parser for dependencies * ref: tests/research/parse-dependencies/test.html */ var REQUIRE_RE = /"(?:\\"|[^"])*"|‘(?:\\‘|[^‘])*‘|\/\*[\S\s]*?\*\/|\/(?:\\\/|[^\/\r\n])+\/(?=[^\/])|\/\/.*|\.\s*require|(?:^|[^$])\brequire\s*\(\s*(["‘])(.+?)\1\s*\)/g var SLASH_RE = /\\\\/g function parseDependencies(code) { var ret = [] code.replace(SLASH_RE, "") .replace(REQUIRE_RE, function(m, m1, m2) { if (m2) { ret.push(m2) } }) return ret }
解析模块代码中require的模块,也就是依赖模块解析
时间: 2024-10-09 00:40:45