Skip to content

Commit 540b134

Browse files
author
Mateusz Krzeszowiak
committed
Refactor JavaScript mixins module
Fixes #25586.
1 parent 2cc9d29 commit 540b134

File tree

1 file changed

+57
-95
lines changed

1 file changed

+57
-95
lines changed

lib/web/mage/requirejs/mixins.js

Lines changed: 57 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,25 @@ define('mixins', [
77
], function (module) {
88
'use strict';
99

10-
var rjsMixins;
10+
var contexts = require.s.contexts,
11+
defContextName = '_',
12+
defContext = contexts[defContextName],
13+
unbundledContext = require.s.newContext('$'),
14+
defaultConfig = defContext.config,
15+
unbundledConfig = {
16+
baseUrl: defaultConfig.baseUrl,
17+
paths: defaultConfig.paths,
18+
shim: defaultConfig.shim,
19+
config: defaultConfig.config,
20+
map: defaultConfig.map
21+
},
22+
rjsMixins;
23+
24+
/**
25+
* Prepare a separate context where modules are not assigned to bundles
26+
* so we are able to get their true path and corresponding mixins.
27+
*/
28+
unbundledContext.configure(unbundledConfig);
1129

1230
/**
1331
* Checks if specified string contains
@@ -50,14 +68,14 @@ define('mixins', [
5068

5169
/**
5270
* Extracts url (without baseUrl prefix)
53-
* from a modules' name.
71+
* from a module name ignoring the fact that it may be bundled.
5472
*
5573
* @param {String} name - Name, path or alias of a module.
56-
* @param {Object} config - Contexts' configuartion.
74+
* @param {Object} config - Context's configuartion.
5775
* @returns {String}
5876
*/
5977
function getPath(name, config) {
60-
var url = require.toUrl(name);
78+
var url = unbundledContext.require.toUrl(name);
6179

6280
return removeBaseUrl(url, config);
6381
}
@@ -73,11 +91,11 @@ define('mixins', [
7391
}
7492

7593
/**
76-
* Iterativly calls mixins passing to them
94+
* Iteratively calls mixins passing to them
7795
* current value of a 'target' parameter.
7896
*
7997
* @param {*} target - Value to be modified.
80-
* @param {...Function} mixins
98+
* @param {...Function} mixins - List of mixins to apply.
8199
* @returns {*} Modified 'target' value.
82100
*/
83101
function applyMixins(target) {
@@ -94,8 +112,13 @@ define('mixins', [
94112

95113
/**
96114
* Loads specified module along with its' mixins.
115+
* This method is called for each module defined with "mixins!" prefix
116+
* in its name that was added by processNames method.
97117
*
98118
* @param {String} name - Module to be loaded.
119+
* @param {Function} req - Local "require" function to use to load other modules.
120+
* @param {Function} onLoad - A function to call with the value for name.
121+
* @param {Object} config - RequireJS configuration object.
99122
*/
100123
load: function (name, req, onLoad, config) {
101124
var path = getPath(name, config),
@@ -110,14 +133,14 @@ define('mixins', [
110133
/**
111134
* Retrieves list of mixins associated with a specified module.
112135
*
113-
* @param {String} path - Path to the module (without base url).
136+
* @param {String} path - Path to the module (without base URL).
114137
* @returns {Array} An array of paths to mixins.
115138
*/
116139
getMixins: function (path) {
117140
var config = module.config() || {},
118-
mixins;
141+
mixins;
119142

120-
// fix for when urlArgs is set
143+
// Fix for when urlArgs is set.
121144
if (path.indexOf('?') !== -1) {
122145
path = path.substring(0, path.indexOf('?'));
123146
}
@@ -131,19 +154,19 @@ define('mixins', [
131154
/**
132155
* Checks if specified module has associated with it mixins.
133156
*
134-
* @param {String} path - Path to the module (without base url).
157+
* @param {String} path - Path to the module (without base URL).
135158
* @returns {Boolean}
136159
*/
137160
hasMixins: function (path) {
138161
return this.getMixins(path).length;
139162
},
140163

141164
/**
142-
* Modifies provided names perpending to them
165+
* Modifies provided names prepending to them
143166
* the 'mixins!' plugin prefix if it's necessary.
144167
*
145168
* @param {(Array|String)} names - Module names, paths or aliases.
146-
* @param {Object} context - Current requirejs context.
169+
* @param {Object} context - Current RequireJS context.
147170
* @returns {Array|String}
148171
*/
149172
processNames: function (names, context) {
@@ -179,101 +202,40 @@ require([
179202
], function (mixins) {
180203
'use strict';
181204

182-
var originalRequire = window.require,
183-
originalDefine = window.define,
184-
contexts = originalRequire.s.contexts,
185-
defContextName = '_',
186-
hasOwn = Object.prototype.hasOwnProperty,
187-
getLastInQueue;
188-
189-
getLastInQueue =
190-
'(function () {' +
191-
'var queue = globalDefQueue,' +
192-
'item = queue[queue.length - 1];' +
193-
'' +
194-
'return item;' +
195-
'})();';
196-
197-
/**
198-
* Returns property of an object if
199-
* it's not defined in it's prototype.
200-
*
201-
* @param {Object} obj - Object whose property should be retrieved.
202-
* @param {String} prop - Name of the property.
203-
* @returns {*} Value of the property or false.
204-
*/
205-
function getOwn(obj, prop) {
206-
return hasOwn.call(obj, prop) && obj[prop];
207-
}
208-
209-
/**
210-
* Overrides global 'require' method adding to it dependencies modfication.
211-
*/
212-
window.require = function (deps, callback, errback, optional) {
213-
var contextName = defContextName,
214-
context,
215-
config;
216-
217-
if (!Array.isArray(deps) && typeof deps !== 'string') {
218-
config = deps;
219-
220-
if (Array.isArray(callback)) {
221-
deps = callback;
222-
callback = errback;
223-
errback = optional;
224-
} else {
225-
deps = [];
226-
}
227-
}
228-
229-
if (config && config.context) {
230-
contextName = config.context;
231-
}
232-
233-
context = getOwn(contexts, contextName);
234-
235-
if (!context) {
236-
context = contexts[contextName] = require.s.newContext(contextName);
237-
}
238-
239-
if (config) {
240-
context.configure(config);
241-
}
242-
243-
deps = mixins.processNames(deps, context);
244-
245-
return context.require(deps, callback, errback);
246-
};
205+
var contexts = require.s.contexts,
206+
defContextName = '_',
207+
defContext = contexts[defContextName],
208+
originalContextRequire = defContext.require,
209+
processNames = mixins.processNames;
247210

248211
/**
249-
* Overrides global 'define' method adding to it dependencies modfication.
212+
* Wrap default context's require function which gets called every time
213+
* module is requested using require call. The upside of this approach
214+
* is that deps parameter is already normalized and guaranteed to be an array.
250215
*/
251-
window.define = function (name, deps, callback) { // eslint-disable-line no-unused-vars
252-
var context = getOwn(contexts, defContextName),
253-
result = originalDefine.apply(this, arguments),
254-
queueItem = require.exec(getLastInQueue),
255-
lastDeps = queueItem && queueItem[1];
256-
257-
if (Array.isArray(lastDeps)) {
258-
queueItem[1] = mixins.processNames(lastDeps, context);
259-
}
216+
defContext.require = function (deps, callback, errback) {
217+
deps = processNames(deps, defContext);
260218

261-
return result;
219+
return originalContextRequire(deps, callback, errback);
262220
};
263221

264222
/**
265223
* Copy properties of original 'require' method.
266224
*/
267-
Object.keys(originalRequire).forEach(function (key) {
268-
require[key] = originalRequire[key];
225+
Object.keys(originalContextRequire).forEach(function (key) {
226+
defContext.require[key] = originalContextRequire[key];
269227
});
270228

271229
/**
272-
* Copy properties of original 'define' method.
230+
* Wrap shift method from context's definitions queue.
231+
* Items are added to the queue when a new module is defined and taken
232+
* from it every time require call happens.
273233
*/
274-
Object.keys(originalDefine).forEach(function (key) {
275-
define[key] = originalDefine[key];
276-
});
234+
defContext.defQueue.shift = function () {
235+
var queueItem = Array.prototype.shift.call(this);
236+
237+
queueItem[1] = processNames(queueItem[1], defContext);
277238

278-
window.requirejs = window.require;
239+
return queueItem;
240+
};
279241
});

0 commit comments

Comments
 (0)