diff --git a/src/core/instance/render-helpers/resolve-filter.js b/src/core/instance/render-helpers/resolve-filter.js index 08a81e1495d..6f11f59e234 100644 --- a/src/core/instance/render-helpers/resolve-filter.js +++ b/src/core/instance/render-helpers/resolve-filter.js @@ -6,5 +6,5 @@ import { identity, resolveAsset } from 'core/util/index' * Runtime helper for resolving filters */ export function resolveFilter (id: string): Function { - return resolveAsset(this.$options, 'filters', id, true) || identity + return resolveAsset(this, 'filters', id, true) || identity } diff --git a/src/core/util/options.js b/src/core/util/options.js index 5f0d10d3361..c9447976252 100644 --- a/src/core/util/options.js +++ b/src/core/util/options.js @@ -13,9 +13,10 @@ import { import { extend, hasOwn, - camelize, toRawType, + camelize, capitalize, + identifierSpellings, isBuiltInTag, isPlainObject } from 'shared/util' @@ -410,7 +411,7 @@ export function mergeOptions ( * to assets defined in its ancestor chain. */ export function resolveAsset ( - options: Object, + context: Component, type: string, id: string, warnMissing?: boolean @@ -419,6 +420,7 @@ export function resolveAsset ( if (typeof id !== 'string') { return } + const options = context.$options const assets = options[type] // check local registration variations first if (hasOwn(assets, id)) return assets[id] @@ -427,7 +429,13 @@ export function resolveAsset ( const PascalCaseId = capitalize(camelizedId) if (hasOwn(assets, PascalCaseId)) return assets[PascalCaseId] // fallback to prototype chain - const res = assets[id] || assets[camelizedId] || assets[PascalCaseId] + let res = assets[id] || assets[camelizedId] || assets[PascalCaseId] + if (!res) { + const getAsset = options['get' + capitalize(type.slice(0, -1))] + if (getAsset instanceof Function) { + res = getAsset.call(context, id, identifierSpellings(id)) + } + } if (process.env.NODE_ENV !== 'production' && warnMissing && !res) { warn( 'Failed to resolve ' + type.slice(0, -1) + ': ' + id, diff --git a/src/core/vdom/create-element.js b/src/core/vdom/create-element.js index c5cde2c6424..4c1ad107d3a 100644 --- a/src/core/vdom/create-element.js +++ b/src/core/vdom/create-element.js @@ -102,7 +102,7 @@ export function _createElement ( config.parsePlatformTagName(tag), data, children, undefined, undefined, context ) - } else if (isDef(Ctor = resolveAsset(context.$options, 'components', tag))) { + } else if (isDef(Ctor = resolveAsset(context, 'components', tag))) { // component vnode = createComponent(Ctor, data, context, children, tag) } else { diff --git a/src/core/vdom/modules/directives.js b/src/core/vdom/modules/directives.js index 639982fab59..0fddcfa60b3 100644 --- a/src/core/vdom/modules/directives.js +++ b/src/core/vdom/modules/directives.js @@ -97,7 +97,7 @@ function normalizeDirectives ( dir.modifiers = emptyModifiers } res[getRawDirName(dir)] = dir - dir.def = resolveAsset(vm.$options, 'directives', dir.name, true) + dir.def = resolveAsset(vm, 'directives', dir.name, true) } // $flow-disable-line return res diff --git a/src/shared/util.js b/src/shared/util.js index e4884734326..ab783365ab3 100644 --- a/src/shared/util.js +++ b/src/shared/util.js @@ -173,6 +173,20 @@ export const hyphenate = cached((str: string): string => { return str.replace(hyphenateRE, '-$1').toLowerCase() }) +/** + * Get all variations of a identifier spelling. + */ +export const identifierSpellings = cached((str: string): Object => { + const camelized = camelize(str) + return { + raw: str, + hyphenated: hyphenate(str), + camelized: camelized, + PascalCase: capitalize(camelized), + toString: () => str + } +}) + /** * Simple bind polyfill for environments that do not support it... e.g. * PhantomJS 1.x. Technically we don't need this anymore since native bind is