From 19b4b3e5ee764484e7a34b60494c15177a2aeb6e Mon Sep 17 00:00:00 2001 From: Robert Jackson Date: Thu, 4 May 2023 16:04:53 -0400 Subject: [PATCH] Simplify repository structure (remove `addon/resolvers/classic`) The `resolvers` subdirectory was created in order to support both the classic resolver and the module unification resolver. Some time later, the MU resolver was removed. This cleans the repo up a bit to make it much simpler (and more "normal"). --- .../classic => }/container-debug-adapter.js | 0 addon/addon/index.js | 479 +++++++++++++++++- addon/addon/resolver.js | 1 - addon/addon/resolvers/classic/index.js | 478 ----------------- addon/app/container-debug-adapter.js | 2 +- test-app/tests/unit/exports-test.js | 16 - .../unit/resolvers/classic/basic-test.js | 8 +- 7 files changed, 483 insertions(+), 501 deletions(-) rename addon/addon/{resolvers/classic => }/container-debug-adapter.js (100%) delete mode 100644 addon/addon/resolver.js delete mode 100644 addon/addon/resolvers/classic/index.js delete mode 100644 test-app/tests/unit/exports-test.js diff --git a/addon/addon/resolvers/classic/container-debug-adapter.js b/addon/addon/container-debug-adapter.js similarity index 100% rename from addon/addon/resolvers/classic/container-debug-adapter.js rename to addon/addon/container-debug-adapter.js diff --git a/addon/addon/index.js b/addon/addon/index.js index b27ffe19..0292db14 100644 --- a/addon/addon/index.js +++ b/addon/addon/index.js @@ -1 +1,478 @@ -export { default } from './resolvers/classic'; +/* globals requirejs, require */ + +import Ember from 'ember'; +import { assert, deprecate, warn } from '@ember/debug'; +import EmberObject from '@ember/object'; +import { dasherize, classify, underscore } from '@ember/string'; +import { DEBUG } from '@glimmer/env'; +import classFactory from './utils/class-factory'; + +if (typeof requirejs.entries === 'undefined') { + requirejs.entries = requirejs._eak_seen; +} + +export class ModuleRegistry { + constructor(entries) { + this._entries = entries || requirejs.entries; + } + moduleNames() { + return Object.keys(this._entries); + } + has(moduleName) { + return moduleName in this._entries; + } + get(...args) { + return require(...args); + } +} + +/** + * This module defines a subclass of Ember.DefaultResolver that adds two + * important features: + * + * 1) The resolver makes the container aware of es6 modules via the AMD + * output. The loader's _moduleEntries is consulted so that classes can be + * resolved directly via the module loader, without needing a manual + * `import`. + * 2) is able to provide injections to classes that implement `extend` + * (as is typical with Ember). + */ +class Resolver extends EmberObject { + static moduleBasedResolver = true; + moduleBasedResolver = true; + + _deprecatedPodModulePrefix = false; + _normalizeCache = Object.create(null); + + /** + A listing of functions to test for moduleName's based on the provided + `parsedName`. This allows easy customization of additional module based + lookup patterns. + + @property moduleNameLookupPatterns + @returns {Ember.Array} + */ + moduleNameLookupPatterns = [ + this.podBasedModuleName, + this.podBasedComponentsInSubdir, + this.mainModuleName, + this.defaultModuleName, + this.nestedColocationComponentModuleName, + ]; + + + constructor() { + super(...arguments); + + if (!this._moduleRegistry) { + this._moduleRegistry = new ModuleRegistry(); + } + + this.pluralizedTypes = this.pluralizedTypes || Object.create(null); + + if (!this.pluralizedTypes.config) { + this.pluralizedTypes.config = 'config'; + } + } + + makeToString(factory, fullName) { + return '' + this.namespace.modulePrefix + '@' + fullName + ':'; + } + + shouldWrapInClassFactory(/* module, parsedName */){ + return false; + } + + parseName(fullName) { + if (fullName.parsedName === true) { return fullName; } + + let prefix, type, name; + let fullNameParts = fullName.split('@'); + + if (fullNameParts.length === 3) { + if (fullNameParts[0].length === 0) { + // leading scoped namespace: `@scope/pkg@type:name` + prefix = `@${fullNameParts[1]}`; + let prefixParts = fullNameParts[2].split(':'); + type = prefixParts[0]; + name = prefixParts[1]; + } else { + // interweaved scoped namespace: `type:@scope/pkg@name` + prefix = `@${fullNameParts[1]}`; + type = fullNameParts[0].slice(0, -1); + name = fullNameParts[2]; + } + + if (type === 'template:components') { + name = `components/${name}`; + type = 'template'; + } + } else if (fullNameParts.length === 2) { + let prefixParts = fullNameParts[0].split(':'); + + if (prefixParts.length === 2) { + if (prefixParts[1].length === 0) { + type = prefixParts[0]; + name = `@${fullNameParts[1]}`; + } else { + prefix = prefixParts[1]; + type = prefixParts[0]; + name = fullNameParts[1]; + } + } else { + let nameParts = fullNameParts[1].split(':'); + + prefix = fullNameParts[0]; + type = nameParts[0]; + name = nameParts[1]; + } + + if (type === 'template' && prefix.lastIndexOf('components/', 0) === 0) { + name = `components/${name}`; + prefix = prefix.slice(11); + } + } else { + fullNameParts = fullName.split(':'); + type = fullNameParts[0]; + name = fullNameParts[1]; + } + + let fullNameWithoutType = name; + let namespace = this.namespace; + let root = namespace; + + return { + parsedName: true, + fullName: fullName, + prefix: prefix || this.prefix({type: type}), + type: type, + fullNameWithoutType: fullNameWithoutType, + name: name, + root: root, + resolveMethodName: "resolve" + classify(type) + }; + } + + resolveOther(parsedName) { + assert('`modulePrefix` must be defined', this.namespace.modulePrefix); + + let normalizedModuleName = this.findModuleName(parsedName); + + if (normalizedModuleName) { + let defaultExport = this._extractDefaultExport(normalizedModuleName, parsedName); + + if (defaultExport === undefined) { + throw new Error(` Expected to find: '${parsedName.fullName}' within '${normalizedModuleName}' but got 'undefined'. Did you forget to 'export default' within '${normalizedModuleName}'?`); + } + + if (this.shouldWrapInClassFactory(defaultExport, parsedName)) { + defaultExport = classFactory(defaultExport); + } + + return defaultExport; + } + } + + normalize(fullName) { + return this._normalizeCache[fullName] || (this._normalizeCache[fullName] = this._normalize(fullName)); + } + + resolve(fullName) { + let parsedName = this.parseName(fullName); + let resolveMethodName = parsedName.resolveMethodName; + let resolved; + + if (typeof this[resolveMethodName] === 'function') { + resolved = this[resolveMethodName](parsedName); + } + + if (resolved == null) { + resolved = this.resolveOther(parsedName); + } + + return resolved; + } + + _normalize(fullName) { + // A) Convert underscores to dashes + // B) Convert camelCase to dash-case, except for components (their + // templates) and helpers where we want to avoid shadowing camelCase + // expressions + // C) replace `.` with `/` in order to make nested controllers work in the following cases + // 1. `needs: ['posts/post']` + // 2. `{{render "posts/post"}}` + // 3. `this.render('posts/post')` from Route + + let split = fullName.split(':'); + if (split.length > 1) { + let type = split[0]; + + if ( + type === 'component' || + type === 'helper' || + type === 'modifier' || + (type === 'template' && split[1].indexOf('components/') === 0) + ) { + return type + ':' + split[1].replace(/_/g, '-'); + } else { + return type + ':' + dasherize(split[1].replace(/\./g, '/')); + } + } else { + return fullName; + } + } + + pluralize(type) { + return this.pluralizedTypes[type] || (this.pluralizedTypes[type] = type + 's'); + } + + podBasedLookupWithPrefix(podPrefix, parsedName) { + let fullNameWithoutType = parsedName.fullNameWithoutType; + + if (parsedName.type === 'template') { + fullNameWithoutType = fullNameWithoutType.replace(/^components\//, ''); + } + + return podPrefix + '/' + fullNameWithoutType + '/' + parsedName.type; + } + + podBasedModuleName(parsedName) { + let podPrefix = this.namespace.podModulePrefix || this.namespace.modulePrefix; + + return this.podBasedLookupWithPrefix(podPrefix, parsedName); + } + + podBasedComponentsInSubdir(parsedName) { + let podPrefix = this.namespace.podModulePrefix || this.namespace.modulePrefix; + podPrefix = podPrefix + '/components'; + + if (parsedName.type === 'component' || /^components/.test(parsedName.fullNameWithoutType)) { + return this.podBasedLookupWithPrefix(podPrefix, parsedName); + } + } + + resolveEngine(parsedName) { + let engineName = parsedName.fullNameWithoutType; + let engineModule = engineName + '/engine'; + + if (this._moduleRegistry.has(engineModule)) { + return this._extractDefaultExport(engineModule); + } + } + + resolveRouteMap(parsedName) { + let engineName = parsedName.fullNameWithoutType; + let engineRoutesModule = engineName + '/routes'; + + if (this._moduleRegistry.has(engineRoutesModule)) { + let routeMap = this._extractDefaultExport(engineRoutesModule); + + assert(`The route map for ${engineName} should be wrapped by 'buildRoutes' before exporting.` , routeMap.isRouteMap); + + return routeMap; + } + } + + resolveTemplate(parsedName) { + let resolved = this.resolveOther(parsedName); + if (resolved == null) { + resolved = Ember.TEMPLATES[parsedName.fullNameWithoutType]; + } + return resolved; + } + + mainModuleName(parsedName) { + if (parsedName.fullNameWithoutType === 'main') { + // if router:main or adapter:main look for a module with just the type first + return parsedName.prefix + '/' + parsedName.type; + } + } + + defaultModuleName(parsedName) { + return parsedName.prefix + '/' + this.pluralize(parsedName.type) + '/' + parsedName.fullNameWithoutType; + } + + nestedColocationComponentModuleName(parsedName) { + if (parsedName.type === 'component') { + return parsedName.prefix + '/' + this.pluralize(parsedName.type) + '/' + parsedName.fullNameWithoutType + '/index'; + } + } + + prefix(parsedName) { + let tmpPrefix = this.namespace.modulePrefix; + + if (this.namespace[parsedName.type + 'Prefix']) { + tmpPrefix = this.namespace[parsedName.type + 'Prefix']; + } + + return tmpPrefix; + } + + findModuleName(parsedName, loggingDisabled){ + let moduleNameLookupPatterns = this.moduleNameLookupPatterns; + let moduleName; + + for (let index = 0, length = moduleNameLookupPatterns.length; index < length; index++) { + let item = moduleNameLookupPatterns[index]; + + let tmpModuleName = item.call(this, parsedName); + + // allow treat all dashed and all underscored as the same thing + // supports components with dashes and other stuff with underscores. + if (tmpModuleName) { + tmpModuleName = this.chooseModuleName(tmpModuleName, parsedName); + } + + if (tmpModuleName && this._moduleRegistry.has(tmpModuleName)) { + moduleName = tmpModuleName; + } + + if (!loggingDisabled) { + this._logLookup(moduleName, parsedName, tmpModuleName); + } + + if (moduleName) { + return moduleName; + } + } + } + + chooseModuleName(moduleName, parsedName) { + let underscoredModuleName = underscore(moduleName); + + if (moduleName !== underscoredModuleName && this._moduleRegistry.has(moduleName) && this._moduleRegistry.has(underscoredModuleName)) { + throw new TypeError(`Ambiguous module names: '${ moduleName}' and '${underscoredModuleName }'`); + } + + if (this._moduleRegistry.has(moduleName)) { + return moduleName; + } else if (this._moduleRegistry.has(underscoredModuleName)) { + return underscoredModuleName; + } + // workaround for dasherized partials: + // something/something/-something => something/something/_something + let partializedModuleName = moduleName.replace(/\/-([^/]*)$/, '/_$1'); + + if (this._moduleRegistry.has(partializedModuleName)) { + deprecate('Modules should not contain underscores. ' + + 'Attempted to lookup "'+moduleName+'" which ' + + 'was not found. Please rename "'+partializedModuleName+'" '+ + 'to "'+moduleName+'" instead.', false, + { + id: 'ember-resolver.underscored-modules', + until: '3.0.0', + for: 'ember-resolver', + since: '0.1.0' + }); + + return partializedModuleName; + } + + if (DEBUG) { + let isCamelCaseHelper = parsedName.type === 'helper' && /[a-z]+[A-Z]+/.test(moduleName); + if (isCamelCaseHelper) { + this._camelCaseHelperWarnedNames = this._camelCaseHelperWarnedNames || []; + let alreadyWarned = this._camelCaseHelperWarnedNames.indexOf(parsedName.fullName) > -1; + if (!alreadyWarned && this._moduleRegistry.has(dasherize(moduleName))) { + this._camelCaseHelperWarnedNames.push(parsedName.fullName); + warn('Attempted to lookup "' + parsedName.fullName + '" which ' + + 'was not found. In previous versions of ember-resolver, a bug would have ' + + 'caused the module at "' + dasherize(moduleName) + '" to be ' + + 'returned for this camel case helper name. This has been fixed. ' + + 'Use the dasherized name to resolve the module that would have been ' + + 'returned in previous versions.', + false, + { id: 'ember-resolver.camelcase-helper-names', until: '3.0.0' }); + } + } + } + } + + // used by Ember.DefaultResolver.prototype._logLookup + lookupDescription(fullName) { + let parsedName = this.parseName(fullName); + + let moduleName = this.findModuleName(parsedName, true); + + return moduleName; + } + + // only needed until 1.6.0-beta.2 can be required + _logLookup(found, parsedName, description) { + if (!Ember.ENV.LOG_MODULE_RESOLVER && !parsedName.root.LOG_RESOLVER) { + return; + } + + let padding; + let symbol = found ? '[✓]' : '[ ]'; + + if (parsedName.fullName.length > 60) { + padding = '.'; + } else { + padding = new Array(60 - parsedName.fullName.length).join('.'); + } + + if (!description) { + description = this.lookupDescription(parsedName); + } + + /* eslint-disable no-console */ + if (console && console.info) { + console.info(symbol, parsedName.fullName, padding, description); + } + } + + knownForType(type) { + let moduleKeys = this._moduleRegistry.moduleNames(); + + let items = Object.create(null); + for (let index = 0, length = moduleKeys.length; index < length; index++) { + let moduleName = moduleKeys[index]; + let fullname = this.translateToContainerFullname(type, moduleName); + + if (fullname) { + items[fullname] = true; + } + } + + return items; + } + + translateToContainerFullname(type, moduleName) { + let prefix = this.prefix({ type }); + + // Note: using string manipulation here rather than regexes for better performance. + // pod modules + // '^' + prefix + '/(.+)/' + type + '$' + let podPrefix = prefix + '/'; + let podSuffix = '/' + type; + let start = moduleName.indexOf(podPrefix); + let end = moduleName.indexOf(podSuffix); + + if (start === 0 && end === (moduleName.length - podSuffix.length) && + moduleName.length > (podPrefix.length + podSuffix.length)) { + return type + ':' + moduleName.slice(start + podPrefix.length, end); + } + + // non-pod modules + // '^' + prefix + '/' + pluralizedType + '/(.+)$' + let pluralizedType = this.pluralize(type); + let nonPodPrefix = prefix + '/' + pluralizedType + '/'; + + if (moduleName.indexOf(nonPodPrefix) === 0 && moduleName.length > nonPodPrefix.length) { + return type + ':' + moduleName.slice(nonPodPrefix.length); + } + } + + _extractDefaultExport(normalizedModuleName) { + let module = this._moduleRegistry.get(normalizedModuleName, null, null, true /* force sync */); + + if (module && module['default']) { + module = module['default']; + } + + return module; + } +} + +export default Resolver; diff --git a/addon/addon/resolver.js b/addon/addon/resolver.js deleted file mode 100644 index b27ffe19..00000000 --- a/addon/addon/resolver.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from './resolvers/classic'; diff --git a/addon/addon/resolvers/classic/index.js b/addon/addon/resolvers/classic/index.js deleted file mode 100644 index 81bd4a33..00000000 --- a/addon/addon/resolvers/classic/index.js +++ /dev/null @@ -1,478 +0,0 @@ -/* globals requirejs, require */ - -import Ember from 'ember'; -import { assert, deprecate, warn } from '@ember/debug'; -import EmberObject from '@ember/object'; -import { dasherize, classify, underscore } from '@ember/string'; -import { DEBUG } from '@glimmer/env'; -import classFactory from '../../utils/class-factory'; - -if (typeof requirejs.entries === 'undefined') { - requirejs.entries = requirejs._eak_seen; -} - -export class ModuleRegistry { - constructor(entries) { - this._entries = entries || requirejs.entries; - } - moduleNames() { - return Object.keys(this._entries); - } - has(moduleName) { - return moduleName in this._entries; - } - get(...args) { - return require(...args); - } -} - -/** - * This module defines a subclass of Ember.DefaultResolver that adds two - * important features: - * - * 1) The resolver makes the container aware of es6 modules via the AMD - * output. The loader's _moduleEntries is consulted so that classes can be - * resolved directly via the module loader, without needing a manual - * `import`. - * 2) is able to provide injections to classes that implement `extend` - * (as is typical with Ember). - */ -class Resolver extends EmberObject { - static moduleBasedResolver = true; - moduleBasedResolver = true; - - _deprecatedPodModulePrefix = false; - _normalizeCache = Object.create(null); - - /** - A listing of functions to test for moduleName's based on the provided - `parsedName`. This allows easy customization of additional module based - lookup patterns. - - @property moduleNameLookupPatterns - @returns {Ember.Array} - */ - moduleNameLookupPatterns = [ - this.podBasedModuleName, - this.podBasedComponentsInSubdir, - this.mainModuleName, - this.defaultModuleName, - this.nestedColocationComponentModuleName, - ]; - - - constructor() { - super(...arguments); - - if (!this._moduleRegistry) { - this._moduleRegistry = new ModuleRegistry(); - } - - this.pluralizedTypes = this.pluralizedTypes || Object.create(null); - - if (!this.pluralizedTypes.config) { - this.pluralizedTypes.config = 'config'; - } - } - - makeToString(factory, fullName) { - return '' + this.namespace.modulePrefix + '@' + fullName + ':'; - } - - shouldWrapInClassFactory(/* module, parsedName */){ - return false; - } - - parseName(fullName) { - if (fullName.parsedName === true) { return fullName; } - - let prefix, type, name; - let fullNameParts = fullName.split('@'); - - if (fullNameParts.length === 3) { - if (fullNameParts[0].length === 0) { - // leading scoped namespace: `@scope/pkg@type:name` - prefix = `@${fullNameParts[1]}`; - let prefixParts = fullNameParts[2].split(':'); - type = prefixParts[0]; - name = prefixParts[1]; - } else { - // interweaved scoped namespace: `type:@scope/pkg@name` - prefix = `@${fullNameParts[1]}`; - type = fullNameParts[0].slice(0, -1); - name = fullNameParts[2]; - } - - if (type === 'template:components') { - name = `components/${name}`; - type = 'template'; - } - } else if (fullNameParts.length === 2) { - let prefixParts = fullNameParts[0].split(':'); - - if (prefixParts.length === 2) { - if (prefixParts[1].length === 0) { - type = prefixParts[0]; - name = `@${fullNameParts[1]}`; - } else { - prefix = prefixParts[1]; - type = prefixParts[0]; - name = fullNameParts[1]; - } - } else { - let nameParts = fullNameParts[1].split(':'); - - prefix = fullNameParts[0]; - type = nameParts[0]; - name = nameParts[1]; - } - - if (type === 'template' && prefix.lastIndexOf('components/', 0) === 0) { - name = `components/${name}`; - prefix = prefix.slice(11); - } - } else { - fullNameParts = fullName.split(':'); - type = fullNameParts[0]; - name = fullNameParts[1]; - } - - let fullNameWithoutType = name; - let namespace = this.namespace; - let root = namespace; - - return { - parsedName: true, - fullName: fullName, - prefix: prefix || this.prefix({type: type}), - type: type, - fullNameWithoutType: fullNameWithoutType, - name: name, - root: root, - resolveMethodName: "resolve" + classify(type) - }; - } - - resolveOther(parsedName) { - assert('`modulePrefix` must be defined', this.namespace.modulePrefix); - - let normalizedModuleName = this.findModuleName(parsedName); - - if (normalizedModuleName) { - let defaultExport = this._extractDefaultExport(normalizedModuleName, parsedName); - - if (defaultExport === undefined) { - throw new Error(` Expected to find: '${parsedName.fullName}' within '${normalizedModuleName}' but got 'undefined'. Did you forget to 'export default' within '${normalizedModuleName}'?`); - } - - if (this.shouldWrapInClassFactory(defaultExport, parsedName)) { - defaultExport = classFactory(defaultExport); - } - - return defaultExport; - } - } - - normalize(fullName) { - return this._normalizeCache[fullName] || (this._normalizeCache[fullName] = this._normalize(fullName)); - } - - resolve(fullName) { - let parsedName = this.parseName(fullName); - let resolveMethodName = parsedName.resolveMethodName; - let resolved; - - if (typeof this[resolveMethodName] === 'function') { - resolved = this[resolveMethodName](parsedName); - } - - if (resolved == null) { - resolved = this.resolveOther(parsedName); - } - - return resolved; - } - - _normalize(fullName) { - // A) Convert underscores to dashes - // B) Convert camelCase to dash-case, except for components (their - // templates) and helpers where we want to avoid shadowing camelCase - // expressions - // C) replace `.` with `/` in order to make nested controllers work in the following cases - // 1. `needs: ['posts/post']` - // 2. `{{render "posts/post"}}` - // 3. `this.render('posts/post')` from Route - - let split = fullName.split(':'); - if (split.length > 1) { - let type = split[0]; - - if ( - type === 'component' || - type === 'helper' || - type === 'modifier' || - (type === 'template' && split[1].indexOf('components/') === 0) - ) { - return type + ':' + split[1].replace(/_/g, '-'); - } else { - return type + ':' + dasherize(split[1].replace(/\./g, '/')); - } - } else { - return fullName; - } - } - - pluralize(type) { - return this.pluralizedTypes[type] || (this.pluralizedTypes[type] = type + 's'); - } - - podBasedLookupWithPrefix(podPrefix, parsedName) { - let fullNameWithoutType = parsedName.fullNameWithoutType; - - if (parsedName.type === 'template') { - fullNameWithoutType = fullNameWithoutType.replace(/^components\//, ''); - } - - return podPrefix + '/' + fullNameWithoutType + '/' + parsedName.type; - } - - podBasedModuleName(parsedName) { - let podPrefix = this.namespace.podModulePrefix || this.namespace.modulePrefix; - - return this.podBasedLookupWithPrefix(podPrefix, parsedName); - } - - podBasedComponentsInSubdir(parsedName) { - let podPrefix = this.namespace.podModulePrefix || this.namespace.modulePrefix; - podPrefix = podPrefix + '/components'; - - if (parsedName.type === 'component' || /^components/.test(parsedName.fullNameWithoutType)) { - return this.podBasedLookupWithPrefix(podPrefix, parsedName); - } - } - - resolveEngine(parsedName) { - let engineName = parsedName.fullNameWithoutType; - let engineModule = engineName + '/engine'; - - if (this._moduleRegistry.has(engineModule)) { - return this._extractDefaultExport(engineModule); - } - } - - resolveRouteMap(parsedName) { - let engineName = parsedName.fullNameWithoutType; - let engineRoutesModule = engineName + '/routes'; - - if (this._moduleRegistry.has(engineRoutesModule)) { - let routeMap = this._extractDefaultExport(engineRoutesModule); - - assert(`The route map for ${engineName} should be wrapped by 'buildRoutes' before exporting.` , routeMap.isRouteMap); - - return routeMap; - } - } - - resolveTemplate(parsedName) { - let resolved = this.resolveOther(parsedName); - if (resolved == null) { - resolved = Ember.TEMPLATES[parsedName.fullNameWithoutType]; - } - return resolved; - } - - mainModuleName(parsedName) { - if (parsedName.fullNameWithoutType === 'main') { - // if router:main or adapter:main look for a module with just the type first - return parsedName.prefix + '/' + parsedName.type; - } - } - - defaultModuleName(parsedName) { - return parsedName.prefix + '/' + this.pluralize(parsedName.type) + '/' + parsedName.fullNameWithoutType; - } - - nestedColocationComponentModuleName(parsedName) { - if (parsedName.type === 'component') { - return parsedName.prefix + '/' + this.pluralize(parsedName.type) + '/' + parsedName.fullNameWithoutType + '/index'; - } - } - - prefix(parsedName) { - let tmpPrefix = this.namespace.modulePrefix; - - if (this.namespace[parsedName.type + 'Prefix']) { - tmpPrefix = this.namespace[parsedName.type + 'Prefix']; - } - - return tmpPrefix; - } - - findModuleName(parsedName, loggingDisabled){ - let moduleNameLookupPatterns = this.moduleNameLookupPatterns; - let moduleName; - - for (let index = 0, length = moduleNameLookupPatterns.length; index < length; index++) { - let item = moduleNameLookupPatterns[index]; - - let tmpModuleName = item.call(this, parsedName); - - // allow treat all dashed and all underscored as the same thing - // supports components with dashes and other stuff with underscores. - if (tmpModuleName) { - tmpModuleName = this.chooseModuleName(tmpModuleName, parsedName); - } - - if (tmpModuleName && this._moduleRegistry.has(tmpModuleName)) { - moduleName = tmpModuleName; - } - - if (!loggingDisabled) { - this._logLookup(moduleName, parsedName, tmpModuleName); - } - - if (moduleName) { - return moduleName; - } - } - } - - chooseModuleName(moduleName, parsedName) { - let underscoredModuleName = underscore(moduleName); - - if (moduleName !== underscoredModuleName && this._moduleRegistry.has(moduleName) && this._moduleRegistry.has(underscoredModuleName)) { - throw new TypeError(`Ambiguous module names: '${ moduleName}' and '${underscoredModuleName }'`); - } - - if (this._moduleRegistry.has(moduleName)) { - return moduleName; - } else if (this._moduleRegistry.has(underscoredModuleName)) { - return underscoredModuleName; - } - // workaround for dasherized partials: - // something/something/-something => something/something/_something - let partializedModuleName = moduleName.replace(/\/-([^/]*)$/, '/_$1'); - - if (this._moduleRegistry.has(partializedModuleName)) { - deprecate('Modules should not contain underscores. ' + - 'Attempted to lookup "'+moduleName+'" which ' + - 'was not found. Please rename "'+partializedModuleName+'" '+ - 'to "'+moduleName+'" instead.', false, - { - id: 'ember-resolver.underscored-modules', - until: '3.0.0', - for: 'ember-resolver', - since: '0.1.0' - }); - - return partializedModuleName; - } - - if (DEBUG) { - let isCamelCaseHelper = parsedName.type === 'helper' && /[a-z]+[A-Z]+/.test(moduleName); - if (isCamelCaseHelper) { - this._camelCaseHelperWarnedNames = this._camelCaseHelperWarnedNames || []; - let alreadyWarned = this._camelCaseHelperWarnedNames.indexOf(parsedName.fullName) > -1; - if (!alreadyWarned && this._moduleRegistry.has(dasherize(moduleName))) { - this._camelCaseHelperWarnedNames.push(parsedName.fullName); - warn('Attempted to lookup "' + parsedName.fullName + '" which ' + - 'was not found. In previous versions of ember-resolver, a bug would have ' + - 'caused the module at "' + dasherize(moduleName) + '" to be ' + - 'returned for this camel case helper name. This has been fixed. ' + - 'Use the dasherized name to resolve the module that would have been ' + - 'returned in previous versions.', - false, - { id: 'ember-resolver.camelcase-helper-names', until: '3.0.0' }); - } - } - } - } - - // used by Ember.DefaultResolver.prototype._logLookup - lookupDescription(fullName) { - let parsedName = this.parseName(fullName); - - let moduleName = this.findModuleName(parsedName, true); - - return moduleName; - } - - // only needed until 1.6.0-beta.2 can be required - _logLookup(found, parsedName, description) { - if (!Ember.ENV.LOG_MODULE_RESOLVER && !parsedName.root.LOG_RESOLVER) { - return; - } - - let padding; - let symbol = found ? '[✓]' : '[ ]'; - - if (parsedName.fullName.length > 60) { - padding = '.'; - } else { - padding = new Array(60 - parsedName.fullName.length).join('.'); - } - - if (!description) { - description = this.lookupDescription(parsedName); - } - - /* eslint-disable no-console */ - if (console && console.info) { - console.info(symbol, parsedName.fullName, padding, description); - } - } - - knownForType(type) { - let moduleKeys = this._moduleRegistry.moduleNames(); - - let items = Object.create(null); - for (let index = 0, length = moduleKeys.length; index < length; index++) { - let moduleName = moduleKeys[index]; - let fullname = this.translateToContainerFullname(type, moduleName); - - if (fullname) { - items[fullname] = true; - } - } - - return items; - } - - translateToContainerFullname(type, moduleName) { - let prefix = this.prefix({ type }); - - // Note: using string manipulation here rather than regexes for better performance. - // pod modules - // '^' + prefix + '/(.+)/' + type + '$' - let podPrefix = prefix + '/'; - let podSuffix = '/' + type; - let start = moduleName.indexOf(podPrefix); - let end = moduleName.indexOf(podSuffix); - - if (start === 0 && end === (moduleName.length - podSuffix.length) && - moduleName.length > (podPrefix.length + podSuffix.length)) { - return type + ':' + moduleName.slice(start + podPrefix.length, end); - } - - // non-pod modules - // '^' + prefix + '/' + pluralizedType + '/(.+)$' - let pluralizedType = this.pluralize(type); - let nonPodPrefix = prefix + '/' + pluralizedType + '/'; - - if (moduleName.indexOf(nonPodPrefix) === 0 && moduleName.length > nonPodPrefix.length) { - return type + ':' + moduleName.slice(nonPodPrefix.length); - } - } - - _extractDefaultExport(normalizedModuleName) { - let module = this._moduleRegistry.get(normalizedModuleName, null, null, true /* force sync */); - - if (module && module['default']) { - module = module['default']; - } - - return module; - } -} - -export default Resolver; diff --git a/addon/app/container-debug-adapter.js b/addon/app/container-debug-adapter.js index 9efe8291..880327bf 100644 --- a/addon/app/container-debug-adapter.js +++ b/addon/app/container-debug-adapter.js @@ -1 +1 @@ -export { default } from "ember-resolver/resolvers/classic/container-debug-adapter"; +export { default } from "ember-resolver/container-debug-adapter"; diff --git a/test-app/tests/unit/exports-test.js b/test-app/tests/unit/exports-test.js deleted file mode 100644 index 49386cae..00000000 --- a/test-app/tests/unit/exports-test.js +++ /dev/null @@ -1,16 +0,0 @@ -import { module, test } from 'qunit'; -import ClassicResolver from 'ember-resolver/resolvers/classic'; -import DefaultResolver from 'ember-resolver/resolver'; -import Resolver from 'ember-resolver/resolver'; - -module('ember-resolver/resolver'); - -test('classic resolver is the default export', function(assert) { - assert.equal( ClassicResolver, Resolver, 'ember-resolver/resolvers/classic and ember-resolver/resolver are the same'); -}); - -module('ember-resolver'); - -test('classic resolver is the default export', function(assert) { - assert.equal( ClassicResolver, DefaultResolver, 'ember-resolver/resolvers/classic and ember-resolver are the same'); -}); diff --git a/test-app/tests/unit/resolvers/classic/basic-test.js b/test-app/tests/unit/resolvers/classic/basic-test.js index 5856c141..6085c229 100644 --- a/test-app/tests/unit/resolvers/classic/basic-test.js +++ b/test-app/tests/unit/resolvers/classic/basic-test.js @@ -2,7 +2,7 @@ import Ember from 'ember'; import { module, test } from 'qunit'; -import Resolver, { ModuleRegistry } from 'ember-resolver/resolvers/classic'; +import Resolver, { ModuleRegistry } from 'ember-resolver'; let originalConsoleInfo, logCalls, resolver, loader; @@ -10,7 +10,7 @@ function setupResolver(options = {}) { if (!options.namespace) { options.namespace = { modulePrefix: 'appkit' }; } - loader = { + loader = { entries: Object.create(null), define(id, deps, callback) { if (deps.length > 0) { @@ -19,7 +19,7 @@ function setupResolver(options = {}) { this.entries[id] = callback; } }; - options._moduleRegistry = new ModuleRegistry(loader.entries) + options._moduleRegistry = new ModuleRegistry(loader.entries) options._moduleRegistry.get = function(moduleName) { return loader.entries[moduleName](); } @@ -322,7 +322,7 @@ test('can lookup a route-map', function(assert) { assert.equal(routeMap, expected, 'default export was returned'); }); -// the assert.expectWarning helper no longer works +// the assert.expectWarning helper no longer works test.skip('warns if looking up a camelCase helper that has a dasherized module present', function(assert){ assert.expect(1);