sea-debug.js 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846
  1. /**
  2. * Sea.js 2.3.0 | seajs.org/LICENSE.md
  3. */
  4. (function(global, undefined) {
  5. // Avoid conflicting when `sea.js` is loaded multiple times
  6. if (global.seajs) {
  7. return
  8. }
  9. var seajs = global.seajs = {
  10. // The current version of Sea.js being used
  11. version: "2.3.0"
  12. }
  13. var data = seajs.data = {}
  14. /**
  15. * util-lang.js - The minimal language enhancement
  16. */
  17. function isType(type) {
  18. return function(obj) {
  19. return {}.toString.call(obj) == "[object " + type + "]"
  20. }
  21. }
  22. var isObject = isType("Object")
  23. var isString = isType("String")
  24. var isArray = Array.isArray || isType("Array")
  25. var isFunction = isType("Function")
  26. var _cid = 0
  27. function cid() {
  28. return _cid++
  29. }
  30. /**
  31. * util-events.js - The minimal events support
  32. */
  33. var events = data.events = {}
  34. // Bind event
  35. seajs.on = function(name, callback) {
  36. var list = events[name] || (events[name] = [])
  37. list.push(callback)
  38. return seajs
  39. }
  40. // Remove event. If `callback` is undefined, remove all callbacks for the
  41. // event. If `event` and `callback` are both undefined, remove all callbacks
  42. // for all events
  43. seajs.off = function(name, callback) {
  44. // Remove *all* events
  45. if (!(name || callback)) {
  46. events = data.events = {}
  47. return seajs
  48. }
  49. var list = events[name]
  50. if (list) {
  51. if (callback) {
  52. for (var i = list.length - 1; i >= 0; i--) {
  53. if (list[i] === callback) {
  54. list.splice(i, 1)
  55. }
  56. }
  57. }
  58. else {
  59. delete events[name]
  60. }
  61. }
  62. return seajs
  63. }
  64. // Emit event, firing all bound callbacks. Callbacks receive the same
  65. // arguments as `emit` does, apart from the event name
  66. var emit = seajs.emit = function(name, data) {
  67. var list = events[name], fn
  68. if (list) {
  69. // Copy callback lists to prevent modification
  70. list = list.slice()
  71. // Execute event callbacks, use index because it's the faster.
  72. for(var i = 0, len = list.length; i < len; i++) {
  73. list[i](data)
  74. }
  75. }
  76. return seajs
  77. }
  78. /**
  79. * util-path.js - The utilities for operating path such as id, uri
  80. */
  81. var DIRNAME_RE = /[^?#]*\//
  82. var DOT_RE = /\/\.\//g
  83. var DOUBLE_DOT_RE = /\/[^/]+\/\.\.\//
  84. var MULTI_SLASH_RE = /([^:/])\/+\//g
  85. // Extract the directory portion of a path
  86. // dirname("a/b/c.js?t=123#xx/zz") ==> "a/b/"
  87. // ref: http://jsperf.com/regex-vs-split/2
  88. function dirname(path) {
  89. return path.match(DIRNAME_RE)[0]
  90. }
  91. // Canonicalize a path
  92. // realpath("http://test.com/a//./b/../c") ==> "http://test.com/a/c"
  93. function realpath(path) {
  94. // /a/b/./c/./d ==> /a/b/c/d
  95. path = path.replace(DOT_RE, "/")
  96. /*
  97. @author wh1100717
  98. a//b/c ==> a/b/c
  99. a///b/////c ==> a/b/c
  100. DOUBLE_DOT_RE matches a/b/c//../d path correctly only if replace // with / first
  101. */
  102. path = path.replace(MULTI_SLASH_RE, "$1/")
  103. // a/b/c/../../d ==> a/b/../d ==> a/d
  104. while (path.match(DOUBLE_DOT_RE)) {
  105. path = path.replace(DOUBLE_DOT_RE, "/")
  106. }
  107. return path
  108. }
  109. // Normalize an id
  110. // normalize("path/to/a") ==> "path/to/a.js"
  111. // NOTICE: substring is faster than negative slice and RegExp
  112. function normalize(path) {
  113. var last = path.length - 1
  114. var lastC = path.charAt(last)
  115. // If the uri ends with `#`, just return it without '#'
  116. if (lastC === "#") {
  117. return path.substring(0, last)
  118. }
  119. return (path.substring(last - 2) === ".js" ||
  120. path.indexOf("?") > 0 ||
  121. lastC === "/") ? path : path + ".js"
  122. }
  123. var PATHS_RE = /^([^/:]+)(\/.+)$/
  124. var VARS_RE = /{([^{]+)}/g
  125. function parseAlias(id) {
  126. var alias = data.alias
  127. return alias && isString(alias[id]) ? alias[id] : id
  128. }
  129. function parsePaths(id) {
  130. var paths = data.paths
  131. var m
  132. if (paths && (m = id.match(PATHS_RE)) && isString(paths[m[1]])) {
  133. id = paths[m[1]] + m[2]
  134. }
  135. return id
  136. }
  137. function parseVars(id) {
  138. var vars = data.vars
  139. if (vars && id.indexOf("{") > -1) {
  140. id = id.replace(VARS_RE, function(m, key) {
  141. return isString(vars[key]) ? vars[key] : m
  142. })
  143. }
  144. return id
  145. }
  146. function parseMap(uri) {
  147. var map = data.map
  148. var ret = uri
  149. if (map) {
  150. for (var i = 0, len = map.length; i < len; i++) {
  151. var rule = map[i]
  152. ret = isFunction(rule) ?
  153. (rule(uri) || uri) :
  154. uri.replace(rule[0], rule[1])
  155. // Only apply the first matched rule
  156. if (ret !== uri) break
  157. }
  158. }
  159. return ret
  160. }
  161. var ABSOLUTE_RE = /^\/\/.|:\//
  162. var ROOT_DIR_RE = /^.*?\/\/.*?\//
  163. function addBase(id, refUri) {
  164. var ret
  165. var first = id.charAt(0)
  166. // Absolute
  167. if (ABSOLUTE_RE.test(id)) {
  168. ret = id
  169. }
  170. // Relative
  171. else if (first === ".") {
  172. ret = realpath((refUri ? dirname(refUri) : data.cwd) + id)
  173. }
  174. // Root
  175. else if (first === "/") {
  176. var m = data.cwd.match(ROOT_DIR_RE)
  177. ret = m ? m[0] + id.substring(1) : id
  178. }
  179. // Top-level
  180. else {
  181. ret = data.base + id
  182. }
  183. // Add default protocol when uri begins with "//"
  184. if (ret.indexOf("//") === 0) {
  185. ret = location.protocol + ret
  186. }
  187. return ret
  188. }
  189. function id2Uri(id, refUri) {
  190. if (!id) return ""
  191. id = parseAlias(id)
  192. id = parsePaths(id)
  193. id = parseVars(id)
  194. id = normalize(id)
  195. var uri = addBase(id, refUri)
  196. uri = parseMap(uri)
  197. return uri
  198. }
  199. var doc = document
  200. var cwd = (!location.href || location.href.indexOf('about:') === 0) ? '' : dirname(location.href)
  201. var scripts = doc.scripts
  202. // Recommend to add `seajsnode` id for the `sea.js` script element
  203. var loaderScript = doc.getElementById("seajsnode") ||
  204. scripts[scripts.length - 1]
  205. // When `sea.js` is inline, set loaderDir to current working directory
  206. var loaderDir = dirname(getScriptAbsoluteSrc(loaderScript) || cwd)
  207. function getScriptAbsoluteSrc(node) {
  208. return node.hasAttribute ? // non-IE6/7
  209. node.src :
  210. // see http://msdn.microsoft.com/en-us/library/ms536429(VS.85).aspx
  211. node.getAttribute("src", 4)
  212. }
  213. // For Developers
  214. seajs.resolve = id2Uri
  215. /**
  216. * util-request.js - The utilities for requesting script and style files
  217. * ref: tests/research/load-js-css/test.html
  218. */
  219. var head = doc.head || doc.getElementsByTagName("head")[0] || doc.documentElement
  220. var baseElement = head.getElementsByTagName("base")[0]
  221. var currentlyAddingScript
  222. var interactiveScript
  223. function request(url, callback, charset) {
  224. var node = doc.createElement("script")
  225. if (charset) {
  226. var cs = isFunction(charset) ? charset(url) : charset
  227. if (cs) {
  228. node.charset = cs
  229. }
  230. }
  231. addOnload(node, callback, url)
  232. node.async = true
  233. node.src = url
  234. // For some cache cases in IE 6-8, the script executes IMMEDIATELY after
  235. // the end of the insert execution, so use `currentlyAddingScript` to
  236. // hold current node, for deriving url in `define` call
  237. currentlyAddingScript = node
  238. // ref: #185 & http://dev.jquery.com/ticket/2709
  239. baseElement ?
  240. head.insertBefore(node, baseElement) :
  241. head.appendChild(node)
  242. currentlyAddingScript = null
  243. }
  244. function addOnload(node, callback, url) {
  245. var supportOnload = "onload" in node
  246. if (supportOnload) {
  247. node.onload = onload
  248. node.onerror = function() {
  249. emit("error", { uri: url, node: node })
  250. onload()
  251. }
  252. }
  253. else {
  254. node.onreadystatechange = function() {
  255. if (/loaded|complete/.test(node.readyState)) {
  256. onload()
  257. }
  258. }
  259. }
  260. function onload() {
  261. // Ensure only run once and handle memory leak in IE
  262. node.onload = node.onerror = node.onreadystatechange = null
  263. // Remove the script to reduce memory leak
  264. if (!data.debug) {
  265. head.removeChild(node)
  266. }
  267. // Dereference the node
  268. node = null
  269. callback()
  270. }
  271. }
  272. function getCurrentScript() {
  273. if (currentlyAddingScript) {
  274. return currentlyAddingScript
  275. }
  276. // For IE6-9 browsers, the script onload event may not fire right
  277. // after the script is evaluated. Kris Zyp found that it
  278. // could query the script nodes and the one that is in "interactive"
  279. // mode indicates the current script
  280. // ref: http://goo.gl/JHfFW
  281. if (interactiveScript && interactiveScript.readyState === "interactive") {
  282. return interactiveScript
  283. }
  284. var scripts = head.getElementsByTagName("script")
  285. for (var i = scripts.length - 1; i >= 0; i--) {
  286. var script = scripts[i]
  287. if (script.readyState === "interactive") {
  288. interactiveScript = script
  289. return interactiveScript
  290. }
  291. }
  292. }
  293. // For Developers
  294. seajs.request = request
  295. /**
  296. * util-deps.js - The parser for dependencies
  297. * ref: tests/research/parse-dependencies/test.html
  298. */
  299. var REQUIRE_RE = /"(?:\\"|[^"])*"|'(?:\\'|[^'])*'|\/\*[\S\s]*?\*\/|\/(?:\\\/|[^\/\r\n])+\/(?=[^\/])|\/\/.*|\.\s*require|(?:^|[^$])\brequire\s*\(\s*(["'])(.+?)\1\s*\)/g
  300. var SLASH_RE = /\\\\/g
  301. function parseDependencies(code) {
  302. var ret = []
  303. code.replace(SLASH_RE, "")
  304. .replace(REQUIRE_RE, function(m, m1, m2) {
  305. if (m2) {
  306. ret.push(m2)
  307. }
  308. })
  309. return ret
  310. }
  311. /**
  312. * module.js - The core of module loader
  313. */
  314. var cachedMods = seajs.cache = {}
  315. var anonymousMeta
  316. var fetchingList = {}
  317. var fetchedList = {}
  318. var callbackList = {}
  319. var STATUS = Module.STATUS = {
  320. // 1 - The `module.uri` is being fetched
  321. FETCHING: 1,
  322. // 2 - The meta data has been saved to cachedMods
  323. SAVED: 2,
  324. // 3 - The `module.dependencies` are being loaded
  325. LOADING: 3,
  326. // 4 - The module are ready to execute
  327. LOADED: 4,
  328. // 5 - The module is being executed
  329. EXECUTING: 5,
  330. // 6 - The `module.exports` is available
  331. EXECUTED: 6
  332. }
  333. function Module(uri, deps) {
  334. this.uri = uri
  335. this.dependencies = deps || []
  336. this.exports = null
  337. this.status = 0
  338. // Who depends on me
  339. this._waitings = {}
  340. // The number of unloaded dependencies
  341. this._remain = 0
  342. }
  343. // Resolve module.dependencies
  344. Module.prototype.resolve = function() {
  345. var mod = this
  346. var ids = mod.dependencies
  347. var uris = []
  348. for (var i = 0, len = ids.length; i < len; i++) {
  349. uris[i] = Module.resolve(ids[i], mod.uri)
  350. }
  351. return uris
  352. }
  353. // Load module.dependencies and fire onload when all done
  354. Module.prototype.load = function() {
  355. var mod = this
  356. // If the module is being loaded, just wait it onload call
  357. if (mod.status >= STATUS.LOADING) {
  358. return
  359. }
  360. mod.status = STATUS.LOADING
  361. // Emit `load` event for plugins such as combo plugin
  362. var uris = mod.resolve()
  363. emit("load", uris)
  364. var len = mod._remain = uris.length
  365. var m
  366. // Initialize modules and register waitings
  367. for (var i = 0; i < len; i++) {
  368. m = Module.get(uris[i])
  369. if (m.status < STATUS.LOADED) {
  370. // Maybe duplicate: When module has dupliate dependency, it should be it's count, not 1
  371. m._waitings[mod.uri] = (m._waitings[mod.uri] || 0) + 1
  372. }
  373. else {
  374. mod._remain--
  375. }
  376. }
  377. if (mod._remain === 0) {
  378. mod.onload()
  379. return
  380. }
  381. // Begin parallel loading
  382. var requestCache = {}
  383. for (i = 0; i < len; i++) {
  384. m = cachedMods[uris[i]]
  385. if (m.status < STATUS.FETCHING) {
  386. m.fetch(requestCache)
  387. }
  388. else if (m.status === STATUS.SAVED) {
  389. m.load()
  390. }
  391. }
  392. // Send all requests at last to avoid cache bug in IE6-9. Issues#808
  393. for (var requestUri in requestCache) {
  394. if (requestCache.hasOwnProperty(requestUri)) {
  395. requestCache[requestUri]()
  396. }
  397. }
  398. }
  399. // Call this method when module is loaded
  400. Module.prototype.onload = function() {
  401. var mod = this
  402. mod.status = STATUS.LOADED
  403. if (mod.callback) {
  404. mod.callback()
  405. }
  406. // Notify waiting modules to fire onload
  407. var waitings = mod._waitings
  408. var uri, m
  409. for (uri in waitings) {
  410. if (waitings.hasOwnProperty(uri)) {
  411. m = cachedMods[uri]
  412. m._remain -= waitings[uri]
  413. if (m._remain === 0) {
  414. m.onload()
  415. }
  416. }
  417. }
  418. // Reduce memory taken
  419. delete mod._waitings
  420. delete mod._remain
  421. }
  422. // Fetch a module
  423. Module.prototype.fetch = function(requestCache) {
  424. var mod = this
  425. var uri = mod.uri
  426. mod.status = STATUS.FETCHING
  427. // Emit `fetch` event for plugins such as combo plugin
  428. var emitData = { uri: uri }
  429. emit("fetch", emitData)
  430. var requestUri = emitData.requestUri || uri
  431. // Empty uri or a non-CMD module
  432. if (!requestUri || fetchedList[requestUri]) {
  433. mod.load()
  434. return
  435. }
  436. if (fetchingList[requestUri]) {
  437. callbackList[requestUri].push(mod)
  438. return
  439. }
  440. fetchingList[requestUri] = true
  441. callbackList[requestUri] = [mod]
  442. // Emit `request` event for plugins such as text plugin
  443. emit("request", emitData = {
  444. uri: uri,
  445. requestUri: requestUri,
  446. onRequest: onRequest,
  447. charset: data.charset
  448. })
  449. if (!emitData.requested) {
  450. requestCache ?
  451. requestCache[emitData.requestUri] = sendRequest :
  452. sendRequest()
  453. }
  454. function sendRequest() {
  455. seajs.request(emitData.requestUri, emitData.onRequest, emitData.charset)
  456. }
  457. function onRequest() {
  458. delete fetchingList[requestUri]
  459. fetchedList[requestUri] = true
  460. // Save meta data of anonymous module
  461. if (anonymousMeta) {
  462. Module.save(uri, anonymousMeta)
  463. anonymousMeta = null
  464. }
  465. // Call callbacks
  466. var m, mods = callbackList[requestUri]
  467. delete callbackList[requestUri]
  468. while ((m = mods.shift())) m.load()
  469. }
  470. }
  471. // Execute a module
  472. Module.prototype.exec = function () {
  473. var mod = this
  474. // When module is executed, DO NOT execute it again. When module
  475. // is being executed, just return `module.exports` too, for avoiding
  476. // circularly calling
  477. if (mod.status >= STATUS.EXECUTING) {
  478. return mod.exports
  479. }
  480. mod.status = STATUS.EXECUTING
  481. // Create require
  482. var uri = mod.uri
  483. function require(id) {
  484. return Module.get(require.resolve(id)).exec()
  485. }
  486. require.resolve = function(id) {
  487. return Module.resolve(id, uri)
  488. }
  489. require.async = function(ids, callback) {
  490. Module.use(ids, callback, uri + "_async_" + cid())
  491. return require
  492. }
  493. // Exec factory
  494. var factory = mod.factory
  495. var exports = isFunction(factory) ?
  496. factory(require, mod.exports = {}, mod) :
  497. factory
  498. if (exports === undefined) {
  499. exports = mod.exports
  500. }
  501. // Reduce memory leak
  502. delete mod.factory
  503. mod.exports = exports
  504. mod.status = STATUS.EXECUTED
  505. // Emit `exec` event
  506. emit("exec", mod)
  507. return exports
  508. }
  509. // Resolve id to uri
  510. Module.resolve = function(id, refUri) {
  511. // Emit `resolve` event for plugins such as text plugin
  512. var emitData = { id: id, refUri: refUri }
  513. emit("resolve", emitData)
  514. return emitData.uri || seajs.resolve(emitData.id, refUri)
  515. }
  516. // Define a module
  517. Module.define = function (id, deps, factory) {
  518. var argsLen = arguments.length
  519. // define(factory)
  520. if (argsLen === 1) {
  521. factory = id
  522. id = undefined
  523. }
  524. else if (argsLen === 2) {
  525. factory = deps
  526. // define(deps, factory)
  527. if (isArray(id)) {
  528. deps = id
  529. id = undefined
  530. }
  531. // define(id, factory)
  532. else {
  533. deps = undefined
  534. }
  535. }
  536. // Parse dependencies according to the module factory code
  537. if (!isArray(deps) && isFunction(factory)) {
  538. deps = parseDependencies(factory.toString())
  539. }
  540. var meta = {
  541. id: id,
  542. uri: Module.resolve(id),
  543. deps: deps,
  544. factory: factory
  545. }
  546. // Try to derive uri in IE6-9 for anonymous modules
  547. if (!meta.uri && doc.attachEvent) {
  548. var script = getCurrentScript()
  549. if (script) {
  550. meta.uri = script.src
  551. }
  552. // NOTE: If the id-deriving methods above is failed, then falls back
  553. // to use onload event to get the uri
  554. }
  555. // Emit `define` event, used in nocache plugin, seajs node version etc
  556. emit("define", meta)
  557. meta.uri ? Module.save(meta.uri, meta) :
  558. // Save information for "saving" work in the script onload event
  559. anonymousMeta = meta
  560. }
  561. // Save meta data to cachedMods
  562. Module.save = function(uri, meta) {
  563. var mod = Module.get(uri)
  564. // Do NOT override already saved modules
  565. if (mod.status < STATUS.SAVED) {
  566. mod.id = meta.id || uri
  567. mod.dependencies = meta.deps || []
  568. mod.factory = meta.factory
  569. mod.status = STATUS.SAVED
  570. emit("save", mod)
  571. }
  572. }
  573. // Get an existed module or create a new one
  574. Module.get = function(uri, deps) {
  575. return cachedMods[uri] || (cachedMods[uri] = new Module(uri, deps))
  576. }
  577. // Use function is equal to load a anonymous module
  578. Module.use = function (ids, callback, uri) {
  579. var mod = Module.get(uri, isArray(ids) ? ids : [ids])
  580. mod.callback = function() {
  581. var exports = []
  582. var uris = mod.resolve()
  583. for (var i = 0, len = uris.length; i < len; i++) {
  584. exports[i] = cachedMods[uris[i]].exec()
  585. }
  586. if (callback) {
  587. callback.apply(global, exports)
  588. }
  589. delete mod.callback
  590. }
  591. mod.load()
  592. }
  593. // Public API
  594. seajs.use = function(ids, callback) {
  595. Module.use(ids, callback, data.cwd + "_use_" + cid())
  596. return seajs
  597. }
  598. Module.define.cmd = {}
  599. global.define = Module.define
  600. // For Developers
  601. seajs.Module = Module
  602. data.fetchedList = fetchedList
  603. data.cid = cid
  604. seajs.require = function(id) {
  605. var mod = Module.get(Module.resolve(id))
  606. if (mod.status < STATUS.EXECUTING) {
  607. mod.onload()
  608. mod.exec()
  609. }
  610. return mod.exports
  611. }
  612. /**
  613. * config.js - The configuration for the loader
  614. */
  615. // The root path to use for id2uri parsing
  616. data.base = loaderDir
  617. // The loader directory
  618. data.dir = loaderDir
  619. // The current working directory
  620. data.cwd = cwd
  621. // The charset for requesting files
  622. data.charset = "utf-8"
  623. // data.alias - An object containing shorthands of module id
  624. // data.paths - An object containing path shorthands in module id
  625. // data.vars - The {xxx} variables in module id
  626. // data.map - An array containing rules to map module uri
  627. // data.debug - Debug mode. The default value is false
  628. seajs.config = function(configData) {
  629. for (var key in configData) {
  630. var curr = configData[key]
  631. var prev = data[key]
  632. // Merge object config such as alias, vars
  633. if (prev && isObject(prev)) {
  634. for (var k in curr) {
  635. prev[k] = curr[k]
  636. }
  637. }
  638. else {
  639. // Concat array config such as map
  640. if (isArray(prev)) {
  641. curr = prev.concat(curr)
  642. }
  643. // Make sure that `data.base` is an absolute path
  644. else if (key === "base") {
  645. // Make sure end with "/"
  646. if (curr.slice(-1) !== "/") {
  647. curr += "/"
  648. }
  649. curr = addBase(curr)
  650. }
  651. // Set config
  652. data[key] = curr
  653. }
  654. }
  655. emit("config", configData)
  656. return seajs
  657. }
  658. })(this);