|
|
@@ -1,127 +1,89 @@
|
|
|
+/* @flow */
|
|
|
+
|
|
|
// this will be preserved during build
|
|
|
+// $flow-disable-line
|
|
|
const VueFactory = require('./factory')
|
|
|
|
|
|
-const instances = {}
|
|
|
-
|
|
|
-/**
|
|
|
- * Prepare framework config.
|
|
|
- * Nothing need to do actually, just an interface provided to weex runtime.
|
|
|
- */
|
|
|
-export function init () {}
|
|
|
-
|
|
|
-/**
|
|
|
- * Reset framework config and clear all registrations.
|
|
|
- */
|
|
|
-export function reset () {
|
|
|
- clear(instances)
|
|
|
-}
|
|
|
+const instanceOptions: { [key: string]: WeexInstanceOption } = {}
|
|
|
|
|
|
/**
|
|
|
- * Delete all keys of an object.
|
|
|
- * @param {object} obj
|
|
|
+ * Create instance context.
|
|
|
*/
|
|
|
-function clear (obj) {
|
|
|
- for (const key in obj) {
|
|
|
- delete obj[key]
|
|
|
+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
|
|
|
}
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * Create an instance with id, code, config and external data.
|
|
|
- * @param {string} instanceId
|
|
|
- * @param {string} appCode
|
|
|
- * @param {object} config
|
|
|
- * @param {object} data
|
|
|
- * @param {object} env { info, config, services }
|
|
|
- */
|
|
|
-export function createInstance (
|
|
|
- instanceId,
|
|
|
- appCode = '',
|
|
|
- config = {},
|
|
|
- data,
|
|
|
- env = {}
|
|
|
-) {
|
|
|
- const weex = env.weex
|
|
|
- const document = weex.document
|
|
|
- const instance = instances[instanceId] = {
|
|
|
- instanceId, config, data,
|
|
|
- document
|
|
|
- }
|
|
|
-
|
|
|
- const timerAPIs = getInstanceTimer(instanceId, weex.requireModule)
|
|
|
|
|
|
// Each instance has a independent `Vue` module instance
|
|
|
const Vue = instance.Vue = createVueModuleInstance(instanceId, weex)
|
|
|
|
|
|
- // The function which create a closure the JS Bundle will run in.
|
|
|
- // It will declare some instance variables like `Vue`, HTML5 Timer APIs etc.
|
|
|
- const instanceVars = Object.assign({
|
|
|
- Vue,
|
|
|
- weex
|
|
|
- }, timerAPIs, env.services)
|
|
|
-
|
|
|
- appCode = `(function(global){ \n${appCode}\n })(Object.create(this))`
|
|
|
- callFunction(instanceVars, appCode)
|
|
|
+ // DEPRECATED
|
|
|
+ const timerAPIs = getInstanceTimer(instanceId, weex.requireModule)
|
|
|
|
|
|
- return instance
|
|
|
+ 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.
|
|
|
- * @param {string} instanceId
|
|
|
*/
|
|
|
-export function destroyInstance (instanceId) {
|
|
|
- const instance = instances[instanceId]
|
|
|
+export function destroyInstance (instanceId: string): void {
|
|
|
+ const instance = instanceOptions[instanceId]
|
|
|
if (instance && instance.app instanceof instance.Vue) {
|
|
|
- instance.document.destroy()
|
|
|
- instance.app.$destroy()
|
|
|
+ try {
|
|
|
+ instance.app.$destroy()
|
|
|
+ instance.document.destroy()
|
|
|
+ } catch (e) {}
|
|
|
delete instance.document
|
|
|
delete instance.app
|
|
|
}
|
|
|
- delete instances[instanceId]
|
|
|
+ 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.
|
|
|
- * @param {string} instanceId
|
|
|
- * @param {object} data
|
|
|
*/
|
|
|
-export function refreshInstance (instanceId, data) {
|
|
|
- const instance = instances[instanceId]
|
|
|
+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!`)
|
|
|
}
|
|
|
- for (const key in data) {
|
|
|
- instance.Vue.set(instance.app, key, data[key])
|
|
|
+ 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' }, [])
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * Get the JSON object of the root element.
|
|
|
- * @param {string} instanceId
|
|
|
- */
|
|
|
-export function getRoot (instanceId) {
|
|
|
- const instance = instances[instanceId]
|
|
|
- if (!instance || !(instance.app instanceof instance.Vue)) {
|
|
|
- return new Error(`getRoot: instance ${instanceId} not found!`)
|
|
|
- }
|
|
|
- return instance.app.$el.toJSON()
|
|
|
-}
|
|
|
-
|
|
|
/**
|
|
|
* Create a fresh instance of Vue for each Weex instance.
|
|
|
*/
|
|
|
-function createVueModuleInstance (instanceId, weex) {
|
|
|
+function createVueModuleInstance (
|
|
|
+ instanceId: string,
|
|
|
+ weex: Weex
|
|
|
+): GlobalAPI {
|
|
|
const exports = {}
|
|
|
VueFactory(exports, weex.document)
|
|
|
const Vue = exports.Vue
|
|
|
|
|
|
- const instance = instances[instanceId]
|
|
|
+ const instance = instanceOptions[instanceId]
|
|
|
|
|
|
// patch reserved tag detection to account for dynamically registered
|
|
|
// components
|
|
|
@@ -161,7 +123,7 @@ function createVueModuleInstance (instanceId, weex) {
|
|
|
mounted () {
|
|
|
const options = this.$options
|
|
|
// root component (vm)
|
|
|
- if (options.el && weex.document) {
|
|
|
+ if (options.el && weex.document && instance.app === this) {
|
|
|
try {
|
|
|
// Send "createFinish" signal to native.
|
|
|
weex.document.taskCenter.send('dom', { action: 'createFinish' }, [])
|
|
|
@@ -185,16 +147,17 @@ function createVueModuleInstance (instanceId, weex) {
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
+ * 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.
|
|
|
- * @param {[type]} instanceId [description]
|
|
|
- * @param {[type]} moduleGetter [description]
|
|
|
- * @return {[type]} [description]
|
|
|
*/
|
|
|
-function getInstanceTimer (instanceId, moduleGetter) {
|
|
|
- const instance = instances[instanceId]
|
|
|
+function getInstanceTimer (
|
|
|
+ instanceId: string,
|
|
|
+ moduleGetter: Function
|
|
|
+): Object {
|
|
|
+ const instance = instanceOptions[instanceId]
|
|
|
const timer = moduleGetter('timer')
|
|
|
const timerAPIs = {
|
|
|
setTimeout: (...args) => {
|
|
|
@@ -222,22 +185,3 @@ function getInstanceTimer (instanceId, moduleGetter) {
|
|
|
}
|
|
|
return timerAPIs
|
|
|
}
|
|
|
-
|
|
|
-/**
|
|
|
- * Call a new function body with some global objects.
|
|
|
- * @param {object} globalObjects
|
|
|
- * @param {string} code
|
|
|
- * @return {any}
|
|
|
- */
|
|
|
-function callFunction (globalObjects, body) {
|
|
|
- const globalKeys = []
|
|
|
- const globalValues = []
|
|
|
- for (const key in globalObjects) {
|
|
|
- globalKeys.push(key)
|
|
|
- globalValues.push(globalObjects[key])
|
|
|
- }
|
|
|
- globalKeys.push(body)
|
|
|
-
|
|
|
- const result = new Function(...globalKeys)
|
|
|
- return result(...globalValues)
|
|
|
-}
|