You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@weex.apache.org by gu...@apache.org on 2017/10/23 07:23:25 UTC
[07/11] incubator-weex git commit: + [jsfm] add weex variable api in
runtime
+ [jsfm] add weex variable api in runtime
Project: http://git-wip-us.apache.org/repos/asf/incubator-weex/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-weex/commit/84ff2660
Tree: http://git-wip-us.apache.org/repos/asf/incubator-weex/tree/84ff2660
Diff: http://git-wip-us.apache.org/repos/asf/incubator-weex/diff/84ff2660
Branch: refs/heads/release-0.16
Commit: 84ff266096243fae98ab1cc59ab035314b9fb9c7
Parents: bef20bd
Author: Hanks <zh...@gmail.com>
Authored: Wed Oct 11 17:19:48 2017 +0800
Committer: jianbai.gbj <ji...@alibaba-inc.com>
Committed: Mon Oct 23 10:02:35 2017 +0800
----------------------------------------------------------------------
html5/runtime/api/WeexInstance.js | 126 +++++++++++++++++++++++++++++++++
html5/runtime/api/component.js | 51 +++++++++++++
html5/runtime/api/init.js | 107 +++++++++++++++++-----------
html5/runtime/api/module.js | 56 +++++++++++++++
4 files changed, 300 insertions(+), 40 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/84ff2660/html5/runtime/api/WeexInstance.js
----------------------------------------------------------------------
diff --git a/html5/runtime/api/WeexInstance.js b/html5/runtime/api/WeexInstance.js
new file mode 100644
index 0000000..2093f17
--- /dev/null
+++ b/html5/runtime/api/WeexInstance.js
@@ -0,0 +1,126 @@
+/*
+ * 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.
+ */
+
+import Document from '../vdom/Document'
+import { isRegisteredModule, getModuleDescription } from './module'
+import { isRegisteredComponent } from './component'
+
+const moduleProxies = {}
+
+function setId (weex, id) {
+ Object.defineProperty(weex, '[[CurrentInstanceId]]', { value: id })
+}
+
+function getId (weex) {
+ return weex['[[CurrentInstanceId]]']
+}
+
+function moduleGetter (module, method, taskCenter) {
+ return (...args) => taskCenter.send('module', { module, method }, args)
+}
+
+export default class WeexInstance {
+ constructor (id, config) {
+ setId(this, id)
+ this.config = config || {}
+ this.document = new Document(id, this.config.bundleUrl)
+ this.requireModule = this.requireModule.bind(this)
+ this.isRegisteredModule = isRegisteredModule
+ this.isRegisteredComponent = isRegisteredComponent
+ }
+
+ requireModule (moduleName) {
+ const id = getId(this)
+ if (!(id && this.document && this.document.taskCenter)) {
+ console.error(`[JS Framework] invalid instance id "${id}"`)
+ return
+ }
+
+ // warn for unknown module
+ if (!isRegisteredModule(moduleName)) {
+ console.warn(`[JS Framework] using unregistered weex module "${moduleName}"`)
+ return
+ }
+
+ // create new module proxy
+ if (!moduleProxies[moduleName]) {
+ const moduleDefine = getModuleDescription(moduleName)
+ const taskCenter = this.document.taskCenter
+
+ // create registered module apis
+ const moduleApis = {}
+ for (const methodName in moduleDefine) {
+ Object.defineProperty(moduleApis, methodName, {
+ enumerable: true,
+ configurable: true,
+ get: () => moduleGetter(moduleName, methodName, taskCenter),
+ set (fn) {
+ if (typeof fn === 'function') {
+ return taskCenter.send('module', {
+ module: moduleName,
+ method: methodName
+ }, [fn])
+ }
+ }
+ })
+ }
+
+ // create module Proxy
+ if (typeof Proxy === 'function') {
+ moduleProxies[moduleName] = new Proxy(moduleApis, {
+ get (target, methodName) {
+ if (methodName in target) {
+ return target[methodName]
+ }
+ console.warn(`[JS Framework] using unregistered method "${moduleName}.${methodName}"`)
+ return moduleGetter(moduleName, methodName, taskCenter)
+ }
+ })
+ }
+ else {
+ moduleProxies[moduleName] = moduleApis
+ }
+ }
+
+ return moduleProxies[moduleName]
+ }
+
+ supports (condition) {
+ if (typeof condition !== 'string') return null
+
+ const res = condition.match(/^@(\w+)\/(\w+)(\.(\w+))?$/i)
+ if (res) {
+ const type = res[1]
+ const name = res[2]
+ const method = res[4]
+ switch (type) {
+ case 'module': return isRegisteredModule(name, method)
+ case 'component': return isRegisteredComponent(name)
+ }
+ }
+
+ return null
+ }
+
+ // registerStyleSheet (styles) {
+ // if (this.document) {
+ // this.document.registerStyleSheet(styles)
+ // }
+ // }
+}
http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/84ff2660/html5/runtime/api/component.js
----------------------------------------------------------------------
diff --git a/html5/runtime/api/component.js b/html5/runtime/api/component.js
new file mode 100644
index 0000000..8a56961
--- /dev/null
+++ b/html5/runtime/api/component.js
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+
+import { registerElement } from '../vdom/WeexElement'
+
+const weexComponents = {}
+
+/**
+ * Register native components information.
+ * @param {array} newComponents
+ */
+export function registerComponents (newComponents) {
+ if (Array.isArray(newComponents)) {
+ newComponents.forEach(component => {
+ if (!component) {
+ return
+ }
+ if (typeof component === 'string') {
+ weexComponents[component] = true
+ }
+ else if (typeof component === 'object' && typeof component.type === 'string') {
+ weexComponents[component.type] = component
+ registerElement(component.type, component.methods)
+ }
+ })
+ }
+}
+
+/**
+ * Check whether the component has been registered.
+ * @param {String} component name
+ */
+export function isRegisteredComponent (name) {
+ return !!weexComponents[name]
+}
http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/84ff2660/html5/runtime/api/init.js
----------------------------------------------------------------------
diff --git a/html5/runtime/api/init.js b/html5/runtime/api/init.js
index 024afa7..cad0179 100644
--- a/html5/runtime/api/init.js
+++ b/html5/runtime/api/init.js
@@ -18,8 +18,10 @@
*/
import { init as initTaskHandler } from '../bridge/TaskCenter'
-import { registerElement } from '../vdom/WeexElement'
+import { registerModules } from './module'
+import { registerComponents } from './component'
import { services, register, unregister } from './service'
+import WeexInstance from './WeexInstance'
let frameworks
let runtimeConfig
@@ -95,58 +97,61 @@ function createInstance (id, code, config, data) {
config = JSON.parse(JSON.stringify(config || {}))
config.env = JSON.parse(JSON.stringify(global.WXEnvironment || {}))
- const context = {
- config,
+ const weex = new WeexInstance(id, config)
+ Object.freeze(weex)
+
+ const runtimeEnv = {
+ weex,
+ config, // TODO: deprecated
created: Date.now(),
framework: bundleType
}
- context.services = createServices(id, context, runtimeConfig)
- instanceMap[id] = context
+ runtimeEnv.services = createServices(id, runtimeEnv, runtimeConfig)
+ instanceMap[id] = runtimeEnv
- if (process.env.NODE_ENV === 'development') {
- console.debug(`[JS Framework] create an ${bundleType} instance`)
- }
+ const runtimeContext = Object.create(null)
+ Object.assign(runtimeContext, runtimeEnv.services, { weex })
- const fm = frameworks[bundleType]
- if (!fm) {
+ const framework = runtimeConfig.frameworks[bundleType]
+ if (!framework) {
return new Error(`invalid bundle type "${bundleType}".`)
}
- return fm.createInstance(id, code, config, data, context)
-}
-
-const methods = {
- createInstance,
- registerService: register,
- unregisterService: unregister
+ // run create instance
+ if (typeof framework.prepareInstanceContext === 'function') {
+ const instanceContext = framework.prepareInstanceContext(runtimeContext)
+ return runInContext(code, instanceContext)
+ }
+ return framework.createInstance(id, code, config, data, runtimeEnv)
}
/**
- * Register methods which init each frameworks.
- * @param {string} methodName
+ * Run js code in a specific context.
+ * @param {string} code
+ * @param {object} context
*/
-function genInit (methodName) {
- methods[methodName] = function (...args) {
- if (methodName === 'registerComponents') {
- checkComponentMethods(args[0])
- }
- for (const name in frameworks) {
- const framework = frameworks[name]
- if (framework && framework[methodName]) {
- framework[methodName](...args)
- }
- }
+function runInContext (code, context) {
+ const keys = []
+ const args = []
+ for (const key in context) {
+ keys.push(key)
+ args.push(context[key])
}
+
+ const bundle = `
+ (function (global) {
+ "use strict";
+ ${code}
+ })(Object.create(this))
+ `
+
+ return (new Function(...keys, bundle))(...args)
}
-function checkComponentMethods (components) {
- if (Array.isArray(components)) {
- components.forEach((name) => {
- if (name && name.type && name.methods) {
- registerElement(name.type, name.methods)
- }
- })
- }
+const methods = {
+ createInstance,
+ registerService: register,
+ unregisterService: unregister
}
/**
@@ -203,6 +208,27 @@ function adaptInstance (methodName, nativeMethodName) {
}
}
+/**
+ * Register methods which init each frameworks.
+ * @param {string} methodName
+ * @param {function} sharedMethod
+ */
+function adaptMethod (methodName, sharedMethod) {
+ methods[methodName] = function (...args) {
+ if (typeof sharedMethod === 'function') {
+ sharedMethod(...args)
+ }
+
+ // TODO: deprecated
+ for (const name in runtimeConfig.frameworks) {
+ const framework = runtimeConfig.frameworks[name]
+ if (framework && framework[methodName]) {
+ framework[methodName](...args)
+ }
+ }
+ }
+}
+
export default function init (config) {
runtimeConfig = config || {}
frameworks = runtimeConfig.frameworks || {}
@@ -216,8 +242,9 @@ export default function init (config) {
framework.init(config)
}
- // @todo: The method `registerMethods` will be re-designed or removed later.
- ; ['registerComponents', 'registerModules', 'registerMethods'].forEach(genInit)
+ adaptMethod('registerComponents', registerComponents)
+ adaptMethod('registerModules', registerModules)
+ adaptMethod('registerMethods')
; ['destroyInstance', 'refreshInstance', 'receiveTasks', 'getRoot'].forEach(genInstance)
http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/84ff2660/html5/runtime/api/module.js
----------------------------------------------------------------------
diff --git a/html5/runtime/api/module.js b/html5/runtime/api/module.js
new file mode 100644
index 0000000..df26b92
--- /dev/null
+++ b/html5/runtime/api/module.js
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+const weexModules = {}
+
+/**
+ * Register native modules information.
+ * @param {object} newModules
+ */
+export function registerModules (newModules) {
+ for (const name in newModules) {
+ if (!weexModules[name]) {
+ weexModules[name] = {}
+ }
+ newModules[name].forEach(method => {
+ if (typeof method === 'string') {
+ weexModules[name][method] = true
+ }
+ else {
+ weexModules[name][method.name] = method.args
+ }
+ })
+ }
+}
+
+/**
+ * Check whether the module or the method has been registered.
+ * @param {String} module name
+ * @param {String} method name (optional)
+ */
+export function isRegisteredModule (name, method) {
+ if (typeof method === 'string') {
+ return !!(weexModules[name] && weexModules[name][method])
+ }
+ return !!weexModules[name]
+}
+
+export function getModuleDescription (name) {
+ return weexModules[name]
+}