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的模块,也就是依赖模块解析

05-11 11:37
查看更多