specialgirlgotoheaven / time-Schedule

timeSchedule;绘制时间计划,周计划,假日计划
1 stars 0 forks source link

seajs源码阅读 #28

Open specialgirlgotoheaven opened 6 years ago

specialgirlgotoheaven commented 6 years ago

https://blog.csdn.net/qq_26708777/article/list/2?t=1

specialgirlgotoheaven commented 6 years ago

/**

// Avoid conflicting when sea.js is loaded multiple times if (global.seajs) { return }

var seajs = global.seajs = { // The current version of Sea.js being used version: "2.2.1" }

var data = seajs.data = {}

/**

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 _cid = 0 function cid() { return _cid++ }

/**

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) { var list = events[name], fn

if (list) { // Copy callback lists to prevent modification list = list.slice() var args = Array.prototype.slice.call(arguments, 1); // Execute event callbacks while ((fn = list.shift())) { fn.apply(null, args); } }

return seajs }

/**

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

/**

var head = doc.head || doc.getElementsByTagName("head")[0] || doc.documentElement var baseElement = head.getElementsByTagName("base")[0]

var IS_CSS_RE = /.css(?:\?|$)/i var currentlyAddingScript var interactiveScript

// onload event is not supported in WebKit < 535.23 and Firefox < 9.0 // ref: // - https://bugs.webkit.org/show_activity.cgi?id=38995 // - https://bugzilla.mozilla.org/show_bug.cgi?id=185236 // - https://developer.mozilla.org/en/HTML/Element/link#Stylesheet_load_events var isOldWebKit = +navigator.userAgent .replace(/.(?:AppleWebKit|AndroidWebKit)\/(\d+)./, "$1") < 536

function request(url, callback, charset) { var isCSS = IS_CSS_RE.test(url) var node = doc.createElement(isCSS ? "link" : "script")

if (charset) { var cs = isFunction(charset) ? charset(url) : charset if (cs) { node.charset = cs } }

addOnload(node, callback, isCSS, url)

if (isCSS) { node.rel = "stylesheet" node.href = url } else { node.async = true node.src = url }

// For some cache cases in IE 6-8, the script executes IMMEDIATELY after // the end of the insert execution, so use currentlyAddingScript to // hold current node, for deriving url in define call currentlyAddingScript = node

// ref: #185 & http://dev.jquery.com/ticket/2709 baseElement ? head.insertBefore(node, baseElement) : head.appendChild(node)

currentlyAddingScript = null }

function addOnload(node, callback, isCSS, url) { var supportOnload = "onload" in node

// for Old WebKit and Old Firefox if (isCSS && (isOldWebKit || !supportOnload)) { setTimeout(function() { pollCss(node, callback) }, 1) // Begin after node insertion return }

if (supportOnload) { node.onload = onload node.onerror = function() { emit("error", { uri: url, node: node }) onload() } } else { node.onreadystatechange = function() { if (/loaded|complete/.test(node.readyState)) { onload() } } }

function onload() { // 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 (!isCSS && !data.debug) {
  head.removeChild(node)
}

// Dereference the node
node = null

callback()

} }

function pollCss(node, callback) { var sheet = node.sheet var isLoaded

// for WebKit < 536 if (isOldWebKit) { if (sheet) { isLoaded = true } } // for Firefox < 9.0 else if (sheet) { try { if (sheet.cssRules) { isLoaded = true } } catch (ex) { // The value of ex.name is changed from "NS_ERROR_DOM_SECURITY_ERR" // to "SecurityError" since Firefox 13.0. But Firefox is less than 9.0 // in here, So it is ok to just rely on "NS_ERROR_DOM_SECURITY_ERR" if (ex.name === "NS_ERROR_DOM_SECURITY_ERR") { isLoaded = true } } }

setTimeout(function() { if (isLoaded) { // Place callback here to give time for style rendering callback() } else { pollCss(node, callback) } }, 20) }

function getCurrentScript() { if (currentlyAddingScript) { return currentlyAddingScript }

// For IE6-9 browsers, the script onload event may not fire right // after the script is evaluated. Kris Zyp found that it // could query the script nodes and the one that is in "interactive" // mode indicates the current script // ref: http://goo.gl/JHfFW if (interactiveScript && interactiveScript.readyState === "interactive") { return interactiveScript }

var scripts = head.getElementsByTagName("script")

for (var i = scripts.length - 1; i >= 0; i--) { var script = scripts[i] if (script.readyState === "interactive") { interactiveScript = script return interactiveScript } } }

// For Developers seajs.request = request

/**

var REQUIRE_RE = /"(?:\"|[^"])"|'(?:\'|[^'])'|\/*[\S\s]?*\/|\/(?:\\/|[^\/\r\n])+\/(?=[^\/])|\/\/.|.\srequire|(?:^|[^$])\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 }

/**

var cachedMods = seajs.cache = {} var anonymousMeta

var fetchingList = {} var fetchedList = {} var callbackList = {}

var STATUS = Module.STATUS = { // 1 - The module.uri is being fetched FETCHING: 1, // 2 - The meta data has been saved to cachedMods SAVED: 2, // 3 - The module.dependencies are being loaded LOADING: 3, // 4 - The module are ready to execute LOADED: 4, // 5 - The module is being executed EXECUTING: 5, // 6 - The module.exports is available EXECUTED: 6 }

function Module(uri, deps) { this.uri = uri this.dependencies = deps || [] this.exports = null this.status = 0

// Who depends on me this._waitings = {}

// The number of unloaded dependencies this._remain = 0 }

// Resolve module.dependencies Module.prototype.resolve = function() { var mod = this var ids = mod.dependencies var uris = []

for (var i = 0, len = ids.length; i < len; i++) { uris[i] = Module.resolve(ids[i], mod.uri) } return uris }

// Load module.dependencies and fire onload when all done Module.prototype.load = function() { var mod = this

// If the module is being loaded, just wait it onload call if (mod.status >= STATUS.LOADING) { return }

mod.status = STATUS.LOADING

// Emit load event for plugins such as combo plugin var uris = mod.resolve() emit("load", uris, mod)

var len = mod._remain = uris.length var m

// Initialize modules and register waitings for (var i = 0; i < len; i++) { m = Module.get(uris[i])

if (m.status < STATUS.LOADED) {
  // Maybe duplicate: When module has dupliate dependency, it should be it's count, not 1
  m._waitings[mod.uri] = (m._waitings[mod.uri] || 0) + 1
}
else {
  mod._remain--
}

}

if (mod._remain === 0) { mod.onload() return }

// Begin parallel loading var requestCache = {}

for (i = 0; i < len; i++) { m = cachedMods[uris[i]]

if (m.status < STATUS.FETCHING) {
  m.fetch(requestCache)
}
else if (m.status === STATUS.SAVED) {
  m.load()
}

}

// Send all requests at last to avoid cache bug in IE6-9. Issues#808 for (var requestUri in requestCache) { if (requestCache.hasOwnProperty(requestUri)) { requestCache[requestUri]() } } }

// Call this method when module is loaded Module.prototype.onload = function() { var mod = this mod.status = STATUS.LOADED

if (mod.callback) { mod.callback() }

// Notify waiting modules to fire onload var waitings = mod._waitings var uri, m

for (uri in waitings) { if (waitings.hasOwnProperty(uri)) { m = cachedMods[uri] m._remain -= waitings[uri] if (m._remain === 0) { m.onload() } } }

// Reduce memory taken delete mod._waitings delete mod._remain }

// Fetch a module Module.prototype.fetch = function(requestCache) { var mod = this var uri = mod.uri

mod.status = STATUS.FETCHING

// Emit fetch event for plugins such as combo plugin var emitData = { uri: uri } emit("fetch", emitData) var requestUri = emitData.requestUri || uri

// Empty uri or a non-CMD module if (!requestUri || fetchedList[requestUri]) { mod.load() return }

if (fetchingList[requestUri]) { callbackList[requestUri].push(mod) return }

fetchingList[requestUri] = true callbackList[requestUri] = [mod]

// Emit request event for plugins such as text plugin emit("request", emitData = { uri: uri, requestUri: requestUri, onRequest: onRequest, charset: data.charset })

if (!emitData.requested) { requestCache ? requestCache[emitData.requestUri] = sendRequest : sendRequest() }

function sendRequest() { seajs.request(emitData.requestUri, emitData.onRequest, emitData.charset) }

function onRequest() { delete fetchingList[requestUri] fetchedList[requestUri] = true

// Save meta data of anonymous module
if (anonymousMeta) {
  Module.save(uri, anonymousMeta)
  anonymousMeta = null
}

// Call callbacks
var m, mods = callbackList[requestUri]
delete callbackList[requestUri]
while ((m = mods.shift())) m.load()

} }

// Execute a module Module.prototype.exec = function () { var mod = this

// When module is executed, DO NOT execute it again. When module // is being executed, just return module.exports too, for avoiding // circularly calling if (mod.status >= STATUS.EXECUTING) { return mod.exports }

mod.status = STATUS.EXECUTING

// Create require var uri = mod.uri

function require(id) { return Module.get(require.resolve(id)).exec() }

require.resolve = function(id) { return Module.resolve(id, uri) }

require.async = function(ids, callback) { Module.use(ids, callback, uri + "async" + cid()) return require }

// Exec factory var factory = mod.factory

var exports = isFunction(factory) ? factory(require, mod.exports = {}, mod) : factory

if (exports === undefined) { exports = mod.exports }

// Reduce memory leak delete mod.factory

mod.exports = exports mod.status = STATUS.EXECUTED

// Emit exec event emit("exec", mod)

return exports }

// Resolve id to uri Module.resolve = function(id, refUri) { // Emit resolve event for plugins such as text plugin var emitData = { id: id, refUri: refUri } emit("resolve", emitData)

return emitData.uri || seajs.resolve(emitData.id, refUri) }

// Define a module Module.define = function (id, deps, factory) { var argsLen = arguments.length

// define(factory) if (argsLen === 1) { factory = id id = undefined } else if (argsLen === 2) { factory = deps

// define(deps, factory)
if (isArray(id)) {
  deps = id
  id = undefined
}
// define(id, factory)
else {
  deps = undefined
}

}

// Parse dependencies according to the module factory code if (!isArray(deps) && isFunction(factory)) { deps = parseDependencies(factory.toString()) }

var meta = { id: id, uri: Module.resolve(id), deps: deps, factory: factory }

// Try to derive uri in IE6-9 for anonymous modules if (!meta.uri && doc.attachEvent) { var script = getCurrentScript()

if (script) {
  meta.uri = script.src
}

// NOTE: If the id-deriving methods above is failed, then falls back
// to use onload event to get the uri

}

// Emit define event, used in nocache plugin, seajs node version etc emit("define", meta)

meta.uri ? Module.save(meta.uri, meta) : // Save information for "saving" work in the script onload event anonymousMeta = meta }

// Save meta data to cachedMods Module.save = function(uri, meta) { var mod = Module.get(uri)

// Do NOT override already saved modules if (mod.status < STATUS.SAVED) { mod.id = meta.id || uri mod.dependencies = meta.deps || [] mod.factory = meta.factory mod.status = STATUS.SAVED } }

// Get an existed module or create a new one Module.get = function(uri, deps) { return cachedMods[uri] || (cachedMods[uri] = new Module(uri, deps)) }

// Use function is equal to load a anonymous module Module.use = function (ids, callback, uri) { var mod = Module.get(uri, isArray(ids) ? ids : [ids])

mod.callback = function() { var exports = [] var uris = mod.resolve()

for (var i = 0, len = uris.length; i < len; i++) {
  exports[i] = cachedMods[uris[i]].exec()
}

if (callback) {
  callback.apply(global, exports)
}

delete mod.callback

}

mod.load() }

// Load preload modules before all other modules Module.preload = function(callback) { var preloadMods = data.preload var len = preloadMods.length

if (len) { Module.use(preloadMods, function() { // Remove the loaded preload modules preloadMods.splice(0, len)

  // Allow preload modules to add new preload modules
  Module.preload(callback)
}, data.cwd + "_preload_" + cid())

} else { callback() } }

// Public API

seajs.use = function(ids, callback) { Module.preload(function() { Module.use(ids, callback, data.cwd + "use" + cid()) }) return seajs }

Module.define.cmd = {} global.define = Module.define

// For Developers

seajs.Module = Module data.fetchedList = fetchedList data.cid = cid

seajs.require = function(id) { var mod = Module.get(Module.resolve(id)) if (mod.status < STATUS.EXECUTING) { mod.onload() mod.exec() } return mod.exports }

/**

var BASE_RE = /^(.+?\/)(\?\?)?(seajs\/)+/

// The root path to use for id2uri parsing // If loaderUri is http://test.com/libs/seajs/[??][seajs/1.2.3/]sea.js, the // baseUri should be http://test.com/libs/ data.base = (loaderDir.match(BASE_RE) || ["", loaderDir])[1]

// The loader directory data.dir = loaderDir

// The current working directory data.cwd = cwd

// The charset for requesting files data.charset = "utf-8"

// Modules that are needed to load before all other modules data.preload = (function() { var plugins = []

// Convert seajs-xxx to seajs-xxx=1 // NOTE: use seajs-xxx=1 flag in uri or cookie to preload seajs-xxx var str = location.search.replace(/(seajs-\w+)(&|$)/g, "$1=1$2")

// Add cookie string str += " " + doc.cookie

// Exclude seajs-xxx=0 str.replace(/(seajs-\w+)=1/g, function(m, name) { plugins.push(name) })

return plugins })()

// data.alias - An object containing shorthands of module id // data.paths - An object containing path shorthands in module id // data.vars - The {xxx} variables in module id // data.map - An array containing rules to map module uri // data.debug - Debug mode. The default value is false

seajs.config = function(configData) {

for (var key in configData) { var curr = configData[key] var prev = data[key]

// Merge object config such as alias, vars
if (prev && isObject(prev)) {
  for (var k in curr) {
    prev[k] = curr[k]
  }
}
else {
  // Concat array config such as map, preload
  if (isArray(prev)) {
    curr = prev.concat(curr)
  }
  // Make sure that `data.base` is an absolute path
  else if (key === "base") {
    // Make sure end with "/"
    if (curr.slice(-1) !== "/") {
      curr += "/"
    }
    curr = addBase(curr)
  }

  // Set config
  data[key] = curr
}

}

emit("config", configData) return seajs }

})(this);

specialgirlgotoheaven commented 6 years ago

前端框架 seajs 使用总结 https://blog.csdn.net/qq_26702065/article/details/78399033