Skip to content

Instantly share code, notes, and snippets.

@undoZen
Created October 15, 2012 08:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save undoZen/3891433 to your computer and use it in GitHub Desktop.
Save undoZen/3891433 to your computer and use it in GitHub Desktop.
ydiff bug
<html>
<head>
<META http-equiv="Content-Type" content="text/html; charset=utf-8">
<LINK href="diff-s.css" rel="stylesheet" type="text/css">
<script type="text/javascript" src="nav-div.js"></script>
</head>
<body>
<div id="left" class="src">
<pre>
<a id='leftstart' tid='rightstart'></a>
/**
* @preserve SeaJS - A Module Loader for the Web
* v1.2.1 | seajs.org | MIT Licensed
*/
/**
* Base namespace for the framework.
*/
<a id='1' tid='2' class='m'>this</a>.<a id='3' tid='4' class='m'>seajs</a> <a id='5' tid='6' class='m'>=</a> { <a id='7' tid='8' class='m'>_seajs</a>: <a id='9' tid='10' class='m'>this</a>.<a id='11' tid='12' class='m'>seajs</a> }
/**
* The version of the framework. It will be replaced with &quot;major.minor.patch&quot;
* when building.
*/
<span class='d'>seajs.version = &#39;1.2.1&#39;</span>
/**
* The private utilities. Internal use only.
*/
<span class='d'>seajs._util</span> = {}
/**
* The private configuration data. Internal use only.
*/
seajs._config = {
/**
* Debug mode. It will be turned off automatically when compressing.
*/
debug: &#39;%DEBUG%&#39;,
/**
* Modules that are needed to load before all other modules.
*/
preload: []
}
/**
* The minimal language enhancement
*/
;(function(util) {
var toString = Object.prototype.toString
var AP = Array.prototype
util.isString = function(val) {
return toString.call(val) === &#39;[object String]&#39;
}
util.isFunction = function(val) {
return toString.call(val) === &#39;[object Function]&#39;
}
util.isRegExp = function(val) {
return toString.call(val) === &#39;[object RegExp]&#39;
}
util.isObject = function(val) {
return val === Object(val)
}
util.isArray = Array.isArray || function(val) {
return toString.call(val) === &#39;[object Array]&#39;
}
util.indexOf = AP.indexOf ?
function(arr, item) {
return arr.indexOf(item)
} :
function(arr, item) {
for (var i = 0; i &lt; arr.length; i++) {
if (arr[i] === item) {
return i
}
}
return -1
}
var forEach = util.forEach = AP.forEach ?
function(arr, fn) {
arr.forEach(fn)
} :
function(arr, fn) {
for (var i = 0; i &lt; arr.length; i++) {
fn(arr[i], i, arr)
}
}
util.map = AP.map ?
function(arr, fn) {
return arr.map(fn)
} :
function(arr, fn) {
var ret = []
forEach(arr, function(item, i, arr) {
ret.push(fn(item, i, arr))
})
return ret
}
util.filter = AP.filter ?
function(arr, fn) {
return arr.filter(fn)
} :
function(arr, fn) {
var ret = []
forEach(arr, function(item, i, arr) {
if (fn(item, i, arr)) {
ret.push(item)
}
})
return ret
}
var keys = util.keys = Object.keys || function(o) {
var ret = []
for (var p in o) {
if (o.hasOwnProperty(p)) {
ret.push(p)
}
}
return ret
}
util.unique = function(arr) {
var o = {}
forEach(arr, function(item) {
o[item] = 1
})
return keys(o)
}
util.now = Date.now || function() {
return new Date().getTime()
}
})(seajs._util)
/**
* The tiny console
*/
;(function(util, config) {
var AP = Array.prototype
/**
* The safe wrapper of console.log/error/...
*/
util.log = function() {
if (typeof console !== &#39;undefined&#39;) {
var args = AP.slice.call(arguments)
var type = &#39;log&#39;
var last = args[args.length - 1]
console[last] && (type = args.pop())
// Only show log info in debug mode
if (type === &#39;log&#39; && !config.debug) return
var out = type === &#39;dir&#39; ? args[0] : AP.join.call(args, &#39; &#39;)
console[type](out)
}
}
})(seajs._util, seajs._config)
/**
* Path utilities
*/
;(function(util, config, global) {
var DIRNAME_RE = /.*(?=\/.*$)/
var MULTIPLE_SLASH_RE = /([^:\/])\/\/+/g
var FILE_EXT_RE = /\.(?:css|js)$/
var ROOT_RE = /^(.*?\w)(?:\/|$)/
/**
* Extracts the directory portion of a path.
* dirname(&#39;a/b/c.js&#39;) ==&gt; &#39;a/b/&#39;
* dirname(&#39;d.js&#39;) ==&gt; &#39;./&#39;
* @see http://jsperf.com/regex-vs-split/2
*/
function dirname(path) {
var s = path.match(DIRNAME_RE)
return (s ? s[0] : &#39;.&#39;) + &#39;/&#39;
}
/**
* Canonicalizes a path.
* realpath(&#39;./a//b/../c&#39;) ==&gt; &#39;a/c&#39;
*/
function realpath(path) {
MULTIPLE_SLASH_RE.lastIndex = 0
// &#39;file:///a//b/c&#39; ==&gt; &#39;file:///a/b/c&#39;
// &#39;http://a//b/c&#39; ==&gt; &#39;http://a/b/c&#39;
if (MULTIPLE_SLASH_RE.test(path)) {
path = path.replace(MULTIPLE_SLASH_RE, &#39;$1\/&#39;)
}
// &#39;a/b/c&#39;, just return.
if (path.indexOf(&#39;.&#39;) === -1) {
return path
}
var original = path.split(&#39;/&#39;)
var ret = [], part
for (var i = 0; i &lt; original.length; i++) {
part = original[i]
if (part === &#39;..&#39;) {
if (ret.length === 0) {
throw new Error(&#39;The path is invalid: &#39; + path)
}
ret.pop()
}
else if (part !== &#39;.&#39;) {
ret.push(part)
}
}
return ret.join(&#39;/&#39;)
}
/**
* Normalizes an uri.
*/
function normalize(uri) {
uri = realpath(uri)
var lastChar = uri.charAt(uri.length - 1)
if (lastChar === &#39;/&#39;) {
return uri
}
// Adds the default &#39;.js&#39; extension except that the uri ends with #.
// ref: http://jsperf.com/get-the-last-character
if (lastChar === &#39;#&#39;) {
uri = uri.slice(0, -1)
}
else if (uri.indexOf(&#39;?&#39;) === -1 && !FILE_EXT_RE.test(uri)) {
uri += &#39;.js&#39;
}
// Remove &#39;:80/&#39; for bug in IE
if (uri.indexOf(&#39;:80/&#39;) &gt; 0) {
uri = uri.replace(&#39;:80/&#39;, &#39;/&#39;)
}
return uri
}
/**
* Parses alias in the module id. Only parse the first part.
*/
function parseAlias(id) {
// #xxx means xxx is already alias-parsed.
if (id.charAt(0) === &#39;#&#39;) {
return id.substring(1)
}
var alias = config.alias
// Only top-level id needs to parse alias.
if (alias && isTopLevel(id)) {
var parts = id.split(&#39;/&#39;)
var first = parts[0]
if (alias.hasOwnProperty(first)) {
parts[0] = alias[first]
id = parts.join(&#39;/&#39;)
}
}
return id
}
var mapCache = {}
/**
* Converts the uri according to the map rules.
*/
function parseMap(uri) {
// map: [[match, replace], ...]
var map = config.map || []
if (!map.length) return uri
var ret = uri
// Apply all matched rules in sequence.
for (var i = 0; i &lt; map.length; i++) {
var rule = map[i]
if (util.isArray(rule) && rule.length === 2) {
var m = rule[0]
if (util.isString(m) && ret.indexOf(m) &gt; -1 ||
util.isRegExp(m) && m.test(ret)) {
ret = ret.replace(m, rule[1])
}
}
else if (util.isFunction(rule)) {
ret = rule(ret)
}
}
if (ret !== uri) {
mapCache[ret] = uri
}
return ret
}
/**
* Gets the original uri.
*/
function unParseMap(uri) {
return mapCache[uri] || uri
}
/**
* Converts id to uri.
*/
function id2Uri(id, refUri) {
if (!id) return &#39;&#39;
id = parseAlias(id)
refUri || (refUri = pageUri)
var ret
// absolute id
if (isAbsolute(id)) {
ret = id
}
// relative id
else if (isRelative(id)) {
// Converts &#39;./a&#39; to &#39;a&#39;, to avoid unnecessary loop in realpath.
if (id.indexOf(&#39;./&#39;) === 0) {
id = id.substring(2)
}
ret = dirname(refUri) + id
}
// root id
else if (isRoot(id)) {
ret = refUri.match(ROOT_RE)[1] + id
}
// top-level id
else {
ret = config.base + &#39;/&#39; + id
}
return normalize(ret)
}
function isAbsolute(id) {
return id.indexOf(&#39;://&#39;) &gt; 0 || id.indexOf(&#39;//&#39;) === 0
}
function isRelative(id) {
return id.indexOf(&#39;./&#39;) === 0 || id.indexOf(&#39;../&#39;) === 0
}
function isRoot(id) {
return id.charAt(0) === &#39;/&#39; && id.charAt(1) !== &#39;/&#39;
}
function isTopLevel(id) {
var c = id.charAt(0)
return id.indexOf(&#39;://&#39;) === -1 && c !== &#39;.&#39; && c !== &#39;/&#39;
}
/**
* Normalizes pathname to start with &#39;/&#39;
* Ref: https://groups.google.com/forum/#!topic/seajs/9R29Inqk1UU
*/
function normalizePathname(pathname) {
if (pathname.charAt(0) !== &#39;/&#39;) {
pathname = &#39;/&#39; + pathname
}
return pathname
}
var loc = global[&#39;location&#39;]
var pageUri = loc.protocol + &#39;//&#39; + loc.host +
normalizePathname(loc.pathname)
// local file in IE: C:\path\to\xx.js
if (pageUri.indexOf(&#39;\\&#39;) &gt; 0) {
pageUri = pageUri.replace(/\\/g, &#39;/&#39;)
}
util.dirname = dirname
util.realpath = realpath
util.normalize = normalize
util.parseAlias = parseAlias
util.parseMap = parseMap
util.unParseMap = unParseMap
util.id2Uri = id2Uri
util.isAbsolute = isAbsolute
util.isRoot = isRoot
util.isTopLevel = isTopLevel
util.pageUri = pageUri
})(seajs._util, seajs._config, this)
/**
* Utilities for fetching js and css files
*/
;(function(util, config) {
var doc = document
var head = doc.head ||
doc.getElementsByTagName(&#39;head&#39;)[0] ||
doc.documentElement
var baseElement = head.getElementsByTagName(&#39;base&#39;)[0]
var IS_CSS_RE = /\.css(?:\?|$)/i
var READY_STATE_RE = /loaded|complete|undefined/
var currentlyAddingScript
var interactiveScript
util.fetch = function(url, callback, charset) {
var isCSS = IS_CSS_RE.test(url)
var node = document.createElement(isCSS ? &#39;link&#39; : &#39;script&#39;)
if (charset) {
var cs = util.isFunction(charset) ? charset(url) : charset
cs && (node.charset = cs)
}
assetOnload(node, callback || noop)
if (isCSS) {
node.rel = &#39;stylesheet&#39;
node.href = url
} else {
node.async = &#39;async&#39;
node.src = url
}
// For some cache cases in IE 6-9, the script executes IMMEDIATELY after
// the end of the insertBefore execution, so use `currentlyAddingScript`
// to hold current node, for deriving url in `define`.
currentlyAddingScript = node
// ref: #185 & http://dev.jquery.com/ticket/2709
baseElement ?
head.insertBefore(node, baseElement) :
head.appendChild(node)
currentlyAddingScript = null
}
function assetOnload(node, callback) {
if (node.nodeName === &#39;SCRIPT&#39;) {
scriptOnload(node, callback)
} else {
styleOnload(node, callback)
}
}
function scriptOnload(node, callback) {
node.onload = node.onerror = node.onreadystatechange = function() {
if (READY_STATE_RE.test(node.readyState)) {
// Ensure only run once and handle memory leak in IE
node.onload = node.onerror = node.onreadystatechange = null
// Remove the script to reduce memory leak
if (node.parentNode && !config.debug) {
head.removeChild(node)
}
// Dereference the node
node = undefined
callback()
}
}
}
function styleOnload(node, callback) {
// for Old WebKit and Old Firefox
if (isOldWebKit || isOldFirefox) {
util.log(&#39;Start poll to fetch css&#39;)
setTimeout(function() {
poll(node, callback)
}, 1) // Begin after node insertion
}
else {
node.onload = node.onerror = function() {
node.onload = node.onerror = null
node = undefined
callback()
}
}
}
function poll(node, callback) {
var isLoaded
// for WebKit &lt; 536
if (isOldWebKit) {
if (node[&#39;sheet&#39;]) {
isLoaded = true
}
}
// for Firefox &lt; 9.0
else if (node[&#39;sheet&#39;]) {
try {
if (node[&#39;sheet&#39;].cssRules) {
isLoaded = true
}
} catch (ex) {
// The value of `ex.name` is changed from
// &#39;NS_ERROR_DOM_SECURITY_ERR&#39; to &#39;SecurityError&#39; since Firefox 13.0
// But Firefox is less than 9.0 in here, So it is ok to just rely on
// &#39;NS_ERROR_DOM_SECURITY_ERR&#39;
if (ex.name === &#39;NS_ERROR_DOM_SECURITY_ERR&#39;) {
isLoaded = true
}
}
}
setTimeout(function() {
if (isLoaded) {
// Place callback in here due to giving time for style rendering.
callback()
} else {
poll(node, callback)
}
}, 1)
}
function noop() {
}
util.getCurrentScript = function() {
if (currentlyAddingScript) {
return currentlyAddingScript
}
// For IE6-9 browsers, the script onload event may not fire right
// after the the script is evaluated. Kris Zyp found that it
// could query the script nodes and the one that is in &quot;interactive&quot;
// mode indicates the current script.
// Ref: http://goo.gl/JHfFW
if (interactiveScript &&
interactiveScript.readyState === &#39;interactive&#39;) {
return interactiveScript
}
var scripts = head.getElementsByTagName(&#39;script&#39;)
for (var i = 0; i &lt; scripts.length; i++) {
var script = scripts[i]
if (script.readyState === &#39;interactive&#39;) {
interactiveScript = script
return script
}
}
}
util.getScriptAbsoluteSrc = function(node) {
return node.hasAttribute ? // non-IE6/7
node.src :
// see http://msdn.microsoft.com/en-us/library/ms536429(VS.85).aspx
node.getAttribute(&#39;src&#39;, 4)
}
util.importStyle = function(cssText, id) {
// Don&#39;t add multi times
if (id && doc.getElementById(id)) return
var element = doc.createElement(&#39;style&#39;)
id && (element.id = id)
// Adds to DOM first to avoid the css hack invalid
head.appendChild(element)
// IE
if (element.styleSheet) {
element.styleSheet.cssText = cssText
}
// W3C
else {
element.appendChild(doc.createTextNode(cssText))
}
}
var UA = navigator.userAgent
// `onload` event is supported in WebKit since 535.23
// Ref:
// - https://bugs.webkit.org/show_activity.cgi?id=38995
var isOldWebKit = Number(UA.replace(/.*AppleWebKit\/(\d+)\..*/, &#39;$1&#39;)) &lt; 536
// `onload/onerror` event is supported since Firefox 9.0
// Ref:
// - https://bugzilla.mozilla.org/show_bug.cgi?id=185236
// - https://developer.mozilla.org/en/HTML/Element/link#Stylesheet_load_events
var isOldFirefox = UA.indexOf(&#39;Firefox&#39;) &gt; 0 &&
!(&#39;onload&#39; in document.createElement(&#39;link&#39;))
/**
* References:
* - http://unixpapa.com/js/dyna.html
* - ../test/research/load-js-css/test.html
* - ../test/issues/load-css/test.html
* - http://www.blaze.io/technical/ies-premature-execution-problem/
*/
})(seajs._util, seajs._config, this)
/**
* The parser for dependencies
*/
;(function(util) {
var REQUIRE_RE = /(?:^|[^.$])\brequire\s*\(\s*([&quot;&#39;])([^&quot;&#39;\s\)]+)\1\s*\)/g
util.parseDependencies = function(code) {
// Parse these `requires`:
// var a = require(&#39;a&#39;);
// someMethod(require(&#39;b&#39;));
// require(&#39;c&#39;);
// ...
// Doesn&#39;t parse:
// someInstance.require(...);
var ret = [], match
code = removeComments(code)
REQUIRE_RE.lastIndex = 0
while ((match = REQUIRE_RE.exec(code))) {
if (match[2]) {
ret.push(match[2])
}
}
return util.unique(ret)
}
// See: research/remove-comments-safely
function removeComments(code) {
return code
.replace(/^\s*\/\*[\s\S]*?\*\/\s*$/mg, &#39;&#39;) // block comments
.replace(/^\s*\/\/.*$/mg, &#39;&#39;) // line comments
}
})(seajs._util)
/**
* The core of loader
*/
;(function(seajs, util, config) {
var cachedModules = {}
var cachedModifiers = {}
var compileStack = []
var STATUS = {
&#39;FETCHING&#39;: 1, // The module file is fetching now.
&#39;FETCHED&#39;: 2, // The module file has been fetched.
&#39;SAVED&#39;: 3, // The module info has been saved.
&#39;READY&#39;: 4, // All dependencies and self are ready to compile.
&#39;COMPILING&#39;: 5, // The module is in compiling now.
&#39;COMPILED&#39;: 6 // The module is compiled and module.exports is available.
}
function Module(uri, status) {
this.uri = uri
this.status = status || 0
// this.id is set when saving
// this.dependencies is set when saving
// this.factory is set when saving
// this.exports is set when compiling
// this.parent is set when compiling
// this.require is set when compiling
}
Module.prototype._use = function(ids, callback) {
util.isString(ids) && (ids = [ids])
var uris = resolve(ids, this.uri)
this._load(uris, function() {
var args = util.map(uris, function(uri) {
return uri ? cachedModules[uri]._compile() : null
})
if (callback) {
callback.apply(null, args)
}
})
}
Module.prototype._load = function(uris, callback) {
var unLoadedUris = util.filter(uris, function(uri) {
return uri && (!cachedModules[uri] ||
cachedModules[uri].status &lt; STATUS.READY)
})
var length = unLoadedUris.length
if (length === 0) {
callback()
return
}
var remain = length
for (var i = 0; i &lt; length; i++) {
(function(uri) {
var module = cachedModules[uri] ||
(cachedModules[uri] = new Module(uri, STATUS.FETCHING))
module.status &gt;= STATUS.FETCHED ? onFetched() : fetch(uri, onFetched)
function onFetched() {
// cachedModules[uri] is changed in un-correspondence case
module = cachedModules[uri]
if (module.status &gt;= STATUS.SAVED) {
var deps = getPureDependencies(module)
if (deps.length) {
Module.prototype._load(deps, function() {
cb(module)
})
}
else {
cb(module)
}
}
// Maybe failed to fetch successfully, such as 404 or non-module.
// // In these cases, module.status stay at FETCHING or FETCHED.
else {
util.log(&#39;It is not a valid CMD module: &#39; + uri)
cb()
}
}
})(unLoadedUris[i])
}
function cb(module) {
(module || {}).status &lt; STATUS.READY && (module.status = STATUS.READY)
--remain === 0 && callback()
}
}
Module.prototype._compile = function() {
var module = this
if (module.status === STATUS.COMPILED) {
return module.exports
}
// Just return null when:
// 1. the module file is 404.
// 2. the module file is not written with valid module format.
// 3. other error cases.
if (module.status &lt; STATUS.READY && !hasModifiers(module)) {
return null
}
module.status = STATUS.COMPILING
function require(id) {
var uri = resolve(id, module.uri)
var child = cachedModules[uri]
// Just return null when uri is invalid.
if (!child) {
return null
}
// Avoids circular calls.
if (child.status === STATUS.COMPILING) {
return child.exports
}
child.parent = module
return child._compile()
}
require.async = function(ids, callback) {
module._use(ids, callback)
}
require.resolve = function(id) {
return resolve(id, module.uri)
}
require.cache = cachedModules
module.require = require
module.exports = {}
var factory = module.factory
if (util.isFunction(factory)) {
compileStack.push(module)
runInModuleContext(factory, module)
compileStack.pop()
}
else if (factory !== undefined) {
module.exports = factory
}
module.status = STATUS.COMPILED
execModifiers(module)
return module.exports
}
Module._define = function(id, deps, factory) {
var argsLength = arguments.length
// define(factory)
if (argsLength === 1) {
factory = id
id = undefined
}
// define(id || deps, factory)
else if (argsLength === 2) {
factory = deps
deps = undefined
// define(deps, factory)
if (util.isArray(id)) {
deps = id
id = undefined
}
}
// Parses dependencies.
if (!util.isArray(deps) && util.isFunction(factory)) {
deps = util.parseDependencies(factory.toString())
}
var meta = { id: id, dependencies: deps, factory: factory }
var derivedUri
// Try to derive uri in IE6-9 for anonymous modules.
if (document.attachEvent) {
// Try to get the current script.
var script = util.getCurrentScript()
if (script) {
derivedUri = util.unParseMap(util.getScriptAbsoluteSrc(script))
}
if (!derivedUri) {
util.log(&#39;Failed to derive URI from interactive script for:&#39;,
factory.toString(), &#39;warn&#39;)
// NOTE: If the id-deriving methods above is failed, then falls back
// to use onload event to get the uri.
}
}
// Gets uri directly for specific module.
var resolvedUri = id ? resolve(id) : derivedUri
if (resolvedUri) {
// For IE:
// If the first module in a package is not the cachedModules[derivedUri]
// self, it should assign to the correct module when found.
if (resolvedUri === derivedUri) {
var refModule = cachedModules[derivedUri]
if (refModule && refModule.realUri &&
refModule.status === STATUS.SAVED) {
cachedModules[derivedUri] = null
}
}
var module = save(resolvedUri, meta)
// For IE:
// Assigns the first module in package to cachedModules[derivedUrl]
if (derivedUri) {
// cachedModules[derivedUri] may be undefined in combo case.
if ((cachedModules[derivedUri] || {}).status === STATUS.FETCHING) {
cachedModules[derivedUri] = module
module.realUri = derivedUri
}
}
else {
firstModuleInPackage || (firstModuleInPackage = module)
}
}
else {
// Saves information for &quot;memoizing&quot; work in the onload event.
anonymousModuleMeta = meta
}
}
Module._getCompilingModule = function() {
return compileStack[compileStack.length - 1]
}
Module._find = function(selector) {
var matches = []
util.forEach(util.keys(cachedModules), function(uri) {
if (util.isString(selector) && uri.indexOf(selector) &gt; -1 ||
util.isRegExp(selector) && selector.test(uri)) {
var module = cachedModules[uri]
module.exports && matches.push(module.exports)
}
})
return matches
}
Module._modify = function(id, modifier) {
var uri = resolve(id)
var module = cachedModules[uri]
if (module && module.status === STATUS.COMPILED) {
runInModuleContext(modifier, module)
}
else {
cachedModifiers[uri] || (cachedModifiers[uri] = [])
cachedModifiers[uri].push(modifier)
}
return seajs
}
// For plugin developers
Module.STATUS = STATUS
Module._resolve = util.id2Uri
Module._fetch = util.fetch
Module.cache = cachedModules
// Helpers
// -------
var fetchingList = {}
var fetchedList = {}
var callbackList = {}
var anonymousModuleMeta = null
var firstModuleInPackage = null
var circularCheckStack = []
function resolve(ids, refUri) {
if (util.isString(ids)) {
return Module._resolve(ids, refUri)
}
return util.map(ids, function(id) {
return resolve(id, refUri)
})
}
function fetch(uri, callback) {
var requestUri = util.parseMap(uri)
if (fetchedList[requestUri]) {
// See test/issues/debug-using-map
cachedModules[uri] = cachedModules[requestUri]
callback()
return
}
if (fetchingList[requestUri]) {
callbackList[requestUri].push(callback)
return
}
fetchingList[requestUri] = true
callbackList[requestUri] = [callback]
// Fetches it
Module._fetch(
requestUri,
function() {
fetchedList[requestUri] = true
// Updates module status
var module = cachedModules[uri]
if (module.status === STATUS.FETCHING) {
module.status = STATUS.FETCHED
}
// Saves anonymous module meta data
if (anonymousModuleMeta) {
save(uri, anonymousModuleMeta)
anonymousModuleMeta = null
}
// Assigns the first module in package to cachedModules[uri]
// See: test/issues/un-correspondence
if (firstModuleInPackage && module.status === STATUS.FETCHED) {
cachedModules[uri] = firstModuleInPackage
firstModuleInPackage.realUri = uri
}
firstModuleInPackage = null
// Clears
if (fetchingList[requestUri]) {
delete fetchingList[requestUri]
}
// Calls callbackList
if (callbackList[requestUri]) {
util.forEach(callbackList[requestUri], function(fn) {
fn()
})
delete callbackList[requestUri]
}
},
config.charset
)
}
function save(uri, meta) {
var module = cachedModules[uri] || (cachedModules[uri] = new Module(uri))
// Don&#39;t override already saved module
if (module.status &lt; STATUS.SAVED) {
// Lets anonymous module id equal to its uri
module.id = meta.id || uri
module.dependencies = resolve(
util.filter(meta.dependencies || [], function(dep) {
return !!dep
}), uri)
module.factory = meta.factory
// Updates module status
module.status = STATUS.SAVED
}
return module
}
function runInModuleContext(fn, module) {
var ret = fn(module.require, module.exports, module)
if (ret !== undefined) {
module.exports = ret
}
}
function hasModifiers(module) {
return !!cachedModifiers[module.realUri || module.uri]
}
function execModifiers(module) {
var uri = module.realUri || module.uri
var modifiers = cachedModifiers[uri]
if (modifiers) {
util.forEach(modifiers, function(modifier) {
runInModuleContext(modifier, module)
})
delete cachedModifiers[uri]
}
}
function getPureDependencies(module) {
var uri = module.uri
return util.filter(module.dependencies, function(dep) {
circularCheckStack = [uri]
var isCircular = isCircularWaiting(cachedModules[dep], uri)
if (isCircular) {
circularCheckStack.push(uri)
printCircularLog(circularCheckStack)
}
return !isCircular
})
}
function isCircularWaiting(module, uri) {
if (!module || module.status !== STATUS.SAVED) {
return false
}
circularCheckStack.push(module.uri)
var deps = module.dependencies
if (deps.length) {
if (util.indexOf(deps, uri) &gt; -1) {
return true
}
for (var i = 0; i &lt; deps.length; i++) {
if (isCircularWaiting(cachedModules[deps[i]], uri)) {
return true
}
}
return false
}
return false
}
function printCircularLog(stack, type) {
util.log(&#39;Found circular dependencies:&#39;, stack.join(&#39; --&gt; &#39;), type)
}
// Public API
// ----------
var globalModule = new Module(util.pageUri, STATUS.COMPILED)
seajs.use = function(ids, callback) {
var preloadMods = config.preload
if (preloadMods.length) {
// Loads preload modules before all other modules.
globalModule._use(preloadMods, function() {
config.preload = []
globalModule._use(ids, callback)
})
}
else {
globalModule._use(ids, callback)
}
return seajs
}
// For normal users
seajs.define = Module._define
seajs.cache = Module.cache
seajs.find = Module._find
seajs.modify = Module._modify
// For plugin developers
seajs.pluginSDK = {
Module: Module,
util: util,
config: config
}
})(seajs, seajs._util, seajs._config)
/**
* The configuration
*/
;(function(seajs, util, config) {
var noCachePrefix = &#39;seajs-ts=&#39;
var noCacheTimeStamp = noCachePrefix + util.now()
// Async inserted script
var loaderScript = document.getElementById(&#39;seajsnode&#39;)
// Static script
if (!loaderScript) {
var scripts = document.getElementsByTagName(&#39;script&#39;)
loaderScript = scripts[scripts.length - 1]
}
var loaderSrc = util.getScriptAbsoluteSrc(loaderScript) ||
util.pageUri // When sea.js is inline, set base to pageUri.
var base = util.dirname(getLoaderActualSrc(loaderSrc))
util.loaderDir = base
// When src is &quot;http://test.com/libs/seajs/1.0.0/sea.js&quot;, redirect base
// to &quot;http://test.com/libs/&quot;
var match = base.match(/^(.+\/)seajs\/[\d\.]+\/$/)
if (match) {
base = match[1]
}
config.base = base
var dataMain = loaderScript.getAttribute(&#39;data-main&#39;)
if (dataMain) {
config.main = dataMain
}
// The default charset of module file.
config.charset = &#39;utf-8&#39;
/**
* The function to configure the framework
* config({
* &#39;base&#39;: &#39;path/to/base&#39;,
* &#39;alias&#39;: {
* &#39;app&#39;: &#39;biz/xx&#39;,
* &#39;jquery&#39;: &#39;jquery-1.5.2&#39;,
* &#39;cart&#39;: &#39;cart?t=20110419&#39;
* },
* &#39;map&#39;: [
* [&#39;test.cdn.cn&#39;, &#39;localhost&#39;]
* ],
* preload: [],
* charset: &#39;utf-8&#39;,
* debug: false
* })
*
*/
seajs.config = function(o) {
for (var k in o) {
if (!o.hasOwnProperty(k)) continue
var previous = config[k]
var current = o[k]
if (previous && k === &#39;alias&#39;) {
for (var p in current) {
if (current.hasOwnProperty(p)) {
var prevValue = previous[p]
var currValue = current[p]
// Converts {jquery: &#39;1.7.2&#39;} to {jquery: &#39;jquery/1.7.2/jquery&#39;}
if (/^\d+\.\d+\.\d+$/.test(currValue)) {
currValue = p + &#39;/&#39; + currValue + &#39;/&#39; + p
}
checkAliasConflict(prevValue, currValue, p)
previous[p] = currValue
}
}
}
else if (previous && (k === &#39;map&#39; || k === &#39;preload&#39;)) {
// for config({ preload: &#39;some-module&#39; })
if (util.isString(current)) {
current = [current]
}
util.forEach(current, function(item) {
if (item) {
previous.push(item)
}
})
}
else {
config[k] = current
}
}
// Makes sure config.base is an absolute path.
var base = config.base
if (base && !util.isAbsolute(base)) {
config.base = util.id2Uri((util.isRoot(base) ? &#39;&#39; : &#39;./&#39;) + base + &#39;/&#39;)
}
// Uses map to implement nocache.
if (config.debug === 2) {
config.debug = 1
seajs.config({
map: [
[/^.*$/, function(url) {
if (url.indexOf(noCachePrefix) === -1) {
url += (url.indexOf(&#39;?&#39;) === -1 ? &#39;?&#39; : &#39;&&#39;) + noCacheTimeStamp
}
return url
}]
]
})
}
debugSync()
return this
}
function debugSync() {
if (config.debug) {
// For convenient reference
seajs.debug = !!config.debug
}
}
debugSync()
function getLoaderActualSrc(src) {
if (src.indexOf(&#39;??&#39;) === -1) {
return src
}
// Such as: http://cdn.com/??seajs/1.2.0/sea.js,jquery/1.7.2/jquery.js
// Only support nginx combo style rule. If you use other combo rule, please
// explicitly config the base path and the alias for plugins.
var parts = src.split(&#39;??&#39;)
var root = parts[0]
var paths = util.filter(parts[1].split(&#39;,&#39;), function(str) {
return str.indexOf(&#39;sea.js&#39;) !== -1
})
return root + paths[0]
}
function checkAliasConflict(previous, current, key) {
if (previous && previous !== current) {
util.log(&#39;The alias config is conflicted:&#39;,
&#39;key =&#39;, &#39;&quot;&#39; + key + &#39;&quot;&#39;,
&#39;previous =&#39;, &#39;&quot;&#39; + previous + &#39;&quot;&#39;,
&#39;current =&#39;, &#39;&quot;&#39; + current + &#39;&quot;&#39;,
&#39;warn&#39;)
}
}
})(seajs, seajs._util, seajs._config)
/**
* Prepare for bootstrapping
*/
;(function(seajs, util, global) {
// The safe and convenient version of console.log
seajs.log = util.log
// Creates a stylesheet from a text blob of rules.
seajs.importStyle = util.importStyle
// Sets a alias to `sea.js` directory for loading plugins.
seajs.config({
alias: { seajs: util.loaderDir }
})
// Uses `seajs-xxx` flag to load plugin-xxx.
util.forEach(getStartupPlugins(), function(name) {
seajs.use(&#39;seajs/plugin-&#39; + name)
// Delays `seajs.use` calls to the onload of `mapfile` in debug mode.
if (name === &#39;debug&#39;) {
seajs._use = seajs.use
seajs._useArgs = []
seajs.use = function() { seajs._useArgs.push(arguments); return seajs }
}
})
// Helpers
// -------
function getStartupPlugins() {
var ret = []
var str = global.location.search
// Converts `seajs-xxx` to `seajs-xxx=1`
str = str.replace(/(seajs-\w+)(&|$)/g, &#39;$1=1$2&#39;)
// Add cookie string
str += &#39; &#39; + document.cookie
// Excludes seajs-xxx=0
str.replace(/seajs-(\w+)=[1-9]/g, function(m, name) {
ret.push(name)
})
return util.unique(ret)
}
})(seajs, seajs._util, this)
/**
* The bootstrap and entrances
*/
;(function(seajs, config, global) {
var _seajs = seajs._seajs
// Avoids conflicting when sea.js is loaded multi times.
if (_seajs && !_seajs[&#39;args&#39;]) {
global.seajs = seajs._seajs
return
}
// Assigns to global define.
global.define = seajs.define
// Loads the data-main module automatically.
config.main && seajs.use(config.main)
// Parses the pre-call of seajs.config/seajs.use/define.
// Ref: test/bootstrap/async-3.html
;(function(args) {
if (args) {
var hash = {
0: &#39;config&#39;,
1: &#39;use&#39;,
2: &#39;define&#39;
}
for (var i = 0; i &lt; args.length; i += 2) {
seajs[hash[args[i]]].apply(seajs, args[i + 1])
}
}
})((_seajs || 0)[&#39;args&#39;])
// Add define.amd property for clear indicator.
global.define.cmd = {}
// Keeps clean!
delete seajs.define
delete seajs._util
delete seajs._config
delete seajs._seajs
})(seajs, seajs._config, this)
</pre>
</div>
<div id="right" class="src">
<pre>
<a id='rightstart' tid='leftstart'></a>
/* SeaJS v1.1.0 | seajs.com | MIT Licensed */
/**
* @fileoverview A CommonJS module loader, focused on web.
* @author lifesinger@gmail.com (Frank Wang)
*/
/**
* Base namespace for the framework.
*/
<a id='2' tid='1' class='m'>this</a>.<a id='4' tid='3' class='m'>seajs</a> <a id='6' tid='5' class='m'>=</a> { <a id='8' tid='7' class='m'>_seajs</a>: <a id='10' tid='9' class='m'>this</a>.<a id='12' tid='11' class='m'>seajs</a> };
/**
* @type {string} The version of the framework. It will be replaced
* with &quot;major.minor.patch&quot; when building.
*/
<span class='i'>seajs.version = &#39;1.1.0&#39;;</span>
// Module status:
// 1. downloaded - The script file has been downloaded to the browser.
// 2. define()d - The define() has been executed.
// 3. memoize()d - The module info has been added to memoizedMods.
// 4. require()d - The module.exports is available.
/**
* The private data. Internal use only.
*/
<span class='i'>seajs._data</span> = {
/**
* The configuration data.
*/
config: {
/**
* Debug mode. It will be turned off automatically when compressing.
* @const
*/
debug: &#39;%DEBUG%&#39;,
/**
* Modules that are needed to load before all other modules.
*/
preload: []
},
/**
* Modules that have been memoize()d.
* { uri: { dependencies: [], factory: fn, exports: {} }, ... }
*/
memoizedMods: {},
/**
* Modules in current fetching package.
*/
packageMods: []
};
/**
* The private utils. Internal use only.
*/
seajs._util = {};
/**
* The inner namespace for methods. Internal use only.
*/
seajs._fn = {};
/**
* @fileoverview The minimal language enhancement.
*/
(function(util) {
var toString = Object.prototype.toString;
var AP = Array.prototype;
util.isString = function(val) {
return toString.call(val) === &#39;[object String]&#39;;
};
util.isObject = function(val) {
return val === Object(val);
};
util.isFunction = function(val) {
return toString.call(val) === &#39;[object Function]&#39;;
};
util.isArray = Array.isArray || function(val) {
return toString.call(val) === &#39;[object Array]&#39;;
};
util.indexOf = AP.indexOf ?
function(arr, item) {
return arr.indexOf(item);
} :
function(arr, item) {
for (var i = 0, len = arr.length; i &lt; len; i++) {
if (arr[i] === item) {
return i;
}
}
return -1;
};
var forEach = util.forEach = AP.forEach ?
function(arr, fn) {
arr.forEach(fn);
} :
function(arr, fn) {
for (var i = 0, len = arr.length; i &lt; len; i++) {
fn(arr[i], i, arr);
}
};
util.map = AP.map ?
function(arr, fn) {
return arr.map(fn);
} :
function(arr, fn) {
var ret = [];
forEach(arr, function(item, i, arr) {
ret.push(fn(item, i, arr));
});
return ret;
};
util.filter = AP.filter ?
function(arr, fn) {
return arr.filter(fn);
} :
function(arr, fn) {
var ret = [];
forEach(arr, function(item, i, arr) {
if (fn(item, i, arr)) {
ret.push(item);
}
});
return ret;
};
util.unique = function(arr) {
var ret = [];
var o = {};
forEach(arr, function(item) {
o[item] = 1;
});
if (Object.keys) {
ret = Object.keys(o);
}
else {
for (var p in o) {
if (o.hasOwnProperty(p)) {
ret.push(p);
}
}
}
return ret;
};
util.now = Date.now || function() {
return new Date().getTime();
};
})(seajs._util);
/**
* @fileoverview The error handler.
*/
(function(util, data) {
util.error = function() {
throw join(arguments);
};
util.log = function() {
if (data.config.debug && typeof console !== &#39;undefined&#39;) {
console.log(join(arguments));
}
};
function join(args) {
return Array.prototype.join.call(args, &#39; &#39;);
}
})(seajs._util, seajs._data);
/**
* @fileoverview Core utilities for the framework.
*/
(function(util, data, fn, global) {
var config = data.config;
/**
* Extracts the directory portion of a path.
* dirname(&#39;a/b/c.js&#39;) ==&gt; &#39;a/b/&#39;
* dirname(&#39;d.js&#39;) ==&gt; &#39;./&#39;
* @see http://jsperf.com/regex-vs-split/2
*/
function dirname(path) {
var s = path.match(/.*(?=\/.*$)/);
return (s ? s[0] : &#39;.&#39;) + &#39;/&#39;;
}
/**
* Canonicalizes a path.
* realpath(&#39;./a//b/../c&#39;) ==&gt; &#39;a/c&#39;
*/
function realpath(path) {
// &#39;file:///a//b/c&#39; ==&gt; &#39;file:///a/b/c&#39;
// &#39;http://a//b/c&#39; ==&gt; &#39;http://a/b/c&#39;
path = path.replace(/([^:\/])\/+/g, &#39;$1\/&#39;);
// &#39;a/b/c&#39;, just return.
if (path.indexOf(&#39;.&#39;) === -1) {
return path;
}
var old = path.split(&#39;/&#39;);
var ret = [], part, i = 0, len = old.length;
for (; i &lt; len; i++) {
part = old[i];
if (part === &#39;..&#39;) {
if (ret.length === 0) {
util.error(&#39;Invalid path:&#39;, path);
}
ret.pop();
}
else if (part !== &#39;.&#39;) {
ret.push(part);
}
}
return ret.join(&#39;/&#39;);
}
/**
* Normalizes an url.
*/
function normalize(url) {
url = realpath(url);
// Adds the default &#39;.js&#39; extension except that the url ends with #.
if (/#$/.test(url)) {
url = url.slice(0, -1);
}
else if (url.indexOf(&#39;?&#39;) === -1 && !/\.(?:css|js)$/.test(url)) {
url += &#39;.js&#39;;
}
return url;
}
/**
* Parses alias in the module id. Only parse the first part.
*/
function parseAlias(id) {
// #xxx means xxx is parsed.
if (id.charAt(0) === &#39;#&#39;) {
return id.substring(1);
}
var alias;
// Only top-level id needs to parse alias.
if (isTopLevel(id) && (alias = config.alias)) {
var parts = id.split(&#39;/&#39;);
var first = parts[0];
if (alias.hasOwnProperty(first)) {
parts[0] = alias[first];
id = parts.join(&#39;/&#39;);
}
}
return id;
}
var mapCache = {};
/**
* Maps the module id.
* @param {string} url The url string.
* @param {Array=} map The optional map array.
*/
function parseMap(url, map) {
// config.map: [[match, replace], ...]
map = map || config[&#39;map&#39;] || [];
if (!map.length) return url;
var ret = url;
util.forEach(map, function(rule) {
if (rule && rule.length &gt; 1) {
ret = ret.replace(rule[0], rule[1]);
}
});
mapCache[ret] = url;
return ret;
}
/**
* Gets the original url.
* @param {string} url The url string.
*/
function unParseMap(url) {
return mapCache[url] || url;
}
/**
* Gets the host portion from url.
*/
function getHost(url) {
return url.replace(/^(\w+:\/\/[^\/]*)\/?.*$/, &#39;$1&#39;);
}
/**
* Normalizes pathname to start with &#39;/&#39;
* Ref: https://groups.google.com/forum/#!topic/seajs/9R29Inqk1UU
*/
function normalizePathname(pathname) {
if (pathname.charAt(0) !== &#39;/&#39;) {
pathname = &#39;/&#39; + pathname;
}
return pathname;
}
var loc = global[&#39;location&#39;];
var pageUrl = loc.protocol + &#39;//&#39; + loc.host +
normalizePathname(loc.pathname);
// local file in IE: C:\path\to\xx.js
if (~pageUrl.indexOf(&#39;\\&#39;)) {
pageUrl = pageUrl.replace(/\\/g, &#39;/&#39;);
}
/**
* Converts id to uri.
* @param {string} id The module id.
* @param {string=} refUrl The referenced uri for relative id.
*/
function id2Uri(id, refUrl) {
id = parseAlias(id);
refUrl = refUrl || pageUrl;
var ret;
// absolute id
if (isAbsolute(id)) {
ret = id;
}
// relative id
else if (isRelative(id)) {
// Converts &#39;./a&#39; to &#39;a&#39;, to avoid unnecessary loop in realpath.
id = id.replace(/^\.\//, &#39;&#39;);
ret = dirname(refUrl) + id;
}
// root id
else if (isRoot(id)) {
ret = getHost(refUrl) + id;
}
// top-level id
else {
ret = config.base + &#39;/&#39; + id;
}
return normalize(ret);
}
function isAbsolute(id) {
return ~id.indexOf(&#39;://&#39;) || id.indexOf(&#39;//&#39;) === 0;
}
function isRelative(id) {
return id.indexOf(&#39;./&#39;) === 0 || id.indexOf(&#39;../&#39;) === 0;
}
function isRoot(id) {
return id.charAt(0) === &#39;/&#39; && id.charAt(1) !== &#39;/&#39;;
}
function isTopLevel(id) {
var c = id.charAt(0);
return id.indexOf(&#39;://&#39;) === -1 && c !== &#39;.&#39; && c !== &#39;/&#39;;
}
util.dirname = dirname;
util.realpath = realpath;
util.normalize = normalize;
util.parseAlias = parseAlias;
util.parseMap = parseMap;
util.unParseMap = unParseMap;
util.id2Uri = id2Uri;
util.isAbsolute = isAbsolute;
util.isTopLevel = isTopLevel;
util.pageUrl = pageUrl;
})(seajs._util, seajs._data, seajs._fn, this);
/**
* @fileoverview Utilities for fetching js ans css files.
*/
(function(util, data) {
var head = document.head ||
document.getElementsByTagName(&#39;head&#39;)[0] ||
document.documentElement;
var UA = navigator.userAgent;
var isWebKit = ~UA.indexOf(&#39;AppleWebKit&#39;);
util.getAsset = function(url, callback, charset) {
var isCSS = /\.css(?:\?|$)/i.test(url);
var node = document.createElement(isCSS ? &#39;link&#39; : &#39;script&#39;);
if (charset) {
node.charset = charset;
}
assetOnload(node, callback);
if (isCSS) {
node.rel = &#39;stylesheet&#39;;
node.href = url;
head.appendChild(node); // Keep style cascading order
}
else {
node.async = &#39;async&#39;;
node.src = url;
//For some cache cases in IE 6-8, the script executes before the end
//of the appendChild execution, so to tie an anonymous define
//call to the module name (which is stored on the node), hold on
//to a reference to this node, but clear after the DOM insertion.
currentlyAddingScript = node;
head.insertBefore(node, head.firstChild);
currentlyAddingScript = null;
}
};
function assetOnload(node, callback) {
if (node.nodeName === &#39;SCRIPT&#39;) {
scriptOnload(node, cb);
} else {
styleOnload(node, cb);
}
var timer = setTimeout(function() {
util.log(&#39;Time is out:&#39;, node.src);
cb();
}, data.config.timeout);
function cb() {
if (!cb.isCalled) {
cb.isCalled = true;
clearTimeout(timer);
callback();
}
}
}
function scriptOnload(node, callback) {
node.onload = node.onerror = node.onreadystatechange =
function() {
if (/loaded|complete|undefined/.test(node.readyState)) {
// Ensure only run once
node.onload = node.onerror = node.onreadystatechange = null;
// Reduce memory leak
if (node.parentNode) {
try {
if (node.clearAttributes) {
node.clearAttributes();
}
else {
for (var p in node) delete node[p];
}
} catch (x) {
}
// Remove the script
head.removeChild(node);
}
// Dereference the node
node = undefined;
callback();
}
};
// NOTICE:
// Nothing will happen in Opera when the file status is 404. In this case,
// the callback will be called when time is out.
}
function styleOnload(node, callback) {
// for IE6-9 and Opera
if (node.attachEvent) {
node.attachEvent(&#39;onload&#39;, callback);
// NOTICE:
// 1. &quot;onload&quot; will be fired in IE6-9 when the file is 404, but in
// this situation, Opera does nothing, so fallback to timeout.
// 2. &quot;onerror&quot; doesn&#39;t fire in any browsers!
}
// Polling for Firefox, Chrome, Safari
else {
setTimeout(function() {
poll(node, callback);
}, 0); // Begin after node insertion
}
}
function poll(node, callback) {
if (callback.isCalled) {
return;
}
var isLoaded;
if (isWebKit) {
if (node[&#39;sheet&#39;]) {
isLoaded = true;
}
}
// for Firefox
else if (node[&#39;sheet&#39;]) {
try {
if (node[&#39;sheet&#39;].cssRules) {
isLoaded = true;
}
} catch (ex) {
// NS_ERROR_DOM_SECURITY_ERR
if (ex.code === 1000) {
isLoaded = true;
}
}
}
setTimeout(function() {
if (isLoaded) {
// Place callback in here due to giving time for style rendering.
callback();
} else {
poll(node, callback);
}
}, 1);
}
var currentlyAddingScript;
var interactiveScript;
util.getCurrentScript = function() {
if (currentlyAddingScript) {
return currentlyAddingScript;
}
// For IE6-9 browsers, the script onload event may not fire right
// after the the script is evaluated. Kris Zyp found that it
// could query the script nodes and the one that is in &quot;interactive&quot;
// mode indicates the current script.
// Ref: http://goo.gl/JHfFW
if (interactiveScript &&
interactiveScript.readyState === &#39;interactive&#39;) {
return interactiveScript;
}
var scripts = head.getElementsByTagName(&#39;script&#39;);
for (var i = 0; i &lt; scripts.length; i++) {
var script = scripts[i];
if (script.readyState === &#39;interactive&#39;) {
interactiveScript = script;
return script;
}
}
};
util.getScriptAbsoluteSrc = function(node) {
return node.hasAttribute ? // non-IE6/7
node.src :
// see http://msdn.microsoft.com/en-us/library/ms536429(VS.85).aspx
node.getAttribute(&#39;src&#39;, 4);
};
util.isOpera = ~UA.indexOf(&#39;Opera&#39;);
})(seajs._util, seajs._data);
/**
* references:
* - http://unixpapa.com/js/dyna.html
* - ../test/research/load-js-css/test.html
* - ../test/issues/load-css/test.html
*/
/**
* @fileoverview Module Constructor.
*/
(function(fn) {
/**
* Module constructor.
* @constructor
* @param {string=} id The module id.
* @param {Array.&lt;string&gt;|string=} deps The module dependencies.
* @param {function()|Object} factory The module factory function.
*/
fn.Module = function(id, deps, factory) {
this.id = id;
this.dependencies = deps || [];
this.factory = factory;
};
})(seajs._fn);
/**
* @fileoverview Module authoring format.
*/
(function(util, data, fn) {
/**
* Defines a module.
* @param {string=} id The module id.
* @param {Array.&lt;string&gt;|string=} deps The module dependencies.
* @param {function()|Object} factory The module factory function.
*/
function define(id, deps, factory) {
var argsLen = arguments.length;
// define(factory)
if (argsLen === 1) {
factory = id;
id = undefined;
}
// define(id || deps, factory)
else if (argsLen === 2) {
factory = deps;
deps = undefined;
// define(deps, factory)
if (util.isArray(id)) {
deps = id;
id = undefined;
}
}
// Parse dependencies
if (!util.isArray(deps) && util.isFunction(factory)) {
deps = parseDependencies(factory.toString());
}
// Get url directly for specific modules.
if (id) {
var url = util.id2Uri(id);
}
// Try to derive url in IE6-9 for anonymous modules.
else if (document.attachEvent && !util.isOpera) {
// Try to get the current script
var script = util.getCurrentScript();
if (script) {
url = util.unParseMap(util.getScriptAbsoluteSrc(script));
}
if (!url) {
util.log(&#39;Failed to derive URL from interactive script for:&#39;,
factory.toString());
// NOTE: If the id-deriving methods above is failed, then falls back
// to use onload event to get the url.
}
}
var mod = new fn.Module(id, deps, factory);
if (url) {
util.memoize(url, mod);
data.packageMods.push(mod);
}
else {
// Saves information for &quot;memoizing&quot; work in the onload event.
data.anonymousMod = mod;
}
}
function parseDependencies(code) {
// Parse these `requires`:
// var a = require(&#39;a&#39;);
// someMethod(require(&#39;b&#39;));
// require(&#39;c&#39;);
// ...
// Doesn&#39;t parse:
// someInstance.require(...);
var pattern = /(?:^|[^.])\brequire\s*\(\s*([&quot;&#39;])([^&quot;&#39;\s\)]+)\1\s*\)/g;
var ret = [], match;
code = removeComments(code);
while ((match = pattern.exec(code))) {
if (match[2]) {
ret.push(match[2]);
}
}
return util.unique(ret);
}
// http://lifesinger.github.com/lab/2011/remove-comments-safely/
function removeComments(code) {
return code
.replace(/(?:^|\n|\r)\s*\/\*[\s\S]*?\*\/\s*(?:\r|\n|$)/g, &#39;\n&#39;)
.replace(/(?:^|\n|\r)\s*\/\/.*(?:\r|\n|$)/g, &#39;\n&#39;);
}
fn.define = define;
})(seajs._util, seajs._data, seajs._fn);
/**
* @fileoverview The factory for &quot;require&quot;.
*/
(function(util, data, fn) {
var slice = Array.prototype.slice;
var RP = Require.prototype;
/**
* the require constructor function
* @param {string} id The module id.
*/
function Require(id) {
var context = this.context;
var uri, mod;
// require(mod) ** inner use ONLY.
if (util.isObject(id)) {
mod = id;
uri = mod.id;
}
// NOTICE: id maybe undefined in 404 etc cases.
else if (util.isString(id)) {
uri = RP.resolve(id, context);
mod = data.memoizedMods[uri];
}
// Just return null when:
// 1. the module file is 404.
// 2. the module file is not written with valid module format.
// 3. other error cases.
if (!mod) {
return null;
}
// Checks circular dependencies.
if (isCircular(context, uri)) {
util.log(&#39;Found circular dependencies:&#39;, uri);
return mod.exports;
}
// Initializes module exports.
if (!mod.exports) {
initExports(mod, {
uri: uri,
parent: context
});
}
return mod.exports;
}
/**
* Use the internal require() machinery to look up the location of a module,
* but rather than loading the module, just return the resolved filepath.
*
* @param {string|Array.&lt;string&gt;} ids The module ids to be resolved.
* @param {Object=} context The context of require function.
*/
RP.resolve = function(ids, context) {
if (util.isString(ids)) {
return util.id2Uri(ids, (context || this.context || {}).uri);
}
return util.map(ids, function(id) {
return RP.resolve(id, context);
});
};
/**
* Loads the specified modules asynchronously and execute the optional
* callback when complete.
* @param {Array.&lt;string&gt;} ids The specified modules.
* @param {function(*)=} callback The optional callback function.
*/
RP.async = function(ids, callback) {
fn.load(ids, callback, this.context);
};
/**
* Plugin can override this method to add custom loading.
*/
RP.load = function(uri, callback, charset) {
util.getAsset(uri, callback, charset);
};
/**
* The factory of &quot;require&quot; function.
* @param {Object} context The data related to &quot;require&quot; instance.
*/
function createRequire(context) {
// context: {
// uri: &#39;&#39;,
// parent: context
// }
var that = { context: context || {} };
function require(id) {
return Require.call(that, id);
}
require.constructor = Require;
for (var p in RP) {
if (RP.hasOwnProperty(p)) {
(function(name) {
require[name] = function() {
return RP[name].apply(that, slice.call(arguments));
};
})(p);
}
}
return require;
}
function initExports(mod, context) {
var ret;
var factory = mod.factory;
mod.exports = {};
delete mod.factory;
delete mod.ready;
if (util.isFunction(factory)) {
ret = factory(createRequire(context), mod.exports, mod);
if (ret !== undefined) {
mod.exports = ret;
}
}
else if (factory !== undefined) {
mod.exports = factory;
}
}
function isCircular(context, uri) {
if (context.uri === uri) {
return true;
}
if (context.parent) {
return isCircular(context.parent, uri);
}
return false;
}
fn.Require = Require;
fn.createRequire = createRequire;
})(seajs._util, seajs._data, seajs._fn);
/**
* @fileoverview Loads a module and gets it ready to be require()d.
*/
(function(util, data, fn) {
/**
* Modules that are being downloaded.
* { uri: scriptNode, ... }
*/
var fetchingMods = {};
var callbackList = {};
var memoizedMods = data.memoizedMods;
var config = data.config;
var RP = fn.Require.prototype;
/**
* Loads preload modules before callback.
* @param {function()} callback The callback function.
*/
function preload(callback) {
var preloadMods = config.preload;
var len = preloadMods.length;
if (len) {
config.preload = preloadMods.slice(len);
load(preloadMods, function() {
preload(callback);
});
}
else {
callback();
}
}
/**
* Loads modules to the environment.
* @param {Array.&lt;string&gt;} ids An array composed of module id.
* @param {function(*)=} callback The callback function.
* @param {Object=} context The context of current executing environment.
*/
function load(ids, callback, context) {
preload(function() {
if (util.isString(ids)) {
ids = [ids];
}
var uris = RP.resolve(ids, context);
provide(uris, function() {
var require = fn.createRequire(context);
var args = util.map(uris, function(uri) {
return require(data.memoizedMods[uri]);
});
if (callback) {
callback.apply(null, args);
}
});
});
}
/**
* Provides modules to the environment.
* @param {Array.&lt;string&gt;} uris An array composed of module uri.
* @param {function()=} callback The callback function.
*/
function provide(uris, callback) {
var unReadyUris = getUnReadyUris(uris);
if (unReadyUris.length === 0) {
return onProvide();
}
for (var i = 0, n = unReadyUris.length, remain = n; i &lt; n; i++) {
(function(uri) {
if (memoizedMods[uri]) {
onLoad();
} else {
fetch(uri, onLoad);
}
function onLoad() {
// Preload here to make sure that:
// 1. RP.resolve etc. modified by some preload plugins can be used
// immediately in the id resolving logic.
// Ref: issues/plugin-coffee
// 2. The functions provided by the preload modules can be used
// immediately in factories of the following modules.
preload(function() {
var mod = memoizedMods[uri];
if (mod) {
var deps = mod.dependencies;
if (deps.length) {
// Converts deps to absolute id.
deps = mod.dependencies = RP.resolve(deps, {
uri: mod.id
});
}
var m = deps.length;
if (m) {
// if a -&gt; [b -&gt; [c -&gt; [a, e], d]]
// when use([&#39;a&#39;, &#39;b&#39;])
// should remove a from c.deps
deps = removeCyclicWaitingUris(uri, deps);
m = deps.length;
}
if (m) {
remain += m;
provide(deps, function() {
remain -= m;
if (remain === 0) onProvide();
});
}
}
if (--remain === 0) onProvide();
});
}
})(unReadyUris[i]);
}
function onProvide() {
setReadyState(unReadyUris);
callback();
}
}
/**
* Fetches a module file.
* @param {string} uri The module uri.
* @param {function()} callback The callback function.
*/
function fetch(uri, callback) {
if (fetchingMods[uri]) {
callbackList[uri].push(callback);
return;
}
callbackList[uri] = [callback];
fetchingMods[uri] = true;
RP.load(
util.parseMap(uri),
function() {
// Memoize anonymous module
var mod = data.anonymousMod;
if (mod) {
// Don&#39;t override existed module
if (!memoizedMods[uri]) {
memoize(uri, mod);
}
data.anonymousMod = null;
}
// Assign the first module in package to memoizeMos[uri]
// See: test/issues/un-correspondence
mod = data.packageMods[0];
if (mod && !memoizedMods[uri]) {
memoizedMods[uri] = mod;
}
data.packageMods = [];
// Clear
if (fetchingMods[uri]) {
delete fetchingMods[uri];
}
// Call callbackList
if (callbackList[uri]) {
util.forEach(callbackList[uri], function(fn) {
fn();
});
delete callbackList[uri];
}
},
data.config.charset
);
}
// Helpers
/**
* Caches mod info to memoizedMods.
*/
function memoize(uri, mod) {
mod.id = uri; // change id to the absolute path.
memoizedMods[uri] = mod;
}
/**
* Set mod.ready to true when all the requires of the module is loaded.
*/
function setReadyState(uris) {
util.forEach(uris, function(uri) {
if (memoizedMods[uri]) {
memoizedMods[uri].ready = true;
}
});
}
/**
* Removes the &quot;ready = true&quot; uris from input.
*/
function getUnReadyUris(uris) {
return util.filter(uris, function(uri) {
var mod = memoizedMods[uri];
return !mod || !mod.ready;
});
}
/**
* if a -&gt; [b -&gt; [c -&gt; [a, e], d]]
* call removeMemoizedCyclicUris(c, [a, e])
* return [e]
*/
function removeCyclicWaitingUris(uri, deps) {
return util.filter(deps, function(dep) {
return !isCyclicWaiting(memoizedMods[dep], uri);
});
}
function isCyclicWaiting(mod, uri) {
if (!mod || mod.ready) {
return false;
}
var deps = mod.dependencies || [];
if (deps.length) {
if (~util.indexOf(deps, uri)) {
return true;
} else {
for (var i = 0; i &lt; deps.length; i++) {
if (isCyclicWaiting(memoizedMods[deps[i]], uri)) {
return true;
}
}
return false;
}
}
return false;
}
// Public API
util.memoize = memoize;
fn.load = load;
})(seajs._util, seajs._data, seajs._fn);
/**
* @fileoverview The configuration.
*/
(function(host, util, data, fn) {
var config = data.config;
var noCachePrefix = &#39;seajs-ts=&#39;;
var noCacheTimeStamp = noCachePrefix + util.now();
// Async inserted script.
var loaderScript = document.getElementById(&#39;seajsnode&#39;);
// Static script.
if (!loaderScript) {
var scripts = document.getElementsByTagName(&#39;script&#39;);
loaderScript = scripts[scripts.length - 1];
}
var loaderSrc = util.getScriptAbsoluteSrc(loaderScript) ||
util.pageUrl; // When sea.js is inline, set base to pageUrl.
var base = util.dirname(loaderSrc);
util.loaderDir = base;
// When src is &quot;http://test.com/libs/seajs/1.0.0/sea.js&quot;, redirect base
// to &quot;http://test.com/libs/&quot;
var match = base.match(/^(.+\/)seajs\/[\d\.]+\/$/);
if (match) {
base = match[1];
}
config.base = base;
var mainAttr = loaderScript.getAttribute(&#39;data-main&#39;);
if (mainAttr) {
// data-main=&quot;abc&quot; is equivalent to data-main=&quot;./abc&quot;
if (util.isTopLevel(mainAttr)) {
mainAttr = &#39;./&#39; + mainAttr;
}
config.main = mainAttr;
}
// The max time to load a script file.
config.timeout = 20000;
/**
* The function to configure the framework.
* config({
* &#39;base&#39;: &#39;path/to/base&#39;,
* &#39;alias&#39;: {
* &#39;app&#39;: &#39;biz/xx&#39;,
* &#39;jquery&#39;: &#39;jquery-1.5.2&#39;,
* &#39;cart&#39;: &#39;cart?t=20110419&#39;
* },
* &#39;map&#39;: [
* [&#39;test.cdn.cn&#39;, &#39;localhost&#39;]
* ],
* preload: [],
* charset: &#39;utf-8&#39;,
* timeout: 20000, // 20s
* debug: false
* });
*
* @param {Object} o The config object.
*/
fn.config = function(o) {
for (var k in o) {
var previous = config[k];
var current = o[k];
if (previous && k === &#39;alias&#39;) {
for (var p in current) {
if (current.hasOwnProperty(p)) {
checkAliasConflict(previous[p], current[p]);
previous[p] = current[p];
}
}
}
else if (previous && (k === &#39;map&#39; || k === &#39;preload&#39;)) {
// for config({ preload: &#39;some-module&#39; })
if (!util.isArray(current)) {
current = [current];
}
util.forEach(current, function(item) {
if (item) { // Ignore empty string.
previous.push(item);
}
});
// NOTICE: no need to check conflict for map and preload.
}
else {
config[k] = current;
}
}
// Make sure config.base is absolute path.
var base = config.base;
if (base && !util.isAbsolute(base)) {
config.base = util.id2Uri(&#39;./&#39; + base + &#39;#&#39;);
}
// Use map to implement nocache
if (config.debug === 2) {
config.debug = 1;
fn.config({
map: [
[/.*/, function(url) {
if (url.indexOf(noCachePrefix) === -1) {
url += (url.indexOf(&#39;?&#39;) === -1 ? &#39;?&#39; : &#39;&&#39;) + noCacheTimeStamp;
}
return url;
}]
]
});
}
// Sync
if (config.debug) {
host.debug = config.debug;
}
return this;
};
function checkAliasConflict(previous, current) {
if (previous && previous !== current) {
util.error(&#39;Alias is conflicted:&#39;, current);
}
}
})(seajs, seajs._util, seajs._data, seajs._fn);
/**
* @fileoverview Prepare for plugins environment.
*/
(function(data, util, fn, global) {
var config = data.config;
// register plugin names
var alias = {};
var loaderDir = util.loaderDir;
util.forEach(
[&#39;base&#39;, &#39;map&#39;, &#39;text&#39;, &#39;json&#39;, &#39;coffee&#39;, &#39;less&#39;],
function(name) {
name = &#39;plugin-&#39; + name;
alias[name] = loaderDir + name;
});
fn.config({
alias: alias
});
// handle seajs-debug
if (~global.location.search.indexOf(&#39;seajs-debug&#39;) ||
~document.cookie.indexOf(&#39;seajs=1&#39;)) {
fn.config({ debug: 2 });
config.preload.push(&#39;plugin-map&#39;);
}
})(seajs._data, seajs._util, seajs._fn, this);
/**
* @fileoverview The bootstrap and entrances.
*/
(function(host, data, fn) {
/**
* Loads modules to the environment.
* @param {Array.&lt;string&gt;} ids An array composed of module id.
* @param {function(*)=} callback The callback function.
*/
fn.use = function(ids, callback) {
fn.load(ids, callback);
};
// data-main
var mainModuleId = data.config.main;
if (mainModuleId) {
fn.use([mainModuleId]);
}
// Parses the pre-call of seajs.config/seajs.use/define.
// Ref: test/bootstrap/async-3.html
(function(args) {
if (args) {
var hash = {
0: &#39;config&#39;,
1: &#39;use&#39;,
2: &#39;define&#39;
};
for (var i = 0; i &lt; args.length; i += 2) {
fn[hash[args[i]]].apply(host, args[i + 1]);
}
delete host._seajs;
}
})((host._seajs || 0)[&#39;args&#39;]);
})(seajs, seajs._data, seajs._fn);
/**
* @fileoverview The public api of seajs.
*/
(function(host, data, fn, global) {
// Avoids conflicting when sea.js is loaded multi times.
if (host._seajs) {
global.seajs = host._seajs;
return;
}
// SeaJS Loader API:
host.config = fn.config;
host.use = fn.use;
// Module Authoring API:
var previousDefine = global.define;
global.define = fn.define;
// For custom loader name.
host.noConflict = function(all) {
global.seajs = host._seajs;
if (all) {
global.define = previousDefine;
host.define = fn.define;
}
return host;
};
// Keep for plugin developers.
host.pluginSDK = {
util: host._util,
data: host._data
};
// For debug mode.
var debug = data.config.debug;
if (debug) {
host.debug = !!debug;
}
// Keeps clean!
delete host._util;
delete host._data;
delete host._fn;
delete host._seajs;
})(seajs, seajs._data, seajs._fn, this);
</pre>
</div>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment