blob: 42596903d91885b68712e6e064fbf1c3ec66d5ca [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/**
* @fileOverview
* instance controls from native
*
* - fire event
* - callback
* - refresh
* - destroy
*
* corresponded with the API of instance manager (framework.js)
*/
import { extend, typof } from '../../util/index'
/**
* Refresh an app with data to its root component options.
* @param {object} app
* @param {any} data
*/
export function refresh (app, data) {
console.debug(`[JS Framework] Refresh with`, data, `in instance[${app.id}]`)
const vm = app.vm
if (vm && data) {
if (typeof vm.refreshData === 'function') {
vm.refreshData(data)
}
else {
extend(vm, data)
}
app.differ.flush()
app.doc.taskCenter.send('dom', { action: 'refreshFinish' }, [])
return
}
return new Error(`invalid data "${data}"`)
}
/**
* Destroy an app.
* @param {object} app
*/
export function destroy (app) {
console.debug(`[JS Framework] Destory an instance(${app.id})`)
if (app.vm) {
destroyVm(app.vm)
}
app.id = ''
app.options = null
app.blocks = null
app.vm = null
app.doc.taskCenter.destroyCallback()
app.doc.destroy()
app.doc = null
app.customComponentMap = null
app.commonModules = null
}
/**
* Destroy an Vm.
* @param {object} vm
*/
export function destroyVm (vm) {
delete vm._app
delete vm._computed
delete vm._css
delete vm._data
delete vm._ids
delete vm._methods
delete vm._options
delete vm._parent
delete vm._parentEl
delete vm._rootEl
// remove all watchers
if (vm._watchers) {
let watcherCount = vm._watchers.length
while (watcherCount--) {
vm._watchers[watcherCount].teardown()
}
delete vm._watchers
}
// destroy child vms recursively
if (vm._childrenVms) {
let vmCount = vm._childrenVms.length
while (vmCount--) {
destroyVm(vm._childrenVms[vmCount])
}
delete vm._childrenVms
}
console.debug(`[JS Framework] "destroyed" lifecycle in Vm(${vm._type})`)
vm.$emit('hook:destroyed')
delete vm._type
delete vm._vmEvents
}
/**
* Get a JSON object to describe the document body.
* @param {object} app
* @return {object}
*/
export function getRootElement (app) {
const doc = app.doc || {}
const body = doc.body || {}
return body.toJSON ? body.toJSON() : {}
}
/**
* Fire an event from renderer. The event has type, an event object and an
* element ref. If the event comes with some virtual-DOM changes, it should
* have one more parameter to describe the changes.
* @param {object} app
* @param {string} ref
* @param {type} type
* @param {object} e
* @param {object} domChanges
*/
export function fireEvent (app, ref, type, e, domChanges) {
console.debug(`[JS Framework] Fire a "${type}" event on an element(${ref}) in instance(${app.id})`)
if (Array.isArray(ref)) {
ref.some((ref) => {
return fireEvent(app, ref, type, e) !== false
})
return
}
const el = app.doc.getRef(ref)
if (el) {
const result = app.doc.fireEvent(el, type, e, domChanges)
app.differ.flush()
app.doc.taskCenter.send('dom', { action: 'updateFinish' }, [])
return result
}
return new Error(`invalid element reference "${ref}"`)
}
/**
* Make a callback for a certain app.
* @param {object} app
* @param {number} callbackId
* @param {any} data
* @param {boolean} ifKeepAlive
*/
export function callback (app, callbackId, data, ifKeepAlive) {
console.debug(`[JS Framework] Invoke a callback(${callbackId}) with`, data, `in instance(${app.id})`)
const result = app.doc.taskCenter.callback(callbackId, data, ifKeepAlive)
updateActions(app)
app.doc.taskCenter.send('dom', { action: 'updateFinish' }, [])
return result
}
/**
* Collect all virtual-DOM mutations together and send them to renderer.
* @param {object} app
*/
export function updateActions (app) {
app.differ.flush()
}
/**
* Call all tasks from an app to renderer (native).
* @param {object} app
* @param {array} tasks
*/
export function callTasks (app, tasks) {
let result
/* istanbul ignore next */
if (typof(tasks) !== 'array') {
tasks = [tasks]
}
tasks.forEach(task => {
result = app.doc.taskCenter.send(
'module',
{
module: task.module,
method: task.method
},
task.args
)
})
return result
}