requirejs-rails 0.9.1 → 0.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,4 +3,6 @@ module Requirejs
3
3
  class MultipleIncludeError < RuntimeError; end
4
4
  # Raised if the configuration fails validation.
5
5
  class ConfigError < ArgumentError; end
6
+ # Raised if the builder encounters an error.
7
+ class BuildError < RuntimeError; end
6
8
  end
@@ -16,7 +16,11 @@ module Requirejs::Rails
16
16
  end
17
17
 
18
18
  def digest_for(path)
19
- Rails.application.assets.file_digest(path).hexdigest
19
+ if !Rails.application.assets.file_digest(path).nil?
20
+ Rails.application.assets.file_digest(path).hexdigest
21
+ else
22
+ raise Requirejs::BuildError, "Cannot compute digest for missing asset: #{path}"
23
+ end
20
24
  end
21
25
 
22
26
  def generate_rjs_driver
@@ -26,4 +30,4 @@ module Requirejs::Rails
26
30
  end
27
31
  end
28
32
  end
29
- end
33
+ end
@@ -9,16 +9,16 @@ module Requirejs::Rails
9
9
  class Config < ::ActiveSupport::OrderedOptions
10
10
  LOADERS = [ :requirejs, :almond ]
11
11
 
12
- def initialize
12
+ def initialize(application)
13
13
  super
14
14
  self.manifest = nil
15
15
 
16
16
  self.logical_asset_filter = [/\.js$/,/\.html$/,/\.txt$/]
17
- self.tmp_dir = Rails.root + 'tmp'
17
+ self.tmp_dir = application.root + 'tmp'
18
18
  self.bin_dir = Pathname.new(__FILE__+'/../../../../bin').cleanpath
19
19
 
20
20
  self.source_dir = self.tmp_dir + 'assets'
21
- self.target_dir = Rails.root + 'public/assets'
21
+ self.target_dir = application.root + 'public/assets'
22
22
  self.rjs_path = self.bin_dir+'r.js'
23
23
 
24
24
  self.loader = :requirejs
@@ -83,6 +83,7 @@ module Requirejs::Rails
83
83
  skipModuleInsertion
84
84
  skipPragmas
85
85
  uglify
86
+ uglify2
86
87
  useStrict
87
88
  wrap
88
89
  }
@@ -101,7 +102,7 @@ module Requirejs::Rails
101
102
  "modules" => [ { 'name' => 'application' } ]
102
103
  self[:build_config].merge!(self.user_config).slice!(*self.build_config_whitelist)
103
104
  case self.loader
104
- when :requirejs
105
+ when :requirejs
105
106
  # nothing to do
106
107
  when :almond
107
108
  mods = self[:build_config]['modules']
@@ -5,10 +5,9 @@ require 'pathname'
5
5
  module Requirejs
6
6
  module Rails
7
7
  class Engine < ::Rails::Engine
8
-
9
8
  ### Configuration setup
10
- config.before_configuration do
11
- config.requirejs = Requirejs::Rails::Config.new
9
+ config.before_configuration do |app|
10
+ config.requirejs = Requirejs::Rails::Config.new(app)
12
11
  config.requirejs.precompile = [/require\.js$/]
13
12
  end
14
13
 
@@ -17,11 +16,12 @@ module Requirejs
17
16
 
18
17
  # Process the user config file in #before_initalization (instead of #before_configuration) so that
19
18
  # environment-specific configuration can be injected into the user configuration file
20
- process_user_config_file(app, config)
19
+ Engine.process_user_config_file(app, config)
21
20
 
22
21
  config.assets.precompile += config.requirejs.precompile
23
22
 
24
- manifest_path = File.join(::Rails.public_path, config.assets.prefix, "rjs_manifest.yml")
23
+ manifest_directory = config.assets.manifest || File.join(::Rails.public_path, config.assets.prefix)
24
+ manifest_path = File.join(manifest_directory, "rjs_manifest.yml")
25
25
  config.requirejs.manifest_path = Pathname.new(manifest_path)
26
26
  end
27
27
 
@@ -34,21 +34,34 @@ module Requirejs
34
34
  end
35
35
  end
36
36
 
37
- initializer "requirejs.manifest", :after => "sprockets.environment" do |app|
38
- config = app.config
39
- if config.requirejs.manifest_path.exist? && config.assets.digests
40
- rjs_digests = YAML.load(ERB.new(File.new(config.requirejs.manifest_path).read).result)
41
- config.assets.digests.merge!(rjs_digests)
37
+ if ::Rails::VERSION::STRING >= "4.0.0"
38
+ config.after_initialize do |app|
39
+ config = app.config
40
+ rails_manifest_path = File.join(app.root, 'public', config.assets.prefix)
41
+ rails_manifest = Sprockets::Manifest.new(app.assets, rails_manifest_path)
42
+ if config.requirejs.manifest_path.exist? && rails_manifest
43
+ rjs_digests = YAML.load(ERB.new(File.new(config.requirejs.manifest_path).read).result)
44
+ rails_manifest.assets.merge!(rjs_digests)
45
+ ActionView::Base.instance_eval do
46
+ self.assets_manifest = rails_manifest
47
+ end
48
+ end
49
+ end
50
+ else
51
+ initializer "requirejs.manifest", :after => "sprockets.environment" do |app|
52
+ config = app.config
53
+ if config.requirejs.manifest_path.exist? && config.assets.digests
54
+ rjs_digests = YAML.load(ERB.new(File.new(config.requirejs.manifest_path).read).result)
55
+ config.assets.digests.merge!(rjs_digests)
56
+ end
42
57
  end
43
58
  end
44
59
 
45
- private
46
-
47
60
  # Process the user-supplied config parameters, which will be
48
61
  # merged with the default params. It should be a YAML file with
49
62
  # a single top-level hash, keys/values corresponding to require.js
50
63
  # config parameters.
51
- def process_user_config_file(app, config)
64
+ def self.process_user_config_file(app, config)
52
65
  config_path = Pathname.new(app.paths["config"].first)
53
66
  config.requirejs.user_config_file = config_path+'requirejs.yml'
54
67
 
@@ -2,13 +2,19 @@
2
2
  var requirejs = require('<%= rjs_path %>'),
3
3
  //Set up basic config, include config that is
4
4
  //common to all the optimize() calls.
5
- basConfig = <%= JSON.pretty_generate(build_config.reject {|k,v| k == 'modules'}) %>;
5
+ baseConfig = <%=
6
+ modifiedHash = build_config.select {|k, _| k != "modules"}
7
+ pathsHash = modifiedHash["paths"]
8
+ modifiedHash["paths"] = pathsHash.select {|_, v| !v.is_a?(Array)} if !pathsHash.nil?
9
+
10
+ JSON.pretty_generate(modifiedHash)
11
+ %>;
6
12
 
7
13
  // Function used to mix in baseConfig to a new config target
8
14
  function mix(target) {
9
- for (var prop in basConfig) {
10
- if (basConfig.hasOwnProperty(prop)) {
11
- target[prop] = basConfig[prop];
15
+ for (var prop in baseConfig) {
16
+ if (baseConfig.hasOwnProperty(prop)) {
17
+ target[prop] = baseConfig[prop];
12
18
  }
13
19
  }
14
20
  return target;
@@ -20,14 +26,21 @@ var module_specs = [
20
26
  <% end %>
21
27
  ];
22
28
 
29
+ // Error handler invoked in case requirejs compilation fails
30
+ var errback = function(error) {
31
+ process.stderr.write(error.toString());
32
+ process.exit(1);
33
+ }
34
+
23
35
  // Do a series of builds of individual files, using the args suggested by:
24
36
  // http://requirejs.org/docs/optimization.html#onejs
25
37
  //
26
38
  // r.js will eventually need a nested call idiom to handle async
27
39
  // builds. Anticipating that need.
28
40
  var async_runner = module_specs.reduceRight(function(prev, curr) {
29
- return function (buildReportText) {
41
+ return function (buildReportText) {
30
42
  requirejs.optimize(mix(curr), prev);
43
+ requirejs.optimize(mix(curr), prev, errback);
31
44
  };
32
45
  }, function(buildReportText) {} );
33
46
 
@@ -1,6 +1,6 @@
1
1
  module Requirejs
2
2
  module Rails
3
- Version = "0.9.1"
4
- LibVersion = "2.1.2"
3
+ Version = "0.9.2"
4
+ LibVersion = "2.1.10"
5
5
  end
6
6
  end
@@ -10,6 +10,14 @@ require 'tempfile'
10
10
  require 'active_support/ordered_options'
11
11
 
12
12
  namespace :requirejs do
13
+ # This method was backported from an earlier version of Sprockets.
14
+ def ruby_rake_task(task)
15
+ env = ENV["RAILS_ENV"] || "production"
16
+ groups = ENV["RAILS_GROUPS"] || "assets"
17
+ args = [$0, task, "RAILS_ENV=#{env}", "RAILS_GROUPS=#{groups}"]
18
+ args << "--trace" if Rake.application.options.trace
19
+ ruby *args
20
+ end
13
21
 
14
22
  # From Rails 3 assets.rake; we have the same problem:
15
23
  #
@@ -32,7 +40,7 @@ namespace :requirejs do
32
40
  end
33
41
 
34
42
  task :setup => ["assets:environment"] do
35
- unless Rails.application.config.assets.enabled
43
+ unless defined?(Sprockets)
36
44
  warn "Cannot precompile assets if sprockets is disabled. Please set config.assets.enabled to true"
37
45
  exit
38
46
  end
@@ -58,7 +66,7 @@ namespace :requirejs do
58
66
  Unable to find 'node' on the current path, required for precompilation
59
67
  using the requirejs-ruby gem. To install node.js, see http://nodejs.org/
60
68
  OS X Homebrew users can use 'brew install node'.
61
- EOM
69
+ EOM
62
70
  exit 1
63
71
  end
64
72
  end
@@ -73,7 +81,13 @@ EOM
73
81
  # Ensure that Sprockets doesn't try to compress assets before they hit
74
82
  # r.js. Failure to do this can cause a build which works in dev, but
75
83
  # emits require.js "notloaded" errors, etc. in production.
76
- Rails.application.config.assets.js_compressor = false
84
+ #
85
+ # Note that a configuration block is used here to ensure that it runs
86
+ # after the environment ("config/application.rb",
87
+ # "config/environments/*.rb") has been set up.
88
+ Rails.application.config.assets.configure do |env|
89
+ env.js_compressor = nil
90
+ end
77
91
  end
78
92
 
79
93
  # Invoke another ruby process if we're called from inside
@@ -107,9 +121,9 @@ EOM
107
121
  "requirejs:test_node"] do
108
122
  requirejs.config.target_dir.mkpath
109
123
 
110
- `node "#{requirejs.config.driver_path}"`
124
+ result = `node "#{requirejs.config.driver_path}"`
111
125
  unless $?.success?
112
- raise RuntimeError, "Asset compilation with node failed."
126
+ raise RuntimeError, "Asset compilation with node failed with error:\n\n#{result}\n"
113
127
  end
114
128
  end
115
129
 
@@ -125,7 +139,7 @@ EOM
125
139
  FileUtils.cp built_asset_path, digest_asset_path
126
140
 
127
141
  # Create the compressed versions
128
- File.open("#{built_asset_path}.gz",'wb') do |f|
142
+ File.open("#{built_asset_path}.gz", 'wb') do |f|
129
143
  zgw = Zlib::GzipWriter.new(f, Zlib::BEST_COMPRESSION)
130
144
  zgw.write built_asset_path.read
131
145
  zgw.close
@@ -133,7 +147,7 @@ EOM
133
147
  FileUtils.cp "#{built_asset_path}.gz", "#{digest_asset_path}.gz"
134
148
 
135
149
  requirejs.config.manifest_path.open('wb') do |f|
136
- YAML.dump(requirejs.manifest,f)
150
+ YAML.dump(requirejs.manifest, f)
137
151
  end
138
152
  end
139
153
  end
@@ -18,8 +18,8 @@ Gem::Specification.new do |s|
18
18
  s.files = git_files
19
19
  s.require_path = 'lib'
20
20
 
21
- s.add_dependency "railties", ">= 3.1.1", "< 3.3"
22
- s.add_development_dependency "rails", ">= 3.1.1", "<= 3.3"
21
+ s.add_dependency "railties", ">= 3.1.1", "< 4.1"
22
+ s.add_development_dependency "rails", ">= 3.1.1", "< 4.1"
23
23
  s.add_development_dependency "sqlite3"
24
24
 
25
25
  s.requirements << "node.js is required for 'rake assets:precompile', used to run the r.js build"
@@ -24,7 +24,7 @@ end
24
24
 
25
25
  class RequirejsRailsConfigTest < ActiveSupport::TestCase
26
26
  def setup
27
- @cfg = Requirejs::Rails::Config.new
27
+ @cfg = Requirejs::Rails::Config.new(Rails.application)
28
28
  end
29
29
 
30
30
  test "config accepts known loaders" do
@@ -129,7 +129,7 @@ class RequirejsHelperTest < ActionView::TestCase
129
129
 
130
130
  test "requirejs_include_tag_with_param" do
131
131
  render :text => wrap(requirejs_include_tag("application"))
132
- assert_select "script:last-of-type[src^=/javascripts/require.js][data-main^=/javascripts/application]", :count => 1
132
+ assert_select "script:last-of-type[src^=/javascripts/require.js][data-main^=javascripts/application]", :count => 1
133
133
  end
134
134
 
135
135
  test "requirejs_include_tag_with_block" do
@@ -138,7 +138,7 @@ class RequirejsHelperTest < ActionView::TestCase
138
138
  end
139
139
 
140
140
  render :text => wrap(requirejs_include_tag("application", &test_block))
141
- assert_select "script:last-of-type[src^=/javascripts/require.js][data-main^=/javascripts/application]", :count => 1
141
+ assert_select "script:last-of-type[src^=/javascripts/require.js][data-main^=javascripts/application]", :count => 1
142
142
  assert_select "script:last-of-type[src^=/javascripts/require.js][data-class^=TestController]", :count => 1
143
143
  end
144
144
 
@@ -1,5 +1,5 @@
1
1
  /**
2
- * almond 0.2.3 Copyright (c) 2011-2012, The Dojo Foundation All Rights Reserved.
2
+ * almond 0.2.5 Copyright (c) 2011-2012, The Dojo Foundation All Rights Reserved.
3
3
  * Available via the MIT or new BSD license.
4
4
  * see: http://github.com/jrburke/almond for details
5
5
  */
@@ -357,9 +357,15 @@ var requirejs, require, define;
357
357
  if (forceSync) {
358
358
  main(undef, deps, callback, relName);
359
359
  } else {
360
+ //Using a non-zero value because of concern for what old browsers
361
+ //do, and latest browsers "upgrade" to 4 if lower value is used:
362
+ //http://www.whatwg.org/specs/web-apps/current-work/multipage/timers.html#dom-windowtimers-settimeout:
363
+ //If want a value immediately, use require('id') instead -- something
364
+ //that works in almond on the global level, but not guaranteed and
365
+ //unlikely to work in other AMD implementations.
360
366
  setTimeout(function () {
361
367
  main(undef, deps, callback, relName);
362
- }, 15);
368
+ }, 4);
363
369
  }
364
370
 
365
371
  return req;
@@ -371,6 +377,9 @@ var requirejs, require, define;
371
377
  */
372
378
  req.config = function (cfg) {
373
379
  config = cfg;
380
+ if (config.deps) {
381
+ req(config.deps, config.callback);
382
+ }
374
383
  return req;
375
384
  };
376
385
 
@@ -393,4 +402,4 @@ var requirejs, require, define;
393
402
  define.amd = {
394
403
  jQuery: true
395
404
  };
396
- }());
405
+ }());
@@ -1,1993 +1,2068 @@
1
1
  /** vim: et:ts=4:sw=4:sts=4
2
- * @license RequireJS 2.1.2 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved.
2
+ * @license RequireJS 2.1.10 Copyright (c) 2010-2014, The Dojo Foundation All Rights Reserved.
3
3
  * Available via the MIT or new BSD license.
4
4
  * see: http://github.com/jrburke/requirejs for details
5
5
  */
6
6
  //Not using strict: uneven strict support in browsers, #392, and causes
7
7
  //problems with requirejs.exec()/transpiler plugins that may not be strict.
8
8
  /*jslint regexp: true, nomen: true, sloppy: true */
9
- /*global window, navigator, document, importScripts, jQuery, setTimeout, opera */
9
+ /*global window, navigator, document, importScripts, setTimeout, opera */
10
10
 
11
11
  var requirejs, require, define;
