-
Notifications
You must be signed in to change notification settings - Fork 668
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
createLocalVue errorHandler Option #1670
Changes from all commits
48f1c14
808fe89
98103d6
fc3be6c
0dca580
094e7db
3db2482
f1005a9
72f1fdb
55647c4
8bbc3d1
75d0afc
ba9f677
3272a85
5783bb6
5ed0f28
d73e8d9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
// @flow | ||
|
||
import Vue from 'vue' | ||
import cloneDeep from 'lodash/cloneDeep' | ||
|
||
/** | ||
* Used internally by vue-server-test-utils and test-utils to propagate/create vue instances. | ||
* This method is wrapped by createLocalVue in test-utils to provide a different public API signature | ||
* @param {Component} _Vue | ||
* @param {VueConfig} config | ||
* @returns {Component} | ||
*/ | ||
function _createLocalVue( | ||
_Vue: Component = Vue, | ||
config: VueConfig = {} | ||
): Component { | ||
const instance = _Vue.extend() | ||
|
||
// clone global APIs | ||
Object.keys(_Vue).forEach(key => { | ||
if (!instance.hasOwnProperty(key)) { | ||
const original = _Vue[key] | ||
// cloneDeep can fail when cloning Vue instances | ||
// cloneDeep checks that the instance has a Symbol | ||
// which errors in Vue < 2.17 (https://github.com/vuejs/vue/pull/7878) | ||
try { | ||
instance[key] = | ||
typeof original === 'object' ? cloneDeep(original) : original | ||
} catch (e) { | ||
instance[key] = original | ||
} | ||
} | ||
}) | ||
|
||
// config is not enumerable | ||
instance.config = cloneDeep(Vue.config) | ||
|
||
// if a user defined errorHandler is defined by a localVue instance via createLocalVue, register it | ||
instance.config.errorHandler = config.errorHandler || Vue.config.errorHandler | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is the only line that has changed within the logic, IE adding There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. shared is private anyway, this should be fine |
||
|
||
// option merge strategies need to be exposed by reference | ||
// so that merge strats registered by plugins can work properly | ||
instance.config.optionMergeStrategies = Vue.config.optionMergeStrategies | ||
|
||
// make sure all extends are based on this instance. | ||
// this is important so that global components registered by plugins, | ||
// e.g. router-link are created using the correct base constructor | ||
instance.options._base = instance | ||
|
||
// compat for vue-router < 2.7.1 where it does not allow multiple installs | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nice job, this must have been a huge pain to figure out There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. oh, it was moved here from somewhere else - even better, that means it's been battle tested |
||
if (instance._installedPlugins && instance._installedPlugins.length) { | ||
instance._installedPlugins.length = 0 | ||
} | ||
const use = instance.use | ||
instance.use = (plugin, ...rest) => { | ||
if (plugin.installed === true) { | ||
plugin.installed = false | ||
} | ||
if (plugin.install && plugin.install.installed === true) { | ||
plugin.install.installed = false | ||
} | ||
use.call(instance, plugin, ...rest) | ||
} | ||
return instance | ||
} | ||
|
||
export default _createLocalVue |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,56 +1,14 @@ | ||
// @flow | ||
|
||
import Vue from 'vue' | ||
import cloneDeep from 'lodash/cloneDeep' | ||
|
||
function createLocalVue(_Vue: Component = Vue): Component { | ||
const instance = _Vue.extend() | ||
|
||
// clone global APIs | ||
Object.keys(_Vue).forEach(key => { | ||
if (!instance.hasOwnProperty(key)) { | ||
const original = _Vue[key] | ||
// cloneDeep can fail when cloning Vue instances | ||
// cloneDeep checks that the instance has a Symbol | ||
// which errors in Vue < 2.17 (https://github.com/vuejs/vue/pull/7878) | ||
try { | ||
instance[key] = | ||
typeof original === 'object' ? cloneDeep(original) : original | ||
} catch (e) { | ||
instance[key] = original | ||
} | ||
} | ||
}) | ||
|
||
// config is not enumerable | ||
instance.config = cloneDeep(Vue.config) | ||
|
||
instance.config.errorHandler = Vue.config.errorHandler | ||
|
||
// option merge strategies need to be exposed by reference | ||
// so that merge strats registered by plugins can work properly | ||
instance.config.optionMergeStrategies = Vue.config.optionMergeStrategies | ||
|
||
// make sure all extends are based on this instance. | ||
// this is important so that global components registered by plugins, | ||
// e.g. router-link are created using the correct base constructor | ||
instance.options._base = instance | ||
|
||
// compat for vue-router < 2.7.1 where it does not allow multiple installs | ||
if (instance._installedPlugins && instance._installedPlugins.length) { | ||
instance._installedPlugins.length = 0 | ||
} | ||
const use = instance.use | ||
instance.use = (plugin, ...rest) => { | ||
if (plugin.installed === true) { | ||
plugin.installed = false | ||
} | ||
if (plugin.install && plugin.install.installed === true) { | ||
plugin.install.installed = false | ||
} | ||
use.call(instance, plugin, ...rest) | ||
} | ||
return instance | ||
import _createLocalVue from 'shared/create-local-vue' | ||
|
||
/** | ||
* Returns a local vue instance to add components, mixins and install plugins without polluting the global Vue class | ||
* @param {VueConfig} config | ||
* @returns {Component} | ||
*/ | ||
function createLocalVue(config: VueConfig = {}): Component { | ||
return _createLocalVue(undefined, config) | ||
} | ||
|
||
export default createLocalVue |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,33 @@ | ||
import { warn } from 'shared/util' | ||
import { findAllInstances } from './find' | ||
import { findAllInstances, findAllParentInstances } from './find' | ||
|
||
function errorHandler(errorOrString, vm) { | ||
function errorHandler(errorOrString, vm, info) { | ||
const error = | ||
typeof errorOrString === 'object' ? errorOrString : new Error(errorOrString) | ||
|
||
// If a user defined errorHandler was register via createLocalVue | ||
// find and call the user defined errorHandler | ||
const instancedErrorHandlers = findAllParentInstances(vm) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe just move this into line |
||
.filter( | ||
_vm => | ||
_vm && | ||
_vm.$options && | ||
_vm.$options.localVue && | ||
_vm.$options.localVue.config && | ||
_vm.$options.localVue.config.errorHandler | ||
) | ||
.map(_vm => _vm.$options.localVue.config.errorHandler) | ||
|
||
if (vm) { | ||
vm._error = error | ||
} | ||
|
||
// should be one error handler, as only once can be registered with local vue | ||
// regardless, if more exist (for whatever reason), invoke the other user defined error handlers | ||
instancedErrorHandlers.forEach(instancedErrorHandler => { | ||
instancedErrorHandler(error, vm, info) | ||
}) | ||
|
||
throw error | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added argument
config: VueConfig = {}