| /* @flow */ | 
|   | 
| // this will be preserved during build | 
| // $flow-disable-line | 
| const VueFactory = require('./factory') | 
|   | 
| const instanceOptions: { [key: string]: WeexInstanceOption } = {} | 
|   | 
| /** | 
|  * Create instance context. | 
|  */ | 
| export function createInstanceContext ( | 
|   instanceId: string, | 
|   runtimeContext: WeexRuntimeContext, | 
|   data: Object = {} | 
| ): WeexInstanceContext { | 
|   const weex: Weex = runtimeContext.weex | 
|   const instance: WeexInstanceOption = instanceOptions[instanceId] = { | 
|     instanceId, | 
|     config: weex.config, | 
|     document: weex.document, | 
|     data | 
|   } | 
|   | 
|   // Each instance has a independent `Vue` module instance | 
|   const Vue = instance.Vue = createVueModuleInstance(instanceId, weex) | 
|   | 
|   // DEPRECATED | 
|   const timerAPIs = getInstanceTimer(instanceId, weex.requireModule) | 
|   | 
|   const instanceContext = Object.assign({ Vue }, timerAPIs) | 
|   Object.freeze(instanceContext) | 
|   return instanceContext | 
| } | 
|   | 
| /** | 
|  * Destroy an instance with id. It will make sure all memory of | 
|  * this instance released and no more leaks. | 
|  */ | 
| export function destroyInstance (instanceId: string): void { | 
|   const instance = instanceOptions[instanceId] | 
|   if (instance && instance.app instanceof instance.Vue) { | 
|     try { | 
|       instance.app.$destroy() | 
|       instance.document.destroy() | 
|     } catch (e) {} | 
|     delete instance.document | 
|     delete instance.app | 
|   } | 
|   delete instanceOptions[instanceId] | 
| } | 
|   | 
| /** | 
|  * Refresh an instance with id and new top-level component data. | 
|  * It will use `Vue.set` on all keys of the new data. So it's better | 
|  * define all possible meaningful keys when instance created. | 
|  */ | 
| export function refreshInstance ( | 
|   instanceId: string, | 
|   data: Object | 
| ): Error | void { | 
|   const instance = instanceOptions[instanceId] | 
|   if (!instance || !(instance.app instanceof instance.Vue)) { | 
|     return new Error(`refreshInstance: instance ${instanceId} not found!`) | 
|   } | 
|   if (instance.Vue && instance.Vue.set) { | 
|     for (const key in data) { | 
|       instance.Vue.set(instance.app, key, data[key]) | 
|     } | 
|   } | 
|   // Finally `refreshFinish` signal needed. | 
|   instance.document.taskCenter.send('dom', { action: 'refreshFinish' }, []) | 
| } | 
|   | 
| /** | 
|  * Create a fresh instance of Vue for each Weex instance. | 
|  */ | 
| function createVueModuleInstance ( | 
|   instanceId: string, | 
|   weex: Weex | 
| ): GlobalAPI { | 
|   const exports = {} | 
|   VueFactory(exports, weex.document) | 
|   const Vue = exports.Vue | 
|   | 
|   const instance = instanceOptions[instanceId] | 
|   | 
|   // patch reserved tag detection to account for dynamically registered | 
|   // components | 
|   const weexRegex = /^weex:/i | 
|   const isReservedTag = Vue.config.isReservedTag || (() => false) | 
|   const isRuntimeComponent = Vue.config.isRuntimeComponent || (() => false) | 
|   Vue.config.isReservedTag = name => { | 
|     return (!isRuntimeComponent(name) && weex.supports(`@component/${name}`)) || | 
|       isReservedTag(name) || | 
|       weexRegex.test(name) | 
|   } | 
|   Vue.config.parsePlatformTagName = name => name.replace(weexRegex, '') | 
|   | 
|   // expose weex-specific info | 
|   Vue.prototype.$instanceId = instanceId | 
|   Vue.prototype.$document = instance.document | 
|   | 
|   // expose weex native module getter on subVue prototype so that | 
|   // vdom runtime modules can access native modules via vnode.context | 
|   Vue.prototype.$requireWeexModule = weex.requireModule | 
|   | 
|   // Hack `Vue` behavior to handle instance information and data | 
|   // before root component created. | 
|   Vue.mixin({ | 
|     beforeCreate () { | 
|       const options = this.$options | 
|       // root component (vm) | 
|       if (options.el) { | 
|         // set external data of instance | 
|         const dataOption = options.data | 
|         const internalData = (typeof dataOption === 'function' ? dataOption() : dataOption) || {} | 
|         options.data = Object.assign(internalData, instance.data) | 
|         // record instance by id | 
|         instance.app = this | 
|       } | 
|     }, | 
|     mounted () { | 
|       const options = this.$options | 
|       // root component (vm) | 
|       if (options.el && weex.document && instance.app === this) { | 
|         try { | 
|           // Send "createFinish" signal to native. | 
|           weex.document.taskCenter.send('dom', { action: 'createFinish' }, []) | 
|         } catch (e) {} | 
|       } | 
|     } | 
|   }) | 
|   | 
|   /** | 
|    * @deprecated Just instance variable `weex.config` | 
|    * Get instance config. | 
|    * @return {object} | 
|    */ | 
|   Vue.prototype.$getConfig = function () { | 
|     if (instance.app instanceof Vue) { | 
|       return instance.config | 
|     } | 
|   } | 
|   | 
|   return Vue | 
| } | 
|   | 
| /** | 
|  * DEPRECATED | 
|  * Generate HTML5 Timer APIs. An important point is that the callback | 
|  * will be converted into callback id when sent to native. So the | 
|  * framework can make sure no side effect of the callback happened after | 
|  * an instance destroyed. | 
|  */ | 
| function getInstanceTimer ( | 
|   instanceId: string, | 
|   moduleGetter: Function | 
| ): Object { | 
|   const instance = instanceOptions[instanceId] | 
|   const timer = moduleGetter('timer') | 
|   const timerAPIs = { | 
|     setTimeout: (...args) => { | 
|       const handler = function () { | 
|         args[0](...args.slice(2)) | 
|       } | 
|   | 
|       timer.setTimeout(handler, args[1]) | 
|       return instance.document.taskCenter.callbackManager.lastCallbackId.toString() | 
|     }, | 
|     setInterval: (...args) => { | 
|       const handler = function () { | 
|         args[0](...args.slice(2)) | 
|       } | 
|   | 
|       timer.setInterval(handler, args[1]) | 
|       return instance.document.taskCenter.callbackManager.lastCallbackId.toString() | 
|     }, | 
|     clearTimeout: (n) => { | 
|       timer.clearTimeout(n) | 
|     }, | 
|     clearInterval: (n) => { | 
|       timer.clearInterval(n) | 
|     } | 
|   } | 
|   return timerAPIs | 
| } |