12
12
  (function (global) {
13
- var req, s, head, baseElement, dataMain, src,
14
- interactiveScript, currentlyAddingScript, mainScript, subPath,
15
- version = '2.1.2',
16
- commentRegExp = /(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg,
17
- cjsRequireRegExp = /[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g,
18
- jsSuffixRegExp = /\.js$/,
19
- currDirRegExp = /^\.\//,
20
- op = Object.prototype,
21
- ostring = op.toString,
22
- hasOwn = op.hasOwnProperty,
23
- ap = Array.prototype,
24
- aps = ap.slice,
25
- apsp = ap.splice,
26
- isBrowser = !!(typeof window !== 'undefined' && navigator && document),
27
- isWebWorker = !isBrowser && typeof importScripts !== 'undefined',
28
- //PS3 indicates loaded and complete, but need to wait for complete
29
- //specifically. Sequence is 'loading', 'loaded', execution,
30
- // then 'complete'. The UA check is unfortunate, but not sure how
31
- //to feature test w/o causing perf issues.
32
- readyRegExp = isBrowser && navigator.platform === 'PLAYSTATION 3' ?
33
- /^complete$/ : /^(complete|loaded)$/,
34
- defContextName = '_',
35
- //Oh the tragedy, detecting opera. See the usage of isOpera for reason.
36
- isOpera = typeof opera !== 'undefined' && opera.toString() === '[object Opera]',
37
- contexts = {},
38
- cfg = {},
39
- globalDefQueue = [],
40
- useInteractive = false;
41
-
42
- function isFunction(it) {
43
- return ostring.call(it) === '[object Function]';
44
- }
45
-
46
- function isArray(it) {
47
- return ostring.call(it) === '[object Array]';
48
- }
49
-
50
- /**
51
- * Helper function for iterating over an array. If the func returns
52
- * a true value, it will break out of the loop.
53
- */
54
- function each(ary, func) {
55
- if (ary) {
56
- var i;
57
- for (i = 0; i < ary.length; i += 1) {
58
- if (ary[i] && func(ary[i], i, ary)) {
59
- break;
60
- }
61
- }
62
- }
63
- }
64
-
65
- /**
66
- * Helper function for iterating over an array backwards. If the func
67
- * returns a true value, it will break out of the loop.
68
- */
69
- function eachReverse(ary, func) {
70
- if (ary) {
71
- var i;
72
- for (i = ary.length - 1; i > -1; i -= 1) {
73
- if (ary[i] && func(ary[i], i, ary)) {
74
- break;
75
- }
76
- }
77
- }
78
- }
79
-
80
- function hasProp(obj, prop) {
81
- return hasOwn.call(obj, prop);
82
- }
83
-
84
- function getOwn(obj, prop) {
85
- return hasProp(obj, prop) && obj[prop];
86
- }
87
-
88
- /**
89
- * Cycles over properties in an object and calls a function for each
90
- * property value. If the function returns a truthy value, then the
91
- * iteration is stopped.
92
- */
93
- function eachProp(obj, func) {
94
- var prop;
95
- for (prop in obj) {
96
- if (hasProp(obj, prop)) {
97
- if (func(obj[prop], prop)) {
98
- break;
99
- }
100
- }
13
+ var req, s, head, baseElement, dataMain, src,
14
+ interactiveScript, currentlyAddingScript, mainScript, subPath,
15
+ version = '2.1.10',
16
+ commentRegExp = /(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg,
17
+ cjsRequireRegExp = /[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g,
18
+ jsSuffixRegExp = /\.js$/,
19
+ currDirRegExp = /^\.\//,
20
+ op = Object.prototype,
21
+ ostring = op.toString,
22
+ hasOwn = op.hasOwnProperty,
23
+ ap = Array.prototype,
24
+ apsp = ap.splice,
25
+ isBrowser = !!(typeof window !== 'undefined' && typeof navigator !== 'undefined' && window.document),
26
+ isWebWorker = !isBrowser && typeof importScripts !== 'undefined',
27
+ //PS3 indicates loaded and complete, but need to wait for complete
28
+ //specifically. Sequence is 'loading', 'loaded', execution,
29
+ // then 'complete'. The UA check is unfortunate, but not sure how
30
+ //to feature test w/o causing perf issues.
31
+ readyRegExp = isBrowser && navigator.platform === 'PLAYSTATION 3' ?
32
+ /^complete$/ : /^(complete|loaded)$/,
33
+ defContextName = '_',
34
+ //Oh the tragedy, detecting opera. See the usage of isOpera for reason.
35
+ isOpera = typeof opera !== 'undefined' && opera.toString() === '[object Opera]',
36
+ contexts = {},
37
+ cfg = {},
38
+ globalDefQueue = [],
39
+ useInteractive = false;
40
+
41
+ function isFunction(it) {
42
+ return ostring.call(it) === '[object Function]';
101
43
  }
102
- }
103
-
104
- /**
105
- * Simple function to mix in properties from source into target,
106
- * but only if target does not already have a property of the same name.
107
- */
108
- function mixin(target, source, force, deepStringMixin) {
109
- if (source) {
110
- eachProp(source, function (value, prop) {
111
- if (force || !hasProp(target, prop)) {
112
- if (deepStringMixin && typeof value !== 'string') {
113
- if (!target[prop]) {
114
- target[prop] = {};
115
- }
116
- mixin(target[prop], value, force, deepStringMixin);
117
- } else {
118
- target[prop] = value;
119
- }
120
- }
121
- });
122
- }
123
- return target;
124
- }
125
-
126
- //Similar to Function.prototype.bind, but the 'this' object is specified
127
- //first, since it is easier to read/figure out what 'this' will be.
128
- function bind(obj, fn) {
129
- return function () {
130
- return fn.apply(obj, arguments);
131
- };
132
- }
133
-
134
- function scripts() {
135
- return document.getElementsByTagName('script');
136
- }
137
44
 
138
- //Allow getting a global that expressed in
139
- //dot notation, like 'a.b.c'.
140
- function getGlobal(value) {
141
- if (!value) {
142
- return value;
45
+ function isArray(it) {
46
+ return ostring.call(it) === '[object Array]';
143
47
  }
144
- var g = global;
145
- each(value.split('.'), function (part) {
146
- g = g[part];
147
- });
148
- return g;
149
- }
150
-
151
- /**
152
- * Constructs an error with a pointer to an URL with more information.
153
- * @param {String} id the error ID that maps to an ID on a web page.
154
- * @param {String} message human readable error.
155
- * @param {Error} [err] the original error, if there is one.
156
- *
157
- * @returns {Error}
158
- */
159
- function makeError(id, msg, err, requireModules) {
160
- var e = new Error(msg + '\nhttp://requirejs.org/docs/errors.html#' + id);
161
- e.requireType = id;
162
- e.requireModules = requireModules;
163
- if (err) {
164
- e.originalError = err;
165
- }
166
- return e;
167
- }
168
-
169
- if (typeof define !== 'undefined') {
170
- //If a define is already in play via another AMD loader,
171
- //do not overwrite.
172
- return;
173
- }
174
-
175
- if (typeof requirejs !== 'undefined') {
176
- if (isFunction(requirejs)) {
177
- //Do not overwrite and existing requirejs instance.
178
- return;
179
- }
180
- cfg = requirejs;
181
- requirejs = undefined;
182
- }
183
-
184
- //Allow for a require config object
185
- if (typeof require !== 'undefined' && !isFunction(require)) {
186
- //assume it is a config object.
187
- cfg = require;
188
- require = undefined;
189
- }
190
-
191
- function newContext(contextName) {
192
- var inCheckLoaded, Module, context, handlers,
193
- checkLoadedTimeoutId,
194
- config = {
195
- waitSeconds: 7,
196
- baseUrl: './',
197
- paths: {},
198
- pkgs: {},
199
- shim: {},
200
- map: {},
201
- config: {}
202
- },
203
- registry = {},
204
- undefEvents = {},
205
- defQueue = [],
206
- defined = {},
207
- urlFetched = {},
208
- requireCounter = 1,
209
- unnormalizedCounter = 1;
210
48
 
211
49
  /**
212
- * Trims the . and .. from an array of path segments.
213
- * It will keep a leading path segment if a .. will become
214
- * the first path segment, to help with module name lookups,
215
- * which act like paths, but can be remapped. But the end result,
216
- * all paths that use this function should look normalized.
217
- * NOTE: this method MODIFIES the input array.
218
- * @param {Array} ary the array of path segments.
50
+ * Helper function for iterating over an array. If the func returns
51
+ * a true value, it will break out of the loop.
219
52
  */
220
- function trimDots(ary) {
221
- var i, part;
222
- for (i = 0; ary[i]; i += 1) {
223
- part = ary[i];
224
- if (part === '.') {
225
- ary.splice(i, 1);
226
- i -= 1;
227
- } else if (part === '..') {
228
- if (i === 1 && (ary[2] === '..' || ary[0] === '..')) {
229
- //End of the line. Keep at least one non-dot
230
- //path segment at the front so it can be mapped
231
- //correctly to disk. Otherwise, there is likely
232
- //no path mapping for a path starting with '..'.
233
- //This can still fail, but catches the most reasonable
234
- //uses of ..
235
- break;
236
- } else if (i > 0) {
237
- ary.splice(i - 1, 2);
238
- i -= 2;
239
- }
53
+ function each(ary, func) {
54
+ if (ary) {
55
+ var i;
56
+ for (i = 0; i < ary.length; i += 1) {
57
+ if (ary[i] && func(ary[i], i, ary)) {
58
+ break;
59
+ }
60
+ }
240
61
  }
241
- }
242
62
  }
243
63
 
244
64
  /**
245
- * Given a relative module name, like ./something, normalize it to
246
- * a real name that can be mapped to a path.
247
- * @param {String} name the relative name
248
- * @param {String} baseName a real name that the name arg is relative
249
- * to.
250
- * @param {Boolean} applyMap apply the map config to the value. Should
251
- * only be done if this normalization is for a dependency ID.
252
- * @returns {String} normalized name
65
+ * Helper function for iterating over an array backwards. If the func
66
+ * returns a true value, it will break out of the loop.
253
67
  */
254
- function normalize(name, baseName, applyMap) {
255
- var pkgName, pkgConfig, mapValue, nameParts, i, j, nameSegment,
256
- foundMap, foundI, foundStarMap, starI,
257
- baseParts = baseName && baseName.split('/'),
258
- normalizedBaseParts = baseParts,
259
- map = config.map,
260
- starMap = map && map['*'];
261
-
262
- //Adjust any relative paths.
263
- if (name && name.charAt(0) === '.') {
264
- //If have a base name, try to normalize against it,
265
- //otherwise, assume it is a top-level require that will
266
- //be relative to baseUrl in the end.
267
- if (baseName) {
268
- if (getOwn(config.pkgs, baseName)) {
269
- //If the baseName is a package name, then just treat it as one
270
- //name to concat the name with.
271
- normalizedBaseParts = baseParts = [baseName];
272
- } else {
273
- //Convert baseName to array, and lop off the last part,
274
- //so that . matches that 'directory' and not name of the baseName's
275
- //module. For instance, baseName of 'one/two/three', maps to
276
- //'one/two/three.js', but we want the directory, 'one/two' for
277
- //this normalization.
278
- normalizedBaseParts = baseParts.slice(0, baseParts.length - 1);
279
- }
280
-
281
- name = normalizedBaseParts.concat(name.split('/'));
282
- trimDots(name);
283
-
284
- //Some use of packages may use a . path to reference the
285
- //'main' module name, so normalize for that.
286
- pkgConfig = getOwn(config.pkgs, (pkgName = name[0]));
287
- name = name.join('/');
288
- if (pkgConfig && name === pkgName + '/' + pkgConfig.main) {
289
- name = pkgName;
290
- }
291
- } else if (name.indexOf('./') === 0) {
292
- // No baseName, so this is ID is resolved relative
293
- // to baseUrl, pull off the leading dot.
294
- name = name.substring(2);
295
- }
296
- }
297
-
298
- //Apply map config if available.
299
- if (applyMap && (baseParts || starMap) && map) {
300
- nameParts = name.split('/');
301
-
302
- for (i = nameParts.length; i > 0; i -= 1) {
303
- nameSegment = nameParts.slice(0, i).join('/');
304
-
305
- if (baseParts) {
306
- //Find the longest baseName segment match in the config.
307
- //So, do joins on the biggest to smallest lengths of baseParts.
308
- for (j = baseParts.length; j > 0; j -= 1) {
309
- mapValue = getOwn(map, baseParts.slice(0, j).join('/'));
310
-
311
- //baseName segment has config, find if it has one for
312
- //this name.
313
- if (mapValue) {
314
- mapValue = getOwn(mapValue, nameSegment);
315
- if (mapValue) {
316
- //Match, update name to the new value.
317
- foundMap = mapValue;
318
- foundI = i;
319
- break;
68
+ function eachReverse(ary, func) {
69
+ if (ary) {
70
+ var i;
71
+ for (i = ary.length - 1; i > -1; i -= 1) {
72
+ if (ary[i] && func(ary[i], i, ary)) {
73
+ break;
320
74
  }
321
- }
322
75
  }
323
- }
324
-
325
- if (foundMap) {
326
- break;
327
- }
328
-
329
- //Check for a star map match, but just hold on to it,
330
- //if there is a shorter segment match later in a matching
331
- //config, then favor over this star map.
332
- if (!foundStarMap && starMap && getOwn(starMap, nameSegment)) {
333
- foundStarMap = getOwn(starMap, nameSegment);
334
- starI = i;
335
- }
336
- }
337
-
338
- if (!foundMap && foundStarMap) {
339
- foundMap = foundStarMap;
340
- foundI = starI;
341
- }
342
-
343
- if (foundMap) {
344
- nameParts.splice(0, foundI, foundMap);
345
- name = nameParts.join('/');
346
76
  }
347
- }
348
-
349
- return name;
350
77
  }
351
78
 
352
- function removeScript(name) {
353
- if (isBrowser) {
354
- each(scripts(), function (scriptNode) {
355
- if (scriptNode.getAttribute('data-requiremodule') === name &&
356
- scriptNode.getAttribute('data-requirecontext') === context.contextName) {
357
- scriptNode.parentNode.removeChild(scriptNode);
358
- return true;
359
- }
360
- });
361
- }
79
+ function hasProp(obj, prop) {
80
+ return hasOwn.call(obj, prop);
362
81
  }
363
82
 
364
- function hasPathFallback(id) {
365
- var pathConfig = getOwn(config.paths, id);
366
- if (pathConfig && isArray(pathConfig) && pathConfig.length > 1) {
367
- removeScript(id);
368
- //Pop off the first array value, since it failed, and
369
- //retry
370
- pathConfig.shift();
371
- context.require.undef(id);
372
- context.require([id]);
373
- return true;
374
- }
83
+ function getOwn(obj, prop) {
84
+ return hasProp(obj, prop) && obj[prop];
375
85
  }
376
86
 
377
- //Turns a plugin!resource to [plugin, resource]
378
- //with the plugin being undefined if the name
379
- //did not have a plugin prefix.
380
- function splitPrefix(name) {
381
- var prefix,
382
- index = name ? name.indexOf('!') : -1;
383
- if (index > -1) {
384
- prefix = name.substring(0, index);
385
- name = name.substring(index + 1, name.length);
386
- }
387
- return [prefix, name];
87
+ /**
88
+ * Cycles over properties in an object and calls a function for each
89
+ * property value. If the function returns a truthy value, then the
90
+ * iteration is stopped.
91
+ */
92
+ function eachProp(obj, func) {
93
+ var prop;
94
+ for (prop in obj) {
95
+ if (hasProp(obj, prop)) {
96
+ if (func(obj[prop], prop)) {
97
+ break;
98
+ }
99
+ }
100
+ }
388
101
  }
389
102
 
390
103
  /**
391
- * Creates a module mapping that includes plugin prefix, module
392
- * name, and path. If parentModuleMap is provided it will
393
- * also normalize the name via require.normalize()
394
- *
395
- * @param {String} name the module name
396
- * @param {String} [parentModuleMap] parent module map
397
- * for the module name, used to resolve relative names.
398
- * @param {Boolean} isNormalized: is the ID already normalized.
399
- * This is true if this call is done for a define() module ID.
400
- * @param {Boolean} applyMap: apply the map config to the ID.
401
- * Should only be true if this map is for a dependency.
402
- *
403
- * @returns {Object}
104
+ * Simple function to mix in properties from source into target,
105
+ * but only if target does not already have a property of the same name.
404
106
  */
405
- function makeModuleMap(name, parentModuleMap, isNormalized, applyMap) {
406
- var url, pluginModule, suffix, nameParts,
407
- prefix = null,
408
- parentName = parentModuleMap ? parentModuleMap.name : null,
409
- originalName = name,
410
- isDefine = true,
411
- normalizedName = '';
412
-
413
- //If no name, then it means it is a require call, generate an
414
- //internal name.
415
- if (!name) {
416
- isDefine = false;
417
- name = '_@r' + (requireCounter += 1);
418
- }
419
-
420
- nameParts = splitPrefix(name);
421
- prefix = nameParts[0];
422
- name = nameParts[1];
423
-
424
- if (prefix) {
425
- prefix = normalize(prefix, parentName, applyMap);
426
- pluginModule = getOwn(defined, prefix);
427
- }
428
-
429
- //Account for relative paths if there is a base name.
430
- if (name) {
431
- if (prefix) {
432
- if (pluginModule && pluginModule.normalize) {
433
- //Plugin is loaded, use its normalize method.
434
- normalizedName = pluginModule.normalize(name, function (name) {
435
- return normalize(name, parentName, applyMap);
107
+ function mixin(target, source, force, deepStringMixin) {
108
+ if (source) {
109
+ eachProp(source, function (value, prop) {
110
+ if (force || !hasProp(target, prop)) {
111
+ if (deepStringMixin && typeof value === 'object' && value &&
112
+ !isArray(value) && !isFunction(value) &&
113
+ !(value instanceof RegExp)) {
114
+
115
+ if (!target[prop]) {
116
+ target[prop] = {};
117
+ }
118
+ mixin(target[prop], value, force, deepStringMixin);
119
+ } else {
120
+ target[prop] = value;
121
+ }
122
+ }
436
123
  });
437
- } else {
438
- normalizedName = normalize(name, parentName, applyMap);
439
- }
440
- } else {
441
- //A regular module.
442
- normalizedName = normalize(name, parentName, applyMap);
443
-
444
- //Normalized name may be a plugin ID due to map config
445
- //application in normalize. The map config values must
446
- //already be normalized, so do not need to redo that part.
447
- nameParts = splitPrefix(normalizedName);
448
- prefix = nameParts[0];
449
- normalizedName = nameParts[1];
450
- isNormalized = true;
451
-
452
- url = context.nameToUrl(normalizedName);
453
124
  }
454
- }
455
-
456
- //If the id is a plugin id that cannot be determined if it needs
457
- //normalization, stamp it with a unique ID so two matching relative
458
- //ids that may conflict can be separate.
459
- suffix = prefix && !pluginModule && !isNormalized ?
460
- '_unnormalized' + (unnormalizedCounter += 1) :
461
- '';
462
-
463
- return {
464
- prefix: prefix,
465
- name: normalizedName,
466
- parentMap: parentModuleMap,
467
- unnormalized: !!suffix,
468
- url: url,
469
- originalName: originalName,
470
- isDefine: isDefine,
471
- id: (prefix ?
472
- prefix + '!' + normalizedName :
473
- normalizedName) + suffix
474
- };
125
+ return target;
475
126
  }
476
127
 
477
- function getModule(depMap) {
478
- var id = depMap.id,
479
- mod = getOwn(registry, id);
128
+ //Similar to Function.prototype.bind, but the 'this' object is specified
129
+ //first, since it is easier to read/figure out what 'this' will be.
130
+ function bind(obj, fn) {
131
+ return function () {
132
+ return fn.apply(obj, arguments);
133
+ };
134
+ }
480
135
 
481
- if (!mod) {
482
- mod = registry[id] = new context.Module(depMap);
483
- }
136
+ function scripts() {
137
+ return document.getElementsByTagName('script');
138
+ }
484
139
 
485
- return mod;
140
+ function defaultOnError(err) {
141
+ throw err;
486
142
  }
487
143
 
488
- function on(depMap, name, fn) {
489
- var id = depMap.id,
490
- mod = getOwn(registry, id);
144
+ //Allow getting a global that expressed in
145
+ //dot notation, like 'a.b.c'.
146
+ function getGlobal(value) {
147
+ if (!value) {
148
+ return value;
149
+ }
150
+ var g = global;
151
+ each(value.split('.'), function (part) {
152
+ g = g[part];
153
+ });
154
+ return g;
155
+ }
491
156
 
492
- if (hasProp(defined, id) &&
493
- (!mod || mod.defineEmitComplete)) {
494
- if (name === 'defined') {
495
- fn(defined[id]);
157
+ /**
158
+ * Constructs an error with a pointer to an URL with more information.
159
+ * @param {String} id the error ID that maps to an ID on a web page.
160
+ * @param {String} message human readable error.
161
+ * @param {Error} [err] the original error, if there is one.
162
+ *
163
+ * @returns {Error}
164
+ */
165
+ function makeError(id, msg, err, requireModules) {
166
+ var e = new Error(msg + '\nhttp://requirejs.org/docs/errors.html#' + id);
167
+ e.requireType = id;
168
+ e.requireModules = requireModules;
169
+ if (err) {
170
+ e.originalError = err;
496
171
  }
497
- } else {
498
- getModule(depMap).on(name, fn);
499
- }
172
+ return e;
500
173
  }
501
174
 
502
- function onError(err, errback) {
503
- var ids = err.requireModules,
504
- notified = false;
505
-
506
- if (errback) {
507
- errback(err);
508
- } else {
509
- each(ids, function (id) {
510
- var mod = getOwn(registry, id);
511
- if (mod) {
512
- //Set error on module, so it skips timeout checks.
513
- mod.error = err;
514
- if (mod.events.error) {
515
- notified = true;
516
- mod.emit('error', err);
517
- }
518
- }
519
- });
175
+ if (typeof define !== 'undefined') {
176
+ //If a define is already in play via another AMD loader,
177
+ //do not overwrite.
178
+ return;
179
+ }
520
180
 
521
- if (!notified) {
522
- req.onError(err);
181
+ if (typeof requirejs !== 'undefined') {
182
+ if (isFunction(requirejs)) {
183
+ //Do not overwrite and existing requirejs instance.
184
+ return;
523
185
  }
524
- }
186
+ cfg = requirejs;
187
+ requirejs = undefined;
525
188
  }
526
189
 
527
- /**
528
- * Internal method to transfer globalQueue items to this context's
529
- * defQueue.
530
- */
531
- function takeGlobalQueue() {
532
- //Push all the globalDefQueue items into the context's defQueue
533
- if (globalDefQueue.length) {
534
- //Array splice in the values since the context code has a
535
- //local var ref to defQueue, so cannot just reassign the one
536
- //on context.
537
- apsp.apply(defQueue,
538
- [defQueue.length - 1, 0].concat(globalDefQueue));
539
- globalDefQueue = [];
540
- }
190
+ //Allow for a require config object
191
+ if (typeof require !== 'undefined' && !isFunction(require)) {
192
+ //assume it is a config object.
193
+ cfg = require;
194
+ require = undefined;
541
195
  }
542
196
 
543
- handlers = {
544
- 'require': function (mod) {
545
- if (mod.require) {
546
- return mod.require;
547
- } else {
548
- return (mod.require = context.makeRequire(mod.map));
549
- }
550
- },
551
- 'exports': function (mod) {
552
- mod.usingExports = true;
553
- if (mod.map.isDefine) {
554
- if (mod.exports) {
555
- return mod.exports;
556
- } else {
557
- return (mod.exports = defined[mod.map.id] = {});
558
- }
559
- }
560
- },
561
- 'module': function (mod) {
562
- if (mod.module) {
563
- return mod.module;
564
- } else {
565
- return (mod.module = {
566
- id: mod.map.id,
567
- uri: mod.map.url,
568
- config: function () {
569
- return (config.config && getOwn(config.config, mod.map.id)) || {};
197
+ function newContext(contextName) {
198
+ var inCheckLoaded, Module, context, handlers,
199
+ checkLoadedTimeoutId,
200
+ config = {
201
+ //Defaults. Do not set a default for map
202
+ //config to speed up normalize(), which
203
+ //will run faster if there is no default.
204
+ waitSeconds: 7,
205
+ baseUrl: './',
206
+ paths: {},
207
+ bundles: {},
208
+ pkgs: {},
209
+ shim: {},
210
+ config: {}
570
211
  },
571
- exports: defined[mod.map.id]
572
- });
212
+ registry = {},
213
+ //registry of just enabled modules, to speed
214
+ //cycle breaking code when lots of modules
215
+ //are registered, but not activated.
216
+ enabledRegistry = {},
217
+ undefEvents = {},
218
+ defQueue = [],
219
+ defined = {},
220
+ urlFetched = {},
221
+ bundlesMap = {},
222
+ requireCounter = 1,
223
+ unnormalizedCounter = 1;
224
+
225
+ /**
226
+ * Trims the . and .. from an array of path segments.
227
+ * It will keep a leading path segment if a .. will become
228
+ * the first path segment, to help with module name lookups,
229
+ * which act like paths, but can be remapped. But the end result,
230
+ * all paths that use this function should look normalized.
231
+ * NOTE: this method MODIFIES the input array.
232
+ * @param {Array} ary the array of path segments.
233
+ */
234
+ function trimDots(ary) {
235
+ var i, part, length = ary.length;
236
+ for (i = 0; i < length; i++) {
237
+ part = ary[i];
238
+ if (part === '.') {
239
+ ary.splice(i, 1);
240
+ i -= 1;
241
+ } else if (part === '..') {
242
+ if (i === 1 && (ary[2] === '..' || ary[0] === '..')) {
243
+ //End of the line. Keep at least one non-dot
244
+ //path segment at the front so it can be mapped
245
+ //correctly to disk. Otherwise, there is likely
246
+ //no path mapping for a path starting with '..'.
247
+ //This can still fail, but catches the most reasonable
248
+ //uses of ..
249
+ break;
250
+ } else if (i > 0) {
251
+ ary.splice(i - 1, 2);
252
+ i -= 2;
253
+ }
254
+ }
255
+ }
573
256
  }
574
- }
575
- };
576
257
 
577
- function cleanRegistry(id) {
578
- //Clean up machinery used for waiting modules.
579
- delete registry[id];
580
- }
581
-
582
- function breakCycle(mod, traced, processed) {
583
- var id = mod.map.id;
584
-
585
- if (mod.error) {
586
- mod.emit('error', mod.error);
587
- } else {
588
- traced[id] = true;
589
- each(mod.depMaps, function (depMap, i) {
590
- var depId = depMap.id,
591
- dep = getOwn(registry, depId);
592
-
593
- //Only force things that have not completed
594
- //being defined, so still in the registry,
595
- //and only if it has not been matched up
596
- //in the module already.
597
- if (dep && !mod.depMatched[i] && !processed[depId]) {
598
- if (getOwn(traced, depId)) {
599
- mod.defineDep(i, defined[depId]);
600
- mod.check(); //pass false?
601
- } else {
602
- breakCycle(dep, traced, processed);
258
+ /**
259
+ * Given a relative module name, like ./something, normalize it to
260
+ * a real name that can be mapped to a path.
261
+ * @param {String} name the relative name
262
+ * @param {String} baseName a real name that the name arg is relative
263
+ * to.
264
+ * @param {Boolean} applyMap apply the map config to the value. Should
265
+ * only be done if this normalization is for a dependency ID.
266
+ * @returns {String} normalized name
267
+ */
268
+ function normalize(name, baseName, applyMap) {
269
+ var pkgMain, mapValue, nameParts, i, j, nameSegment, lastIndex,
270
+ foundMap, foundI, foundStarMap, starI,
271
+ baseParts = baseName && baseName.split('/'),
272
+ normalizedBaseParts = baseParts,
273
+ map = config.map,
274
+ starMap = map && map['*'];
275
+
276
+ //Adjust any relative paths.
277
+ if (name && name.charAt(0) === '.') {
278
+ //If have a base name, try to normalize against it,
279
+ //otherwise, assume it is a top-level require that will
280
+ //be relative to baseUrl in the end.
281
+ if (baseName) {
282
+ //Convert baseName to array, and lop off the last part,
283
+ //so that . matches that 'directory' and not name of the baseName's
284
+ //module. For instance, baseName of 'one/two/three', maps to
285
+ //'one/two/three.js', but we want the directory, 'one/two' for
286
+ //this normalization.
287
+ normalizedBaseParts = baseParts.slice(0, baseParts.length - 1);
288
+ name = name.split('/');
289
+ lastIndex = name.length - 1;
290
+
291
+ // If wanting node ID compatibility, strip .js from end
292
+ // of IDs. Have to do this here, and not in nameToUrl
293
+ // because node allows either .js or non .js to map
294
+ // to same file.
295
+ if (config.nodeIdCompat && jsSuffixRegExp.test(name[lastIndex])) {
296
+ name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, '');
297
+ }
298
+
299
+ name = normalizedBaseParts.concat(name);
300
+ trimDots(name);
301
+ name = name.join('/');
302
+ } else if (name.indexOf('./') === 0) {
303
+ // No baseName, so this is ID is resolved relative
304
+ // to baseUrl, pull off the leading dot.
305
+ name = name.substring(2);
306
+ }
603
307
  }
604
- }
605
- });
606
- processed[id] = true;
607
- }
608
- }
609
308
 
610
- function checkLoaded() {
611
- var map, modId, err, usingPathFallback,
612
- waitInterval = config.waitSeconds * 1000,
613
- //It is possible to disable the wait interval by using waitSeconds of 0.
614
- expired = waitInterval && (context.startTime + waitInterval) < new Date().getTime(),
615
- noLoads = [],
616
- reqCalls = [],
617
- stillLoading = false,
618
- needCycleCheck = true;
619
-
620
- //Do not bother if this call was a result of a cycle break.
621
- if (inCheckLoaded) {
622
- return;
623
- }
309
+ //Apply map config if available.
310
+ if (applyMap && map && (baseParts || starMap)) {
311
+ nameParts = name.split('/');
312
+
313
+ outerLoop: for (i = nameParts.length; i > 0; i -= 1) {
314
+ nameSegment = nameParts.slice(0, i).join('/');
315
+
316
+ if (baseParts) {
317
+ //Find the longest baseName segment match in the config.
318
+ //So, do joins on the biggest to smallest lengths of baseParts.
319
+ for (j = baseParts.length; j > 0; j -= 1) {
320
+ mapValue = getOwn(map, baseParts.slice(0, j).join('/'));
321
+
322
+ //baseName segment has config, find if it has one for
323
+ //this name.
324
+ if (mapValue) {
325
+ mapValue = getOwn(mapValue, nameSegment);
326
+ if (mapValue) {
327
+ //Match, update name to the new value.
328
+ foundMap = mapValue;
329
+ foundI = i;
330
+ break outerLoop;
331
+ }
332
+ }
333
+ }
334
+ }
335
+
336
+ //Check for a star map match, but just hold on to it,
337
+ //if there is a shorter segment match later in a matching
338
+ //config, then favor over this star map.
339
+ if (!foundStarMap && starMap && getOwn(starMap, nameSegment)) {
340
+ foundStarMap = getOwn(starMap, nameSegment);
341
+ starI = i;
342
+ }
343
+ }
624
344
 
625
- inCheckLoaded = true;
345
+ if (!foundMap && foundStarMap) {
346
+ foundMap = foundStarMap;
347
+ foundI = starI;
348
+ }
626
349
 
627
- //Figure out the state of all the modules.
628
- eachProp(registry, function (mod) {
629
- map = mod.map;
630
- modId = map.id;
350
+ if (foundMap) {
351
+ nameParts.splice(0, foundI, foundMap);
352
+ name = nameParts.join('/');
353
+ }
354
+ }
631
355
 
632
- //Skip things that are not enabled or in error state.
633
- if (!mod.enabled) {
634
- return;
635
- }
356
+ // If the name points to a package's name, use
357
+ // the package main instead.
358
+ pkgMain = getOwn(config.pkgs, name);
636
359
 
637
- if (!map.isDefine) {
638
- reqCalls.push(mod);
360
+ return pkgMain ? pkgMain : name;
639
361
  }
640
362
 
641
- if (!mod.error) {
642
- //If the module should be executed, and it has not
643
- //been inited and time is up, remember it.
644
- if (!mod.inited && expired) {
645
- if (hasPathFallback(modId)) {
646
- usingPathFallback = true;
647
- stillLoading = true;
648
- } else {
649
- noLoads.push(modId);
650
- removeScript(modId);
651
- }
652
- } else if (!mod.inited && mod.fetched && map.isDefine) {
653
- stillLoading = true;
654
- if (!map.prefix) {
655
- //No reason to keep looking for unfinished
656
- //loading. If the only stillLoading is a
657
- //plugin resource though, keep going,
658
- //because it may be that a plugin resource
659
- //is waiting on a non-plugin cycle.
660
- return (needCycleCheck = false);
363
+ function removeScript(name) {
364
+ if (isBrowser) {
365
+ each(scripts(), function (scriptNode) {
366
+ if (scriptNode.getAttribute('data-requiremodule') === name &&
367
+ scriptNode.getAttribute('data-requirecontext') === context.contextName) {
368
+ scriptNode.parentNode.removeChild(scriptNode);
369
+ return true;
370
+ }
371
+ });
661
372
  }
662
- }
663
373
  }
664
- });
665
-
666
- if (expired && noLoads.length) {
667
- //If wait time expired, throw error of unloaded modules.
668
- err = makeError('timeout', 'Load timeout for modules: ' + noLoads, null, noLoads);
669
- err.contextName = context.contextName;
670
- return onError(err);
671
- }
672
-
673
- //Not expired, check for a cycle.
674
- if (needCycleCheck) {
675
- each(reqCalls, function (mod) {
676
- breakCycle(mod, {}, {});
677
- });
678
- }
679
-
680
- //If still waiting on loads, and the waiting load is something
681
- //other than a plugin resource, or there are still outstanding
682
- //scripts, then just try back later.
683
- if ((!expired || usingPathFallback) && stillLoading) {
684
- //Something is still waiting to load. Wait for it, but only
685
- //if a timeout is not already in effect.
686
- if ((isBrowser || isWebWorker) && !checkLoadedTimeoutId) {
687
- checkLoadedTimeoutId = setTimeout(function () {
688
- checkLoadedTimeoutId = 0;
689
- checkLoaded();
690
- }, 50);
374
+
375
+ function hasPathFallback(id) {
376
+ var pathConfig = getOwn(config.paths, id);
377
+ if (pathConfig && isArray(pathConfig) && pathConfig.length > 1) {
378
+ //Pop off the first array value, since it failed, and
379
+ //retry
380
+ pathConfig.shift();
381
+ context.require.undef(id);
382
+ context.require([id]);
383
+ return true;
384
+ }
691
385
  }
692
- }
693
386
 
694
- inCheckLoaded = false;
695
- }
387
+ //Turns a plugin!resource to [plugin, resource]
388
+ //with the plugin being undefined if the name
389
+ //did not have a plugin prefix.
390
+ function splitPrefix(name) {
391
+ var prefix,
392
+ index = name ? name.indexOf('!') : -1;
393
+ if (index > -1) {
394
+ prefix = name.substring(0, index);
395
+ name = name.substring(index + 1, name.length);
396
+ }
397
+ return [prefix, name];
398
+ }
696
399
 
697
- Module = function (map) {
698
- this.events = getOwn(undefEvents, map.id) || {};
699
- this.map = map;
700
- this.shim = getOwn(config.shim, map.id);
701
- this.depExports = [];
702
- this.depMaps = [];
703
- this.depMatched = [];
704
- this.pluginMaps = {};
705
- this.depCount = 0;
706
-
707
- /* this.exports this.factory
708
- this.depMaps = [],
709
- this.enabled, this.fetched
710
- */
711
- };
400
+ /**
401
+ * Creates a module mapping that includes plugin prefix, module
402
+ * name, and path. If parentModuleMap is provided it will
403
+ * also normalize the name via require.normalize()
404
+ *
405
+ * @param {String} name the module name
406
+ * @param {String} [parentModuleMap] parent module map
407
+ * for the module name, used to resolve relative names.
408
+ * @param {Boolean} isNormalized: is the ID already normalized.
409
+ * This is true if this call is done for a define() module ID.
410
+ * @param {Boolean} applyMap: apply the map config to the ID.
411
+ * Should only be true if this map is for a dependency.
412
+ *
413
+ * @returns {Object}
414
+ */
415
+ function makeModuleMap(name, parentModuleMap, isNormalized, applyMap) {
416
+ var url, pluginModule, suffix, nameParts,
417
+ prefix = null,
418
+ parentName = parentModuleMap ? parentModuleMap.name : null,
419
+ originalName = name,
420
+ isDefine = true,
421
+ normalizedName = '';
422
+
423
+ //If no name, then it means it is a require call, generate an
424
+ //internal name.
425
+ if (!name) {
426
+ isDefine = false;
427
+ name = '_@r' + (requireCounter += 1);
428
+ }
712
429
 
713
- Module.prototype = {
714
- init: function (depMaps, factory, errback, options) {
715
- options = options || {};
430
+ nameParts = splitPrefix(name);
431
+ prefix = nameParts[0];
432
+ name = nameParts[1];
716
433
 
717
- //Do not do more inits if already done. Can happen if there
718
- //are multiple define calls for the same module. That is not
719
- //a normal, common case, but it is also not unexpected.
720
- if (this.inited) {
721
- return;
722
- }
434
+ if (prefix) {
435
+ prefix = normalize(prefix, parentName, applyMap);
436
+ pluginModule = getOwn(defined, prefix);
437
+ }
723
438
 
724
- this.factory = factory;
725
-
726
- if (errback) {
727
- //Register for errors on this module.
728
- this.on('error', errback);
729
- } else if (this.events.error) {
730
- //If no errback already, but there are error listeners
731
- //on this module, set up an errback to pass to the deps.
732
- errback = bind(this, function (err) {
733
- this.emit('error', err);
734
- });
735
- }
439
+ //Account for relative paths if there is a base name.
440
+ if (name) {
441
+ if (prefix) {
442
+ if (pluginModule && pluginModule.normalize) {
443
+ //Plugin is loaded, use its normalize method.
444
+ normalizedName = pluginModule.normalize(name, function (name) {
445
+ return normalize(name, parentName, applyMap);
446
+ });
447
+ } else {
448
+ normalizedName = normalize(name, parentName, applyMap);
449
+ }
450
+ } else {
451
+ //A regular module.
452
+ normalizedName = normalize(name, parentName, applyMap);
453
+
454
+ //Normalized name may be a plugin ID due to map config
455
+ //application in normalize. The map config values must
456
+ //already be normalized, so do not need to redo that part.
457
+ nameParts = splitPrefix(normalizedName);
458
+ prefix = nameParts[0];
459
+ normalizedName = nameParts[1];
460
+ isNormalized = true;
461
+
462
+ url = context.nameToUrl(normalizedName);
463
+ }
464
+ }
736
465
 
737
- //Do a copy of the dependency array, so that
738
- //source inputs are not modified. For example
739
- //"shim" deps are passed in here directly, and
740
- //doing a direct modification of the depMaps array
741
- //would affect that config.
742
- this.depMaps = depMaps && depMaps.slice(0);
743
-
744
- this.errback = errback;
745
-
746
- //Indicate this module has be initialized
747
- this.inited = true;
748
-
749
- this.ignore = options.ignore;
750
-
751
- //Could have option to init this module in enabled mode,
752
- //or could have been previously marked as enabled. However,
753
- //the dependencies are not known until init is called. So
754
- //if enabled previously, now trigger dependencies as enabled.
755
- if (options.enabled || this.enabled) {
756
- //Enable this module and dependencies.
757
- //Will call this.check()
758
- this.enable();
759
- } else {
760
- this.check();
761
- }
762
- },
763
-
764
- defineDep: function (i, depExports) {
765
- //Because of cycles, defined callback for a given
766
- //export can be called more than once.
767
- if (!this.depMatched[i]) {
768
- this.depMatched[i] = true;
769
- this.depCount -= 1;
770
- this.depExports[i] = depExports;
466
+ //If the id is a plugin id that cannot be determined if it needs
467
+ //normalization, stamp it with a unique ID so two matching relative
468
+ //ids that may conflict can be separate.
469
+ suffix = prefix && !pluginModule && !isNormalized ?
470
+ '_unnormalized' + (unnormalizedCounter += 1) :
471
+ '';
472
+
473
+ return {
474
+ prefix: prefix,
475
+ name: normalizedName,
476
+ parentMap: parentModuleMap,
477
+ unnormalized: !!suffix,
478
+ url: url,
479
+ originalName: originalName,
480
+ isDefine: isDefine,
481
+ id: (prefix ?
482
+ prefix + '!' + normalizedName :
483
+ normalizedName) + suffix
484
+ };
771
485
  }
772
- },
773
486
 
774
- fetch: function () {
775
- if (this.fetched) {
776
- return;
777
- }
778
- this.fetched = true;
779
-
780
- context.startTime = (new Date()).getTime();
781
-
782
- var map = this.map;
783
-
784
- //If the manager is for a plugin managed resource,
785
- //ask the plugin to load it now.
786
- if (this.shim) {
787
- context.makeRequire(this.map, {
788
- enableBuildCallback: true
789
- })(this.shim.deps || [], bind(this, function () {
790
- return map.prefix ? this.callPlugin() : this.load();
791
- }));
792
- } else {
793
- //Regular dependency.
794
- return map.prefix ? this.callPlugin() : this.load();
795
- }
796
- },
487
+ function getModule(depMap) {
488
+ var id = depMap.id,
489
+ mod = getOwn(registry, id);
797
490
 
798
- load: function () {
799
- var url = this.map.url;
491
+ if (!mod) {
492
+ mod = registry[id] = new context.Module(depMap);
493
+ }
800
494
 
801
- //Regular dependency.
802
- if (!urlFetched[url]) {
803
- urlFetched[url] = true;
804
- context.load(this.map.id, url);
805
- }
806
- },
807
-
808
- /**
809
- * Checks is the module is ready to define itself, and if so,
810
- * define it.
811
- */
812
- check: function () {
813
- if (!this.enabled || this.enabling) {
814
- return;
495
+ return mod;
815
496
  }
816
497
 
817
- var err, cjsModule,
818
- id = this.map.id,
819
- depExports = this.depExports,
820
- exports = this.exports,
821
- factory = this.factory;
822
-
823
- if (!this.inited) {
824
- this.fetch();
825
- } else if (this.error) {
826
- this.emit('error', this.error);
827
- } else if (!this.defining) {
828
- //The factory could trigger another require call
829
- //that would result in checking this module to
830
- //define itself again. If already in the process
831
- //of doing that, skip this work.
832
- this.defining = true;
833
-
834
- if (this.depCount < 1 && !this.defined) {
835
- if (isFunction(factory)) {
836
- //If there is an error listener, favor passing
837
- //to that instead of throwing an error.
838
- if (this.events.error) {
839
- try {
840
- exports = context.execCb(id, factory, depExports, exports);
841
- } catch (e) {
842
- err = e;
498
+ function on(depMap, name, fn) {
499
+ var id = depMap.id,
500
+ mod = getOwn(registry, id);
501
+
502
+ if (hasProp(defined, id) &&
503
+ (!mod || mod.defineEmitComplete)) {
504
+ if (name === 'defined') {
505
+ fn(defined[id]);
843
506
  }
844
- } else {
845
- exports = context.execCb(id, factory, depExports, exports);
846
- }
847
-
848
- if (this.map.isDefine) {
849
- //If setting exports via 'module' is in play,
850
- //favor that over return value and exports. After that,
851
- //favor a non-undefined return value over exports use.
852
- cjsModule = this.module;
853
- if (cjsModule &&
854
- cjsModule.exports !== undefined &&
855
- //Make sure it is not already the exports value
856
- cjsModule.exports !== this.exports) {
857
- exports = cjsModule.exports;
858
- } else if (exports === undefined && this.usingExports) {
859
- //exports already set the defined value.
860
- exports = this.exports;
507
+ } else {
508
+ mod = getModule(depMap);
509
+ if (mod.error && name === 'error') {
510
+ fn(mod.error);
511
+ } else {
512
+ mod.on(name, fn);
861
513
  }
862
- }
514
+ }
515
+ }
863
516
 
864
- if (err) {
865
- err.requireMap = this.map;
866
- err.requireModules = [this.map.id];
867
- err.requireType = 'define';
868
- return onError((this.error = err));
869
- }
517
+ function onError(err, errback) {
518
+ var ids = err.requireModules,
519
+ notified = false;
870
520
 
521
+ if (errback) {
522
+ errback(err);
871
523
  } else {
872
- //Just a literal value
873
- exports = factory;
524
+ each(ids, function (id) {
525
+ var mod = getOwn(registry, id);
526
+ if (mod) {
527
+ //Set error on module, so it skips timeout checks.
528
+ mod.error = err;
529
+ if (mod.events.error) {
530
+ notified = true;
531
+ mod.emit('error', err);
532
+ }
533
+ }
534
+ });
535
+
536
+ if (!notified) {
537
+ req.onError(err);
538
+ }
874
539
  }
540
+ }
875
541
 
876
- this.exports = exports;
877
-
878
- if (this.map.isDefine && !this.ignore) {
879
- defined[id] = exports;
542
+ /**
543
+ * Internal method to transfer globalQueue items to this context's
544
+ * defQueue.
545
+ */
546
+ function takeGlobalQueue() {
547
+ //Push all the globalDefQueue items into the context's defQueue
548
+ if (globalDefQueue.length) {
549
+ //Array splice in the values since the context code has a
550
+ //local var ref to defQueue, so cannot just reassign the one
551
+ //on context.
552
+ apsp.apply(defQueue,
553
+ [defQueue.length, 0].concat(globalDefQueue));
554
+ globalDefQueue = [];
555
+ }
556
+ }
880
557
 
881
- if (req.onResourceLoad) {
882
- req.onResourceLoad(context, this.map, this.depMaps);
883
- }
558
+ handlers = {
559
+ 'require': function (mod) {
560
+ if (mod.require) {
561
+ return mod.require;
562
+ } else {
563
+ return (mod.require = context.makeRequire(mod.map));
564
+ }
565
+ },
566
+ 'exports': function (mod) {
567
+ mod.usingExports = true;
568
+ if (mod.map.isDefine) {
569
+ if (mod.exports) {
570
+ return mod.exports;
571
+ } else {
572
+ return (mod.exports = defined[mod.map.id] = {});
573
+ }
574
+ }
575
+ },
576
+ 'module': function (mod) {
577
+ if (mod.module) {
578
+ return mod.module;
579
+ } else {
580
+ return (mod.module = {
581
+ id: mod.map.id,
582
+ uri: mod.map.url,
583
+ config: function () {
584
+ return getOwn(config.config, mod.map.id) || {};
585
+ },
586
+ exports: handlers.exports(mod)
587
+ });
588
+ }
884
589
  }
590
+ };
885
591
 
886
- //Clean up
592
+ function cleanRegistry(id) {
593
+ //Clean up machinery used for waiting modules.
887
594
  delete registry[id];
595
+ delete enabledRegistry[id];
596
+ }
888
597
 
889
- this.defined = true;
890
- }
891
-
892
- //Finished the define stage. Allow calling check again
893
- //to allow define notifications below in the case of a
894
- //cycle.
895
- this.defining = false;
896
-
897
- if (this.defined && !this.defineEmitted) {
898
- this.defineEmitted = true;
899
- this.emit('defined', this.exports);
900
- this.defineEmitComplete = true;
901
- }
598
+ function breakCycle(mod, traced, processed) {
599
+ var id = mod.map.id;
902
600
 
601
+ if (mod.error) {
602
+ mod.emit('error', mod.error);
603
+ } else {
604
+ traced[id] = true;
605
+ each(mod.depMaps, function (depMap, i) {
606
+ var depId = depMap.id,
607
+ dep = getOwn(registry, depId);
608
+
609
+ //Only force things that have not completed
610
+ //being defined, so still in the registry,
611
+ //and only if it has not been matched up
612
+ //in the module already.
613
+ if (dep && !mod.depMatched[i] && !processed[depId]) {
614
+ if (getOwn(traced, depId)) {
615
+ mod.defineDep(i, defined[depId]);
616
+ mod.check(); //pass false?
617
+ } else {
618
+ breakCycle(dep, traced, processed);
619
+ }
620
+ }
621
+ });
622
+ processed[id] = true;
623
+ }
903
624
  }
904
- },
905
-
906
- callPlugin: function () {
907
- var map = this.map,
908
- id = map.id,
909
- //Map already normalized the prefix.
910
- pluginMap = makeModuleMap(map.prefix);
911
-
912
- //Mark this as a dependency for this plugin, so it
913
- //can be traced for cycles.
914
- this.depMaps.push(pluginMap);
915
-
916
- on(pluginMap, 'defined', bind(this, function (plugin) {
917
- var load, normalizedMap, normalizedMod,
918
- name = this.map.name,
919
- parentName = this.map.parentMap ? this.map.parentMap.name : null,
920
- localRequire = context.makeRequire(map.parentMap, {
921
- enableBuildCallback: true,
922
- skipMap: true
923
- });
924
-
925
- //If current map is not normalized, wait for that
926
- //normalized name to load instead of continuing.
927
- if (this.map.unnormalized) {
928
- //Normalize the ID if the plugin allows it.
929
- if (plugin.normalize) {
930
- name = plugin.normalize(name, function (name) {
931
- return normalize(name, parentName, true);
932
- }) || '';
625
+
626
+ function checkLoaded() {
627
+ var err, usingPathFallback,
628
+ waitInterval = config.waitSeconds * 1000,
629
+ //It is possible to disable the wait interval by using waitSeconds of 0.
630
+ expired = waitInterval && (context.startTime + waitInterval) < new Date().getTime(),
631
+ noLoads = [],
632
+ reqCalls = [],
633
+ stillLoading = false,
634
+ needCycleCheck = true;
635
+
636
+ //Do not bother if this call was a result of a cycle break.
637
+ if (inCheckLoaded) {
638
+ return;
933
639
  }
934
640
 
935
- //prefix and name should already be normalized, no need
936
- //for applying map config again either.
937
- normalizedMap = makeModuleMap(map.prefix + '!' + name,
938
- this.map.parentMap);
939
- on(normalizedMap,
940
- 'defined', bind(this, function (value) {
941
- this.init([], function () { return value; }, null, {
942
- enabled: true,
943
- ignore: true
944
- });
945
- }));
641
+ inCheckLoaded = true;
946
642
 
947
- normalizedMod = getOwn(registry, normalizedMap.id);
948
- if (normalizedMod) {
949
- //Mark this as a dependency for this plugin, so it
950
- //can be traced for cycles.
951
- this.depMaps.push(normalizedMap);
643
+ //Figure out the state of all the modules.
644
+ eachProp(enabledRegistry, function (mod) {
645
+ var map = mod.map,
646
+ modId = map.id;
952
647
 
953
- if (this.events.error) {
954
- normalizedMod.on('error', bind(this, function (err) {
955
- this.emit('error', err);
956
- }));
957
- }
958
- normalizedMod.enable();
959
- }
648
+ //Skip things that are not enabled or in error state.
649
+ if (!mod.enabled) {
650
+ return;
651
+ }
960
652
 
961
- return;
962
- }
653
+ if (!map.isDefine) {
654
+ reqCalls.push(mod);
655
+ }
963
656
 
964
- load = bind(this, function (value) {
965
- this.init([], function () { return value; }, null, {
966
- enabled: true
967
- });
968
- });
969
-
970
- load.error = bind(this, function (err) {
971
- this.inited = true;
972
- this.error = err;
973
- err.requireModules = [id];
974
-
975
- //Remove temp unnormalized modules for this module,
976
- //since they will never be resolved otherwise now.
977
- eachProp(registry, function (mod) {
978
- if (mod.map.id.indexOf(id + '_unnormalized') === 0) {
979
- cleanRegistry(mod.map.id);
980
- }
657
+ if (!mod.error) {
658
+ //If the module should be executed, and it has not
659
+ //been inited and time is up, remember it.
660
+ if (!mod.inited && expired) {
661
+ if (hasPathFallback(modId)) {
662
+ usingPathFallback = true;
663
+ stillLoading = true;
664
+ } else {
665
+ noLoads.push(modId);
666
+ removeScript(modId);
667
+ }
668
+ } else if (!mod.inited && mod.fetched && map.isDefine) {
669
+ stillLoading = true;
670
+ if (!map.prefix) {
671
+ //No reason to keep looking for unfinished
672
+ //loading. If the only stillLoading is a
673
+ //plugin resource though, keep going,
674
+ //because it may be that a plugin resource
675
+ //is waiting on a non-plugin cycle.
676
+ return (needCycleCheck = false);
677
+ }
678
+ }
679
+ }
981
680
  });
982
681
 
983
- onError(err);
984
- });
985
-
986
- //Allow plugins to load other code without having to know the
987
- //context or how to 'complete' the load.
988
- load.fromText = bind(this, function (text, textAlt) {
989
- /*jslint evil: true */
990
- var moduleName = map.name,
991
- moduleMap = makeModuleMap(moduleName),
992
- hasInteractive = useInteractive;
993
-
994
- //As of 2.1.0, support just passing the text, to reinforce
995
- //fromText only being called once per resource. Still
996
- //support old style of passing moduleName but discard
997
- //that moduleName in favor of the internal ref.
998
- if (textAlt) {
999
- text = textAlt;
682
+ if (expired && noLoads.length) {
683
+ //If wait time expired, throw error of unloaded modules.
684
+ err = makeError('timeout', 'Load timeout for modules: ' + noLoads, null, noLoads);
685
+ err.contextName = context.contextName;
686
+ return onError(err);
1000
687
  }
1001
688
 
1002
- //Turn off interactive script matching for IE for any define
1003
- //calls in the text, then turn it back on at the end.
1004
- if (hasInteractive) {
1005
- useInteractive = false;
689
+ //Not expired, check for a cycle.
690
+ if (needCycleCheck) {
691
+ each(reqCalls, function (mod) {
692
+ breakCycle(mod, {}, {});
693
+ });
1006
694
  }
1007
695
 
1008
- //Prime the system by creating a module instance for
1009
- //it.
1010
- getModule(moduleMap);
1011
-
1012
- //Transfer any config to this other module.
1013
- if (hasProp(config.config, id)) {
1014
- config.config[moduleName] = config.config[id];
696
+ //If still waiting on loads, and the waiting load is something
697
+ //other than a plugin resource, or there are still outstanding
698
+ //scripts, then just try back later.
699
+ if ((!expired || usingPathFallback) && stillLoading) {
700
+ //Something is still waiting to load. Wait for it, but only
701
+ //if a timeout is not already in effect.
702
+ if ((isBrowser || isWebWorker) && !checkLoadedTimeoutId) {
703
+ checkLoadedTimeoutId = setTimeout(function () {
704
+ checkLoadedTimeoutId = 0;
705
+ checkLoaded();
706
+ }, 50);
707
+ }
1015
708
  }
1016
709
 
1017
- try {
1018
- req.exec(text);
1019
- } catch (e) {
1020
- throw new Error('fromText eval for ' + moduleName +
1021
- ' failed: ' + e);
1022
- }
710
+ inCheckLoaded = false;
711
+ }
1023
712
 
1024
- if (hasInteractive) {
1025
- useInteractive = true;
1026
- }
713
+ Module = function (map) {
714
+ this.events = getOwn(undefEvents, map.id) || {};
715
+ this.map = map;
716
+ this.shim = getOwn(config.shim, map.id);
717
+ this.depExports = [];
718
+ this.depMaps = [];
719
+ this.depMatched = [];
720
+ this.pluginMaps = {};
721
+ this.depCount = 0;
722
+
723
+ /* this.exports this.factory
724
+ this.depMaps = [],
725
+ this.enabled, this.fetched
726
+ */
727
+ };
728
+
729
+ Module.prototype = {
730
+ init: function (depMaps, factory, errback, options) {
731
+ options = options || {};
732
+
733
+ //Do not do more inits if already done. Can happen if there
734
+ //are multiple define calls for the same module. That is not
735
+ //a normal, common case, but it is also not unexpected.
736
+ if (this.inited) {
737
+ return;
738
+ }
1027
739
 
1028
- //Mark this as a dependency for the plugin
1029
- //resource
1030
- this.depMaps.push(moduleMap);
1031
-
1032
- //Support anonymous modules.
1033
- context.completeLoad(moduleName);
1034
-
1035
- //Bind the value of that module to the value for this
1036
- //resource ID.
1037
- localRequire([moduleName], load);
1038
- });
1039
-
1040
- //Use parentName here since the plugin's name is not reliable,
1041
- //could be some weird string with no path that actually wants to
1042
- //reference the parentName's path.
1043
- plugin.load(map.name, localRequire, load, config);
1044
- }));
1045
-
1046
- context.enable(pluginMap, this);
1047
- this.pluginMaps[pluginMap.id] = pluginMap;
1048
- },
1049
-
1050
- enable: function () {
1051
- this.enabled = true;
1052
-
1053
- //Set flag mentioning that the module is enabling,
1054
- //so that immediate calls to the defined callbacks
1055
- //for dependencies do not trigger inadvertent load
1056
- //with the depCount still being zero.
1057
- this.enabling = true;
1058
-
1059
- //Enable each dependency
1060
- each(this.depMaps, bind(this, function (depMap, i) {
1061
- var id, mod, handler;
1062
-
1063
- if (typeof depMap === 'string') {
1064
- //Dependency needs to be converted to a depMap
1065
- //and wired up to this module.
1066
- depMap = makeModuleMap(depMap,
1067
- (this.map.isDefine ? this.map : this.map.parentMap),
1068
- false,
1069
- !this.skipMap);
1070
- this.depMaps[i] = depMap;
1071
-
1072
- handler = getOwn(handlers, depMap.id);
1073
-
1074
- if (handler) {
1075
- this.depExports[i] = handler(this);
1076
- return;
1077
- }
740
+ this.factory = factory;
741
+
742
+ if (errback) {
743
+ //Register for errors on this module.
744
+ this.on('error', errback);
745
+ } else if (this.events.error) {
746
+ //If no errback already, but there are error listeners
747
+ //on this module, set up an errback to pass to the deps.
748
+ errback = bind(this, function (err) {
749
+ this.emit('error', err);
750
+ });
751
+ }
1078
752
 
1079
- this.depCount += 1;
753
+ //Do a copy of the dependency array, so that
754
+ //source inputs are not modified. For example
755
+ //"shim" deps are passed in here directly, and
756
+ //doing a direct modification of the depMaps array
757
+ //would affect that config.
758
+ this.depMaps = depMaps && depMaps.slice(0);
759
+
760
+ this.errback = errback;
761
+
762
+ //Indicate this module has be initialized
763
+ this.inited = true;
764
+
765
+ this.ignore = options.ignore;
766
+
767
+ //Could have option to init this module in enabled mode,
768
+ //or could have been previously marked as enabled. However,
769
+ //the dependencies are not known until init is called. So
770
+ //if enabled previously, now trigger dependencies as enabled.
771
+ if (options.enabled || this.enabled) {
772
+ //Enable this module and dependencies.
773
+ //Will call this.check()
774
+ this.enable();
775
+ } else {
776
+ this.check();
777
+ }
778
+ },
1080
779
 
1081
- on(depMap, 'defined', bind(this, function (depExports) {
1082
- this.defineDep(i, depExports);
1083
- this.check();
1084
- }));
780
+ defineDep: function (i, depExports) {
781
+ //Because of cycles, defined callback for a given
782
+ //export can be called more than once.
783
+ if (!this.depMatched[i]) {
784
+ this.depMatched[i] = true;
785
+ this.depCount -= 1;
786
+ this.depExports[i] = depExports;
787
+ }
788
+ },
1085
789
 
1086
- if (this.errback) {
1087
- on(depMap, 'error', this.errback);
1088
- }
1089
- }
1090
-
1091
- id = depMap.id;
1092
- mod = registry[id];
1093
-
1094
- //Skip special modules like 'require', 'exports', 'module'
1095
- //Also, don't call enable if it is already enabled,
1096
- //important in circular dependency cases.
1097
- if (!hasProp(handlers, id) && mod && !mod.enabled) {
1098
- context.enable(depMap, this);
1099
- }
1100
- }));
1101
-
1102
- //Enable each plugin that is used in
1103
- //a dependency
1104
- eachProp(this.pluginMaps, bind(this, function (pluginMap) {
1105
- var mod = getOwn(registry, pluginMap.id);
1106
- if (mod && !mod.enabled) {
1107
- context.enable(pluginMap, this);
1108
- }
1109
- }));
1110
-
1111
- this.enabling = false;
1112
-
1113
- this.check();
1114
- },
1115
-
1116
- on: function (name, cb) {
1117
- var cbs = this.events[name];
1118
- if (!cbs) {
1119
- cbs = this.events[name] = [];
1120
- }
1121
- cbs.push(cb);
1122
- },
790
+ fetch: function () {
791
+ if (this.fetched) {
792
+ return;
793
+ }
794
+ this.fetched = true;
795
+
796
+ context.startTime = (new Date()).getTime();
797
+
798
+ var map = this.map;
799
+
800
+ //If the manager is for a plugin managed resource,
801
+ //ask the plugin to load it now.
802
+ if (this.shim) {
803
+ context.makeRequire(this.map, {
804
+ enableBuildCallback: true
805
+ })(this.shim.deps || [], bind(this, function () {
806
+ return map.prefix ? this.callPlugin() : this.load();
807
+ }));
808
+ } else {
809
+ //Regular dependency.
810
+ return map.prefix ? this.callPlugin() : this.load();
811
+ }
812
+ },
1123
813
 
1124
- emit: function (name, evt) {
1125
- each(this.events[name], function (cb) {
1126
- cb(evt);
1127
- });
1128
- if (name === 'error') {
1129
- //Now that the error handler was triggered, remove
1130
- //the listeners, since this broken Module instance
1131
- //can stay around for a while in the registry.
1132
- delete this.events[name];
1133
- }
1134
- }
1135
- };
814
+ load: function () {
815
+ var url = this.map.url;
1136
816
 
1137
- function callGetModule(args) {
1138
- //Skip modules already defined.
1139
- if (!hasProp(defined, args[0])) {
1140
- getModule(makeModuleMap(args[0], null, true)).init(args[1], args[2]);
1141
- }
1142
- }
817
+ //Regular dependency.
818
+ if (!urlFetched[url]) {
819
+ urlFetched[url] = true;
820
+ context.load(this.map.id, url);
821
+ }
822
+ },
1143
823
 
1144
- function removeListener(node, func, name, ieName) {
1145
- //Favor detachEvent because of IE9
1146
- //issue, see attachEvent/addEventListener comment elsewhere
1147
- //in this file.
1148
- if (node.detachEvent && !isOpera) {
1149
- //Probably IE. If not it will throw an error, which will be
1150
- //useful to know.
1151
- if (ieName) {
1152
- node.detachEvent(ieName, func);
1153
- }
1154
- } else {
1155
- node.removeEventListener(name, func, false);
1156
- }
1157
- }
824
+ /**
825
+ * Checks if the module is ready to define itself, and if so,
826
+ * define it.
827
+ */
828
+ check: function () {
829
+ if (!this.enabled || this.enabling) {
830
+ return;
831
+ }
1158
832
 
1159
- /**
1160
- * Given an event from a script node, get the requirejs info from it,
1161
- * and then removes the event listeners on the node.
1162
- * @param {Event} evt
1163
- * @returns {Object}
1164
- */
1165
- function getScriptData(evt) {
1166
- //Using currentTarget instead of target for Firefox 2.0's sake. Not
1167
- //all old browsers will be supported, but this one was easy enough
1168
- //to support and still makes sense.
1169
- var node = evt.currentTarget || evt.srcElement;
1170
-
1171
- //Remove the listeners once here.
1172
- removeListener(node, context.onScriptLoad, 'load', 'onreadystatechange');
1173
- removeListener(node, context.onScriptError, 'error');
1174
-
1175
- return {
1176
- node: node,
1177
- id: node && node.getAttribute('data-requiremodule')
1178
- };
1179
- }
833
+ var err, cjsModule,
834
+ id = this.map.id,
835
+ depExports = this.depExports,
836
+ exports = this.exports,
837
+ factory = this.factory;
838
+
839
+ if (!this.inited) {
840
+ this.fetch();
841
+ } else if (this.error) {
842
+ this.emit('error', this.error);
843
+ } else if (!this.defining) {
844
+ //The factory could trigger another require call
845
+ //that would result in checking this module to
846
+ //define itself again. If already in the process
847
+ //of doing that, skip this work.
848
+ this.defining = true;
849
+
850
+ if (this.depCount < 1 && !this.defined) {
851
+ if (isFunction(factory)) {
852
+ //If there is an error listener, favor passing
853
+ //to that instead of throwing an error. However,
854
+ //only do it for define()'d modules. require
855
+ //errbacks should not be called for failures in
856
+ //their callbacks (#699). However if a global
857
+ //onError is set, use that.
858
+ if ((this.events.error && this.map.isDefine) ||
859
+ req.onError !== defaultOnError) {
860
+ try {
861
+ exports = context.execCb(id, factory, depExports, exports);
862
+ } catch (e) {
863
+ err = e;
864
+ }
865
+ } else {
866
+ exports = context.execCb(id, factory, depExports, exports);
867
+ }
868
+
869
+ // Favor return value over exports. If node/cjs in play,
870
+ // then will not have a return value anyway. Favor
871
+ // module.exports assignment over exports object.
872
+ if (this.map.isDefine && exports === undefined) {
873
+ cjsModule = this.module;
874
+ if (cjsModule) {
875
+ exports = cjsModule.exports;
876
+ } else if (this.usingExports) {
877
+ //exports already set the defined value.
878
+ exports = this.exports;
879
+ }
880
+ }
881
+
882
+ if (err) {
883
+ err.requireMap = this.map;
884
+ err.requireModules = this.map.isDefine ? [this.map.id] : null;
885
+ err.requireType = this.map.isDefine ? 'define' : 'require';
886
+ return onError((this.error = err));
887
+ }
888
+
889
+ } else {
890
+ //Just a literal value
891
+ exports = factory;
892
+ }
893
+
894
+ this.exports = exports;
895
+
896
+ if (this.map.isDefine && !this.ignore) {
897
+ defined[id] = exports;
898
+
899
+ if (req.onResourceLoad) {
900
+ req.onResourceLoad(context, this.map, this.depMaps);
901
+ }
902
+ }
903
+
904
+ //Clean up
905
+ cleanRegistry(id);
906
+
907
+ this.defined = true;
908
+ }
909
+
910
+ //Finished the define stage. Allow calling check again
911
+ //to allow define notifications below in the case of a
912
+ //cycle.
913
+ this.defining = false;
914
+
915
+ if (this.defined && !this.defineEmitted) {
916
+ this.defineEmitted = true;
917
+ this.emit('defined', this.exports);
918
+ this.defineEmitComplete = true;
919
+ }
1180
920
 
1181
- function intakeDefines() {
1182
- var args;
1183
-
1184
- //Any defined modules in the global queue, intake them now.
1185
- takeGlobalQueue();
1186
-
1187
- //Make sure any remaining defQueue items get properly processed.
1188
- while (defQueue.length) {
1189
- args = defQueue.shift();
1190
- if (args[0] === null) {
1191
- return onError(makeError('mismatch', 'Mismatched anonymous define() module: ' + args[args.length - 1]));
1192
- } else {
1193
- //args are id, deps, factory. Should be normalized by the
1194
- //define() function.
1195
- callGetModule(args);
1196
- }
1197
- }
1198
- }
921
+ }
922
+ },
1199
923
 
1200
- context = {
1201
- config: config,
1202
- contextName: contextName,
1203
- registry: registry,
1204
- defined: defined,
1205
- urlFetched: urlFetched,
1206
- defQueue: defQueue,
1207
- Module: Module,
1208
- makeModuleMap: makeModuleMap,
1209
- nextTick: req.nextTick,
1210
-
1211
- /**
1212
- * Set a configuration for the context.
1213
- * @param {Object} cfg config object to integrate.
1214
- */
1215
- configure: function (cfg) {
1216
- //Make sure the baseUrl ends in a slash.
1217
- if (cfg.baseUrl) {
1218
- if (cfg.baseUrl.charAt(cfg.baseUrl.length - 1) !== '/') {
1219
- cfg.baseUrl += '/';
1220
- }
1221
- }
924
+ callPlugin: function () {
925
+ var map = this.map,
926
+ id = map.id,
927
+ //Map already normalized the prefix.
928
+ pluginMap = makeModuleMap(map.prefix);
929
+
930
+ //Mark this as a dependency for this plugin, so it
931
+ //can be traced for cycles.
932
+ this.depMaps.push(pluginMap);
933
+
934
+ on(pluginMap, 'defined', bind(this, function (plugin) {
935
+ var load, normalizedMap, normalizedMod,
936
+ bundleId = getOwn(bundlesMap, this.map.id),
937
+ name = this.map.name,
938
+ parentName = this.map.parentMap ? this.map.parentMap.name : null,
939
+ localRequire = context.makeRequire(map.parentMap, {
940
+ enableBuildCallback: true
941
+ });
942
+
943
+ //If current map is not normalized, wait for that
944
+ //normalized name to load instead of continuing.
945
+ if (this.map.unnormalized) {
946
+ //Normalize the ID if the plugin allows it.
947
+ if (plugin.normalize) {
948
+ name = plugin.normalize(name, function (name) {
949
+ return normalize(name, parentName, true);
950
+ }) || '';
951
+ }
952
+
953
+ //prefix and name should already be normalized, no need
954
+ //for applying map config again either.
955
+ normalizedMap = makeModuleMap(map.prefix + '!' + name,
956
+ this.map.parentMap);
957
+ on(normalizedMap,
958
+ 'defined', bind(this, function (value) {
959
+ this.init([], function () { return value; }, null, {
960
+ enabled: true,
961
+ ignore: true
962
+ });
963
+ }));
964
+
965
+ normalizedMod = getOwn(registry, normalizedMap.id);
966
+ if (normalizedMod) {
967
+ //Mark this as a dependency for this plugin, so it
968
+ //can be traced for cycles.
969
+ this.depMaps.push(normalizedMap);
970
+
971
+ if (this.events.error) {
972
+ normalizedMod.on('error', bind(this, function (err) {
973
+ this.emit('error', err);
974
+ }));
975
+ }
976
+ normalizedMod.enable();
977
+ }
978
+
979
+ return;
980
+ }
981
+
982
+ //If a paths config, then just load that file instead to
983
+ //resolve the plugin, as it is built into that paths layer.
984
+ if (bundleId) {
985
+ this.map.url = context.nameToUrl(bundleId);
986
+ this.load();
987
+ return;
988
+ }
989
+
990
+ load = bind(this, function (value) {
991
+ this.init([], function () { return value; }, null, {
992
+ enabled: true
993
+ });
994
+ });
995
+
996
+ load.error = bind(this, function (err) {
997
+ this.inited = true;
998
+ this.error = err;
999
+ err.requireModules = [id];
1000
+
1001
+ //Remove temp unnormalized modules for this module,
1002
+ //since they will never be resolved otherwise now.
1003
+ eachProp(registry, function (mod) {
1004
+ if (mod.map.id.indexOf(id + '_unnormalized') === 0) {
1005
+ cleanRegistry(mod.map.id);
1006
+ }
1007
+ });
1008
+
1009
+ onError(err);
1010
+ });
1011
+
1012
+ //Allow plugins to load other code without having to know the
1013
+ //context or how to 'complete' the load.
1014
+ load.fromText = bind(this, function (text, textAlt) {
1015
+ /*jslint evil: true */
1016
+ var moduleName = map.name,
1017
+ moduleMap = makeModuleMap(moduleName),
1018
+ hasInteractive = useInteractive;
1019
+
1020
+ //As of 2.1.0, support just passing the text, to reinforce
1021
+ //fromText only being called once per resource. Still
1022
+ //support old style of passing moduleName but discard
1023
+ //that moduleName in favor of the internal ref.
1024
+ if (textAlt) {
1025
+ text = textAlt;
1026
+ }
1027
+
1028
+ //Turn off interactive script matching for IE for any define
1029
+ //calls in the text, then turn it back on at the end.
1030
+ if (hasInteractive) {
1031
+ useInteractive = false;
1032
+ }
1033
+
1034
+ //Prime the system by creating a module instance for
1035
+ //it.
1036
+ getModule(moduleMap);
1037
+
1038
+ //Transfer any config to this other module.
1039
+ if (hasProp(config.config, id)) {
1040
+ config.config[moduleName] = config.config[id];
1041
+ }
1042
+
1043
+ try {
1044
+ req.exec(text);
1045
+ } catch (e) {
1046
+ return onError(makeError('fromtexteval',
1047
+ 'fromText eval for ' + id +
1048
+ ' failed: ' + e,
1049
+ e,
1050
+ [id]));
1051
+ }
1052
+
1053
+ if (hasInteractive) {
1054
+ useInteractive = true;
1055
+ }
1056
+
1057
+ //Mark this as a dependency for the plugin
1058
+ //resource
1059
+ this.depMaps.push(moduleMap);
1060
+
1061
+ //Support anonymous modules.
1062
+ context.completeLoad(moduleName);
1063
+
1064
+ //Bind the value of that module to the value for this
1065
+ //resource ID.
1066
+ localRequire([moduleName], load);
1067
+ });
1068
+
1069
+ //Use parentName here since the plugin's name is not reliable,
1070
+ //could be some weird string with no path that actually wants to
1071
+ //reference the parentName's path.
1072
+ plugin.load(map.name, localRequire, load, config);
1073
+ }));
1222
1074
 
1223
- //Save off the paths and packages since they require special processing,
1224
- //they are additive.
1225
- var pkgs = config.pkgs,
1226
- shim = config.shim,
1227
- objs = {
1228
- paths: true,
1229
- config: true,
1230
- map: true
1231
- };
1075
+ context.enable(pluginMap, this);
1076
+ this.pluginMaps[pluginMap.id] = pluginMap;
1077
+ },
1232
1078
 
1233
- eachProp(cfg, function (value, prop) {
1234
- if (objs[prop]) {
1235
- if (prop === 'map') {
1236
- mixin(config[prop], value, true, true);
1237
- } else {
1238
- mixin(config[prop], value, true);
1079
+ enable: function () {
1080
+ enabledRegistry[this.map.id] = this;
1081
+ this.enabled = true;
1082
+
1083
+ //Set flag mentioning that the module is enabling,
1084
+ //so that immediate calls to the defined callbacks
1085
+ //for dependencies do not trigger inadvertent load
1086
+ //with the depCount still being zero.
1087
+ this.enabling = true;
1088
+
1089
+ //Enable each dependency
1090
+ each(this.depMaps, bind(this, function (depMap, i) {
1091
+ var id, mod, handler;
1092
+
1093
+ if (typeof depMap === 'string') {
1094
+ //Dependency needs to be converted to a depMap
1095
+ //and wired up to this module.
1096
+ depMap = makeModuleMap(depMap,
1097
+ (this.map.isDefine ? this.map : this.map.parentMap),
1098
+ false,
1099
+ !this.skipMap);
1100
+ this.depMaps[i] = depMap;
1101
+
1102
+ handler = getOwn(handlers, depMap.id);
1103
+
1104
+ if (handler) {
1105
+ this.depExports[i] = handler(this);
1106
+ return;
1107
+ }
1108
+
1109
+ this.depCount += 1;
1110
+
1111
+ on(depMap, 'defined', bind(this, function (depExports) {
1112
+ this.defineDep(i, depExports);
1113
+ this.check();
1114
+ }));
1115
+
1116
+ if (this.errback) {
1117
+ on(depMap, 'error', bind(this, this.errback));
1118
+ }
1119
+ }
1120
+
1121
+ id = depMap.id;
1122
+ mod = registry[id];
1123
+
1124
+ //Skip special modules like 'require', 'exports', 'module'
1125
+ //Also, don't call enable if it is already enabled,
1126
+ //important in circular dependency cases.
1127
+ if (!hasProp(handlers, id) && mod && !mod.enabled) {
1128
+ context.enable(depMap, this);
1129
+ }
1130
+ }));
1131
+
1132
+ //Enable each plugin that is used in
1133
+ //a dependency
1134
+ eachProp(this.pluginMaps, bind(this, function (pluginMap) {
1135
+ var mod = getOwn(registry, pluginMap.id);
1136
+ if (mod && !mod.enabled) {
1137
+ context.enable(pluginMap, this);
1138
+ }
1139
+ }));
1140
+
1141
+ this.enabling = false;
1142
+
1143
+ this.check();
1144
+ },
1145
+
1146
+ on: function (name, cb) {
1147
+ var cbs = this.events[name];
1148
+ if (!cbs) {
1149
+ cbs = this.events[name] = [];
1150
+ }
1151
+ cbs.push(cb);
1152
+ },
1153
+
1154
+ emit: function (name, evt) {
1155
+ each(this.events[name], function (cb) {
1156
+ cb(evt);
1157
+ });
1158
+ if (name === 'error') {
1159
+ //Now that the error handler was triggered, remove
1160
+ //the listeners, since this broken Module instance
1161
+ //can stay around for a while in the registry.
1162
+ delete this.events[name];
1163
+ }
1239
1164
  }
1240
- } else {
1241
- config[prop] = value;
1242
- }
1243
- });
1165
+ };
1244
1166
 
1245
- //Merge shim
1246
- if (cfg.shim) {
1247
- eachProp(cfg.shim, function (value, id) {
1248
- //Normalize the structure
1249
- if (isArray(value)) {
1250
- value = {
1251
- deps: value
1252
- };
1167
+ function callGetModule(args) {
1168
+ //Skip modules already defined.
1169
+ if (!hasProp(defined, args[0])) {
1170
+ getModule(makeModuleMap(args[0], null, true)).init(args[1], args[2]);
1253
1171
  }
1254
- if ((value.exports || value.init) && !value.exportsFn) {
1255
- value.exportsFn = context.makeShimExports(value);
1172
+ }
1173
+
1174
+ function removeListener(node, func, name, ieName) {
1175
+ //Favor detachEvent because of IE9
1176
+ //issue, see attachEvent/addEventListener comment elsewhere
1177
+ //in this file.
1178
+ if (node.detachEvent && !isOpera) {
1179
+ //Probably IE. If not it will throw an error, which will be
1180
+ //useful to know.
1181
+ if (ieName) {
1182
+ node.detachEvent(ieName, func);
1183
+ }
1184
+ } else {
1185
+ node.removeEventListener(name, func, false);
1256
1186
  }
1257
- shim[id] = value;
1258
- });
1259
- config.shim = shim;
1260
1187
  }
1261
1188
 
1262
- //Adjust packages if necessary.
1263
- if (cfg.packages) {
1264
- each(cfg.packages, function (pkgObj) {
1265
- var location;
1266
-
1267
- pkgObj = typeof pkgObj === 'string' ? { name: pkgObj } : pkgObj;
1268
- location = pkgObj.location;
1269
-
1270
- //Create a brand new object on pkgs, since currentPackages can
1271
- //be passed in again, and config.pkgs is the internal transformed
1272
- //state for all package configs.
1273
- pkgs[pkgObj.name] = {
1274
- name: pkgObj.name,
1275
- location: location || pkgObj.name,
1276
- //Remove leading dot in main, so main paths are normalized,
1277
- //and remove any trailing .js, since different package
1278
- //envs have different conventions: some use a module name,
1279
- //some use a file name.
1280
- main: (pkgObj.main || 'main')
1281
- .replace(currDirRegExp, '')
1282
- .replace(jsSuffixRegExp, '')
1189
+ /**
1190
+ * Given an event from a script node, get the requirejs info from it,
1191
+ * and then removes the event listeners on the node.
1192
+ * @param {Event} evt
1193
+ * @returns {Object}
1194
+ */
1195
+ function getScriptData(evt) {
1196
+ //Using currentTarget instead of target for Firefox 2.0's sake. Not
1197
+ //all old browsers will be supported, but this one was easy enough
1198
+ //to support and still makes sense.
1199
+ var node = evt.currentTarget || evt.srcElement;
1200
+
1201
+ //Remove the listeners once here.
1202
+ removeListener(node, context.onScriptLoad, 'load', 'onreadystatechange');
1203
+ removeListener(node, context.onScriptError, 'error');
1204
+
1205
+ return {
1206
+ node: node,
1207
+ id: node && node.getAttribute('data-requiremodule')
1283
1208
  };
1284
- });
1285
-
1286
- //Done with modifications, assing packages back to context config
1287
- config.pkgs = pkgs;
1288
1209
  }
1289
1210
 
1290
- //If there are any "waiting to execute" modules in the registry,
1291
- //update the maps for them, since their info, like URLs to load,
1292
- //may have changed.
1293
- eachProp(registry, function (mod, id) {
1294
- //If module already has init called, since it is too
1295
- //late to modify them, and ignore unnormalized ones
1296
- //since they are transient.
1297
- if (!mod.inited && !mod.map.unnormalized) {
1298
- mod.map = makeModuleMap(id);
1299
- }
1300
- });
1211
+ function intakeDefines() {
1212
+ var args;
1301
1213
 
1302
- //If a deps array or a config callback is specified, then call
1303
- //require with those args. This is useful when require is defined as a
1304
- //config object before require.js is loaded.
1305
- if (cfg.deps || cfg.callback) {
1306
- context.require(cfg.deps || [], cfg.callback);
1307
- }
1308
- },
1309
-
1310
- makeShimExports: function (value) {
1311
- function fn() {
1312
- var ret;
1313
- if (value.init) {
1314
- ret = value.init.apply(global, arguments);
1315
- }
1316
- return ret || (value.exports && getGlobal(value.exports));
1214
+ //Any defined modules in the global queue, intake them now.
1215
+ takeGlobalQueue();
1216
+
1217
+ //Make sure any remaining defQueue items get properly processed.
1218
+ while (defQueue.length) {
1219
+ args = defQueue.shift();
1220
+ if (args[0] === null) {
1221
+ return onError(makeError('mismatch', 'Mismatched anonymous define() module: ' + args[args.length - 1]));
1222
+ } else {
1223
+ //args are id, deps, factory. Should be normalized by the
1224
+ //define() function.
1225
+ callGetModule(args);
1226
+ }
1227
+ }
1317
1228
  }
1318
- return fn;
1319
- },
1320
1229
 
1321
- makeRequire: function (relMap, options) {
1322
- options = options || {};
1230
+ context = {
1231
+ config: config,
1232
+ contextName: contextName,
1233
+ registry: registry,
1234
+ defined: defined,
1235
+ urlFetched: urlFetched,
1236
+ defQueue: defQueue,
1237
+ Module: Module,
1238
+ makeModuleMap: makeModuleMap,
1239
+ nextTick: req.nextTick,
1240
+ onError: onError,
1241
+
1242
+ /**
1243
+ * Set a configuration for the context.
1244
+ * @param {Object} cfg config object to integrate.
1245
+ */
1246
+ configure: function (cfg) {
1247
+ //Make sure the baseUrl ends in a slash.
1248
+ if (cfg.baseUrl) {
1249
+ if (cfg.baseUrl.charAt(cfg.baseUrl.length - 1) !== '/') {
1250
+ cfg.baseUrl += '/';
1251
+ }
1252
+ }
1323
1253
 
1324
- function localRequire(deps, callback, errback) {
1325
- var id, map, requireMod;
1254
+ //Save off the paths since they require special processing,
1255
+ //they are additive.
1256
+ var shim = config.shim,
1257
+ objs = {
1258
+ paths: true,
1259
+ bundles: true,
1260
+ config: true,
1261
+ map: true
1262
+ };
1263
+
1264
+ eachProp(cfg, function (value, prop) {
1265
+ if (objs[prop]) {
1266
+ if (!config[prop]) {
1267
+ config[prop] = {};
1268
+ }
1269
+ mixin(config[prop], value, true, true);
1270
+ } else {
1271
+ config[prop] = value;
1272
+ }
1273
+ });
1274
+
1275
+ //Reverse map the bundles
1276
+ if (cfg.bundles) {
1277
+ eachProp(cfg.bundles, function (value, prop) {
1278
+ each(value, function (v) {
1279
+ if (v !== prop) {
1280
+ bundlesMap[v] = prop;
1281
+ }
1282
+ });
1283
+ });
1284
+ }
1326
1285
 
1327
- if (options.enableBuildCallback && callback && isFunction(callback)) {
1328
- callback.__requireJsBuild = true;
1329
- }
1286
+ //Merge shim
1287
+ if (cfg.shim) {
1288
+ eachProp(cfg.shim, function (value, id) {
1289
+ //Normalize the structure
1290
+ if (isArray(value)) {
1291
+ value = {
1292
+ deps: value
1293
+ };
1294
+ }
1295
+ if ((value.exports || value.init) && !value.exportsFn) {
1296
+ value.exportsFn = context.makeShimExports(value);
1297
+ }
1298
+ shim[id] = value;
1299
+ });
1300
+ config.shim = shim;
1301
+ }
1330
1302
 
1331
- if (typeof deps === 'string') {
1332
- if (isFunction(callback)) {
1333
- //Invalid call
1334
- return onError(makeError('requireargs', 'Invalid require call'), errback);
1335
- }
1303
+ //Adjust packages if necessary.
1304
+ if (cfg.packages) {
1305
+ each(cfg.packages, function (pkgObj) {
1306
+ var location, name;
1307
+
1308
+ pkgObj = typeof pkgObj === 'string' ? { name: pkgObj } : pkgObj;
1309
+
1310
+ name = pkgObj.name;
1311
+ location = pkgObj.location;
1312
+ if (location) {
1313
+ config.paths[name] = pkgObj.location;
1314
+ }
1315
+
1316
+ //Save pointer to main module ID for pkg name.
1317
+ //Remove leading dot in main, so main paths are normalized,
1318
+ //and remove any trailing .js, since different package
1319
+ //envs have different conventions: some use a module name,
1320
+ //some use a file name.
1321
+ config.pkgs[name] = pkgObj.name + '/' + (pkgObj.main || 'main')
1322
+ .replace(currDirRegExp, '')
1323
+ .replace(jsSuffixRegExp, '');
1324
+ });
1325
+ }
1336
1326
 
1337
- //If require|exports|module are requested, get the
1338
- //value for them from the special handlers. Caveat:
1339
- //this only works while module is being defined.
1340
- if (relMap && hasProp(handlers, deps)) {
1341
- return handlers[deps](registry[relMap.id]);
1342
- }
1327
+ //If there are any "waiting to execute" modules in the registry,
1328
+ //update the maps for them, since their info, like URLs to load,
1329
+ //may have changed.
1330
+ eachProp(registry, function (mod, id) {
1331
+ //If module already has init called, since it is too
1332
+ //late to modify them, and ignore unnormalized ones
1333
+ //since they are transient.
1334
+ if (!mod.inited && !mod.map.unnormalized) {
1335
+ mod.map = makeModuleMap(id);
1336
+ }
1337
+ });
1338
+
1339
+ //If a deps array or a config callback is specified, then call
1340
+ //require with those args. This is useful when require is defined as a
1341
+ //config object before require.js is loaded.
1342
+ if (cfg.deps || cfg.callback) {
1343
+ context.require(cfg.deps || [], cfg.callback);
1344
+ }
1345
+ },
1343
1346
 
1344
- //Synchronous access to one module. If require.get is
1345
- //available (as in the Node adapter), prefer that.
1346
- if (req.get) {
1347
- return req.get(context, deps, relMap);
1348
- }
1347
+ makeShimExports: function (value) {
1348
+ function fn() {
1349
+ var ret;
1350
+ if (value.init) {
1351
+ ret = value.init.apply(global, arguments);
1352
+ }
1353
+ return ret || (value.exports && getGlobal(value.exports));
1354
+ }
1355
+ return fn;
1356
+ },
1349
1357
 
1350
- //Normalize module name, if it contains . or ..
1351
- map = makeModuleMap(deps, relMap, false, true);
1352
- id = map.id;
1358
+ makeRequire: function (relMap, options) {
1359
+ options = options || {};
1360
+
1361
+ function localRequire(deps, callback, errback) {
1362
+ var id, map, requireMod;
1363
+
1364
+ if (options.enableBuildCallback && callback && isFunction(callback)) {
1365
+ callback.__requireJsBuild = true;
1366
+ }
1367
+
1368
+ if (typeof deps === 'string') {
1369
+ if (isFunction(callback)) {
1370
+ //Invalid call
1371
+ return onError(makeError('requireargs', 'Invalid require call'), errback);
1372
+ }
1373
+
1374
+ //If require|exports|module are requested, get the
1375
+ //value for them from the special handlers. Caveat:
1376
+ //this only works while module is being defined.
1377
+ if (relMap && hasProp(handlers, deps)) {
1378
+ return handlers[deps](registry[relMap.id]);
1379
+ }
1380
+
1381
+ //Synchronous access to one module. If require.get is
1382
+ //available (as in the Node adapter), prefer that.
1383
+ if (req.get) {
1384
+ return req.get(context, deps, relMap, localRequire);
1385
+ }
1386
+
1387
+ //Normalize module name, if it contains . or ..
1388
+ map = makeModuleMap(deps, relMap, false, true);
1389
+ id = map.id;
1390
+
1391
+ if (!hasProp(defined, id)) {
1392
+ return onError(makeError('notloaded', 'Module name "' +
1393
+ id +
1394
+ '" has not been loaded yet for context: ' +
1395
+ contextName +
1396
+ (relMap ? '' : '. Use require([])')));
1397
+ }
1398
+ return defined[id];
1399
+ }
1400
+
1401
+ //Grab defines waiting in the global queue.
1402
+ intakeDefines();
1403
+
1404
+ //Mark all the dependencies as needing to be loaded.
1405
+ context.nextTick(function () {
1406
+ //Some defines could have been added since the
1407
+ //require call, collect them.
1408
+ intakeDefines();
1409
+
1410
+ requireMod = getModule(makeModuleMap(null, relMap));
1411
+
1412
+ //Store if map config should be applied to this require
1413
+ //call for dependencies.
1414
+ requireMod.skipMap = options.skipMap;
1415
+
1416
+ requireMod.init(deps, callback, errback, {
1417
+ enabled: true
1418
+ });
1419
+
1420
+ checkLoaded();
1421
+ });
1422
+
1423
+ return localRequire;
1424
+ }
1353
1425
 
1354
- if (!hasProp(defined, id)) {
1355
- return onError(makeError('notloaded', 'Module name "' +
1356
- id +
1357
- '" has not been loaded yet for context: ' +
1358
- contextName +
1359
- (relMap ? '' : '. Use require([])')));
1360
- }
1361
- return defined[id];
1362
- }
1426
+ mixin(localRequire, {
1427
+ isBrowser: isBrowser,
1428
+
1429
+ /**
1430
+ * Converts a module name + .extension into an URL path.
1431
+ * *Requires* the use of a module name. It does not support using
1432
+ * plain URLs like nameToUrl.
1433
+ */
1434
+ toUrl: function (moduleNamePlusExt) {
1435
+ var ext,
1436
+ index = moduleNamePlusExt.lastIndexOf('.'),
1437
+ segment = moduleNamePlusExt.split('/')[0],
1438
+ isRelative = segment === '.' || segment === '..';
1439
+
1440
+ //Have a file extension alias, and it is not the
1441
+ //dots from a relative path.
1442
+ if (index !== -1 && (!isRelative || index > 1)) {
1443
+ ext = moduleNamePlusExt.substring(index, moduleNamePlusExt.length);
1444
+ moduleNamePlusExt = moduleNamePlusExt.substring(0, index);
1445
+ }
1446
+
1447
+ return context.nameToUrl(normalize(moduleNamePlusExt,
1448
+ relMap && relMap.id, true), ext, true);
1449
+ },
1450
+
1451
+ defined: function (id) {
1452
+ return hasProp(defined, makeModuleMap(id, relMap, false, true).id);
1453
+ },
1454
+
1455
+ specified: function (id) {
1456
+ id = makeModuleMap(id, relMap, false, true).id;
1457
+ return hasProp(defined, id) || hasProp(registry, id);
1458
+ }
1459
+ });
1460
+
1461
+ //Only allow undef on top level require calls
1462
+ if (!relMap) {
1463
+ localRequire.undef = function (id) {
1464
+ //Bind any waiting define() calls to this context,
1465
+ //fix for #408
1466
+ takeGlobalQueue();
1467
+
1468
+ var map = makeModuleMap(id, relMap, true),
1469
+ mod = getOwn(registry, id);
1470
+
1471
+ removeScript(id);
1472
+
1473
+ delete defined[id];
1474
+ delete urlFetched[map.url];
1475
+ delete undefEvents[id];
1476
+
1477
+ //Clean queued defines too. Go backwards
1478
+ //in array so that the splices do not
1479
+ //mess up the iteration.
1480
+ eachReverse(defQueue, function(args, i) {
1481
+ if(args[0] === id) {
1482
+ defQueue.splice(i, 1);
1483
+ }
1484
+ });
1485
+
1486
+ if (mod) {
1487
+ //Hold on to listeners in case the
1488
+ //module will be attempted to be reloaded
1489
+ //using a different config.
1490
+ if (mod.events.defined) {
1491
+ undefEvents[id] = mod.events;
1492
+ }
1493
+
1494
+ cleanRegistry(id);
1495
+ }
1496
+ };
1497
+ }
1363
1498
 
1364
- //Grab defines waiting in the global queue.
1365
- intakeDefines();
1499
+ return localRequire;
1500
+ },
1366
1501
 
1367
- //Mark all the dependencies as needing to be loaded.
1368
- context.nextTick(function () {
1369
- //Some defines could have been added since the
1370
- //require call, collect them.
1371
- intakeDefines();
1502
+ /**
1503
+ * Called to enable a module if it is still in the registry
1504
+ * awaiting enablement. A second arg, parent, the parent module,
1505
+ * is passed in for context, when this method is overriden by
1506
+ * the optimizer. Not shown here to keep code compact.
1507
+ */
1508
+ enable: function (depMap) {
1509
+ var mod = getOwn(registry, depMap.id);
1510
+ if (mod) {
1511
+ getModule(depMap).enable();
1512
+ }
1513
+ },
1372
1514
 
1373
- requireMod = getModule(makeModuleMap(null, relMap));
1515
+ /**
1516
+ * Internal method used by environment adapters to complete a load event.
1517
+ * A load event could be a script load or just a load pass from a synchronous
1518
+ * load call.
1519
+ * @param {String} moduleName the name of the module to potentially complete.
1520
+ */
1521
+ completeLoad: function (moduleName) {
1522
+ var found, args, mod,
1523
+ shim = getOwn(config.shim, moduleName) || {},
1524
+ shExports = shim.exports;
1525
+
1526
+ takeGlobalQueue();
1527
+
1528
+ while (defQueue.length) {
1529
+ args = defQueue.shift();
1530
+ if (args[0] === null) {
1531
+ args[0] = moduleName;
1532
+ //If already found an anonymous module and bound it
1533
+ //to this name, then this is some other anon module
1534
+ //waiting for its completeLoad to fire.
1535
+ if (found) {
1536
+ break;
1537
+ }
1538
+ found = true;
1539
+ } else if (args[0] === moduleName) {
1540
+ //Found matching define call for this script!
1541
+ found = true;
1542
+ }
1543
+
1544
+ callGetModule(args);
1545
+ }
1374
1546
 
1375
- //Store if map config should be applied to this require
1376
- //call for dependencies.
1377
- requireMod.skipMap = options.skipMap;
1547
+ //Do this after the cycle of callGetModule in case the result
1548
+ //of those calls/init calls changes the registry.
1549
+ mod = getOwn(registry, moduleName);
1550
+
1551
+ if (!found && !hasProp(defined, moduleName) && mod && !mod.inited) {
1552
+ if (config.enforceDefine && (!shExports || !getGlobal(shExports))) {
1553
+ if (hasPathFallback(moduleName)) {
1554
+ return;
1555
+ } else {
1556
+ return onError(makeError('nodefine',
1557
+ 'No define call for ' + moduleName,
1558
+ null,
1559
+ [moduleName]));
1560
+ }
1561
+ } else {
1562
+ //A script that does not call define(), so just simulate
1563
+ //the call for it.
1564
+ callGetModule([moduleName, (shim.deps || []), shim.exportsFn]);
1565
+ }
1566
+ }
1378
1567
 
1379
- requireMod.init(deps, callback, errback, {
1380
- enabled: true
1381
- });
1568
+ checkLoaded();
1569
+ },
1382
1570
 
1383
- checkLoaded();
1384
- });
1571
+ /**
1572
+ * Converts a module name to a file path. Supports cases where
1573
+ * moduleName may actually be just an URL.
1574
+ * Note that it **does not** call normalize on the moduleName,
1575
+ * it is assumed to have already been normalized. This is an
1576
+ * internal API, not a public one. Use toUrl for the public API.
1577
+ */
1578
+ nameToUrl: function (moduleName, ext, skipExt) {
1579
+ var paths, syms, i, parentModule, url,
1580
+ parentPath, bundleId,
1581
+ pkgMain = getOwn(config.pkgs, moduleName);
1582
+
1583
+ if (pkgMain) {
1584
+ moduleName = pkgMain;
1585
+ }
1385
1586
 
1386
- return localRequire;
1387
- }
1587
+ bundleId = getOwn(bundlesMap, moduleName);
1388
1588
 
1389
- mixin(localRequire, {
1390
- isBrowser: isBrowser,
1391
-
1392
- /**
1393
- * Converts a module name + .extension into an URL path.
1394
- * *Requires* the use of a module name. It does not support using
1395
- * plain URLs like nameToUrl.
1396
- */
1397
- toUrl: function (moduleNamePlusExt) {
1398
- var index = moduleNamePlusExt.lastIndexOf('.'),
1399
- ext = null;
1400
-
1401
- if (index !== -1) {
1402
- ext = moduleNamePlusExt.substring(index, moduleNamePlusExt.length);
1403
- moduleNamePlusExt = moduleNamePlusExt.substring(0, index);
1404
- }
1589
+ if (bundleId) {
1590
+ return context.nameToUrl(bundleId, ext, skipExt);
1591
+ }
1405
1592
 
1406
- return context.nameToUrl(normalize(moduleNamePlusExt,
1407
- relMap && relMap.id, true), ext);
1408
- },
1593
+ //If a colon is in the URL, it indicates a protocol is used and it is just
1594
+ //an URL to a file, or if it starts with a slash, contains a query arg (i.e. ?)
1595
+ //or ends with .js, then assume the user meant to use an url and not a module id.
1596
+ //The slash is important for protocol-less URLs as well as full paths.
1597
+ if (req.jsExtRegExp.test(moduleName)) {
1598
+ //Just a plain path, not module name lookup, so just return it.
1599
+ //Add extension if it is included. This is a bit wonky, only non-.js things pass
1600
+ //an extension, this method probably needs to be reworked.
1601
+ url = moduleName + (ext || '');
1602
+ } else {
1603
+ //A module that needs to be converted to a path.
1604
+ paths = config.paths;
1605
+
1606
+ syms = moduleName.split('/');
1607
+ //For each module name segment, see if there is a path
1608
+ //registered for it. Start with most specific name
1609
+ //and work up from it.
1610
+ for (i = syms.length; i > 0; i -= 1) {
1611
+ parentModule = syms.slice(0, i).join('/');
1612
+
1613
+ parentPath = getOwn(paths, parentModule);
1614
+ if (parentPath) {
1615
+ //If an array, it means there are a few choices,
1616
+ //Choose the one that is desired
1617
+ if (isArray(parentPath)) {
1618
+ parentPath = parentPath[0];
1619
+ }
1620
+ syms.splice(0, i, parentPath);
1621
+ break;
1622
+ }
1623
+ }
1624
+
1625
+ //Join the path parts together, then figure out if baseUrl is needed.
1626
+ url = syms.join('/');
1627
+ url += (ext || (/^data\:|\?/.test(url) || skipExt ? '' : '.js'));
1628
+ url = (url.charAt(0) === '/' || url.match(/^[\w\+\.\-]+:/) ? '' : config.baseUrl) + url;
1629
+ }
1409
1630
 
1410
- defined: function (id) {
1411
- return hasProp(defined, makeModuleMap(id, relMap, false, true).id);
1412
- },
1631
+ return config.urlArgs ? url +
1632
+ ((url.indexOf('?') === -1 ? '?' : '&') +
1633
+ config.urlArgs) : url;
1634
+ },
1413
1635
 
1414
- specified: function (id) {
1415
- id = makeModuleMap(id, relMap, false, true).id;
1416
- return hasProp(defined, id) || hasProp(registry, id);
1417
- }
1418
- });
1636
+ //Delegates to req.load. Broken out as a separate function to
1637
+ //allow overriding in the optimizer.
1638
+ load: function (id, url) {
1639
+ req.load(context, id, url);
1640
+ },
1419
1641
 
1420
- //Only allow undef on top level require calls
1421
- if (!relMap) {
1422
- localRequire.undef = function (id) {
1423
- //Bind any waiting define() calls to this context,
1424
- //fix for #408
1425
- takeGlobalQueue();
1642
+ /**
1643
+ * Executes a module callback function. Broken out as a separate function
1644
+ * solely to allow the build system to sequence the files in the built
1645
+ * layer in the right sequence.
1646
+ *
1647
+ * @private
1648
+ */
1649
+ execCb: function (name, callback, args, exports) {
1650
+ return callback.apply(exports, args);
1651
+ },
1426
1652
 
1427
- var map = makeModuleMap(id, relMap, true),
1428
- mod = getOwn(registry, id);
1653
+ /**
1654
+ * callback for script loads, used to check status of loading.
1655
+ *
1656
+ * @param {Event} evt the event from the browser for the script
1657
+ * that was loaded.
1658
+ */
1659
+ onScriptLoad: function (evt) {
1660
+ //Using currentTarget instead of target for Firefox 2.0's sake. Not
1661
+ //all old browsers will be supported, but this one was easy enough
1662
+ //to support and still makes sense.
1663
+ if (evt.type === 'load' ||
1664
+ (readyRegExp.test((evt.currentTarget || evt.srcElement).readyState))) {
1665
+ //Reset interactive script so a script node is not held onto for
1666
+ //to long.
1667
+ interactiveScript = null;
1668
+
1669
+ //Pull out the name of the module and the context.
1670
+ var data = getScriptData(evt);
1671
+ context.completeLoad(data.id);
1672
+ }
1673
+ },
1429
1674
 
1430
- delete defined[id];
1431
- delete urlFetched[map.url];
1432
- delete undefEvents[id];
1675
+ /**
1676
+ * Callback for script errors.
1677
+ */
1678
+ onScriptError: function (evt) {
1679
+ var data = getScriptData(evt);
1680
+ if (!hasPathFallback(data.id)) {
1681
+ return onError(makeError('scripterror', 'Script error for: ' + data.id, evt, [data.id]));
1682
+ }
1683
+ }
1684
+ };
1433
1685
 
1434
- if (mod) {
1435
- //Hold on to listeners in case the
1436
- //module will be attempted to be reloaded
1437
- //using a different config.
1438
- if (mod.events.defined) {
1439
- undefEvents[id] = mod.events;
1440
- }
1686
+ context.require = context.makeRequire();
1687
+ return context;
1688
+ }
1441
1689
 
1442
- cleanRegistry(id);
1690
+ /**
1691
+ * Main entry point.
1692
+ *
1693
+ * If the only argument to require is a string, then the module that
1694
+ * is represented by that string is fetched for the appropriate context.
1695
+ *
1696
+ * If the first argument is an array, then it will be treated as an array
1697
+ * of dependency string names to fetch. An optional function callback can
1698
+ * be specified to execute when all of those dependencies are available.
1699
+ *
1700
+ * Make a local req variable to help Caja compliance (it assumes things
1701
+ * on a require that are not standardized), and to give a short
1702
+ * name for minification/local scope use.
1703
+ */
1704
+ req = requirejs = function (deps, callback, errback, optional) {
1705
+
1706
+ //Find the right context, use default
1707
+ var context, config,
1708
+ contextName = defContextName;
1709
+
1710
+ // Determine if have config object in the call.
1711
+ if (!isArray(deps) && typeof deps !== 'string') {
1712
+ // deps is a config object
1713
+ config = deps;
1714
+ if (isArray(callback)) {
1715
+ // Adjust args if there are dependencies
1716
+ deps = callback;
1717
+ callback = errback;
1718
+ errback = optional;
1719
+ } else {
1720
+ deps = [];
1443
1721
  }
1444
- };
1445
1722
  }
1446
1723
 
1447
- return localRequire;
1448
- },
1449
-
1450
- /**
1451
- * Called to enable a module if it is still in the registry
1452
- * awaiting enablement. parent module is passed in for context,
1453
- * used by the optimizer.
1454
- */
1455
- enable: function (depMap, parent) {
1456
- var mod = getOwn(registry, depMap.id);
1457
- if (mod) {
1458
- getModule(depMap).enable();
1724
+ if (config && config.context) {
1725
+ contextName = config.context;
1459
1726
  }
1460
- },
1461
-
1462
- /**
1463
- * Internal method used by environment adapters to complete a load event.
1464
- * A load event could be a script load or just a load pass from a synchronous
1465
- * load call.
1466
- * @param {String} moduleName the name of the module to potentially complete.
1467
- */
1468
- completeLoad: function (moduleName) {
1469
- var found, args, mod,
1470
- shim = getOwn(config.shim, moduleName) || {},
1471
- shExports = shim.exports;
1472
-
1473
- takeGlobalQueue();
1474
-
1475
- while (defQueue.length) {
1476
- args = defQueue.shift();
1477
- if (args[0] === null) {
1478
- args[0] = moduleName;
1479
- //If already found an anonymous module and bound it
1480
- //to this name, then this is some other anon module
1481
- //waiting for its completeLoad to fire.
1482
- if (found) {
1483
- break;
1484
- }
1485
- found = true;
1486
- } else if (args[0] === moduleName) {
1487
- //Found matching define call for this script!
1488
- found = true;
1489
- }
1490
1727
 
1491
- callGetModule(args);
1728
+ context = getOwn(contexts, contextName);
1729
+ if (!context) {
1730
+ context = contexts[contextName] = req.s.newContext(contextName);
1492
1731
  }
1493
1732
 
1494
- //Do this after the cycle of callGetModule in case the result
1495
- //of those calls/init calls changes the registry.
1496
- mod = getOwn(registry, moduleName);
1733
+ if (config) {
1734
+ context.configure(config);
1735
+ }
1497
1736
 
1498
- if (!found && !hasProp(defined, moduleName) && mod && !mod.inited) {
1499
- if (config.enforceDefine && (!shExports || !getGlobal(shExports))) {
1500
- if (hasPathFallback(moduleName)) {
1501
- return;
1502
- } else {
1503
- return onError(makeError('nodefine',
1504
- 'No define call for ' + moduleName,
1505
- null,
1506
- [moduleName]));
1507
- }
1508
- } else {
1509
- //A script that does not call define(), so just simulate
1510
- //the call for it.
1511
- callGetModule([moduleName, (shim.deps || []), shim.exportsFn]);
1512
- }
1737
+ return context.require(deps, callback, errback);
1738
+ };
1739
+
1740
+ /**
1741
+ * Support require.config() to make it easier to cooperate with other
1742
+ * AMD loaders on globally agreed names.
1743
+ */
1744
+ req.config = function (config) {
1745
+ return req(config);
1746
+ };
1747
+
1748
+ /**
1749
+ * Execute something after the current tick
1750
+ * of the event loop. Override for other envs
1751
+ * that have a better solution than setTimeout.
1752
+ * @param {Function} fn function to execute later.
1753
+ */
1754
+ req.nextTick = typeof setTimeout !== 'undefined' ? function (fn) {
1755
+ setTimeout(fn, 4);
1756
+ } : function (fn) { fn(); };
1757
+
1758
+ /**
1759
+ * Export require as a global, but only if it does not already exist.
1760
+ */
1761
+ if (!require) {
1762
+ require = req;
1763
+ }
1764
+
1765
+ req.version = version;
1766
+
1767
+ //Used to filter out dependencies that are already paths.
1768
+ req.jsExtRegExp = /^\/|:|\?|\.js$/;
1769
+ req.isBrowser = isBrowser;
1770
+ s = req.s = {
1771
+ contexts: contexts,
1772
+ newContext: newContext
1773
+ };
1774
+
1775
+ //Create default context.
1776
+ req({});
1777
+
1778
+ //Exports some context-sensitive methods on global require.
1779
+ each([
1780
+ 'toUrl',
1781
+ 'undef',
1782
+ 'defined',
1783
+ 'specified'
1784
+ ], function (prop) {
1785
+ //Reference from contexts instead of early binding to default context,
1786
+ //so that during builds, the latest instance of the default context
1787
+ //with its config gets used.
1788
+ req[prop] = function () {
1789
+ var ctx = contexts[defContextName];
1790
+ return ctx.require[prop].apply(ctx, arguments);
1791
+ };
1792
+ });
1793
+
1794
+ if (isBrowser) {
1795
+ head = s.head = document.getElementsByTagName('head')[0];
1796
+ //If BASE tag is in play, using appendChild is a problem for IE6.
1797
+ //When that browser dies, this can be removed. Details in this jQuery bug:
1798
+ //http://dev.jquery.com/ticket/2709
1799
+ baseElement = document.getElementsByTagName('base')[0];
1800
+ if (baseElement) {
1801
+ head = s.head = baseElement.parentNode;
1513
1802
  }
1803
+ }
1514
1804
 
1515
- checkLoaded();
1516
- },
1517
-
1518
- /**
1519
- * Converts a module name to a file path. Supports cases where
1520
- * moduleName may actually be just an URL.
1521
- * Note that it **does not** call normalize on the moduleName,
1522
- * it is assumed to have already been normalized. This is an
1523
- * internal API, not a public one. Use toUrl for the public API.
1524
- */
1525
- nameToUrl: function (moduleName, ext) {
1526
- var paths, pkgs, pkg, pkgPath, syms, i, parentModule, url,
1527
- parentPath;
1528
-
1529
- //If a colon is in the URL, it indicates a protocol is used and it is just
1530
- //an URL to a file, or if it starts with a slash, contains a query arg (i.e. ?)
1531
- //or ends with .js, then assume the user meant to use an url and not a module id.
1532
- //The slash is important for protocol-less URLs as well as full paths.
1533
- if (req.jsExtRegExp.test(moduleName)) {
1534
- //Just a plain path, not module name lookup, so just return it.
1535
- //Add extension if it is included. This is a bit wonky, only non-.js things pass
1536
- //an extension, this method probably needs to be reworked.
1537
- url = moduleName + (ext || '');
1538
- } else {
1539
- //A module that needs to be converted to a path.
1540
- paths = config.paths;
1541
- pkgs = config.pkgs;
1542
-
1543
- syms = moduleName.split('/');
1544
- //For each module name segment, see if there is a path
1545
- //registered for it. Start with most specific name
1546
- //and work up from it.
1547
- for (i = syms.length; i > 0; i -= 1) {
1548
- parentModule = syms.slice(0, i).join('/');
1549
- pkg = getOwn(pkgs, parentModule);
1550
- parentPath = getOwn(paths, parentModule);
1551
- if (parentPath) {
1552
- //If an array, it means there are a few choices,
1553
- //Choose the one that is desired
1554
- if (isArray(parentPath)) {
1555
- parentPath = parentPath[0];
1556
- }
1557
- syms.splice(0, i, parentPath);
1558
- break;
1559
- } else if (pkg) {
1560
- //If module name is just the package name, then looking
1561
- //for the main module.
1562
- if (moduleName === pkg.name) {
1563
- pkgPath = pkg.location + '/' + pkg.main;
1564
- } else {
1565
- pkgPath = pkg.location;
1566
- }
1567
- syms.splice(0, i, pkgPath);
1568
- break;
1805
+ /**
1806
+ * Any errors that require explicitly generates will be passed to this
1807
+ * function. Intercept/override it if you want custom error handling.
1808
+ * @param {Error} err the error object.
1809
+ */
1810
+ req.onError = defaultOnError;
1811
+
1812
+ /**
1813
+ * Creates the node for the load command. Only used in browser envs.
1814
+ */
1815
+ req.createNode = function (config, moduleName, url) {
1816
+ var node = config.xhtml ?
1817
+ document.createElementNS('http://www.w3.org/1999/xhtml', 'html:script') :
1818
+ document.createElement('script');
1819
+ node.type = config.scriptType || 'text/javascript';
1820
+ node.charset = 'utf-8';
1821
+ node.async = true;
1822
+ return node;
1823
+ };
1824
+
1825
+ /**
1826
+ * Does the request to load a module for the browser case.
1827
+ * Make this a separate function to allow other environments
1828
+ * to override it.
1829
+ *
1830
+ * @param {Object} context the require context to find state.
1831
+ * @param {String} moduleName the name of the module.
1832
+ * @param {Object} url the URL to the module.
1833
+ */
1834
+ req.load = function (context, moduleName, url) {
1835
+ var config = (context && context.config) || {},
1836
+ node;
1837
+ if (isBrowser) {
1838
+ //In the browser so use a script tag
1839
+ node = req.createNode(config, moduleName, url);
1840
+
1841
+ node.setAttribute('data-requirecontext', context.contextName);
1842
+ node.setAttribute('data-requiremodule', moduleName);
1843
+
1844
+ //Set up load listener. Test attachEvent first because IE9 has
1845
+ //a subtle issue in its addEventListener and script onload firings
1846
+ //that do not match the behavior of all other browsers with
1847
+ //addEventListener support, which fire the onload event for a
1848
+ //script right after the script execution. See:
1849
+ //https://connect.microsoft.com/IE/feedback/details/648057/script-onload-event-is-not-fired-immediately-after-script-execution
1850
+ //UNFORTUNATELY Opera implements attachEvent but does not follow the script
1851
+ //script execution mode.
1852
+ if (node.attachEvent &&
1853
+ //Check if node.attachEvent is artificially added by custom script or
1854
+ //natively supported by browser
1855
+ //read https://github.com/jrburke/requirejs/issues/187
1856
+ //if we can NOT find [native code] then it must NOT natively supported.
1857
+ //in IE8, node.attachEvent does not have toString()
1858
+ //Note the test for "[native code" with no closing brace, see:
1859
+ //https://github.com/jrburke/requirejs/issues/273
1860
+ !(node.attachEvent.toString && node.attachEvent.toString().indexOf('[native code') < 0) &&
1861
+ !isOpera) {
1862
+ //Probably IE. IE (at least 6-8) do not fire
1863
+ //script onload right after executing the script, so
1864
+ //we cannot tie the anonymous define call to a name.
1865
+ //However, IE reports the script as being in 'interactive'
1866
+ //readyState at the time of the define call.
1867
+ useInteractive = true;
1868
+
1869
+ node.attachEvent('onreadystatechange', context.onScriptLoad);
1870
+ //It would be great to add an error handler here to catch
1871
+ //404s in IE9+. However, onreadystatechange will fire before
1872
+ //the error handler, so that does not help. If addEventListener
1873
+ //is used, then IE will fire error before load, but we cannot
1874
+ //use that pathway given the connect.microsoft.com issue
1875
+ //mentioned above about not doing the 'script execute,
1876
+ //then fire the script load event listener before execute
1877
+ //next script' that other browsers do.
1878
+ //Best hope: IE10 fixes the issues,
1879
+ //and then destroys all installs of IE 6-9.
1880
+ //node.attachEvent('onerror', context.onScriptError);
1881
+ } else {
1882
+ node.addEventListener('load', context.onScriptLoad, false);
1883
+ node.addEventListener('error', context.onScriptError, false);
1569
1884
  }
1570
- }
1885
+ node.src = url;
1886
+
1887
+ //For some cache cases in IE 6-8, the script executes before the end
1888
+ //of the appendChild execution, so to tie an anonymous define
1889
+ //call to the module name (which is stored on the node), hold on
1890
+ //to a reference to this node, but clear after the DOM insertion.
1891
+ currentlyAddingScript = node;
1892
+ if (baseElement) {
1893
+ head.insertBefore(node, baseElement);
1894
+ } else {
1895
+ head.appendChild(node);
1896
+ }
1897
+ currentlyAddingScript = null;
1571
1898
 
1572
- //Join the path parts together, then figure out if baseUrl is needed.
1573
- url = syms.join('/');
1574
- url += (ext || (/\?/.test(url) ? '' : '.js'));
1575
- url = (url.charAt(0) === '/' || url.match(/^[\w\+\.\-]+:/) ? '' : config.baseUrl) + url;
1899
+ return node;
1900
+ } else if (isWebWorker) {
1901
+ try {
1902
+ //In a web worker, use importScripts. This is not a very
1903
+ //efficient use of importScripts, importScripts will block until
1904
+ //its script is downloaded and evaluated. However, if web workers
1905
+ //are in play, the expectation that a build has been done so that
1906
+ //only one script needs to be loaded anyway. This may need to be
1907
+ //reevaluated if other use cases become common.
1908
+ importScripts(url);
1909
+
1910
+ //Account for anonymous modules
1911
+ context.completeLoad(moduleName);
1912
+ } catch (e) {
1913
+ context.onError(makeError('importscripts',
1914
+ 'importScripts failed for ' +
1915
+ moduleName + ' at ' + url,
1916
+ e,
1917
+ [moduleName]));
1918
+ }
1576
1919
  }
1920
+ };
1577
1921
 
1578
- return config.urlArgs ? url +
1579
- ((url.indexOf('?') === -1 ? '?' : '&') +
1580
- config.urlArgs) : url;
1581
- },
1582
-
1583
- //Delegates to req.load. Broken out as a separate function to
1584
- //allow overriding in the optimizer.
1585
- load: function (id, url) {
1586
- req.load(context, id, url);
1587
- },
1588
-
1589
- /**
1590
- * Executes a module callack function. Broken out as a separate function
1591
- * solely to allow the build system to sequence the files in the built
1592
- * layer in the right sequence.
1593
- *
1594
- * @private
1595
- */
1596
- execCb: function (name, callback, args, exports) {
1597
- return callback.apply(exports, args);
1598
- },
1599
-
1600
- /**
1601
- * callback for script loads, used to check status of loading.
1602
- *
1603
- * @param {Event} evt the event from the browser for the script
1604
- * that was loaded.
1605
- */
1606
- onScriptLoad: function (evt) {
1607
- //Using currentTarget instead of target for Firefox 2.0's sake. Not
1608
- //all old browsers will be supported, but this one was easy enough
1609
- //to support and still makes sense.
1610
- if (evt.type === 'load' ||
1611
- (readyRegExp.test((evt.currentTarget || evt.srcElement).readyState))) {
1612
- //Reset interactive script so a script node is not held onto for
1613
- //to long.
1614
- interactiveScript = null;
1615
-
1616
- //Pull out the name of the module and the context.
1617
- var data = getScriptData(evt);
1618
- context.completeLoad(data.id);
1619
- }
1620
- },
1621
-
1622
- /**
1623
- * Callback for script errors.
1624
- */
1625
- onScriptError: function (evt) {
1626
- var data = getScriptData(evt);
1627
- if (!hasPathFallback(data.id)) {
1628
- return onError(makeError('scripterror', 'Script error', evt, [data.id]));
1922
+ function getInteractiveScript() {
1923
+ if (interactiveScript && interactiveScript.readyState === 'interactive') {
1924
+ return interactiveScript;
1629
1925
  }
1630
- }
1631
- };
1632
1926
 
1633
- context.require = context.makeRequire();
1634
- return context;
1635
- }
1636
-
1637
- /**
1638
- * Main entry point.
1639
- *
1640
- * If the only argument to require is a string, then the module that
1641
- * is represented by that string is fetched for the appropriate context.
1642
- *
1643
- * If the first argument is an array, then it will be treated as an array
1644
- * of dependency string names to fetch. An optional function callback can
1645
- * be specified to execute when all of those dependencies are available.
1646
- *
1647
- * Make a local req variable to help Caja compliance (it assumes things
1648
- * on a require that are not standardized), and to give a short
1649
- * name for minification/local scope use.
1650
- */
1651
- req = requirejs = function (deps, callback, errback, optional) {
1652
-
1653
- //Find the right context, use default
1654
- var context, config,
1655
- contextName = defContextName;
1656
-
1657
- // Determine if have config object in the call.
1658
- if (!isArray(deps) && typeof deps !== 'string') {
1659
- // deps is a config object
1660
- config = deps;
1661
- if (isArray(callback)) {
1662
- // Adjust args if there are dependencies
1663
- deps = callback;
1664
- callback = errback;
1665
- errback = optional;
1666
- } else {
1667
- deps = [];
1668
- }
1927
+ eachReverse(scripts(), function (script) {
1928
+ if (script.readyState === 'interactive') {
1929
+ return (interactiveScript = script);
1930
+ }
1931
+ });
1932
+ return interactiveScript;
1669
1933
  }
1670
1934
 
1671
- if (config && config.context) {
1672
- contextName = config.context;
1673
- }
1935
+ //Look for a data-main script attribute, which could also adjust the baseUrl.
1936
+ if (isBrowser && !cfg.skipDataMain) {
1937
+ //Figure out baseUrl. Get it from the script tag with require.js in it.
1938
+ eachReverse(scripts(), function (script) {
1939
+ //Set the 'head' where we can append children by
1940
+ //using the script's parent.
1941
+ if (!head) {
1942
+ head = script.parentNode;
1943
+ }
1674
1944
 
1675
- context = getOwn(contexts, contextName);
1676
- if (!context) {
1677
- context = contexts[contextName] = req.s.newContext(contextName);
1678
- }
1945
+ //Look for a data-main attribute to set main script for the page
1946
+ //to load. If it is there, the path to data main becomes the
1947
+ //baseUrl, if it is not already set.
1948
+ dataMain = script.getAttribute('data-main');
1949
+ if (dataMain) {
1950
+ //Preserve dataMain in case it is a path (i.e. contains '?')
1951
+ mainScript = dataMain;
1952
+
1953
+ //Set final baseUrl if there is not already an explicit one.
1954
+ if (!cfg.baseUrl) {
1955
+ //Pull off the directory of data-main for use as the
1956
+ //baseUrl.
1957
+ src = mainScript.split('/');
1958
+ mainScript = src.pop();
1959
+ subPath = src.length ? src.join('/') + '/' : './';
1960
+
1961
+ cfg.baseUrl = subPath;
1962
+ }
1679
1963
 
1680
- if (config) {
1681
- context.configure(config);
1682
- }
1964
+ //Strip off any trailing .js since mainScript is now
1965
+ //like a module name.
1966
+ mainScript = mainScript.replace(jsSuffixRegExp, '');
1683
1967
 
1684
- return context.require(deps, callback, errback);
1685
- };
1686
-
1687
- /**
1688
- * Support require.config() to make it easier to cooperate with other
1689
- * AMD loaders on globally agreed names.
1690
- */
1691
- req.config = function (config) {
1692
- return req(config);
1693
- };
1694
-
1695
- /**
1696
- * Execute something after the current tick
1697
- * of the event loop. Override for other envs
1698
- * that have a better solution than setTimeout.
1699
- * @param {Function} fn function to execute later.
1700
- */
1701
- req.nextTick = typeof setTimeout !== 'undefined' ? function (fn) {
1702
- setTimeout(fn, 4);
1703
- } : function (fn) { fn(); };
1704
-
1705
- /**
1706
- * Export require as a global, but only if it does not already exist.
1707
- */
1708
- if (!require) {
1709
- require = req;
1710
- }
1711
-
1712
- req.version = version;
1713
-
1714
- //Used to filter out dependencies that are already paths.
1715
- req.jsExtRegExp = /^\/|:|\?|\.js$/;
1716
- req.isBrowser = isBrowser;
1717
- s = req.s = {
1718
- contexts: contexts,
1719
- newContext: newContext
1720
- };
1721
-
1722
- //Create default context.
1723
- req({});
1724
-
1725
- //Exports some context-sensitive methods on global require.
1726
- each([
1727
- 'toUrl',
1728
- 'undef',
1729
- 'defined',
1730
- 'specified'
1731
- ], function (prop) {
1732
- //Reference from contexts instead of early binding to default context,
1733
- //so that during builds, the latest instance of the default context
1734
- //with its config gets used.
1735
- req[prop] = function () {
1736
- var ctx = contexts[defContextName];
1737
- return ctx.require[prop].apply(ctx, arguments);
1738
- };
1739
- });
1740
-
1741
- if (isBrowser) {
1742
- head = s.head = document.getElementsByTagName('head')[0];
1743
- //If BASE tag is in play, using appendChild is a problem for IE6.
1744
- //When that browser dies, this can be removed. Details in this jQuery bug:
1745
- //http://dev.jquery.com/ticket/2709
1746
- baseElement = document.getElementsByTagName('base')[0];
1747
- if (baseElement) {
1748
- head = s.head = baseElement.parentNode;
1749
- }
1750
- }
1751
-
1752
- /**
1753
- * Any errors that require explicitly generates will be passed to this
1754
- * function. Intercept/override it if you want custom error handling.
1755
- * @param {Error} err the error object.
1756
- */
1757
- req.onError = function (err) {
1758
- throw err;
1759
- };
1760
-
1761
- /**
1762
- * Does the request to load a module for the browser case.
1763
- * Make this a separate function to allow other environments
1764
- * to override it.
1765
- *
1766
- * @param {Object} context the require context to find state.
1767
- * @param {String} moduleName the name of the module.
1768
- * @param {Object} url the URL to the module.
1769
- */
1770
- req.load = function (context, moduleName, url) {
1771
- var config = (context && context.config) || {},
1772
- node;
1773
- if (isBrowser) {
1774
- //In the browser so use a script tag
1775
- node = config.xhtml ?
1776
- document.createElementNS('http://www.w3.org/1999/xhtml', 'html:script') :
1777
- document.createElement('script');
1778
- node.type = config.scriptType || 'text/javascript';
1779
- node.charset = 'utf-8';
1780
- node.async = true;
1781
-
1782
- node.setAttribute('data-requirecontext', context.contextName);
1783
- node.setAttribute('data-requiremodule', moduleName);
1784
-
1785
- //Set up load listener. Test attachEvent first because IE9 has
1786
- //a subtle issue in its addEventListener and script onload firings
1787
- //that do not match the behavior of all other browsers with
1788
- //addEventListener support, which fire the onload event for a
1789
- //script right after the script execution. See:
1790
- //https://connect.microsoft.com/IE/feedback/details/648057/script-onload-event-is-not-fired-immediately-after-script-execution
1791
- //UNFORTUNATELY Opera implements attachEvent but does not follow the script
1792
- //script execution mode.
1793
- if (node.attachEvent &&
1794
- //Check if node.attachEvent is artificially added by custom script or
1795
- //natively supported by browser
1796
- //read https://github.com/jrburke/requirejs/issues/187
1797
- //if we can NOT find [native code] then it must NOT natively supported.
1798
- //in IE8, node.attachEvent does not have toString()
1799
- //Note the test for "[native code" with no closing brace, see:
1800
- //https://github.com/jrburke/requirejs/issues/273
1801
- !(node.attachEvent.toString && node.attachEvent.toString().indexOf('[native code') < 0) &&
1802
- !isOpera) {
1803
- //Probably IE. IE (at least 6-8) do not fire
1804
- //script onload right after executing the script, so
1805
- //we cannot tie the anonymous define call to a name.
1806
- //However, IE reports the script as being in 'interactive'
1807
- //readyState at the time of the define call.
1808
- useInteractive = true;
1809
-
1810
- node.attachEvent('onreadystatechange', context.onScriptLoad);
1811
- //It would be great to add an error handler here to catch
1812
- //404s in IE9+. However, onreadystatechange will fire before
1813
- //the error handler, so that does not help. If addEvenListener
1814
- //is used, then IE will fire error before load, but we cannot
1815
- //use that pathway given the connect.microsoft.com issue
1816
- //mentioned above about not doing the 'script execute,
1817
- //then fire the script load event listener before execute
1818
- //next script' that other browsers do.
1819
- //Best hope: IE10 fixes the issues,
1820
- //and then destroys all installs of IE 6-9.
1821
- //node.attachEvent('onerror', context.onScriptError);
1822
- } else {
1823
- node.addEventListener('load', context.onScriptLoad, false);
1824
- node.addEventListener('error', context.onScriptError, false);
1825
- }
1826
- node.src = url;
1827
-
1828
- //For some cache cases in IE 6-8, the script executes before the end
1829
- //of the appendChild execution, so to tie an anonymous define
1830
- //call to the module name (which is stored on the node), hold on
1831
- //to a reference to this node, but clear after the DOM insertion.
1832
- currentlyAddingScript = node;
1833
- if (baseElement) {
1834
- head.insertBefore(node, baseElement);
1835
- } else {
1836
- head.appendChild(node);
1837
- }
1838
- currentlyAddingScript = null;
1839
-
1840
- return node;
1841
- } else if (isWebWorker) {
1842
- //In a web worker, use importScripts. This is not a very
1843
- //efficient use of importScripts, importScripts will block until
1844
- //its script is downloaded and evaluated. However, if web workers
1845
- //are in play, the expectation that a build has been done so that
1846
- //only one script needs to be loaded anyway. This may need to be
1847
- //reevaluated if other use cases become common.
1848
- importScripts(url);
1849
-
1850
- //Account for anonymous modules
1851
- context.completeLoad(moduleName);
1852
- }
1853
- };
1968
+ //If mainScript is still a path, fall back to dataMain
1969
+ if (req.jsExtRegExp.test(mainScript)) {
1970
+ mainScript = dataMain;
1971
+ }
1854
1972
 
1855
- function getInteractiveScript() {
1856
- if (interactiveScript && interactiveScript.readyState === 'interactive') {
1857
- return interactiveScript;
1973
+ //Put the data-main script in the files to load.
1974
+ cfg.deps = cfg.deps ? cfg.deps.concat(mainScript) : [mainScript];
1975
+
1976
+ return true;
1977
+ }
1978
+ });
1858
1979
  }
1859
1980
 
1860
- eachReverse(scripts(), function (script) {
1861
- if (script.readyState === 'interactive') {
1862
- return (interactiveScript = script);
1863
- }
1864
- });
1865
- return interactiveScript;
1866
- }
1867
-
1868
- //Look for a data-main script attribute, which could also adjust the baseUrl.
1869
- if (isBrowser) {
1870
- //Figure out baseUrl. Get it from the script tag with require.js in it.
1871
- eachReverse(scripts(), function (script) {
1872
- //Set the 'head' where we can append children by
1873
- //using the script's parent.
1874
- if (!head) {
1875
- head = script.parentNode;
1876
- }
1877
-
1878
- //Look for a data-main attribute to set main script for the page
1879
- //to load. If it is there, the path to data main becomes the
1880
- //baseUrl, if it is not already set.
1881
- dataMain = script.getAttribute('data-main');
1882
- if (dataMain) {
1883
- //Set final baseUrl if there is not already an explicit one.
1884
- if (!cfg.baseUrl) {
1885
- //Pull off the directory of data-main for use as the
1886
- //baseUrl.
1887
- src = dataMain.split('/');
1888
- mainScript = src.pop();
1889
- subPath = src.length ? src.join('/') + '/' : './';
1890
-
1891
- cfg.baseUrl = subPath;
1892
- dataMain = mainScript;
1981
+ /**
1982
+ * The function that handles definitions of modules. Differs from
1983
+ * require() in that a string for the module should be the first argument,
1984
+ * and the function to execute after dependencies are loaded should
1985
+ * return a value to define the module corresponding to the first argument's
1986
+ * name.
1987
+ */
1988
+ define = function (name, deps, callback) {
1989
+ var node, context;
1990
+
1991
+ //Allow for anonymous modules
1992
+ if (typeof name !== 'string') {
1993
+ //Adjust args appropriately
1994
+ callback = deps;
1995
+ deps = name;
1996
+ name = null;
1893
1997
  }
1894
1998
 
1895
- //Strip off any trailing .js since dataMain is now
1896
- //like a module name.
1897
- dataMain = dataMain.replace(jsSuffixRegExp, '');
1999
+ //This module may not have dependencies
2000
+ if (!isArray(deps)) {
2001
+ callback = deps;
2002
+ deps = null;
2003
+ }
1898
2004
 
1899
- //Put the data-main script in the files to load.
1900
- cfg.deps = cfg.deps ? cfg.deps.concat(dataMain) : [dataMain];
2005
+ //If no name, and callback is a function, then figure out if it a
2006
+ //CommonJS thing with dependencies.
2007
+ if (!deps && isFunction(callback)) {
2008
+ deps = [];
2009
+ //Remove comments from the callback string,
2010
+ //look for require calls, and pull them into the dependencies,
2011
+ //but only if there are function args.
2012
+ if (callback.length) {
2013
+ callback
2014
+ .toString()
2015
+ .replace(commentRegExp, '')
2016
+ .replace(cjsRequireRegExp, function (match, dep) {
2017
+ deps.push(dep);
2018
+ });
2019
+
2020
+ //May be a CommonJS thing even without require calls, but still
2021
+ //could use exports, and module. Avoid doing exports and module
2022
+ //work though if it just needs require.
2023
+ //REQUIRES the function to expect the CommonJS variables in the
2024
+ //order listed below.
2025
+ deps = (callback.length === 1 ? ['require'] : ['require', 'exports', 'module']).concat(deps);
2026
+ }
2027
+ }
1901
2028
 
1902
- return true;
1903
- }
1904
- });
1905
- }
1906
-
1907
- /**
1908
- * The function that handles definitions of modules. Differs from
1909
- * require() in that a string for the module should be the first argument,
1910
- * and the function to execute after dependencies are loaded should
1911
- * return a value to define the module corresponding to the first argument's
1912
- * name.
1913
- */
1914
- define = function (name, deps, callback) {
1915
- var node, context;
1916
-
1917
- //Allow for anonymous modules
1918
- if (typeof name !== 'string') {
1919
- //Adjust args appropriately
1920
- callback = deps;
1921
- deps = name;
1922
- name = null;
1923
- }
2029
+ //If in IE 6-8 and hit an anonymous define() call, do the interactive
2030
+ //work.
2031
+ if (useInteractive) {
2032
+ node = currentlyAddingScript || getInteractiveScript();
2033
+ if (node) {
2034
+ if (!name) {
2035
+ name = node.getAttribute('data-requiremodule');
2036
+ }
2037
+ context = contexts[node.getAttribute('data-requirecontext')];
2038
+ }
2039
+ }
1924
2040
 
1925
- //This module may not have dependencies
1926
- if (!isArray(deps)) {
1927
- callback = deps;
1928
- deps = [];
1929
- }
2041
+ //Always save off evaluating the def call until the script onload handler.
2042
+ //This allows multiple modules to be in a file without prematurely
2043
+ //tracing dependencies, and allows for anonymous module support,
2044
+ //where the module name is not known until the script onload event
2045
+ //occurs. If no context, use the global queue, and get it processed
2046
+ //in the onscript load callback.
2047
+ (context ? context.defQueue : globalDefQueue).push([name, deps, callback]);
2048
+ };
1930
2049
 
1931
- //If no name, and callback is a function, then figure out if it a
1932
- //CommonJS thing with dependencies.
1933
- if (!deps.length && isFunction(callback)) {
1934
- //Remove comments from the callback string,
1935
- //look for require calls, and pull them into the dependencies,
1936
- //but only if there are function args.
1937
- if (callback.length) {
1938
- callback
1939
- .toString()
1940
- .replace(commentRegExp, '')
1941
- .replace(cjsRequireRegExp, function (match, dep) {
1942
- deps.push(dep);
1943
- });
2050
+ define.amd = {
2051
+ jQuery: true
2052
+ };
1944
2053
 
1945
- //May be a CommonJS thing even without require calls, but still
1946
- //could use exports, and module. Avoid doing exports and module
1947
- //work though if it just needs require.
1948
- //REQUIRES the function to expect the CommonJS variables in the
1949
- //order listed below.
1950
- deps = (callback.length === 1 ? ['require'] : ['require', 'exports', 'module']).concat(deps);
1951
- }
1952
- }
1953
2054
 
1954
- //If in IE 6-8 and hit an anonymous define() call, do the interactive
1955
- //work.
1956
- if (useInteractive) {
1957
- node = currentlyAddingScript || getInteractiveScript();
1958
- if (node) {
1959
- if (!name) {
1960
- name = node.getAttribute('data-requiremodule');
1961
- }
1962
- context = contexts[node.getAttribute('data-requirecontext')];
1963
- }
1964
- }
2055
+ /**
2056
+ * Executes the text. Normally just uses eval, but can be modified
2057
+ * to use a better, environment-specific call. Only used for transpiling
2058
+ * loader plugins, not for plain JS modules.
2059
+ * @param {String} text the text to execute/evaluate.
2060
+ */
2061
+ req.exec = function (text) {
2062
+ /*jslint evil: true */
2063
+ return eval(text);
2064
+ };
1965
2065
 
1966
- //Always save off evaluating the def call until the script onload handler.
1967
- //This allows multiple modules to be in a file without prematurely
1968
- //tracing dependencies, and allows for anonymous module support,
1969
- //where the module name is not known until the script onload event
1970
- //occurs. If no context, use the global queue, and get it processed
1971
- //in the onscript load callback.
1972
- (context ? context.defQueue : globalDefQueue).push([name, deps, callback]);
1973
- };
1974
-
1975
- define.amd = {
1976
- jQuery: true
1977
- };
1978
-
1979
-
1980
- /**
1981
- * Executes the text. Normally just uses eval, but can be modified
1982
- * to use a better, environment-specific call. Only used for transpiling
1983
- * loader plugins, not for plain JS modules.
1984
- * @param {String} text the text to execute/evaluate.
1985
- */
1986
- req.exec = function (text) {
1987
- /*jslint evil: true */
1988
- return eval(text);
1989
- };
1990
-
1991
- //Set up with config info.
1992
- req(cfg);
1993
- }(this));
2066
+ //Set up with config info.
2067
+ req(cfg);
2068
+ }(this));