|
- /**
- * Copyright © Magento, Inc. All rights reserved.
- * See COPYING.txt for license details.
- */
- define('mixins', [
- 'module'
- ], function (module) {
- 'use strict';
-
- var contexts = require.s.contexts,
- defContextName = '_',
- defContext = contexts[defContextName],
- unbundledContext = require.s.newContext('$'),
- defaultConfig = defContext.config,
- unbundledConfig = {
- baseUrl: defaultConfig.baseUrl,
- paths: defaultConfig.paths,
- shim: defaultConfig.shim,
- config: defaultConfig.config,
- map: defaultConfig.map
- },
- rjsMixins;
-
- /**
- * Prepare a separate context where modules are not assigned to bundles
- * so we are able to get their true path and corresponding mixins.
- */
- unbundledContext.configure(unbundledConfig);
-
- /**
- * Checks if specified string contains
- * a plugin spacer '!' substring.
- *
- * @param {String} name - Name, path or alias of a module.
- * @returns {Boolean}
- */
- function hasPlugin(name) {
- return !!~name.indexOf('!');
- }
-
- /**
- * Adds 'mixins!' prefix to the specified string.
- *
- * @param {String} name - Name, path or alias of a module.
- * @returns {String} Modified name.
- */
- function addPlugin(name) {
- return 'mixins!' + name;
- }
-
- /**
- * Removes base url from the provided string.
- *
- * @param {String} url - Url to be processed.
- * @param {Object} config - Contexts' configuration object.
- * @returns {String} String without base url.
- */
- function removeBaseUrl(url, config) {
- var baseUrl = config.baseUrl || '',
- index = url.indexOf(baseUrl);
-
- if (~index) {
- url = url.substring(baseUrl.length - index);
- }
-
- return url;
- }
-
- /**
- * Extracts url (without baseUrl prefix)
- * from a module name ignoring the fact that it may be bundled.
- *
- * @param {String} name - Name, path or alias of a module.
- * @param {Object} config - Context's configuration.
- * @returns {String}
- */
- function getPath(name, config) {
- var url = unbundledContext.require.toUrl(name);
-
- return removeBaseUrl(url, config);
- }
-
- /**
- * Checks if specified string represents a relative path (../).
- *
- * @param {String} name - Name, path or alias of a module.
- * @returns {Boolean}
- */
- function isRelative(name) {
- return !!~name.indexOf('./');
- }
-
- /**
- * Iteratively calls mixins passing to them
- * current value of a 'target' parameter.
- *
- * @param {*} target - Value to be modified.
- * @param {...Function} mixins - List of mixins to apply.
- * @returns {*} Modified 'target' value.
- */
- function applyMixins(target) {
- var mixins = Array.prototype.slice.call(arguments, 1);
-
- mixins.forEach(function (mixin) {
- target = mixin(target);
- });
-
- return target;
- }
-
- rjsMixins = {
-
- /**
- * Loads specified module along with its' mixins.
- * This method is called for each module defined with "mixins!" prefix
- * in its name that was added by processNames method.
- *
- * @param {String} name - Module to be loaded.
- * @param {Function} req - Local "require" function to use to load other modules.
- * @param {Function} onLoad - A function to call with the value for name.
- * @param {Object} config - RequireJS configuration object.
- */
- load: function (name, req, onLoad, config) {
- var path = getPath(name, config),
- mixins = this.getMixins(path),
- deps = [name].concat(mixins);
-
- req(deps, function () {
- onLoad(applyMixins.apply(null, arguments));
- });
- },
-
- /**
- * Retrieves list of mixins associated with a specified module.
- *
- * @param {String} path - Path to the module (without base URL).
- * @returns {Array} An array of paths to mixins.
- */
- getMixins: function (path) {
- var config = module.config() || {},
- mixins;
-
- // Fix for when urlArgs is set.
- if (path.indexOf('?') !== -1) {
- path = path.substring(0, path.indexOf('?'));
- }
- mixins = config[path] || {};
-
- return Object.keys(mixins).filter(function (mixin) {
- return mixins[mixin] !== false;
- });
- },
-
- /**
- * Checks if specified module has associated with it mixins.
- *
- * @param {String} path - Path to the module (without base URL).
- * @returns {Boolean}
- */
- hasMixins: function (path) {
- return this.getMixins(path).length;
- },
-
- /**
- * Modifies provided names prepending to them
- * the 'mixins!' plugin prefix if it's necessary.
- *
- * @param {(Array|String)} names - Module names, paths or aliases.
- * @param {Object} context - Current RequireJS context.
- * @returns {Array|String}
- */
- processNames: function (names, context) {
- var config = context.config;
-
- /**
- * Prepends 'mixin' plugin to a single name.
- *
- * @param {String} name
- * @returns {String}
- */
- function processName(name) {
- var path = getPath(name, config);
-
- if (!hasPlugin(name) && (isRelative(name) || rjsMixins.hasMixins(path))) {
- return addPlugin(name);
- }
-
- return name;
- }
-
- return typeof names !== 'string' ?
- names.map(processName) :
- processName(names);
- }
- };
-
- return rjsMixins;
- });
-
- require([
- 'mixins'
- ], function (mixins) {
- 'use strict';
-
- var contexts = require.s.contexts,
- defContextName = '_',
- defContext = contexts[defContextName],
- originalContextRequire = defContext.require,
- processNames = mixins.processNames;
-
- /**
- * Wrap default context's require function which gets called every time
- * module is requested using require call. The upside of this approach
- * is that deps parameter is already normalized and guaranteed to be an array.
- */
- defContext.require = function (deps, callback, errback) {
- deps = processNames(deps, defContext);
-
- return originalContextRequire(deps, callback, errback);
- };
-
- /**
- * Copy properties of original 'require' method.
- */
- Object.keys(originalContextRequire).forEach(function (key) {
- defContext.require[key] = originalContextRequire[key];
- });
-
- /**
- * Wrap shift method from context's definitions queue.
- * Items are added to the queue when a new module is defined and taken
- * from it every time require call happens.
- */
- defContext.defQueue.shift = function () {
- var queueItem = Array.prototype.shift.call(this),
- lastDeps = queueItem && queueItem[1];
-
- if (Array.isArray(lastDeps)) {
- queueItem[1] = processNames(queueItem[1], defContext);
- }
-
- return queueItem;
- };
- });
|