@quicktvui/web-renderer 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +24 -0
- package/src/adapters/es3-video-player.js +828 -0
- package/src/components/Modal.js +119 -0
- package/src/components/QtAnimationView.js +678 -0
- package/src/components/QtBaseComponent.js +165 -0
- package/src/components/QtFastListView.js +1920 -0
- package/src/components/QtFlexView.js +799 -0
- package/src/components/QtImage.js +203 -0
- package/src/components/QtItemFrame.js +239 -0
- package/src/components/QtItemStoreView.js +93 -0
- package/src/components/QtItemView.js +125 -0
- package/src/components/QtListView.js +331 -0
- package/src/components/QtLoadingView.js +55 -0
- package/src/components/QtPageRootView.js +19 -0
- package/src/components/QtPlayMark.js +168 -0
- package/src/components/QtProgressBar.js +199 -0
- package/src/components/QtQRCode.js +78 -0
- package/src/components/QtReplaceChild.js +149 -0
- package/src/components/QtRippleView.js +166 -0
- package/src/components/QtSeekBar.js +409 -0
- package/src/components/QtText.js +679 -0
- package/src/components/QtTransitionImage.js +170 -0
- package/src/components/QtView.js +706 -0
- package/src/components/QtWebView.js +613 -0
- package/src/components/TabsView.js +420 -0
- package/src/components/ViewPager.js +206 -0
- package/src/components/index.js +24 -0
- package/src/components/plugins/TextV2Component.js +70 -0
- package/src/components/plugins/index.js +7 -0
- package/src/core/SceneBuilder.js +58 -0
- package/src/core/TVFocusManager.js +2014 -0
- package/src/core/asyncLocalStorage.js +175 -0
- package/src/core/autoProxy.js +165 -0
- package/src/core/componentRegistry.js +84 -0
- package/src/core/constants.js +6 -0
- package/src/core/index.js +8 -0
- package/src/core/moduleUtils.js +36 -0
- package/src/core/patches.js +958 -0
- package/src/core/templateBinding.js +666 -0
- package/src/index.js +246 -0
- package/src/modules/AndroidDevelopModule.js +101 -0
- package/src/modules/AndroidDeviceModule.js +341 -0
- package/src/modules/AndroidNetworkModule.js +178 -0
- package/src/modules/AndroidSharedPreferencesModule.js +100 -0
- package/src/modules/ESDeviceInfoModule.js +450 -0
- package/src/modules/ESGroupDataModule.js +195 -0
- package/src/modules/ESIJKAudioPlayerModule.js +477 -0
- package/src/modules/ESLocalStorageModule.js +100 -0
- package/src/modules/ESLogModule.js +65 -0
- package/src/modules/ESModule.js +106 -0
- package/src/modules/ESNetworkSpeedModule.js +117 -0
- package/src/modules/ESToastModule.js +172 -0
- package/src/modules/EsNativeModule.js +117 -0
- package/src/modules/FastListModule.js +101 -0
- package/src/modules/FocusModule.js +145 -0
- package/src/modules/RuntimeDeviceModule.js +176 -0
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 异步 localStorage 适配层
|
|
3
|
+
*
|
|
4
|
+
* 将浏览器同步的 localStorage API 包装为异步 API
|
|
5
|
+
* 以保持与 Android 平台的一致性
|
|
6
|
+
*
|
|
7
|
+
* 用法:
|
|
8
|
+
* localStorage.getItem(key).then(value => { ... })
|
|
9
|
+
* localStorage.setItem(key, value).then(() => { ... })
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const rawLocalStorage = window.localStorage
|
|
13
|
+
|
|
14
|
+
// 存储变更监听器
|
|
15
|
+
const changeListeners = new Map()
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* 异步 localStorage 适配器
|
|
19
|
+
* 包装浏览器原生 localStorage,提供异步 API
|
|
20
|
+
*/
|
|
21
|
+
export const asyncLocalStorage = {
|
|
22
|
+
/**
|
|
23
|
+
* 异步获取存储项
|
|
24
|
+
* @param {string} key - 键名
|
|
25
|
+
* @returns {Promise<string|null>} - 返回 Promise
|
|
26
|
+
*/
|
|
27
|
+
getItem(key) {
|
|
28
|
+
return new Promise((resolve) => {
|
|
29
|
+
// 使用 setTimeout 模拟异步行为
|
|
30
|
+
setTimeout(() => {
|
|
31
|
+
try {
|
|
32
|
+
const value = rawLocalStorage.getItem(key)
|
|
33
|
+
resolve(value)
|
|
34
|
+
} catch (e) {
|
|
35
|
+
console.warn('[AsyncLocalStorage] getItem error:', e)
|
|
36
|
+
resolve(null)
|
|
37
|
+
}
|
|
38
|
+
}, 0)
|
|
39
|
+
})
|
|
40
|
+
},
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* 异步设置存储项
|
|
44
|
+
* @param {string} key - 键名
|
|
45
|
+
* @param {string} value - 值
|
|
46
|
+
* @returns {Promise<void>}
|
|
47
|
+
*/
|
|
48
|
+
setItem(key, value) {
|
|
49
|
+
return new Promise((resolve, reject) => {
|
|
50
|
+
setTimeout(() => {
|
|
51
|
+
try {
|
|
52
|
+
const oldValue = rawLocalStorage.getItem(key)
|
|
53
|
+
rawLocalStorage.setItem(key, value)
|
|
54
|
+
// 触发变更事件
|
|
55
|
+
_notifyChange(key, oldValue, value)
|
|
56
|
+
resolve()
|
|
57
|
+
} catch (e) {
|
|
58
|
+
console.warn('[AsyncLocalStorage] setItem error:', e)
|
|
59
|
+
reject(e)
|
|
60
|
+
}
|
|
61
|
+
}, 0)
|
|
62
|
+
})
|
|
63
|
+
},
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* 异步删除存储项
|
|
67
|
+
* @param {string} key - 键名
|
|
68
|
+
* @returns {Promise<void>}
|
|
69
|
+
*/
|
|
70
|
+
removeItem(key) {
|
|
71
|
+
return new Promise((resolve) => {
|
|
72
|
+
setTimeout(() => {
|
|
73
|
+
try {
|
|
74
|
+
const oldValue = rawLocalStorage.getItem(key)
|
|
75
|
+
rawLocalStorage.removeItem(key)
|
|
76
|
+
_notifyChange(key, oldValue, null)
|
|
77
|
+
resolve()
|
|
78
|
+
} catch (e) {
|
|
79
|
+
console.warn('[AsyncLocalStorage] removeItem error:', e)
|
|
80
|
+
resolve()
|
|
81
|
+
}
|
|
82
|
+
}, 0)
|
|
83
|
+
})
|
|
84
|
+
},
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* 异步清空存储
|
|
88
|
+
* @returns {Promise<void>}
|
|
89
|
+
*/
|
|
90
|
+
clear() {
|
|
91
|
+
return new Promise((resolve) => {
|
|
92
|
+
setTimeout(() => {
|
|
93
|
+
try {
|
|
94
|
+
rawLocalStorage.clear()
|
|
95
|
+
resolve()
|
|
96
|
+
} catch (e) {
|
|
97
|
+
console.warn('[AsyncLocalStorage] clear error:', e)
|
|
98
|
+
resolve()
|
|
99
|
+
}
|
|
100
|
+
}, 0)
|
|
101
|
+
})
|
|
102
|
+
},
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* 获取所有键名
|
|
106
|
+
* @param {number} index - 索引
|
|
107
|
+
* @returns {Promise<string|null>}
|
|
108
|
+
*/
|
|
109
|
+
key(index) {
|
|
110
|
+
return new Promise((resolve) => {
|
|
111
|
+
setTimeout(() => {
|
|
112
|
+
try {
|
|
113
|
+
resolve(rawLocalStorage.key(index))
|
|
114
|
+
} catch (e) {
|
|
115
|
+
console.warn('[AsyncLocalStorage] key error:', e)
|
|
116
|
+
resolve(null)
|
|
117
|
+
}
|
|
118
|
+
}, 0)
|
|
119
|
+
})
|
|
120
|
+
},
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* 同步获取存储长度(保持同步,因为通常不需要异步)
|
|
124
|
+
*/
|
|
125
|
+
get length() {
|
|
126
|
+
return rawLocalStorage.length
|
|
127
|
+
},
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* 监听存储变更
|
|
131
|
+
* @param {function} callback - 回调函数 (key, newValue, oldValue) => void
|
|
132
|
+
* @returns {function} 取消监听函数
|
|
133
|
+
*/
|
|
134
|
+
addChangeListener(callback) {
|
|
135
|
+
const id = Date.now() + Math.random()
|
|
136
|
+
changeListeners.set(id, callback)
|
|
137
|
+
return () => changeListeners.delete(id)
|
|
138
|
+
},
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* 通知存储变更
|
|
143
|
+
*/
|
|
144
|
+
function _notifyChange(key, oldValue, newValue) {
|
|
145
|
+
changeListeners.forEach((callback) => {
|
|
146
|
+
try {
|
|
147
|
+
callback(key, newValue, oldValue)
|
|
148
|
+
} catch (e) {
|
|
149
|
+
console.warn('[AsyncLocalStorage] listener error:', e)
|
|
150
|
+
}
|
|
151
|
+
})
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* 初始化异步 localStorage
|
|
156
|
+
* 替换全局 localStorage 为异步版本
|
|
157
|
+
*/
|
|
158
|
+
export function initAsyncLocalStorage() {
|
|
159
|
+
// 保存原生 localStorage 引用
|
|
160
|
+
globalThis.__nativeLocalStorage = rawLocalStorage
|
|
161
|
+
|
|
162
|
+
// 替换为异步版本
|
|
163
|
+
globalThis.__localStorage = asyncLocalStorage
|
|
164
|
+
|
|
165
|
+
// 同时替换 window.localStorage(某些代码可能直接使用 window.localStorage)
|
|
166
|
+
Object.defineProperty(window, 'localStorage', {
|
|
167
|
+
value: asyncLocalStorage,
|
|
168
|
+
writable: false,
|
|
169
|
+
configurable: true,
|
|
170
|
+
})
|
|
171
|
+
|
|
172
|
+
console.log('[AsyncLocalStorage] Initialized - localStorage methods now return Promises')
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
export default asyncLocalStorage
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 自动代理模块 - 开发环境下自动拦截 fetch/XMLHttpRequest 请求并代理
|
|
3
|
+
*
|
|
4
|
+
* 原理:
|
|
5
|
+
* 1. 拦截所有 fetch/XHR 请求
|
|
6
|
+
* 2. 如果是外部 URL,转换为本地代理路径
|
|
7
|
+
* 3. 由 webpack-dev-server 代理到目标服务器
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
// 是否启用自动代理(仅开发环境)
|
|
11
|
+
const ENABLE_AUTO_PROXY = process.env.NODE_ENV === 'development'
|
|
12
|
+
|
|
13
|
+
// 需要代理的域名列表(可通过环境变量配置)
|
|
14
|
+
const PROXY_DOMAINS = (process.env.VUE_APP_PROXY_DOMAINS || '')
|
|
15
|
+
.split(',')
|
|
16
|
+
.map((d) => d.trim())
|
|
17
|
+
.filter(Boolean)
|
|
18
|
+
|
|
19
|
+
// 默认代理的常见域名模式
|
|
20
|
+
const DEFAULT_PROXY_PATTERNS = [
|
|
21
|
+
// 常见 API 域名
|
|
22
|
+
/api\./i,
|
|
23
|
+
/-api\./i,
|
|
24
|
+
/\.api\./i,
|
|
25
|
+
// CDN 和图片服务
|
|
26
|
+
/qcloudimg\./i,
|
|
27
|
+
/cdnott\./i,
|
|
28
|
+
/baidu\./i,
|
|
29
|
+
// 自定义域名(从环境变量读取)
|
|
30
|
+
...PROXY_DOMAINS.map((d) => new RegExp(d.replace(/\./g, '\\.'), 'i')),
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* 判断 URL 是否需要代理
|
|
35
|
+
*/
|
|
36
|
+
function shouldProxy(url) {
|
|
37
|
+
if (!url) return false
|
|
38
|
+
|
|
39
|
+
try {
|
|
40
|
+
const urlObj = new URL(url, window.location.origin)
|
|
41
|
+
|
|
42
|
+
// 同源请求不需要代理
|
|
43
|
+
if (urlObj.origin === window.location.origin) {
|
|
44
|
+
return false
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// 检查是否匹配代理模式
|
|
48
|
+
return DEFAULT_PROXY_PATTERNS.some((pattern) => pattern.test(urlObj.hostname))
|
|
49
|
+
} catch (e) {
|
|
50
|
+
return false
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* 将外部 URL 转换为代理路径
|
|
56
|
+
*/
|
|
57
|
+
function toProxyUrl(url) {
|
|
58
|
+
if (!url) return url
|
|
59
|
+
|
|
60
|
+
try {
|
|
61
|
+
const urlObj = new URL(url, window.location.origin)
|
|
62
|
+
|
|
63
|
+
// 构建代理路径: /proxy/{protocol}/{host}{pathname}{search}
|
|
64
|
+
const proxyPath = `/proxy/${urlObj.protocol.replace(':', '')}/${urlObj.host}${urlObj.pathname}${urlObj.search}`
|
|
65
|
+
|
|
66
|
+
console.log(`[AutoProxy] ${url} -> ${proxyPath}`)
|
|
67
|
+
return proxyPath
|
|
68
|
+
} catch (e) {
|
|
69
|
+
return url
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* 处理 URL(如果是外部 URL 则转换为代理路径)
|
|
75
|
+
*/
|
|
76
|
+
export function proxyUrl(url) {
|
|
77
|
+
if (!ENABLE_AUTO_PROXY) return url
|
|
78
|
+
if (!shouldProxy(url)) return url
|
|
79
|
+
return toProxyUrl(url)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* 初始化自动代理
|
|
84
|
+
*/
|
|
85
|
+
export function initAutoProxy() {
|
|
86
|
+
if (!ENABLE_AUTO_PROXY) {
|
|
87
|
+
console.log('[AutoProxy] Disabled (not development mode)')
|
|
88
|
+
return
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
console.log('[AutoProxy] Initializing...')
|
|
92
|
+
console.log(
|
|
93
|
+
'[AutoProxy] Proxy patterns:',
|
|
94
|
+
DEFAULT_PROXY_PATTERNS.map((p) => p.toString())
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
// ===== 拦截 fetch =====
|
|
98
|
+
const originalFetch = window.fetch
|
|
99
|
+
window.fetch = function (input, init = {}) {
|
|
100
|
+
let url = typeof input === 'string' ? input : input.url
|
|
101
|
+
|
|
102
|
+
if (shouldProxy(url)) {
|
|
103
|
+
const proxyUrlStr = toProxyUrl(url)
|
|
104
|
+
|
|
105
|
+
// 更新 input
|
|
106
|
+
if (typeof input === 'string') {
|
|
107
|
+
input = proxyUrlStr
|
|
108
|
+
} else if (input instanceof Request) {
|
|
109
|
+
// 创建新的 Request 对象
|
|
110
|
+
input = new Request(proxyUrlStr, {
|
|
111
|
+
method: input.method,
|
|
112
|
+
headers: input.headers,
|
|
113
|
+
body: input.body,
|
|
114
|
+
mode: 'cors', // 使用代理时改为同源
|
|
115
|
+
credentials: input.credentials,
|
|
116
|
+
cache: input.cache,
|
|
117
|
+
redirect: input.redirect,
|
|
118
|
+
referrer: input.referrer,
|
|
119
|
+
integrity: input.integrity,
|
|
120
|
+
})
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return originalFetch.call(this, input, init)
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// ===== 拦截 XMLHttpRequest =====
|
|
128
|
+
const originalXHROpen = XMLHttpRequest.prototype.open
|
|
129
|
+
XMLHttpRequest.prototype.open = function (method, url, async, user, password) {
|
|
130
|
+
if (shouldProxy(url)) {
|
|
131
|
+
url = toProxyUrl(url)
|
|
132
|
+
}
|
|
133
|
+
return originalXHROpen.call(this, method, url, async !== false, user, password)
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// ===== 拦截 Image =====
|
|
137
|
+
const originalImageSrcDescriptor = Object.getOwnPropertyDescriptor(
|
|
138
|
+
HTMLImageElement.prototype,
|
|
139
|
+
'src'
|
|
140
|
+
)
|
|
141
|
+
if (originalImageSrcDescriptor && originalImageSrcDescriptor.set) {
|
|
142
|
+
Object.defineProperty(HTMLImageElement.prototype, 'src', {
|
|
143
|
+
...originalImageSrcDescriptor,
|
|
144
|
+
set(value) {
|
|
145
|
+
if (value.startsWith('http://127.0.0.1:38989')) {
|
|
146
|
+
return originalImageSrcDescriptor.set.call(
|
|
147
|
+
this,
|
|
148
|
+
value.replace('http://127.0.0.1:38989/', './')
|
|
149
|
+
)
|
|
150
|
+
}
|
|
151
|
+
const proxyValue = shouldProxy(value) ? toProxyUrl(value) : value
|
|
152
|
+
return originalImageSrcDescriptor.set.call(this, proxyValue)
|
|
153
|
+
},
|
|
154
|
+
})
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
console.log('[AutoProxy] Initialized successfully')
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export default {
|
|
161
|
+
init: initAutoProxy,
|
|
162
|
+
proxyUrl,
|
|
163
|
+
shouldProxy,
|
|
164
|
+
toProxyUrl,
|
|
165
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
// Component Registry for callUIFunction support
|
|
2
|
+
// Local component registry for components that need callUIFunction support
|
|
3
|
+
|
|
4
|
+
let webEngine = null
|
|
5
|
+
|
|
6
|
+
const componentRegistry = new Map()
|
|
7
|
+
|
|
8
|
+
// SID (string id) to component mapping for ExtendModule.callUIFunction support
|
|
9
|
+
const sidRegistry = new Map()
|
|
10
|
+
|
|
11
|
+
// Set the web engine reference
|
|
12
|
+
export function setWebEngine(engine) {
|
|
13
|
+
webEngine = engine
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function getWebEngine() {
|
|
17
|
+
return webEngine
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Register a component by nodeId
|
|
21
|
+
export function registerComponent(nodeId, component) {
|
|
22
|
+
componentRegistry.set(nodeId, component)
|
|
23
|
+
console.log('[Web Renderer] Registered component:', nodeId, component.constructor.name)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Register a component by sid (string id)
|
|
27
|
+
export function registerComponentBySid(sid, component) {
|
|
28
|
+
if (!sid || typeof sid !== 'string') {
|
|
29
|
+
return
|
|
30
|
+
}
|
|
31
|
+
sidRegistry.set(sid, component)
|
|
32
|
+
console.log(
|
|
33
|
+
'[Web Renderer] Registered component by sid:',
|
|
34
|
+
sid,
|
|
35
|
+
component.constructor?.name || component.tagName
|
|
36
|
+
)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Unregister a component by sid
|
|
40
|
+
export function unregisterComponentBySid(sid) {
|
|
41
|
+
if (sidRegistry.has(sid)) {
|
|
42
|
+
sidRegistry.delete(sid)
|
|
43
|
+
console.log('[Web Renderer] Unregistered component by sid:', sid)
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Find component by sid (string id)
|
|
48
|
+
export function findComponentBySid(sid) {
|
|
49
|
+
if (sidRegistry.has(sid)) {
|
|
50
|
+
return sidRegistry.get(sid)
|
|
51
|
+
}
|
|
52
|
+
return null
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Find component by nodeId - check local registry first, then UIManagerModule
|
|
56
|
+
export function findComponentById(nodeId) {
|
|
57
|
+
// If nodeId is a string, it's likely a sid
|
|
58
|
+
if (typeof nodeId === 'string') {
|
|
59
|
+
return findComponentBySid(nodeId)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Check local registry first
|
|
63
|
+
if (componentRegistry.has(nodeId)) {
|
|
64
|
+
return componentRegistry.get(nodeId)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (!webEngine) {
|
|
68
|
+
return null
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
try {
|
|
72
|
+
// getModuleByName is on context, not engine
|
|
73
|
+
const uiManager = webEngine.context?.getModuleByName?.('UIManagerModule')
|
|
74
|
+
if (uiManager && uiManager.findViewById) {
|
|
75
|
+
const component = uiManager.findViewById(nodeId)
|
|
76
|
+
if (component) {
|
|
77
|
+
return component
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
} catch (e) {
|
|
81
|
+
console.error('[Web Renderer] Error finding component:', e)
|
|
82
|
+
}
|
|
83
|
+
return null
|
|
84
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// Module utility functions for web renderer
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Resolve addon callback pattern used by HippyWebEngine
|
|
5
|
+
* Many native module methods receive an addon object as the last argument
|
|
6
|
+
* with a resolve function that should be called with the result.
|
|
7
|
+
*
|
|
8
|
+
* @param {Array} args - The arguments array passed to the module method
|
|
9
|
+
* @param {*} value - The value to resolve/return
|
|
10
|
+
* @returns {*} The value (also calls resolve if addon exists)
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* async getDeviceInfo(...args) {
|
|
14
|
+
* return resolveAddon(args, { model: 'Web', ... })
|
|
15
|
+
* }
|
|
16
|
+
*/
|
|
17
|
+
export function resolveAddon(args, value) {
|
|
18
|
+
const last = args && args.length ? args[args.length - 1] : null
|
|
19
|
+
if (last && typeof last.resolve === 'function') {
|
|
20
|
+
last.resolve(value)
|
|
21
|
+
}
|
|
22
|
+
return value
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Create a standard module init method
|
|
27
|
+
* @param {Array} args - Arguments passed to init
|
|
28
|
+
* @returns {Promise<boolean>}
|
|
29
|
+
*/
|
|
30
|
+
export function createModuleInit(args) {
|
|
31
|
+
const addon = args && args.length ? args[args.length - 1] : null
|
|
32
|
+
if (addon && typeof addon.resolve === 'function') {
|
|
33
|
+
addon.resolve(true)
|
|
34
|
+
}
|
|
35
|
+
return Promise.resolve(true)
|
|
36
|
+
}
|