From feaf164601a0d5fcf40255304db3d78717e7645f Mon Sep 17 00:00:00 2001 From: fxy060608 Date: Fri, 24 Sep 2021 12:23:03 +0800 Subject: [PATCH] feat(automator): support safari,firefox --- .prettierignore | 9 +- packages/uni-app-plus/lib/automator.js | 1714 +++++++---------- packages/uni-app-plus/lib/uni.automator.js | 554 +++--- .../lib/template/__uniappautomator.js | 545 +----- packages/uni-automator/dist/environment.js | 45 +- packages/uni-automator/dist/index.js | 1483 +------------- packages/uni-automator/dist/teardown.js | 14 +- packages/uni-h5/lib/automator.js | 1630 +++++++--------- packages/uni-h5/lib/uni.automator.js | 252 ++- packages/uni-mp-baidu/lib/automator.js | 489 +---- packages/uni-mp-baidu/lib/uni.automator.js | 557 +----- packages/uni-mp-weixin/lib/automator.js | 490 +---- packages/uni-mp-weixin/lib/uni.automator.js | 362 +--- 13 files changed, 1870 insertions(+), 6274 deletions(-) diff --git a/.prettierignore b/.prettierignore index cc952deac..0aaae449b 100644 --- a/.prettierignore +++ b/.prettierignore @@ -5,5 +5,12 @@ packages/uni-automator/lib packages/uni-cli-nvue/lib packages/uni-cli-shared/lib packages/uni-components/lib +packages/uni-cloud/lib +packages/uni-mp-alipay/lib +packages/uni-mp-baidu/lib +packages/uni-mp-kuaishou/lib +packages/uni-mp-qq/lib +packages/uni-mp-toutiao/lib packages/uni-mp-vue/lib -packages/uni-cloud/lib \ No newline at end of file +packages/uni-mp-weixin/lib +packages/uni-mp-quickapp-webview/lib \ No newline at end of file diff --git a/packages/uni-app-plus/lib/automator.js b/packages/uni-app-plus/lib/automator.js index 07ac14f71..c8754d173 100644 --- a/packages/uni-app-plus/lib/automator.js +++ b/packages/uni-app-plus/lib/automator.js @@ -1,478 +1,308 @@ -var hasOwnProperty = Object.prototype.hasOwnProperty -var hasOwn = function (val, key) { - return hasOwnProperty.call(val, key) -} -var isUndef = function (v) { - return v === undefined || v === null -} -var isArray = Array.isArray -var isPromise = function (obj) { +var e, + t = Object.prototype.hasOwnProperty, + n = function (e) { + return null == e + }, + r = Array.isArray, + o = function (e) { + var t = Object.create(null) + return function (n) { + return t[n] || (t[n] = e(n)) + } + }, + u = /\B([A-Z])/g, + i = o(function (e) { + return e.replace(u, '-$1').toLowerCase() + }), + c = /-(\w)/g, + a = o(function (e) { + return e.replace(c, function (e, t) { + return t ? t.toUpperCase() : '' + }) + }), + s = o(function (e) { + return e.charAt(0).toUpperCase() + e.slice(1) + }), + f = + /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g +function l(e, n) { + if (r(e)) return e + if (n && ((o = n), (u = e), t.call(o, u))) return [e] + var o, + u, + i = [] return ( - !!obj && - (typeof obj === 'object' || typeof obj === 'function') && - typeof obj.then === 'function' + e.replace(f, function (e, t, n, r) { + return i.push(n ? r.replace(/\\(\\)?/g, '$1') : t || e), r + }), + i ) } -var cacheStringFunction = function (fn) { - var cache = Object.create(null) - return function (str) { - var hit = cache[str] - return hit || (cache[str] = fn(str)) - } -} -var hyphenateRE = /\B([A-Z])/g -var hyphenate = cacheStringFunction(function (str) { - return str.replace(hyphenateRE, '-$1').toLowerCase() -}) -var camelizeRE = /-(\w)/g -var camelize = cacheStringFunction(function (str) { - return str.replace(camelizeRE, function (_, c) { - return c ? c.toUpperCase() : '' - }) -}) -var capitalize = cacheStringFunction(function (str) { - return str.charAt(0).toUpperCase() + str.slice(1) -}) -var PATH_RE = - /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g -function getPaths(path, data) { - if (isArray(path)) { - return path - } - if (data && hasOwn(data, path)) { - return [path] - } - var res = [] - path.replace(PATH_RE, function (match, p1, offset, string) { - res.push(offset ? string.replace(/\\(\\)?/g, '$1') : p1 || match) - return string - }) - return res -} -function getDataByPath(data, path) { - var paths = getPaths(path, data) - var dataPath - for (dataPath = paths.shift(); !isUndef(dataPath); ) { - if (null == (data = data[dataPath])) { - return - } - dataPath = paths.shift() - } - return data -} -function findParent(vm) { - var parent = vm.$parent - while (parent) { - if (parent._$id) { - return parent - } - parent = parent.$parent - } -} -function getVmNodeId(vm) { - //@ts-ignore - { - if (vm._$weex) { - return vm._uid - } - if (vm._$id) { - return vm._$id - } - var parent_1 = findParent(vm) - if (!vm.$parent) { - return '-1' - } - var vnode = vm.$vnode - var context = vnode.context - // slot 内的组件,需要补充 context 的 id,否则可能与内部组件索引值一致,导致 id 冲突 - if (context && context !== parent_1 && context._$id) { - return context._$id + ';' + parent_1._$id + ',' + vnode.data.attrs._i - } - return parent_1._$id + ',' + vnode.data.attrs._i - } -} - -function getPageId(page) { - if (page.__wxWebviewId__) { - //mp-weixin - return page.__wxWebviewId__ - } - if (page.privateProperties) { - //mp-baidu - return page.privateProperties.slaveId - } - if (page.$page) { - //h5 and app-plus - return page.$page.id - } -} -function getPagePath(page) { - return page.route || page.uri -} -function getPageQuery(page) { - return page.options || (page.$page && page.$page.options) || {} -} -function parsePage(page) { - return { - id: getPageId(page), - path: getPagePath(page), - query: getPageQuery(page), - } -} -function getPageById(id) { - return getCurrentPages().find(function (page) { - return getPageId(page) === id - }) -} -function getPageVm(id) { - var page = getPageById(id) - return page && page.$vm -} -function matchNodeId(vm, nodeId) { - //@ts-ignore - { - return getVmNodeId(vm) === nodeId - } -} -function findComponentVm(vm, nodeId) { - var res - if (vm) { - if (matchNodeId(vm, nodeId)) { - res = vm - } else { - vm.$children.find(function (child) { - res = findComponentVm(child, nodeId) - return res - }) - } - } - return res -} -function getComponentVm(pageId, nodeId) { - var pageVm = getPageVm(pageId) - return pageVm && findComponentVm(pageVm, nodeId) -} -function getData(vm, path) { - var data - if (vm) { - data = path ? getDataByPath(vm.$data, path) : Object.assign({}, vm.$data) - } - return Promise.resolve({ data: data }) -} -function setData(vm, data) { - if (vm) { - Object.keys(data).forEach(function (name) { - vm[name] = data[name] +function d(e, t) { + var r, + o = l(t, e) + for (r = o.shift(); !n(r); ) { + if (null == (e = e[r])) return + r = o.shift() + } + return e +} +function p(e) { + return e.__wxWebviewId__ + ? e.__wxWebviewId__ + : e.privateProperties + ? e.privateProperties.slaveId + : e.$page + ? e.$page.id + : void 0 +} +function g(e) { + return e.route || e.uri +} +function m(e) { + return e.options || (e.$page && e.$page.options) || {} +} +function v(e) { + return { id: p(e), path: g(e), query: m(e) } +} +function _(e) { + var t = (function (e) { + return getCurrentPages().find(function (t) { + return p(t) === e }) - } - return Promise.resolve() + })(e) + return t && t.$vm } -var CALL_METHOD_ERROR -;(function (CALL_METHOD_ERROR) { - CALL_METHOD_ERROR['VM_NOT_EXISTS'] = 'VM_NOT_EXISTS' - CALL_METHOD_ERROR['METHOD_NOT_EXISTS'] = 'METHOD_NOT_EXISTS' -})(CALL_METHOD_ERROR || (CALL_METHOD_ERROR = {})) -function callMethod(vm, method, args) { - return new Promise(function (resolve, reject) { - if (!vm) { - return reject(CALL_METHOD_ERROR.VM_NOT_EXISTS) - } - if (!vm[method]) { - return reject(CALL_METHOD_ERROR.VM_NOT_EXISTS) - } - var ret = vm[method].apply(vm, args) - isPromise(ret) - ? ret.then(function (res) { - resolve({ result: res }) - }) - : resolve({ result: ret }) - }) -} - -var SYNC_APIS = [ - 'stopRecord', - 'getRecorderManager', - 'pauseVoice', - 'stopVoice', - 'pauseBackgroundAudio', - 'stopBackgroundAudio', - 'getBackgroundAudioManager', - 'createAudioContext', - 'createInnerAudioContext', - 'createVideoContext', - 'createCameraContext', - 'createMapContext', - 'canIUse', - 'startAccelerometer', - 'stopAccelerometer', - 'startCompass', - 'stopCompass', - 'hideToast', - 'hideLoading', - 'showNavigationBarLoading', - 'hideNavigationBarLoading', - 'navigateBack', - 'createAnimation', - 'pageScrollTo', - 'createSelectorQuery', - 'createCanvasContext', - 'createContext', - 'drawCanvas', - 'hideKeyboard', - 'stopPullDownRefresh', - 'arrayBufferToBase64', - 'base64ToArrayBuffer', -] -var originUni = {} -var SYNC_API_RE = /Sync$/ -var MOCK_API_BLACKLIST_RE = /^on|^off/ -function isSyncApi(method) { - return SYNC_API_RE.test(method) || SYNC_APIS.indexOf(method) !== -1 +function h(e, t) { + var n = _(e) + return ( + n && + (function e(t, n) { + var r + return ( + t && + (!(function (e, t) { + return ( + (function (e) { + if (e._$weex) return e._uid + if (e._$id) return e._$id + var t = (function (e) { + for (var t = e.$parent; t; ) { + if (t._$id) return t + t = t.$parent + } + })(e) + if (!e.$parent) return '-1' + var n = e.$vnode, + r = n.context + return r && r !== t && r._$id + ? r._$id + ';' + t._$id + ',' + n.data.attrs._i + : t._$id + ',' + n.data.attrs._i + })(e) === t + ) + })(t, n) + ? t.$children.find(function (t) { + return (r = e(t, n)) + }) + : (r = t)), + r + ) + })(n, t) + ) } -function canIMock(method) { - return !MOCK_API_BLACKLIST_RE.test(method) +function E(e, t) { + var n + return ( + e && (n = t ? d(e.$data, t) : Object.assign({}, e.$data)), + Promise.resolve({ data: n }) + ) } -var App = { - getPageStack: function () { - return Promise.resolve({ - pageStack: getCurrentPages().map(function (page) { - return parsePage(page) +function y(e, t) { + return ( + e && + Object.keys(t).forEach(function (n) { + e[n] = t[n] }), - }) - }, - getCurrentPage: function () { - var pages = getCurrentPages() - var len = pages.length - return new Promise(function (resolve, reject) { - if (!len) { - reject(Error('getCurrentPages().length=0')) - } else { - resolve(parsePage(pages[len - 1])) - } - }) - }, - callUniMethod: function (params) { - var method = params.method - var args = params.args - return new Promise(function (resolve, reject) { - if (!uni[method]) { - return reject(Error('uni.' + method + ' not exists')) - } - if (isSyncApi(method)) { - return resolve({ - result: uni[method].apply(uni, args), - }) - } - var params = [ - Object.assign({}, args[0] || {}, { - success: function (result) { - var timeout = method === 'pageScrollTo' ? 350 : 0 - setTimeout(function () { - resolve({ result: result }) - }, timeout) - }, - fail: function (res) { - reject(Error(res.errMsg.replace(method + ':fail ', ''))) - }, - }), - ] - uni[method].apply(uni, params) - }) - }, - mockUniMethod: function (params) { - var method = params.method - if (!uni[method]) { - throw Error('uni.' + method + ' not exists') - } - if (!canIMock(method)) { - throw Error("You can't mock uni." + method) - } - // TODO getOwnPropertyDescriptor? - var result = params.result - if (isUndef(result)) { - // restoreUniMethod - if (originUni[method]) { - uni[method] = originUni[method] - delete originUni[method] - } - return Promise.resolve() - } - var mockFn = isSyncApi(method) - ? function () { - return result - } - : function (params) { - setTimeout(function () { - var isFail = result.errMsg && result.errMsg.indexOf(':fail') !== -1 - if (isFail) { - params.fail && params.fail(result) - } else { - params.success && params.success(result) - } - params.complete && params.complete(result) - }, 4) - } - // mockFn.origin = originUni[method] || uni[method]; - if (!originUni[method]) { - originUni[method] = uni[method] - } - uni[method] = mockFn - return Promise.resolve() - }, -} - -var Page = { - getData: function (params) { - return getData(getPageVm(params.pageId), params.path) - }, - setData: function (params) { - return setData(getPageVm(params.pageId), params.data) - }, - callMethod: function (params) { - var _a - var err = - ((_a = {}), - (_a[CALL_METHOD_ERROR.VM_NOT_EXISTS] = - 'Page[' + params.pageId + '] not exists'), - (_a[CALL_METHOD_ERROR.METHOD_NOT_EXISTS] = - 'page.' + params.method + ' not exists'), - _a) - return new Promise(function (resolve, reject) { - callMethod(getPageVm(params.pageId), params.method, params.args) - .then(function (res) { - return resolve(res) - }) - .catch(function (type) { - reject(Error(err[type])) - }) - }) - }, -} - -function getNodeId(params) { - return params.nodeId || params.elementId + Promise.resolve() + ) } -var Element = { - getData: function (params) { - return getData( - getComponentVm(params.pageId, getNodeId(params)), - params.path - ) - }, - setData: function (params) { - return setData( - getComponentVm(params.pageId, getNodeId(params)), - params.data - ) - }, - callMethod: function (params) { - var _a - var nodeId = getNodeId(params) - var err = - ((_a = {}), - (_a[CALL_METHOD_ERROR.VM_NOT_EXISTS] = - 'Component[' + params.pageId + ':' + nodeId + '] not exists'), - (_a[CALL_METHOD_ERROR.METHOD_NOT_EXISTS] = - 'component.' + params.method + ' not exists'), - _a) - return new Promise(function (resolve, reject) { - callMethod( - getComponentVm(params.pageId, nodeId), - params.method, - params.args - ) - .then(function (res) { - return resolve(res) - }) - .catch(function (type) { - reject(Error(err[type])) +function w(t, n, r) { + return new Promise(function (o, u) { + if (!t) return u(e.VM_NOT_EXISTS) + if (!t[n]) return u(e.VM_NOT_EXISTS) + var i, + c = t[n].apply(t, r) + !(i = c) || + ('object' != typeof i && 'function' != typeof i) || + 'function' != typeof i.then + ? o({ result: c }) + : c.then(function (e) { + o({ result: e }) }) - }) - }, -} - -function initPage(adapter) { - return { - 'Page.getElement': function (params) { - return adapter.querySelector( - adapter.getDocument(params.pageId), - params.selector - ) - }, - 'Page.getElements': function (params) { - return adapter.querySelectorAll( - adapter.getDocument(params.pageId), - params.selector - ) - }, - 'Page.getWindowProperties': function (params) { - return adapter.queryProperties( - adapter.getWindow(params.pageId), - params.names - ) - }, - } + }) } - -function initElement(adapter) { - var getEl = function (params) { - return adapter.getEl(params.elementId, params.pageId) - } - return { - 'Element.getElement': function (params) { - return adapter.querySelector(getEl(params), params.selector) - }, - 'Element.getElements': function (params) { - return adapter.querySelectorAll(getEl(params), params.selector) - }, - 'Element.getDOMProperties': function (params) { - return adapter.queryProperties(getEl(params), params.names) - }, - 'Element.getProperties': function (params) { - var el = getEl(params) - var ctx = el.__vue__ || el.attr || {} - return adapter.queryProperties(ctx, params.names) - }, - 'Element.getOffset': function (params) { - return adapter.getOffset(getEl(params)) - }, - 'Element.getAttributes': function (params) { - return adapter.queryAttributes(getEl(params), params.names) - }, - 'Element.getStyles': function (params) { - return adapter.queryStyles(getEl(params), params.names) - }, - 'Element.getHTML': function (params) { - return adapter.queryHTML(getEl(params), params.type) - }, - 'Element.tap': function (params) { - return adapter.dispatchTapEvent(getEl(params)) - }, - 'Element.longpress': function (params) { - return adapter.dispatchLongpressEvent(getEl(params)) - }, - 'Element.touchstart': function (params) { - return adapter.dispatchTouchEvent(getEl(params), 'touchstart', params) +!(function (e) { + ;(e.VM_NOT_EXISTS = 'VM_NOT_EXISTS'), + (e.METHOD_NOT_EXISTS = 'METHOD_NOT_EXISTS') +})(e || (e = {})) +var T = [ + 'stopRecord', + 'getRecorderManager', + 'pauseVoice', + 'stopVoice', + 'pauseBackgroundAudio', + 'stopBackgroundAudio', + 'getBackgroundAudioManager', + 'createAudioContext', + 'createInnerAudioContext', + 'createVideoContext', + 'createCameraContext', + 'createMapContext', + 'canIUse', + 'startAccelerometer', + 'stopAccelerometer', + 'startCompass', + 'stopCompass', + 'hideToast', + 'hideLoading', + 'showNavigationBarLoading', + 'hideNavigationBarLoading', + 'navigateBack', + 'createAnimation', + 'pageScrollTo', + 'createSelectorQuery', + 'createCanvasContext', + 'createContext', + 'drawCanvas', + 'hideKeyboard', + 'stopPullDownRefresh', + 'arrayBufferToBase64', + 'base64ToArrayBuffer', + ], + x = {}, + P = /Sync$/, + S = /^on|^off/ +function O(e) { + return P.test(e) || -1 !== T.indexOf(e) +} +var $ = { + getPageStack: function () { + return Promise.resolve({ + pageStack: getCurrentPages().map(function (e) { + return v(e) + }), + }) }, - 'Element.touchmove': function (params) { - return adapter.dispatchTouchEvent(getEl(params), 'touchmove', params) + getCurrentPage: function () { + var e = getCurrentPages(), + t = e.length + return new Promise(function (n, r) { + t ? n(v(e[t - 1])) : r(Error('getCurrentPages().length=0')) + }) }, - 'Element.touchend': function (params) { - return adapter.dispatchTouchEvent(getEl(params), 'touchend', params) + callUniMethod: function (e) { + var t = e.method, + n = e.args + return new Promise(function (e, r) { + if (!uni[t]) return r(Error('uni.' + t + ' not exists')) + if (O(t)) return e({ result: uni[t].apply(uni, n) }) + var o = [ + Object.assign({}, n[0] || {}, { + success: function (n) { + setTimeout( + function () { + e({ result: n }) + }, + 'pageScrollTo' === t ? 350 : 0 + ) + }, + fail: function (e) { + r(Error(e.errMsg.replace(t + ':fail ', ''))) + }, + }), + ] + uni[t].apply(uni, o) + }) }, - 'Element.callFunction': function (params) { - return adapter.callFunction( - getEl(params), - params.functionName, - params.args + mockUniMethod: function (e) { + var t = e.method + if (!uni[t]) throw Error('uni.' + t + ' not exists') + if ( + !(function (e) { + return !S.test(e) + })(t) ) - }, - 'Element.triggerEvent': function (params) { - return adapter.triggerEvent(getEl(params), params.type, params.detail) + throw Error("You can't mock uni." + t) + var r = e.result + if (n(r)) return x[t] && ((uni[t] = x[t]), delete x[t]), Promise.resolve() + var o = O(t) + ? function () { + return r + } + : function (e) { + setTimeout(function () { + r.errMsg && -1 !== r.errMsg.indexOf(':fail') + ? e.fail && e.fail(r) + : e.success && e.success(r), + e.complete && e.complete(r) + }, 4) + } + return x[t] || (x[t] = uni[t]), (uni[t] = o), Promise.resolve() + }, + }, + b = { + getData: function (e) { + return E(_(e.pageId), e.path) + }, + setData: function (e) { + return y(_(e.pageId), e.data) + }, + callMethod: function (t) { + var n, + r = + (((n = {})[e.VM_NOT_EXISTS] = 'Page[' + t.pageId + '] not exists'), + (n[e.METHOD_NOT_EXISTS] = 'page.' + t.method + ' not exists'), + n) + return new Promise(function (e, n) { + w(_(t.pageId), t.method, t.args) + .then(function (t) { + return e(t) + }) + .catch(function (e) { + n(Error(r[e])) + }) + }) }, } +function I(e) { + return e.nodeId || e.elementId +} +var C = { + getData: function (e) { + return E(h(e.pageId, I(e)), e.path) + }, + setData: function (e) { + return y(h(e.pageId, I(e)), e.data) + }, + callMethod: function (t) { + var n, + r = I(t), + o = + (((n = {})[e.VM_NOT_EXISTS] = + 'Component[' + t.pageId + ':' + r + '] not exists'), + (n[e.METHOD_NOT_EXISTS] = 'component.' + t.method + ' not exists'), + n) + return new Promise(function (e, n) { + w(h(t.pageId, r), t.method, t.args) + .then(function (t) { + return e(t) + }) + .catch(function (e) { + n(Error(o[e])) + }) + }) + }, } - /*! ***************************************************************************** Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use @@ -487,645 +317,549 @@ MERCHANTABLITY OR NON-INFRINGEMENT. See the Apache Version 2.0 License for specific language governing permissions and limitations under the License. ***************************************************************************** */ - -function __spreadArrays() { - for (var s = 0, i = 0, il = arguments.length; i < il; i++) - s += arguments[i].length - for (var r = Array(s), k = 0, i = 0; i < il; i++) - for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++) - r[k] = a[j] +function M() { + for (var e = 0, t = 0, n = arguments.length; t < n; t++) + e += arguments[t].length + var r = Array(e), + o = 0 + for (t = 0; t < n; t++) + for (var u = arguments[t], i = 0, c = u.length; i < c; i++, o++) r[o] = u[i] return r } - -// Unique ID creation requires a high quality random # generator. In the browser we therefore -// require the crypto API and do not support built-in fallback to lower quality random number -// generators (like Math.random()). -// getRandomValues needs to be invoked in a context where "this" is a Crypto implementation. Also, -// find the complete implementation of crypto (msCrypto) on IE11. -var getRandomValues = - (typeof crypto != 'undefined' && - crypto.getRandomValues && - crypto.getRandomValues.bind(crypto)) || - (typeof msCrypto != 'undefined' && - typeof msCrypto.getRandomValues == 'function' && +;('undefined' != typeof crypto && + crypto.getRandomValues && + crypto.getRandomValues.bind(crypto)) || + ('undefined' != typeof msCrypto && + 'function' == typeof msCrypto.getRandomValues && msCrypto.getRandomValues.bind(msCrypto)) - -/** - * Convert array of 16 byte values to UUID string format of the form: - * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX - */ -var byteToHex = [] - -for (var i = 0; i < 256; ++i) { - byteToHex[i] = (i + 0x100).toString(16).substr(1) -} - -function getDocument(pageId) { - var page = getCurrentPages().find(function (page) { - return page.$page.id === pageId +for (var A = [], D = 0; D < 256; ++D) A[D] = (D + 256).toString(16).substr(1) +function N(e) { + var t = getCurrentPages().find(function (t) { + return t.$page.id === e }) - if (!page) { - throw Error('page[' + pageId + '] not found') - } - var weex = page.$vm._$weex - if (!weex.document.__$weex__) { - weex.document.__$weex__ = weex - } - return weex.document + if (!t) throw Error('page[' + e + '] not found') + var n = t.$vm._$weex + return n.document.__$weex__ || (n.document.__$weex__ = n), n.document } -var TAGS = {} -var U_TAGS = {} +var k = {}, + q = {} ;['text', 'image', 'input', 'textarea', 'video', 'web-view', 'slider'].forEach( - function (tag) { - TAGS[tag] = true - U_TAGS['u-' + tag] = true + function (e) { + ;(k[e] = !0), (q['u-' + e] = !0) } ) -var BUILITIN = [ - 'movable-view', - 'picker', - 'ad', - 'button', - 'checkbox-group', - 'checkbox', - 'form', - 'icon', - 'label', - 'movable-area', - 'navigator', - 'picker-view-column', - 'picker-view', - 'progress', - 'radio-group', - 'radio', - 'rich-text', - 'u-slider', - 'swiper-item', - 'swiper', - 'switch', -] -var BUILITIN_ALIAS = BUILITIN.map(function (tag) { - return capitalize(camelize(tag)) -}) -function transTagName(el) { - var tagName = el.type - if (U_TAGS[tagName]) { - return tagName.replace('u-', '') - } - var componentName = el.__vue__ && el.__vue__.$options.name - if (componentName === 'USlider') { - return 'slider' - } - if (componentName && BUILITIN_ALIAS.indexOf(componentName) !== -1) { - return hyphenate(componentName) - } - return tagName -} -function transEl(el) { - var elem = { - elementId: el.nodeId, - tagName: transTagName(el), - nvue: true, - } - var vm = el.__vue__ - if (vm && !vm.$options.isReserved) { - elem.nodeId = vm._uid - } - if (elem.tagName === 'video') { - elem.videoId = elem.nodeId - } - return elem -} -function querySelectorByFn(node, match, result) { - var children = node.children - for (var i = 0; i < children.length; i++) { - var childNode = children[i] - if (match(childNode)) { - if (result) { - result.push(childNode) - } else { - return childNode - } - } - if (result) { - querySelectorByFn(childNode, match, result) - } else { - var res = querySelectorByFn(childNode, match, result) - if (res) { - return res - } - } - } - return result -} -function querySelector(context, selector, result) { - var matchSelector - var match - if (selector.indexOf('#') === 0) { - matchSelector = selector.substr(1) - match = function (node) { - return node.attr && node.attr.id === matchSelector - } - } else if (selector.indexOf('.') === 0) { - matchSelector = selector.substr(1) - match = function (node) { - return node.classList && node.classList.indexOf(matchSelector) !== -1 - } - } - if (match) { - var ret_1 = querySelectorByFn(context, match, result) - if (!ret_1) { - throw Error('Node(' + selector + ') not exists') - } - return ret_1 - } - if (selector === 'body') { - return Object.assign({}, context, { type: 'page' }) - } - if (selector.indexOf('uni-') === 0) { - selector = selector.replace('uni-', '') - } - var tagName = TAGS[selector] ? 'u-' + selector : selector - var aliasTagName = - BUILITIN.indexOf(tagName) !== -1 ? capitalize(camelize(tagName)) : '' - var ret = querySelectorByFn( - context, - function (node) { - return ( - node.type === tagName || - (aliasTagName && - node.__vue__ && - node.__vue__.$options.name === aliasTagName) - ) - }, - result +var j = [ + 'movable-view', + 'picker', + 'ad', + 'button', + 'checkbox-group', + 'checkbox', + 'form', + 'icon', + 'label', + 'movable-area', + 'navigator', + 'picker-view-column', + 'picker-view', + 'progress', + 'radio-group', + 'radio', + 'rich-text', + 'u-slider', + 'swiper-item', + 'swiper', + 'switch', + ], + R = j.map(function (e) { + return s(a(e)) + }) +function V(e) { + var t = e.type + if (q[t]) return t.replace('u-', '') + var n = e.__vue__ && e.__vue__.$options.name + return 'USlider' === n ? 'slider' : n && -1 !== R.indexOf(n) ? i(n) : t +} +function L(e) { + var t = { elementId: e.nodeId, tagName: V(e), nvue: !0 }, + n = e.__vue__ + return ( + n && !n.$options.isReserved && (t.nodeId = n._uid), + 'video' === t.tagName && (t.videoId = t.nodeId), + t ) - if (!ret) { - throw Error('Node(' + selector + ') not exists') - } - return ret } -var DOM_PROPERTIES = [ +function B(e, t, n) { + for (var r = e.children, o = 0; o < r.length; o++) { + var u = r[o] + if (t(u)) { + if (!n) return u + n.push(u) + } + if (n) B(u, t, n) + else { + var i = B(u, t, n) + if (i) return i + } + } + return n +} +function H(e, t, n) { + var r, o + if ( + (0 === t.indexOf('#') + ? ((r = t.substr(1)), + (o = function (e) { + return e.attr && e.attr.id === r + })) + : 0 === t.indexOf('.') && + ((r = t.substr(1)), + (o = function (e) { + return e.classList && -1 !== e.classList.indexOf(r) + })), + o) + ) { + var u = B(e, o, n) + if (!u) throw Error('Node(' + t + ') not exists') + return u + } + if ('body' === t) return Object.assign({}, e, { type: 'page' }) + 0 === t.indexOf('uni-') && (t = t.replace('uni-', '')) + var i = k[t] ? 'u-' + t : t, + c = -1 !== j.indexOf(i) ? s(a(i)) : '', + f = B( + e, + function (e) { + return e.type === i || (c && e.__vue__ && e.__vue__.$options.name === c) + }, + n + ) + if (!f) throw Error('Node(' + t + ') not exists') + return f +} +var U = [ { - test: function (names) { + test: function (e) { return ( - names.length === 2 && - names.indexOf('document.documentElement.scrollWidth') !== -1 && - names.indexOf('document.documentElement.scrollHeight') !== -1 + 2 === e.length && + -1 !== e.indexOf('document.documentElement.scrollWidth') && + -1 !== e.indexOf('document.documentElement.scrollHeight') ) }, - call: function (node) { - var weex = node.__$weex__ || node.ownerDocument.__$weex__ - return new Promise(function (resolve) { - if (node.type === 'scroll-view' && node.children.length === 1) { - node = node.children[0] - } - weex.requireModule('dom').getComponentRect(node.ref, function (res) { - if (res.result) { - resolve([res.size.width, res.size.height]) - } else { - resolve([0, 0]) - } - }) + call: function (e) { + var t = e.__$weex__ || e.ownerDocument.__$weex__ + return new Promise(function (n) { + 'scroll-view' === e.type && + 1 === e.children.length && + (e = e.children[0]), + t.requireModule('dom').getComponentRect(e.ref, function (e) { + e.result ? n([e.size.width, e.size.height]) : n([0, 0]) + }) }) }, }, { - test: function (names) { - return ( - names.length === 1 && names[0] === 'document.documentElement.scrollTop' - ) - }, - call: function (node) { - var weex = node.__$weex__ || node.ownerDocument.__$weex__ - return new Promise(function (resolve) { - if (node.type === 'scroll-view' && node.children.length === 1) { - node = node.children[0] - } - weex.requireModule('dom').getComponentRect(node.ref, function (res) { - resolve([(res.size && Math.abs(res.size.top)) || 0]) - }) + test: function (e) { + return 1 === e.length && 'document.documentElement.scrollTop' === e[0] + }, + call: function (e) { + var t = e.__$weex__ || e.ownerDocument.__$weex__ + return new Promise(function (n) { + 'scroll-view' === e.type && + 1 === e.children.length && + (e = e.children[0]), + t.requireModule('dom').getComponentRect(e.ref, function (e) { + n([(e.size && Math.abs(e.size.top)) || 0]) + }) }) }, }, { - test: function (names) { + test: function (e) { return ( - names.length === 2 && - names.indexOf('offsetWidth') !== -1 && - names.indexOf('offsetHeight') !== -1 + 2 === e.length && + -1 !== e.indexOf('offsetWidth') && + -1 !== e.indexOf('offsetHeight') ) }, - call: function (node) { - var weex = node.__$weex__ || node.ownerDocument.__$weex__ - return new Promise(function (resolve) { - weex.requireModule('dom').getComponentRect(node.ref, function (res) { - if (res.result) { - resolve([res.size.width, res.size.height]) - } else { - resolve([0, 0]) - } + call: function (e) { + var t = e.__$weex__ || e.ownerDocument.__$weex__ + return new Promise(function (n) { + t.requireModule('dom').getComponentRect(e.ref, function (e) { + e.result ? n([e.size.width, e.size.height]) : n([0, 0]) }) }) }, }, { - test: function (names, node) { - return names.length === 1 && names[0] === 'innerText' + test: function (e, t) { + return 1 === e.length && 'innerText' === e[0] }, - call: function (node) { - return Promise.resolve([toText(node, []).join('')]) + call: function (e) { + return Promise.resolve([X(e, []).join('')]) }, }, ] -function toText(node, res) { - if (node.type === 'u-text') { - res.push(node.attr.value) - } else { - node.pureChildren.map(function (child) { - return toText(child, res) - }) - } - return res -} -function formatHTML(html) { - return html.replace(/\n/g, '').replace(/' + formatHTML(toHTML(node, 'inner')) + '' - } - return formatHTML(node.toString()) - } - return formatHTML( - node.pureChildren - .map(function (child) { - return child.toString() - }) - .join('') +function X(e, t) { + return ( + 'u-text' === e.type + ? t.push(e.attr.value) + : e.pureChildren.map(function (e) { + return X(e, t) + }), + t ) } -var FUNCTIONS = { +function W(e) { + return e.replace(/\n/g, '').replace(/' + W(z(e, 'inner')) + '' + : W(e.toString()) + : W( + e.pureChildren + .map(function (e) { + return e.toString() + }) + .join('') + ) +} +var J = { input: { - input: function (el, value) { - el.setValue(value) + input: function (e, t) { + e.setValue(t) }, }, textarea: { - input: function (el, value) { - el.setValue(value) + input: function (e, t) { + e.setValue(t) }, }, 'scroll-view': { - scrollTo: function (el, x, y) { - // TODO - el.scrollTo(y) + scrollTo: function (e, t, n) { + e.scrollTo(n) }, - scrollTop: function (el) { - // TODO + scrollTop: function (e) { return 0 }, - scrollLeft: function (el) { - // TODO + scrollLeft: function (e) { return 0 }, - scrollWidth: function (el) { - // TODO + scrollWidth: function (e) { return 0 }, - scrollHeight: function (el) { - // TODO + scrollHeight: function (e) { return 0 }, }, swiper: { - swipeTo: function (el, index) { - el.__vue__.current = index + swipeTo: function (e, t) { + e.__vue__.current = t }, }, 'movable-view': { - moveTo: function (el, x, y) { - var vm = el.__vue__ - vm.x = x - vm.y = y + moveTo: function (e, t, n) { + var r = e.__vue__ + ;(r.x = t), (r.y = n) }, }, switch: { - tap: function (el) { - var vm = el.__vue__ - vm.checked = !vm.checked + tap: function (e) { + var t = e.__vue__ + t.checked = !t.checked }, }, slider: { - slideTo: function (el, value) { - el.__vue__.value = value + slideTo: function (e, t) { + e.__vue__.value = t }, }, } -function getRoot(pageId) { - var doc = getDocument(pageId) - return doc.body +function F(e) { + return N(e).body } -var adapter = { - getWindow: function (pageId) { - return getRoot(pageId) +var K = { + getWindow: function (e) { + return F(e) }, - getDocument: function (pageId) { - return getRoot(pageId) + getDocument: function (e) { + return F(e) }, - getEl: function (elementId, pageId) { - var doc = getDocument(pageId) - var element = doc.getRef(elementId) - if (!element) { - throw Error('element destroyed') - } - return element + getEl: function (e, t) { + var n = N(t).getRef(e) + if (!n) throw Error('element destroyed') + return n }, - getOffset: function (node) { - var weex = node.__$weex__ || node.ownerDocument.__$weex__ - return new Promise(function (resolve) { - weex.requireModule('dom').getComponentRect(node.ref, function (res) { - if (res.result) { - resolve({ - left: res.size.left, - top: res.size.top, - }) - } else { - resolve({ - left: 0, - top: 0, - }) - } + getOffset: function (e) { + var t = e.__$weex__ || e.ownerDocument.__$weex__ + return new Promise(function (n) { + t.requireModule('dom').getComponentRect(e.ref, function (e) { + e.result + ? n({ left: e.size.left, top: e.size.top }) + : n({ left: 0, top: 0 }) }) }) }, - querySelector: function (context, selector) { - return Promise.resolve(transEl(querySelector(context, selector))) + querySelector: function (e, t) { + return Promise.resolve(L(H(e, t))) }, - querySelectorAll: function (context, selector) { + querySelectorAll: function (e, t) { return Promise.resolve({ - elements: querySelector(context, selector, []).map(function (el) { - return transEl(el) + elements: H(e, t, []).map(function (e) { + return L(e) }), }) }, - queryProperties: function (context, names) { - var options = DOM_PROPERTIES.find(function (options) { - return options.test(names, context) - }) - if (options) { - return options.call(context).then(function (properties) { - return { - properties: properties, - } - }) - } - return Promise.resolve({ - properties: names.map(function (name) { - return getDataByPath(context, name) - }), + queryProperties: function (e, t) { + var n = U.find(function (n) { + return n.test(t, e) }) + return n + ? n.call(e).then(function (e) { + return { properties: e } + }) + : Promise.resolve({ + properties: t.map(function (t) { + return d(e, t) + }), + }) }, - queryAttributes: function (context, names) { - var attr = context.attr + queryAttributes: function (e, t) { + var n = e.attr return Promise.resolve({ - attributes: names.map(function (name) { - if (name === 'class') { - return (context.classList || []).join(' ') - } - return String(attr[name] || attr[camelize(name)] || '') + attributes: t.map(function (t) { + return 'class' === t + ? (e.classList || []).join(' ') + : String(n[t] || n[a(t)] || '') }), }) }, - queryStyles: function (context, names) { - var style = context.style + queryStyles: function (e, t) { + var n = e.style return Promise.resolve({ - styles: names.map(function (name) { - return style[name] + styles: t.map(function (e) { + return n[e] }), }) }, - queryHTML: function (context, type) { - return Promise.resolve({ - html: toHTML(context, type), - }) + queryHTML: function (e, t) { + return Promise.resolve({ html: z(e, t) }) }, - dispatchTapEvent: function (el) { - el.fireEvent( - 'click', - { - timeStamp: Date.now(), - target: el, - currentTarget: el, - }, - true + dispatchTapEvent: function (e) { + return ( + e.fireEvent( + 'click', + { timeStamp: Date.now(), target: e, currentTarget: e }, + !0 + ), + Promise.resolve() ) - return Promise.resolve() }, - dispatchLongpressEvent: function (el) { - el.fireEvent( - 'longpress', - { - timeStamp: Date.now(), - target: el, - currentTarget: el, - }, - true + dispatchLongpressEvent: function (e) { + return ( + e.fireEvent( + 'longpress', + { timeStamp: Date.now(), target: e, currentTarget: e }, + !0 + ), + Promise.resolve() ) - return Promise.resolve() }, - dispatchTouchEvent: function (el, type, eventInitDict) { - if (!eventInitDict) { - eventInitDict = {} - } - if (!eventInitDict.touches) { - eventInitDict.touches = [] - } - if (!eventInitDict.changedTouches) { - eventInitDict.changedTouches = [] - } - if (!eventInitDict.touches.length) { - eventInitDict.touches.push({ - identifier: Date.now(), - target: el, - }) - } - el.fireEvent( - type, - Object.assign( - { - timeStamp: Date.now(), - target: el, - currentTarget: el, - }, - eventInitDict + dispatchTouchEvent: function (e, t, n) { + return ( + n || (n = {}), + n.touches || (n.touches = []), + n.changedTouches || (n.changedTouches = []), + n.touches.length || n.touches.push({ identifier: Date.now(), target: e }), + e.fireEvent( + t, + Object.assign( + { timeStamp: Date.now(), target: e, currentTarget: e }, + n + ), + !0 ), - true + Promise.resolve() ) - return Promise.resolve() }, - callFunction: function (el, functionName, args) { - var fn = getDataByPath(FUNCTIONS, functionName) - if (!fn) { - return Promise.reject(Error(functionName + ' not exists')) - } - return Promise.resolve({ - result: fn.apply(null, __spreadArrays([el], args)), - }) - }, - triggerEvent: function (el, type, detail) { - var vm = el.__vue__ - if (vm) { - vm.$trigger && vm.$trigger(type, {}, detail) - } else { - el.fireEvent( - type, - { - timeStamp: Date.now(), - target: el, - currentTarget: el, - }, - false, - { params: [{ detail: detail }] } - ) - } - return Promise.resolve() + callFunction: function (e, t, n) { + var r = d(J, t) + return r + ? Promise.resolve({ result: r.apply(null, M([e], n)) }) + : Promise.reject(Error(t + ' not exists')) + }, + triggerEvent: function (e, t, n) { + var r = e.__vue__ + return ( + r + ? r.$trigger && r.$trigger(t, {}, n) + : e.fireEvent( + t, + { timeStamp: Date.now(), target: e, currentTarget: e }, + !1, + { params: [{ detail: n }] } + ), + Promise.resolve() + ) }, } - -function initNativeApi() { - return Object.assign({}, initPage(adapter), initElement(adapter)) -} - -var Api = {} -Object.keys(App).forEach(function (method) { - Api['App.' + method] = App[method] -}) -Object.keys(Page).forEach(function (method) { - Api['Page.' + method] = Page[method] -}) -Object.keys(Element).forEach(function (method) { - Api['Element.' + method] = Element[method] -}) -var wsEndpoint = process.env.UNI_AUTOMATOR_WS_ENDPOINT -var NVueApi -var fallback -var socketTask -//@ts-ignore -{ - fallback = function (id, method, params, data) { - var pageId = params.pageId - var page = findPageByPageId(pageId) - if (!page) { - data.error = { - message: 'page[' + pageId + '] not exists', - } - send(data) - return true - } - var isNVue = !!page.$page.meta.isNVue - //@ts-ignore - if (!isNVue) { - UniServiceJSBridge.publishHandler( - 'sendAutoMessage', - { - id: id, - method: method, - params: params, - }, - pageId - ) - return true - } - if (!NVueApi) { - NVueApi = initNativeApi() - } - return NVueApi[method] - } - UniServiceJSBridge.subscribe('onAutoMessageReceive', function (res) { - send(res) +var Q = {} +Object.keys($).forEach(function (e) { + Q['App.' + e] = $[e] +}), + Object.keys(b).forEach(function (e) { + Q['Page.' + e] = b[e] + }), + Object.keys(C).forEach(function (e) { + Q['Element.' + e] = C[e] }) -} -function send(data) { - socketTask.send({ data: JSON.stringify(data) }) -} -function findPageByPageId(pageId) { - var pages = getCurrentPages() - if (!pageId) { - return pages[pages.length - 1] - } - return pages.find(function (page) { - return page.$page.id === pageId - }) -} -function onMessage(res) { - var _a = JSON.parse(res.data), - id = _a.id, - method = _a.method, - params = _a.params - var data = { id: id } - var fn = Api[method] - if (!fn) { - if (fallback) { - var result = fallback(id, method, params, data) - if (result === true) { - return - } - fn = result - } - if (!fn) { - data.error = { - message: method + ' unimplemented', - } - return send(data) - } +var Y, + Z, + G, + ee = process.env.UNI_AUTOMATOR_WS_ENDPOINT +function te(e) { + G.send({ data: JSON.stringify(e) }) +} +function ne(e) { + var t = JSON.parse(e.data), + n = t.id, + r = t.method, + o = t.params, + u = { id: n }, + i = Q[r] + if (!i) { + if (Z) { + var c = Z(n, r, o, u) + if (!0 === c) return + i = c + } + if (!i) return (u.error = { message: r + ' unimplemented' }), te(u) } try { - fn(params) - .then(function (res) { - res && (data.result = res) + i(o) + .then(function (e) { + e && (u.result = e) }) - .catch(function (err) { - data.error = { - message: err.message, - } + .catch(function (e) { + u.error = { message: e.message } }) .finally(function () { - send(data) + te(u) }) - } catch (err) { - data.error = { - message: err.message, - } - send(data) + } catch (e) { + ;(u.error = { message: e.message }), te(u) } } -function initRuntimeAutomator(options) { - if (options === void 0) { - options = {} - } - socketTask = uni.connectSocket({ - url: wsEndpoint, - complete: function () {}, - }) - socketTask.onMessage(onMessage) - socketTask.onOpen(function (res) { - options.success && options.success() - console.log('已开启自动化测试...') - }) - socketTask.onError(function (res) { - console.log('automator.onError', res) - }) - socketTask.onClose(function () { - options.fail && options.fail({ errMsg: '$$initRuntimeAutomator:fail' }) - console.log('automator.onClose') - }) -} -//@ts-ignore -{ +;(Z = function (e, t, n, r) { + var o = n.pageId, + u = (function (e) { + var t = getCurrentPages() + if (!e) return t[t.length - 1] + return t.find(function (t) { + return t.$page.id === e + }) + })(o) + return u + ? !u.$page.meta.isNVue + ? (UniServiceJSBridge.publishHandler( + 'sendAutoMessage', + { id: e, method: t, params: n }, + o + ), + !0) + : (Y || + (Y = Object.assign( + {}, + (function (e) { + return { + 'Page.getElement': function (t) { + return e.querySelector(e.getDocument(t.pageId), t.selector) + }, + 'Page.getElements': function (t) { + return e.querySelectorAll(e.getDocument(t.pageId), t.selector) + }, + 'Page.getWindowProperties': function (t) { + return e.queryProperties(e.getWindow(t.pageId), t.names) + }, + } + })(K), + (function (e) { + var t = function (t) { + return e.getEl(t.elementId, t.pageId) + } + return { + 'Element.getElement': function (n) { + return e.querySelector(t(n), n.selector) + }, + 'Element.getElements': function (n) { + return e.querySelectorAll(t(n), n.selector) + }, + 'Element.getDOMProperties': function (n) { + return e.queryProperties(t(n), n.names) + }, + 'Element.getProperties': function (n) { + var r = t(n), + o = r.__vue__ || r.attr || {} + return e.queryProperties(o, n.names) + }, + 'Element.getOffset': function (n) { + return e.getOffset(t(n)) + }, + 'Element.getAttributes': function (n) { + return e.queryAttributes(t(n), n.names) + }, + 'Element.getStyles': function (n) { + return e.queryStyles(t(n), n.names) + }, + 'Element.getHTML': function (n) { + return e.queryHTML(t(n), n.type) + }, + 'Element.tap': function (n) { + return e.dispatchTapEvent(t(n)) + }, + 'Element.longpress': function (n) { + return e.dispatchLongpressEvent(t(n)) + }, + 'Element.touchstart': function (n) { + return e.dispatchTouchEvent(t(n), 'touchstart', n) + }, + 'Element.touchmove': function (n) { + return e.dispatchTouchEvent(t(n), 'touchmove', n) + }, + 'Element.touchend': function (n) { + return e.dispatchTouchEvent(t(n), 'touchend', n) + }, + 'Element.callFunction': function (n) { + return e.callFunction(t(n), n.functionName, n.args) + }, + 'Element.triggerEvent': function (n) { + return e.triggerEvent(t(n), n.type, n.detail) + }, + } + })(K) + )), + Y[t]) + : ((r.error = { message: 'page[' + o + '] not exists' }), te(r), !0) +}), + UniServiceJSBridge.subscribe('onAutoMessageReceive', function (e) { + te(e) + }), setTimeout(function () { - // (global as any).testMessage = onMessage; - initRuntimeAutomator() + var e + void 0 === e && (e = {}), + (G = uni.connectSocket({ url: ee, complete: function () {} })).onMessage( + ne + ), + G.onOpen(function (t) { + e.success && e.success(), console.log('已开启自动化测试...') + }), + G.onError(function (e) { + console.log('automator.onError', e) + }), + G.onClose(function () { + e.fail && e.fail({ errMsg: '$$initRuntimeAutomator:fail' }), + console.log('automator.onClose') + }) }, 500) -} diff --git a/packages/uni-app-plus/lib/uni.automator.js b/packages/uni-app-plus/lib/uni.automator.js index 40156ff82..b928c2ede 100644 --- a/packages/uni-app-plus/lib/uni.automator.js +++ b/packages/uni-app-plus/lib/uni.automator.js @@ -1,259 +1,206 @@ 'use strict' - -function _interopDefault(ex) { - return ex && typeof ex === 'object' && 'default' in ex ? ex['default'] : ex +function t(t) { + return t && 'object' == typeof t && 'default' in t ? t.default : t } - -var fs = _interopDefault(require('fs')) -var debug = _interopDefault(require('debug')) -var parser = _interopDefault(require('postcss-selector-parser')) -var fs$1 = _interopDefault(require('fs-extra')) -var dateFormat = _interopDefault(require('licia/dateFormat')) -var path = require('path') -var util = require('util') -require('address') -require('default-gateway') -require('licia/isStr') -require('licia/getPort') - -function transform(selectors) { - selectors.walk((selector) => { - if (selector.type === 'tag') { - const value = selector.value - if (value === 'page') { - //@ts-ignore - { - selector.value = 'body' - } - } else { - selector.value = 'uni-' + value - } +var e = t(require('fs')), + s = t(require('debug')), + i = t(require('postcss-selector-parser')), + r = t(require('fs-extra')), + a = t(require('licia/dateFormat')), + n = require('path'), + o = require('util') +require('address'), + require('default-gateway'), + require('licia/isStr'), + require('licia/getPort') +s('automator:devtool') +function l(t) { + t.walk((t) => { + if ('tag' === t.type) { + const e = t.value + t.value = 'page' === e ? 'body' : 'uni-' + e } }) } -function transSelector(method) { - return { - reflect: async (send, params) => send(method, params, false), - params(params) { - if (params.selector) { - params.selector = parser(transform).processSync(params.selector) - } - return params - }, - } -} -const methods = [ +const c = [ 'Page.getElement', 'Page.getElements', 'Element.getElement', 'Element.getElements', ] -function initAdapter(adapter) { - methods.forEach((method) => { - adapter[method] = transSelector(method) - }) -} - -const qrCodeTerminal = require('qrcode-terminal') -const QrCodeReader = require('qrcode-reader') -const isWin = /^win/.test(process.platform) -const normalizePath = (path) => (isWin ? path.replace(/\\/g, '/') : path) - -const debugLauncher = debug('automator:launcher') -const APPID = 'HBuilder' -const PACKAGE = 'io.dcloud.HBuilder' -const readdir = util.promisify(fs.readdir) -const stat = util.promisify(fs.stat) -async function getFiles(dir) { - const subdirs = await readdir(dir) - const files = await Promise.all( - subdirs.map(async (subdir) => { - const res = path.resolve(dir, subdir) - return (await stat(res)).isDirectory() ? getFiles(res) : res - }) - ) - return files.reduce((a, f) => a.concat(f), []) -} -class Launcher { - constructor(options) { - this.id = options.id - this.app = options.executablePath - this.appid = options.appid || APPID - this.package = options.package || PACKAGE +require('qrcode-terminal'), require('qrcode-reader') +const h = /^win/.test(process.platform), + u = s('automator:launcher'), + d = o.promisify(e.readdir), + p = o.promisify(e.stat) +class m { + constructor(t) { + ;(this.id = t.id), + (this.app = t.executablePath), + (this.appid = t.appid || 'HBuilder'), + (this.package = t.package || 'io.dcloud.HBuilder') } shouldPush() { return this.exists(this.FILE_APP_SERVICE) - .then(() => { - debugLauncher( - `${dateFormat('yyyy-mm-dd HH:MM:ss:l')} ${ - this.FILE_APP_SERVICE - } exists` + .then( + () => ( + u(`${a('yyyy-mm-dd HH:MM:ss:l')} ${this.FILE_APP_SERVICE} exists`), !1 ) - return false - }) - .catch(() => { - debugLauncher( - `${dateFormat('yyyy-mm-dd HH:MM:ss:l')} ${ - this.FILE_APP_SERVICE - } not exists` + ) + .catch( + () => ( + u( + `${a('yyyy-mm-dd HH:MM:ss:l')} ${this.FILE_APP_SERVICE} not exists` + ), + !0 ) - return true - }) + ) } - push(from) { - return getFiles(from) - .then((files) => { - const pushs = files.map((file) => { - const to = normalizePath( - path.join(this.DIR_WWW, path.relative(from, file)) + push(t) { + return (async function t(e) { + const s = await d(e) + return ( + await Promise.all( + s.map(async (s) => { + const i = n.resolve(e, s) + return (await p(i)).isDirectory() ? t(i) : i + }) + ) + ).reduce((t, e) => t.concat(e), []) + })(t) + .then((e) => { + const s = e.map((e) => { + const s = ((t) => (h ? t.replace(/\\/g, '/') : t))( + n.join(this.DIR_WWW, n.relative(t, e)) ) - debugLauncher( - `${dateFormat('yyyy-mm-dd HH:MM:ss:l')} push ${file} ${to}` + return ( + u(`${a('yyyy-mm-dd HH:MM:ss:l')} push ${e} ${s}`), + this.pushFile(e, s) ) - return this.pushFile(file, to) }) - return Promise.all(pushs) + return Promise.all(s) }) - .then((res) => true) + .then((t) => !0) } get FILE_APP_SERVICE() { - return `${this.DIR_WWW}/app-service.js` + return this.DIR_WWW + '/app-service.js' } } - -const debugClient = debug('automator:simctl') -function padZero(str) { - const num = parseInt(str) - return num > 9 ? String(num) : '0' + num +const y = s('automator:simctl') +function f(t) { + const e = parseInt(t) + return e > 9 ? String(e) : '0' + e } -class IOS extends Launcher { +class g extends m { constructor() { - super(...arguments) - this.bundleVersion = '' + super(...arguments), (this.bundleVersion = '') } async init() { - const Simctl = require('node-simctl').Simctl - this.tool = new Simctl({ udid: this.id }) + const t = require('node-simctl').Simctl + this.tool = new t({ udid: this.id }) try { await this.tool.bootDevice() - } catch (e) {} - await this.initSDCard() - debugClient(`${dateFormat('yyyy-mm-dd HH:MM:ss:l')} init ${this.id}`) + } catch (t) {} + await this.initSDCard(), y(`${a('yyyy-mm-dd HH:MM:ss:l')} init ${this.id}`) } async initSDCard() { - const appInfo = await this.tool.appInfo(this.package) - debugClient(`${dateFormat('yyyy-mm-dd HH:MM:ss:l')} appInfo ${appInfo}`) - const matches = appInfo.match(/DataContainer\s+=\s+"(.*)"/) - if (!matches) { - return Promise.resolve('') - } - const versionMatches = appInfo.match(/CFBundleVersion\s+=\s+(.*);/) - if (!versionMatches) { - return Promise.resolve('') - } - this.sdcard = matches[1].replace('file:', '') - this.bundleVersion = versionMatches[1] - debugClient(`${dateFormat('yyyy-mm-dd HH:MM:ss:l')} install ${this.sdcard}`) + const t = await this.tool.appInfo(this.package) + y(`${a('yyyy-mm-dd HH:MM:ss:l')} appInfo ${t}`) + const e = t.match(/DataContainer\s+=\s+"(.*)"/) + if (!e) return Promise.resolve('') + const s = t.match(/CFBundleVersion\s+=\s+(.*);/) + if (!s) return Promise.resolve('') + ;(this.sdcard = e[1].replace('file:', '')), + (this.bundleVersion = s[1]), + y(`${a('yyyy-mm-dd HH:MM:ss:l')} install ${this.sdcard}`) } async version() { return Promise.resolve(this.bundleVersion) } - formatVersion(version) { - const versions = version.split('.') - if (versions.length !== 3) { - return version - } - return versions[0] + padZero(versions[1]) + padZero(versions[2]) + formatVersion(t) { + const e = t.split('.') + return 3 !== e.length ? t : e[0] + f(e[1]) + f(e[2]) } async install() { - debugClient(`${dateFormat('yyyy-mm-dd HH:MM:ss:l')} install ${this.app}`) - await this.tool.installApp(this.app) - await this.tool.grantPermission(this.package, 'all') - await this.initSDCard() - return Promise.resolve(true) + return ( + y(`${a('yyyy-mm-dd HH:MM:ss:l')} install ${this.app}`), + await this.tool.installApp(this.app), + await this.tool.grantPermission(this.package, 'all'), + await this.initSDCard(), + Promise.resolve(!0) + ) } async start() { try { - await this.tool.terminateApp(this.package) - await this.tool.launchApp(this.package) - } catch (e) {} - return Promise.resolve(true) + await this.tool.terminateApp(this.package), + await this.tool.launchApp(this.package) + } catch (t) {} + return Promise.resolve(!0) } async exit() { - await this.tool.terminateApp(this.package) - await this.tool.shutdownDevice() - return Promise.resolve(true) + return ( + await this.tool.terminateApp(this.package), + await this.tool.shutdownDevice(), + Promise.resolve(!0) + ) } async captureScreenshot() { return Promise.resolve(await this.tool.getScreenshot()) } - exists(file) { - return fs$1.existsSync(file) - ? Promise.resolve(true) - : Promise.reject(Error(`${file} not exists`)) + exists(t) { + return r.existsSync(t) + ? Promise.resolve(!0) + : Promise.reject(Error(t + ' not exists')) } - pushFile(from, to) { - return Promise.resolve(fs$1.copySync(from, to)) + pushFile(t, e) { + return Promise.resolve(r.copySync(t, e)) } get DIR_WWW() { return `${this.sdcard}/Documents/Pandora/apps/${this.appid}/www/` } } - -const adb = require('adbkit') -const debugClient$1 = debug('automator:adb') -const $EXTERNAL_STORAGE = '$EXTERNAL_STORAGE' -class Android extends Launcher { +const w = require('adbkit'), + M = s('automator:adb') +class P extends m { async init() { - // adbkit 异常时,可能不会关闭 socket - this.tool = adb.createClient() - if (!this.id) { - const devices = await this.tool.listDevices() - if (!devices.length) { - throw Error(`Device not found`) - } - this.id = devices[0].id + if (((this.tool = w.createClient()), !this.id)) { + const t = await this.tool.listDevices() + if (!t.length) throw Error('Device not found') + this.id = t[0].id } - this.sdcard = (await this.shell(this.COMMAND_EXTERNAL)).trim() - debugClient$1( - `${dateFormat('yyyy-mm-dd HH:MM:ss:l')} init ${this.id} ${this.sdcard}` - ) + ;(this.sdcard = (await this.shell(this.COMMAND_EXTERNAL)).trim()), + M(`${a('yyyy-mm-dd HH:MM:ss:l')} init ${this.id} ${this.sdcard}`) } version() { - return this.shell(this.COMMAND_VERSION).then((output) => { - const matches = output.match(/versionName=(.*)/) - if (matches && matches.length > 1) { - return matches[1] - } - return '' + return this.shell(this.COMMAND_VERSION).then((t) => { + const e = t.match(/versionName=(.*)/) + return e && e.length > 1 ? e[1] : '' }) } - formatVersion(version) { - return version + formatVersion(t) { + return t } async install() { - let grant = true + let t = !0 try { - const props = await this.tool.getProperties(this.id) - const version = props['ro.build.version.release'].split('.')[0] - if (parseInt(version) < 6) { - grant = false - } - } catch (e) {} - debugClient$1( - `${dateFormat('yyyy-mm-dd HH:MM:ss:l')} install ${ - this.app - } permission=${grant}` - ) - if (grant) { - const Command = require('adbkit/lib/adb/command.js') - const oldSend = Command.prototype._send - Command.prototype._send = function send(data) { - if (data.indexOf('shell:pm install -r ') === 0) { - data = data.replace('shell:pm install -r ', 'shell:pm install -r -g ') - debugClient$1(`${dateFormat('yyyy-mm-dd HH:MM:ss:l')} ${data} `) - } - return oldSend.call(this, data) + const e = (await this.tool.getProperties(this.id))[ + 'ro.build.version.release' + ].split('.')[0] + parseInt(e) < 6 && (t = !1) + } catch (t) {} + if ( + (M(`${a('yyyy-mm-dd HH:MM:ss:l')} install ${this.app} permission=${t}`), + t) + ) { + const t = require('adbkit/lib/adb/command.js'), + e = t.prototype._send + t.prototype._send = function (t) { + return ( + 0 === t.indexOf('shell:pm install -r ') && + ((t = t.replace('shell:pm install -r ', 'shell:pm install -r -g ')), + M(`${a('yyyy-mm-dd HH:MM:ss:l')} ${t} `)), + e.call(this, t) + ) } } return this.tool.install(this.id, this.app).then(() => this.init()) @@ -265,151 +212,126 @@ class Android extends Launcher { return this.shell(this.COMMAND_STOP) } captureScreenshot() { - return this.tool.screencap(this.id).then((stream) => { - return new Promise((resolve) => { - const chunks = [] - stream.on('data', function (chunk) { - chunks.push(chunk) - }) - stream.on('end', function () { - resolve(Buffer.concat(chunks).toString('base64')) + return this.tool.screencap(this.id).then( + (t) => + new Promise((e) => { + const s = [] + t.on('data', function (t) { + s.push(t) + }), + t.on('end', function () { + e(Buffer.concat(s).toString('base64')) + }) }) - }) - }) - } - exists(file) { - return this.tool.stat(this.id, file) - } - pushFile(from, to) { - return this.tool.push(this.id, from, to) + ) } - shell(command) { - debugClient$1(`${dateFormat('yyyy-mm-dd HH:MM:ss:l')} SEND ► ${command}`) - return this.tool - .shell(this.id, command) - .then(adb.util.readAll) - .then((output) => { - const res = output.toString() - debugClient$1(`${dateFormat('yyyy-mm-dd HH:MM:ss:l')} ◀ RECV ${res}`) - return res - }) + exists(t) { + return this.tool.stat(this.id, t) + } + pushFile(t, e) { + return this.tool.push(this.id, t, e) + } + shell(t) { + return ( + M(`${a('yyyy-mm-dd HH:MM:ss:l')} SEND ► ${t}`), + this.tool + .shell(this.id, t) + .then(w.util.readAll) + .then((t) => { + const e = t.toString() + return M(`${a('yyyy-mm-dd HH:MM:ss:l')} ◀ RECV ${e}`), e + }) + ) } get DIR_WWW() { return `${this.sdcard}/Android/data/${this.package}/apps/${this.appid}/www` } get COMMAND_EXTERNAL() { - return `echo ${$EXTERNAL_STORAGE}` + return 'echo $EXTERNAL_STORAGE' } get COMMAND_VERSION() { - return `dumpsys package ${this.package}` + return 'dumpsys package ' + this.package } get COMMAND_STOP() { - return `am force-stop ${this.package}` + return 'am force-stop ' + this.package } get COMMAND_START() { return `am start -n ${this.package}/io.dcloud.PandoraEntry --es ${this.appid} --ez needUpdateApp false --ez reload true` } } - -const debugDevtools = debug('automator:devtool') -let launcher -let install = false -function createLauncher(platform, options) { - if (platform === 'ios') { - return new IOS(options) - } - return new Android(options) -} -const VERSIONS_RE = { - android: /android_version=(.*)/, - ios: /iphone_version=(.*)/, -} -function getVersion(version, platform) { - if (version.endsWith('.txt')) { - try { - const versionStr = fs.readFileSync(version).toString() - const matches = versionStr.match(VERSIONS_RE[platform]) - if (matches) { - return matches[1] - } - } catch (e) { - console.error(e) - } - } - return version -} -async function validateDevtools(options, puppet) { - options.platform = ( - options.platform || process.env.UNI_OS_NAME - ).toLocaleLowerCase() - Object.assign(options, options[options.platform]) - launcher = createLauncher(options.platform, options) - await launcher.init() // check device - const version = await launcher.version() - if (!version) { - install = true - } else if (options.version) { - const newVersion = launcher.formatVersion( - getVersion(options.version, options.platform) - ) - debugDevtools(`version: ${version}`) - debugDevtools(`newVersion: ${newVersion}`) - if (newVersion !== version) { - install = true - } - } - if (install) { - if (!options.executablePath) { - throw Error( - `app-plus->${options.platform}->executablePath is not provided` - ) - } - if (!fs.existsSync(options.executablePath)) { - throw Error(`${options.executablePath} not exists`) - } - } - return options -} -async function createDevtools(projectPath, options, puppet) { - if (install) { - //install - await launcher.install() - } - if (install || puppet.compiled || (await launcher.shouldPush())) { - await launcher.push(projectPath) - } - await launcher.start() -} -const adapter = { - 'Tool.close': { - reflect: async () => {}, - }, - 'App.exit': { - reflect: async () => launcher.exit(), - }, - 'App.enableLog': { - reflect: () => Promise.resolve(), - }, +const v = s('automator:devtool') +let E, + $ = !1 +const S = { android: /android_version=(.*)/, ios: /iphone_version=(.*)/ } +const A = { + 'Tool.close': { reflect: async () => {} }, + 'App.exit': { reflect: async () => E.exit() }, + 'App.enableLog': { reflect: () => Promise.resolve() }, 'App.captureScreenshot': { - reflect: async (send, params) => { - const data = await launcher.captureScreenshot(params) - debugDevtools(`App.captureScreenshot ${data.length}`) - return { - data, - } + reflect: async (t, e) => { + const s = await E.captureScreenshot(e) + return v('App.captureScreenshot ' + s.length), { data: s } }, }, } -initAdapter(adapter) -const puppet = { +!(function (t) { + c.forEach((e) => { + t[e] = (function (t) { + return { + reflect: async (e, s) => e(t, s, !1), + params: (t) => ( + t.selector && (t.selector = i(l).processSync(t.selector)), t + ), + } + })(e) + }) +})(A) +const _ = { devtools: { name: 'App', paths: [], required: ['manifest.json', 'app-service.js'], - validate: validateDevtools, - create: createDevtools, + validate: async function (t, s) { + ;(t.platform = ( + t.platform || process.env.UNI_OS_NAME + ).toLocaleLowerCase()), + Object.assign(t, t[t.platform]), + (E = (function (t, e) { + return 'ios' === t ? new g(e) : new P(e) + })(t.platform, t)), + await E.init() + const i = await E.version() + if (i) { + if (t.version) { + const s = E.formatVersion( + (function (t, s) { + if (t.endsWith('.txt')) + try { + const i = e.readFileSync(t).toString().match(S[s]) + if (i) return i[1] + } catch (t) { + console.error(t) + } + return t + })(t.version, t.platform) + ) + v('version: ' + i), v('newVersion: ' + s), s !== i && ($ = !0) + } + } else $ = !0 + if ($) { + if (!t.executablePath) + throw Error(`app-plus->${t.platform}->executablePath is not provided`) + if (!e.existsSync(t.executablePath)) + throw Error(t.executablePath + ' not exists') + } + return t + }, + create: async function (t, e, s) { + $ && (await E.install()), + ($ || s.compiled || (await E.shouldPush())) && (await E.push(t)), + await E.start() + }, }, - adapter, + adapter: A, } - -module.exports = puppet +module.exports = _ diff --git a/packages/uni-app-vite/lib/template/__uniappautomator.js b/packages/uni-app-vite/lib/template/__uniappautomator.js index 4c1bc618b..3c286dca9 100644 --- a/packages/uni-app-vite/lib/template/__uniappautomator.js +++ b/packages/uni-app-vite/lib/template/__uniappautomator.js @@ -1,530 +1,15 @@ -!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n():"function"==typeof define&&define.amd?define(n):n()}(0,function(){"use strict";function e(e){var n=this.constructor;return this.then(function(t){return n.resolve(e()).then(function(){return t})},function(t){return n.resolve(e()).then(function(){return n.reject(t)})})}function n(e){return!(!e||"undefined"==typeof e.length)}function t(){}function o(e){if(!(this instanceof o))throw new TypeError("Promises must be constructed via new");if("function"!=typeof e)throw new TypeError("not a function");this._state=0,this._handled=!1,this._value=undefined,this._deferreds=[],c(e,this)}function r(e,n){for(;3===e._state;)e=e._value;0!==e._state?(e._handled=!0,o._immediateFn(function(){var t=1===e._state?n.onFulfilled:n.onRejected;if(null!==t){var o;try{o=t(e._value)}catch(r){return void f(n.promise,r)}i(n.promise,o)}else(1===e._state?i:f)(n.promise,e._value)})):e._deferreds.push(n)}function i(e,n){try{if(n===e)throw new TypeError("A promise cannot be resolved with itself.");if(n&&("object"==typeof n||"function"==typeof n)){var t=n.then;if(n instanceof o)return e._state=3,e._value=n,void u(e);if("function"==typeof t)return void c(function(e,n){return function(){e.apply(n,arguments)}}(t,n),e)}e._state=1,e._value=n,u(e)}catch(r){f(e,r)}}function f(e,n){e._state=2,e._value=n,u(e)}function u(e){2===e._state&&0===e._deferreds.length&&o._immediateFn(function(){e._handled||o._unhandledRejectionFn(e._value)});for(var n=0,t=e._deferreds.length;t>n;n++)r(e,e._deferreds[n]);e._deferreds=null}function c(e,n){var t=!1;try{e(function(e){t||(t=!0,i(n,e))},function(e){t||(t=!0,f(n,e))})}catch(o){if(t)return;t=!0,f(n,o)}}var a=setTimeout;o.prototype["catch"]=function(e){return this.then(null,e)},o.prototype.then=function(e,n){var o=new this.constructor(t);return r(this,new function(e,n,t){this.onFulfilled="function"==typeof e?e:null,this.onRejected="function"==typeof n?n:null,this.promise=t}(e,n,o)),o},o.prototype["finally"]=e,o.all=function(e){return new o(function(t,o){function r(e,n){try{if(n&&("object"==typeof n||"function"==typeof n)){var u=n.then;if("function"==typeof u)return void u.call(n,function(n){r(e,n)},o)}i[e]=n,0==--f&&t(i)}catch(c){o(c)}}if(!n(e))return o(new TypeError("Promise.all accepts an array"));var i=Array.prototype.slice.call(e);if(0===i.length)return t([]);for(var f=i.length,u=0;i.length>u;u++)r(u,i[u])})},o.resolve=function(e){return e&&"object"==typeof e&&e.constructor===o?e:new o(function(n){n(e)})},o.reject=function(e){return new o(function(n,t){t(e)})},o.race=function(e){return new o(function(t,r){if(!n(e))return r(new TypeError("Promise.race accepts an array"));for(var i=0,f=e.length;f>i;i++)o.resolve(e[i]).then(t,r)})},o._immediateFn="function"==typeof setImmediate&&function(e){setImmediate(e)}||function(e){a(e,0)},o._unhandledRejectionFn=function(e){void 0!==console&&console&&console.warn("Possible Unhandled Promise Rejection:",e)};var l=function(){if("undefined"!=typeof self)return self;if("undefined"!=typeof window)return window;if("undefined"!=typeof global)return global;throw Error("unable to locate global object")}();"Promise"in l?l.Promise.prototype["finally"]||(l.Promise.prototype["finally"]=e):l.Promise=o}); - -function initPage(adapter) { - return { - "Page.getElement": function (params) { - return adapter.querySelector(adapter.getDocument(params.pageId), params.selector); - }, - "Page.getElements": function (params) { - return adapter.querySelectorAll(adapter.getDocument(params.pageId), params.selector); - }, - "Page.getWindowProperties": function (params) { - return adapter.queryProperties(adapter.getWindow(params.pageId), params.names); - }, - }; -} - -function initElement(adapter) { - var getEl = function (params) { return adapter.getEl(params.elementId, params.pageId); }; - return { - "Element.getElement": function (params) { - return adapter.querySelector(getEl(params), params.selector); - }, - "Element.getElements": function (params) { - return adapter.querySelectorAll(getEl(params), params.selector); - }, - "Element.getDOMProperties": function (params) { - return adapter.queryProperties(getEl(params), params.names); - }, - "Element.getProperties": function (params) { - var el = getEl(params); - var ctx = el.__vue__ || el.attr || {}; - return adapter.queryProperties(ctx, params.names); - }, - "Element.getOffset": function (params) { - return adapter.getOffset(getEl(params)); - }, - "Element.getAttributes": function (params) { - return adapter.queryAttributes(getEl(params), params.names); - }, - "Element.getStyles": function (params) { - return adapter.queryStyles(getEl(params), params.names); - }, - "Element.getHTML": function (params) { - return adapter.queryHTML(getEl(params), params.type); - }, - "Element.tap": function (params) { - return adapter.dispatchTapEvent(getEl(params)); - }, - "Element.longpress": function (params) { - return adapter.dispatchLongpressEvent(getEl(params)); - }, - "Element.touchstart": function (params) { - return adapter.dispatchTouchEvent(getEl(params), "touchstart", params); - }, - "Element.touchmove": function (params) { - return adapter.dispatchTouchEvent(getEl(params), "touchmove", params); - }, - "Element.touchend": function (params) { - return adapter.dispatchTouchEvent(getEl(params), "touchend", params); - }, - "Element.callFunction": function (params) { - return adapter.callFunction(getEl(params), params.functionName, params.args); - }, - "Element.triggerEvent": function (params) { - return adapter.triggerEvent(getEl(params), params.type, params.detail); - }, - }; -} - -/*! ***************************************************************************** -Copyright (c) Microsoft Corporation. All rights reserved. -Licensed 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 - -THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED -WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, -MERCHANTABLITY OR NON-INFRINGEMENT. - -See the Apache Version 2.0 License for specific language governing permissions -and limitations under the License. -***************************************************************************** */ - -function __spreadArrays() { - for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length; - for (var r = Array(s), k = 0, i = 0; i < il; i++) - for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++) - r[k] = a[j]; - return r; -} - -// Unique ID creation requires a high quality random # generator. In the browser we therefore -// require the crypto API and do not support built-in fallback to lower quality random number -// generators (like Math.random()). -// getRandomValues needs to be invoked in a context where "this" is a Crypto implementation. Also, -// find the complete implementation of crypto (msCrypto) on IE11. -var getRandomValues = typeof crypto != 'undefined' && crypto.getRandomValues && crypto.getRandomValues.bind(crypto) || typeof msCrypto != 'undefined' && typeof msCrypto.getRandomValues == 'function' && msCrypto.getRandomValues.bind(msCrypto); -var rnds8 = new Uint8Array(16); // eslint-disable-line no-undef - -function rng() { - if (!getRandomValues) { - throw new Error('crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported'); - } - - return getRandomValues(rnds8); -} - -/** - * Convert array of 16 byte values to UUID string format of the form: - * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX - */ -var byteToHex = []; - -for (var i = 0; i < 256; ++i) { - byteToHex[i] = (i + 0x100).toString(16).substr(1); -} - -function bytesToUuid(buf, offset) { - var i = offset || 0; - var bth = byteToHex; // join used to fix memory issue caused by concatenation: https://bugs.chromium.org/p/v8/issues/detail?id=3175#c4 - - return [bth[buf[i++]], bth[buf[i++]], bth[buf[i++]], bth[buf[i++]], '-', bth[buf[i++]], bth[buf[i++]], '-', bth[buf[i++]], bth[buf[i++]], '-', bth[buf[i++]], bth[buf[i++]], '-', bth[buf[i++]], bth[buf[i++]], bth[buf[i++]], bth[buf[i++]], bth[buf[i++]], bth[buf[i++]]].join(''); -} - -function v4(options, buf, offset) { - var i = buf && offset || 0; - - if (typeof options == 'string') { - buf = options === 'binary' ? new Array(16) : null; - options = null; - } - - options = options || {}; - var rnds = options.random || (options.rng || rng)(); // Per 4.4, set bits for version and `clock_seq_hi_and_reserved` - - rnds[6] = rnds[6] & 0x0f | 0x40; - rnds[8] = rnds[8] & 0x3f | 0x80; // Copy bytes to buffer, if provided - - if (buf) { - for (var ii = 0; ii < 16; ++ii) { - buf[i + ii] = rnds[ii]; - } - } - - return buf || bytesToUuid(rnds); -} - -var hasOwnProperty = Object.prototype.hasOwnProperty; -var hasOwn = function (val, key) { return hasOwnProperty.call(val, key); }; -var isUndef = function (v) { - return v === undefined || v === null; -}; -var isArray = Array.isArray; -var cacheStringFunction = function (fn) { - var cache = Object.create(null); - return (function (str) { - var hit = cache[str]; - return hit || (cache[str] = fn(str)); - }); -}; -var camelizeRE = /-(\w)/g; -var camelize = cacheStringFunction(function (str) { - return str.replace(camelizeRE, function (_, c) { return (c ? c.toUpperCase() : ""); }); -}); -var capitalize = cacheStringFunction(function (str) { - return str.charAt(0).toUpperCase() + str.slice(1); -}); -var PATH_RE = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g; -function getPaths(path, data) { - if (isArray(path)) { - return path; - } - if (data && hasOwn(data, path)) { - return [path]; - } - var res = []; - path.replace(PATH_RE, function (match, p1, offset, string) { - res.push(offset ? string.replace(/\\(\\)?/g, "$1") : p1 || match); - return string; - }); - return res; -} -function getDataByPath(data, path) { - var paths = getPaths(path, data); - var dataPath; - for (dataPath = paths.shift(); !isUndef(dataPath);) { - if (null == (data = data[dataPath])) { - return; - } - dataPath = paths.shift(); - } - return data; -} -function findParent(vm) { - var parent = vm.$parent; - while (parent) { - if (parent._$id) { - return parent; - } - parent = parent.$parent; - } -} -function getVmNodeId(vm) { - //@ts-ignore - { - if (vm._$weex) { - return vm._uid; - } - if (vm._$id) { - return vm._$id; - } - var parent_1 = findParent(vm); - if (!vm.$parent) { - return "-1"; - } - var vnode = vm.$vnode; - var context = vnode.context; - // slot 内的组件,需要补充 context 的 id,否则可能与内部组件索引值一致,导致 id 冲突 - if (context && context !== parent_1 && context._$id) { - return context._$id + ";" + parent_1._$id + "," + vnode.data.attrs._i; - } - return parent_1._$id + "," + vnode.data.attrs._i; - } -} - -var elementMap = new Map(); -function getElId(element) { - var elementId = element._id; - if (!elementId) { - elementId = v4(); - element._id = elementId; - elementMap.set(elementId, { id: elementId, element: element }); - } - return elementId; -} -function isValidEl(el) { - if (el) { - var tagName = el.tagName; - return tagName.indexOf("UNI-") === 0 || tagName === "BODY"; - } - return false; -} -function transEl(el) { - if (!isValidEl(el)) { - throw Error("no such element"); - } - var elem = { - elementId: getElId(el), - tagName: el.tagName.toLocaleLowerCase().replace("uni-", ""), - }; - var vm = el.__vue__; - if (vm) { - if (vm.$parent && vm.$parent.$el === el) { - vm = vm.$parent; - } - if (vm && !vm.$options.isReserved) { - elem.nodeId = getVmNodeId(vm); - } - } - if (elem.tagName === "video") { - elem.videoId = elem.nodeId; - } - return elem; -} -function formatHTML(html) { - return html - .replace(/\n/g, "") - .replace(/(]*>)(]*>[^<]*<\/span>)(.*?<\/uni-text>)/g, "$1$3") - .replace(/<\/?[^>]*>/g, function (replacement) { - if (-1 < replacement.indexOf(""; - } - else if ("" === replacement) { - return ""; - } - else if (0 !== replacement.indexOf("t;t++)o(e,e._deferreds[t]);e._deferreds=null}function a(e,t){var n=!1;try{e((function(e){n||(n=!0,i(t,e))}),(function(e){n||(n=!0,u(t,e))}))}catch(e){if(n)return;n=!0,u(t,e)}}var s=setTimeout;r.prototype.catch=function(e){return this.then(null,e)},r.prototype.then=function(e,t){var r=new this.constructor(n);return o(this,new function(e,t,n){this.onFulfilled="function"==typeof e?e:null,this.onRejected="function"==typeof t?t:null,this.promise=n}(e,t,r)),r},r.prototype.finally=e,r.all=function(e){return new r((function(n,r){function o(e,t){try{if(t&&("object"==typeof t||"function"==typeof t)){var c=t.then;if("function"==typeof c)return void c.call(t,(function(t){o(e,t)}),r)}i[e]=t,0==--u&&n(i)}catch(e){r(e)}}if(!t(e))return r(new TypeError("Promise.all accepts an array"));var i=Array.prototype.slice.call(e);if(0===i.length)return n([]);for(var u=i.length,c=0;i.length>c;c++)o(c,i[c])}))},r.resolve=function(e){return e&&"object"==typeof e&&e.constructor===r?e:new r((function(t){t(e)}))},r.reject=function(e){return new r((function(t,n){n(e)}))},r.race=function(e){return new r((function(n,o){if(!t(e))return o(new TypeError("Promise.race accepts an array"));for(var i=0,u=e.length;u>i;i++)r.resolve(e[i]).then(n,o)}))},r._immediateFn="function"==typeof setImmediate&&function(e){setImmediate(e)}||function(e){s(e,0)},r._unhandledRejectionFn=function(e){void 0!==console&&console&&console.warn("Possible Unhandled Promise Rejection:",e)};var l=function(){if("undefined"!=typeof self)return self;if("undefined"!=typeof window)return window;if("undefined"!=typeof global)return global;throw Error("unable to locate global object")}();"Promise"in l?l.Promise.prototype.finally||(l.Promise.prototype.finally=e):l.Promise=r}));var t="undefined"!=typeof crypto&&crypto.getRandomValues&&crypto.getRandomValues.bind(crypto)||"undefined"!=typeof msCrypto&&"function"==typeof msCrypto.getRandomValues&&msCrypto.getRandomValues.bind(msCrypto),n=new Uint8Array(16);function r(){if(!t)throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");return t(n)}for(var o=[],i=0;i<256;++i)o[i]=(i+256).toString(16).substr(1);function u(e,t,n){var i=t&&n||0;"string"==typeof e&&(t="binary"===e?new Array(16):null,e=null);var u=(e=e||{}).random||(e.rng||r)();if(u[6]=15&u[6]|64,u[8]=63&u[8]|128,t)for(var c=0;c<16;++c)t[i+c]=u[c];return t||function(e,t){var n=t||0,r=o;return[r[e[n++]],r[e[n++]],r[e[n++]],r[e[n++]],"-",r[e[n++]],r[e[n++]],"-",r[e[n++]],r[e[n++]],"-",r[e[n++]],r[e[n++]],"-",r[e[n++]],r[e[n++]],r[e[n++]],r[e[n++]],r[e[n++]],r[e[n++]]].join("")}(u)}var c=Object.prototype.hasOwnProperty,a=Array.isArray,s=function(e){var t=Object.create(null);return function(n){return t[n]||(t[n]=e(n))}},l=/-(\w)/g,f=s((function(e){return e.replace(l,(function(e,t){return t?t.toUpperCase():""}))})),d=s((function(e){return e.charAt(0).toUpperCase()+e.slice(1)})),p=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g;function m(e,t){if(a(e))return e;if(t&&(n=t,r=e,c.call(n,r)))return[e];var n,r,o=[];return e.replace(p,(function(e,t,n,r){return o.push(n?r.replace(/\\(\\)?/g,"$1"):t||e),r})),o}function v(e,t){var n,r=m(t,e);for(n=r.shift();null!=n;){if(null==(e=e[n]))return;n=r.shift()}return e}var h=new Map;function g(e){if(!function(e){if(e){var t=e.tagName;return 0===t.indexOf("UNI-")||"BODY"===t}return!1}(e))throw Error("no such element");var t,n,r={elementId:(t=e,n=t._id,n||(n=u(),t._id=n,h.set(n,{id:n,element:t})),n),tagName:e.tagName.toLocaleLowerCase().replace("uni-","")},o=e.__vue__;return o&&(o.$parent&&o.$parent.$el===e&&(o=o.$parent),o&&!o.$options.isReserved&&(r.nodeId=function(e){if(e._$weex)return e._uid;if(e._$id)return e._$id;var t=function(e){for(var t=e.$parent;t;){if(t._$id)return t;t=t.$parent}}(e);if(!e.$parent)return"-1";var n=e.$vnode,r=n.context;return r&&r!==t&&r._$id?r._$id+";"+t._$id+","+n.data.attrs._i:t._$id+","+n.data.attrs._i}(o))),"video"===r.tagName&&(r.videoId=r.nodeId),r}var _={input:{input:function(e,t){var n=e.__vue__;n.valueSync=t,n.$triggerInput({},{value:t})}},textarea:{input:function(e,t){var n=e.__vue__;n.valueSync=t,n.$triggerInput({},{value:t})}},"scroll-view":{scrollTo:function(e,t,n){var r=e.__vue__.$refs.main;r.scrollLeft=t,r.scrollTop=n},scrollTop:function(e){return e.__vue__.$refs.main.scrollTop},scrollLeft:function(e){return e.__vue__.$refs.main.scrollLeft},scrollWidth:function(e){return e.__vue__.$refs.main.scrollWidth},scrollHeight:function(e){return e.__vue__.$refs.main.scrollHeight}},swiper:{swipeTo:function(e,t){e.__vue__.current=t}},"movable-view":{moveTo:function(e,t,n){e.__vue__._animationTo(t,n)}},switch:{tap:function(e){e.click()}},slider:{slideTo:function(e,t){var n=e.__vue__,r=n.$refs["uni-slider"],o=r.offsetWidth,i=r.getBoundingClientRect().left;n.value=t,n._onClick({x:(t-n.min)*o/(n.max-n.min)+i})}}},y={getWindow:function(e){return window},getDocument:function(e){return document},getEl:function(e){var t=h.get(e);if(!t)throw Error("element destroyed");return t.element},getOffset:function(e){var t=e.getBoundingClientRect();return Promise.resolve({left:t.left+window.pageXOffset,top:t.top+window.pageYOffset})},querySelector:function(e,t){return"page"===t&&(t="body"),Promise.resolve(g(e.querySelector(t)))},querySelectorAll:function(e,t){var n=[],r=document.querySelectorAll(t);return[].forEach.call(r,(function(e){try{n.push(g(e))}catch(e){}})),Promise.resolve({elements:n})},queryProperties:function(e,t){return Promise.resolve({properties:t.map((function(t){var n=v(e,t);return"document.documentElement.scrollTop"===t&&0===n&&(n=v(e,"document.body.scrollTop")),n}))})},queryAttributes:function(e,t){return Promise.resolve({attributes:t.map((function(t){return String(e.getAttribute(t))}))})},queryStyles:function(e,t){var n=getComputedStyle(e);return Promise.resolve({styles:t.map((function(e){return n[e]}))})},queryHTML:function(e,t){return Promise.resolve({html:(n="outer"===t?e.outerHTML:e.innerHTML,n.replace(/\n/g,"").replace(/(]*>)(]*>[^<]*<\/span>)(.*?<\/uni-text>)/g,"$1$3").replace(/<\/?[^>]*>/g,(function(e){return-1":""===e?"":0!==e.indexOf(" { - this.emit("message", event.data); - }); - this.ws.addEventListener("close", () => { - this.emit("close"); - }); - } - send(message) { - this.ws.send(message); - } - close() { - this.ws.close(); - } -} - -const CLOSE_ERR_TIP = "Connection closed"; -class Connection extends events.EventEmitter { - constructor(transport, puppet, namespace) { - super(); - this.puppet = puppet; - this.namespace = namespace; - this.callbacks = new Map(); - this.transport = transport; - this.debug = debug("automator:protocol:" + this.namespace); - this.onMessage = (msg) => { - this.debug(`${dateFormat("yyyy-mm-dd HH:MM:ss:l")} ◀ RECV ${msg}`); - const { id, method, error, result, params } = JSON.parse(msg); - if (!id) { - return this.puppet.emit(method, params); - } - const { callbacks } = this; - if (id && callbacks.has(id)) { - const promise = callbacks.get(id); - callbacks.delete(id); - error ? promise.reject(Error(error.message)) : promise.resolve(result); - } - }; - this.onClose = () => { - this.callbacks.forEach((promise) => { - promise.reject(Error(CLOSE_ERR_TIP)); - }); - }; - this.transport.on("message", this.onMessage); - this.transport.on("close", this.onClose); - } - send(method, params = {}, reflect = true) { - if (reflect && this.puppet.adapter.has(method)) { - return this.puppet.adapter.send(this, method, params); - } - const id = uuid(); - const data = stringify({ - id, - method, - params, - }); - this.debug(`${dateFormat("yyyy-mm-dd HH:MM:ss:l")} SEND ► ${data}`); - return new Promise((resolve, reject) => { - try { - this.transport.send(data); - } - catch (e) { - reject(Error(CLOSE_ERR_TIP)); - } - this.callbacks.set(id, { - resolve, - reject, - }); - }); - } - dispose() { - this.transport.close(); - } - static createDevtoolConnection(url, puppet) { - return new Promise((resolve, reject) => { - const ws = new WebSocket(url); - ws.addEventListener("open", () => { - resolve(new Connection(new Transport(ws), puppet, "devtool")); - }); - ws.addEventListener("error", reject); - }); - } - static createRuntimeConnection(port, puppet, timeout) { - return new Promise((resolve, reject) => { - debug("automator:runtime")(`${dateFormat("yyyy-mm-dd HH:MM:ss:l")} port=${port}`); - const wss = new WebSocket.Server({ - port, - }); - waitUntil(async () => { - if (puppet.runtimeConnection) { - return true; - } - }, timeout, 1e3).catch(() => { - wss.close(); - reject("Failed to connect to runtime, please make sure the project is running"); - }); - wss.on("connection", function connection(ws) { - debug("automator:runtime")(`${dateFormat("yyyy-mm-dd HH:MM:ss:l")} connected`); - const connection = new Connection(new Transport(ws), puppet, "runtime"); - // 可能会被重新连接,刷新成最新的 - puppet.setRuntimeConnection(connection); - resolve(connection); - }); - puppet.setRuntimeServer(wss); - }); - } -} - -const qrCodeTerminal = require("qrcode-terminal"); -const QrCodeReader = require("qrcode-reader"); -const isWin = /^win/.test(process.platform); -function printQrCode(content) { - return new Promise((resolve) => { - qrCodeTerminal.generate(content, { - small: true, - }, (qrcode) => { - process.stdout.write(qrcode); - resolve(); - }); - }); -} -function toArray(str) { - if (isStr(str)) { - return [true, [str]]; - } - return [false, str]; -} -async function invokeManyToMany(fn, str) { - const [isSingle, strArr] = toArray(str); - const result = await fn(strArr); - return isSingle ? result[0] : result; -} -async function resolvePort(port, defaultPort) { - const newPort = await getPort(port || defaultPort); - if (port && newPort !== port) { - throw Error(`Port ${port} is in use, please specify another port`); - } - return newPort; -} -function getWsEndpoint(port) { - let host; - try { - // This can only return an IPv4 address - const result = defaultGateway.v4.sync(); - host = address.ip(result && result.interface); - if (host) { - // Check if the address is a private ip - // https://en.wikipedia.org/wiki/Private_network#Private_IPv4_address_spaces - if (!/^10[.]|^172[.](1[6-9]|2[0-9]|3[0-1])[.]|^192[.]168[.]/.test(host)) { - // Address is not private, so we will discard it - host = undefined; - } - } - } - catch (_e) { - // ignored - } - return "ws://" + (host || "localhost") + ":" + port; -} - -/*! ***************************************************************************** -Copyright (c) Microsoft Corporation. All rights reserved. -Licensed 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 - -THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED -WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, -MERCHANTABLITY OR NON-INFRINGEMENT. - -See the Apache Version 2.0 License for specific language governing permissions -and limitations under the License. -***************************************************************************** */ - -function __decorate(decorators, target, key, desc) { - var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; - if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); - else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; - return c > 3 && r && Object.defineProperty(target, key, r), r; -} - -var TYPES; -(function (TYPES) { - TYPES["RUNTIME"] = "runtime"; - TYPES["DEVTOOL"] = "devtool"; -})(TYPES || (TYPES = {})); -function wrapper(type, descriptor) { - const method = descriptor.value; - descriptor.value = async function (params) { - const fn = await (method === null || method === void 0 ? void 0 : method.call(this, params)); - return fn(type); - }; - return descriptor; -} -function runtime(target, propertyName, descriptor) { - return wrapper(TYPES.RUNTIME, descriptor); -} -function devtool(target, propertyName, descriptor) { - return wrapper(TYPES.DEVTOOL, descriptor); -} -class Base { - constructor(puppet) { - this.puppet = puppet; - } - invoke(method, params) { - return async (type) => { - if (!this.puppet.devtoolConnection) { - return this.puppet.runtimeConnection.send(method, params); - } - return (type === TYPES.DEVTOOL - ? this.puppet.devtoolConnection - : this.puppet.runtimeConnection).send(method, params); - }; - } - on(method, listener) { - this.puppet.on(method, listener); - } -} - -class Element extends Base { - constructor(puppet, options) { - super(puppet); - this.id = options.elementId; - this.pageId = options.pageId; - this.nodeId = options.nodeId; - this.videoId = options.videoId; - } - async getData(params) { - return this.invokeMethod("Element.getData", params); - } - async setData(params) { - return this.invokeMethod("Element.setData", params); - } - async callMethod(params) { - return this.invokeMethod("Element.callMethod", params); - } - async getElement(params) { - return this.invokeMethod("Element.getElement", params); - } - async getElements(params) { - return this.invokeMethod("Element.getElements", params); - } - async getOffset() { - return this.invokeMethod("Element.getOffset"); - } - async getHTML(params) { - return this.invokeMethod("Element.getHTML", params); - } - async getAttributes(params) { - return this.invokeMethod("Element.getAttributes", params); - } - async getStyles(params) { - return this.invokeMethod("Element.getStyles", params); - } - async getDOMProperties(params) { - return this.invokeMethod("Element.getDOMProperties", params); - } - async getProperties(params) { - return this.invokeMethod("Element.getProperties", params); - } - async tap() { - return this.invokeMethod("Element.tap"); - } - async longpress() { - return this.invokeMethod("Element.longpress"); - } - async touchstart(params) { - return this.invokeMethod("Element.touchstart", params); - } - async touchmove(params) { - return this.invokeMethod("Element.touchmove", params); - } - async touchend(params) { - return this.invokeMethod("Element.touchend", params); - } - async triggerEvent(params) { - return this.invokeMethod("Element.triggerEvent", params); - } - async callFunction(params) { - return this.invokeMethod("Element.callFunction", params); - } - async callContextMethod(params) { - return this.invokeMethod("Element.callContextMethod", params); - } - invokeMethod(method, params = {}) { - params.elementId = this.id; - params.pageId = this.pageId; - this.nodeId && (params.nodeId = this.nodeId); - this.videoId && (params.videoId = this.videoId); - return this.invoke(method, params); - } -} -__decorate([ - runtime -], Element.prototype, "getData", null); -__decorate([ - runtime -], Element.prototype, "setData", null); -__decorate([ - runtime -], Element.prototype, "callMethod", null); -__decorate([ - devtool -], Element.prototype, "getElement", null); -__decorate([ - devtool -], Element.prototype, "getElements", null); -__decorate([ - devtool -], Element.prototype, "getOffset", null); -__decorate([ - devtool -], Element.prototype, "getHTML", null); -__decorate([ - devtool -], Element.prototype, "getAttributes", null); -__decorate([ - devtool -], Element.prototype, "getStyles", null); -__decorate([ - devtool -], Element.prototype, "getDOMProperties", null); -__decorate([ - devtool -], Element.prototype, "getProperties", null); -__decorate([ - devtool -], Element.prototype, "tap", null); -__decorate([ - devtool -], Element.prototype, "longpress", null); -__decorate([ - devtool -], Element.prototype, "touchstart", null); -__decorate([ - devtool -], Element.prototype, "touchmove", null); -__decorate([ - devtool -], Element.prototype, "touchend", null); -__decorate([ - devtool -], Element.prototype, "triggerEvent", null); -__decorate([ - devtool -], Element.prototype, "callFunction", null); -__decorate([ - devtool -], Element.prototype, "callContextMethod", null); - -const util = require("util"); -class Element$1 { - constructor(puppet, options, elementMap) { - this.puppet = puppet; - this.id = options.elementId; - this.pageId = options.pageId; - this.nodeId = options.nodeId || null; - this.videoId = options.videoId || null; - this.tagName = options.tagName; - this.nvue = options.nvue; - this.elementMap = elementMap; - // 统一格式化为 page - if (this.tagName === "body" || this.tagName === "page-body") { - this.tagName = "page"; - } - this.api = new Element(puppet, options); - } - toJSON() { - return JSON.stringify({ - id: this.id, - tagName: this.tagName, - pageId: this.pageId, - nodeId: this.nodeId, - videoId: this.videoId, - }); - } - toString() { - return this.toJSON(); - } - [util.inspect.custom]() { - return this.toJSON(); - } - async $(selector) { - try { - const element = await this.api.getElement({ selector }); - return Element$1.create(this.puppet, Object.assign({}, element, { - pageId: this.pageId, - }), this.elementMap); - } - catch (e) { - return null; - } - } - async $$(selector) { - const { elements } = await this.api.getElements({ selector }); - return elements.map((elem) => Element$1.create(this.puppet, Object.assign({}, elem, { - pageId: this.pageId, - }), this.elementMap)); - } - async size() { - const [width, height] = await this.domProperty([ - "offsetWidth", - "offsetHeight", - ]); - return { - width, - height, - }; - } - async offset() { - const { left, top } = await this.api.getOffset(); - return { - left, - top, - }; - } - async text() { - return this.domProperty("innerText"); - } - async attribute(name) { - if (!isStr(name)) { - throw Error("name must be a string"); - } - return (await this.api.getAttributes({ names: [name] })).attributes[0]; - } - async value() { - return this.property("value"); - } - async property(name) { - if (!isStr(name)) { - throw Error("name must be a string"); - } - if (this.puppet.checkProperty) { - let props = this.publicProps; - if (!props) { - this.publicProps = props = await this._property("__propPublic"); - } - if (!props[name]) { - throw Error(`${this.tagName}.${name} not exists`); - } - } - return this._property(name); - } - async html() { - return (await this.api.getHTML({ type: "inner" })).html; - } - async outerHtml() { - return (await this.api.getHTML({ type: "outer" })).html; - } - async style(name) { - if (!isStr(name)) { - throw Error("name must be a string"); - } - return (await this.api.getStyles({ names: [name] })).styles[0]; - } - async tap() { - return this.api.tap(); - } - async longpress() { - if (this.nvue) { - return this.api.longpress(); - } - await this.touchstart(); - await sleep$1(350); - return this.touchend(); - } - async trigger(type, detail) { - const event = { - type, - }; - if (!isUndef(detail)) { - event.detail = detail; - } - return this.api.triggerEvent(event); - } - async touchstart(options) { - return this.api.touchstart(options); - } - async touchmove(options) { - return this.api.touchmove(options); - } - async touchend(options) { - return this.api.touchend(options); - } - async domProperty(name) { - return invokeManyToMany(async (names) => (await this.api.getDOMProperties({ names })).properties, name); - } - _property(name) { - return invokeManyToMany(async (names) => (await this.api.getProperties({ names })).properties, name); - } - send(method, params) { - params.elementId = this.id; - params.pageId = this.pageId; - this.nodeId && (params.nodeId = this.nodeId); - this.videoId && (params.videoId = this.videoId); - return this.puppet.send(method, params); - } - async callFunction(functionName, ...args) { - return (await this.api.callFunction({ - functionName, - args, - })).result; - } - static create(puppet, options, elementMap) { - let element = elementMap.get(options.elementId); - if (element) { - return element; - } - let ElementClass; - if (options.nodeId) { - ElementClass = CustomElement; - } - else { - switch (options.tagName) { - case "input": - ElementClass = InputElement; - break; - case "textarea": - ElementClass = TextareaElement; - break; - case "scroll-view": - ElementClass = ScrollViewElement; - break; - case "swiper": - ElementClass = SwiperElement; - break; - case "movable-view": - ElementClass = MovableViewElement; - break; - case "switch": - ElementClass = SwitchElement; - break; - case "slider": - ElementClass = SliderElement; - break; - case "video": - ElementClass = ContextElement; - break; - default: - ElementClass = Element$1; - } - } - element = new ElementClass(puppet, options, elementMap); - elementMap.set(options.elementId, element); - return element; - } -} -class CustomElement extends Element$1 { - async setData(data) { - return this.api.setData({ data }); - } - async data(path) { - const data = {}; - if (path) { - data.path = path; - } - return (await this.api.getData(data)).data; - } - async callMethod(method, ...args) { - return (await this.api.callMethod({ - method, - args, - })).result; - } -} -class InputElement extends Element$1 { - async input(value) { - return this.callFunction("input.input", value); - } -} -class TextareaElement extends Element$1 { - async input(value) { - return this.callFunction("textarea.input", value); - } -} -class ScrollViewElement extends Element$1 { - async scrollTo(x, y) { - return this.callFunction("scroll-view.scrollTo", x, y); - } - async property(name) { - if (name === "scrollTop") { - return this.callFunction("scroll-view.scrollTop"); - } - else if (name === "scrollLeft") { - return this.callFunction("scroll-view.scrollLeft"); - } - return super.property(name); - } - async scrollWidth() { - return this.callFunction("scroll-view.scrollWidth"); - } - async scrollHeight() { - return this.callFunction("scroll-view.scrollHeight"); - } -} -class SwiperElement extends Element$1 { - async swipeTo(index) { - return this.callFunction("swiper.swipeTo", index); - } -} -class MovableViewElement extends Element$1 { - async moveTo(x, y) { - return this.callFunction("movable-view.moveTo", x, y); - } - async property(name) { - if (name === "x") { - return this._property("_translateX"); - } - else if (name === "y") { - return this._property("_translateY"); - } - return super.property(name); - } -} -class SwitchElement extends Element$1 { - async tap() { - return this.callFunction("switch.tap"); - } -} -class SliderElement extends Element$1 { - async slideTo(value) { - return this.callFunction("slider.slideTo", value); - } -} -class ContextElement extends Element$1 { - async callContextMethod(method, ...args) { - const result = await this.api.callContextMethod({ - method, - args, - }); - return result; - } -} - -class Page extends Base { - constructor(puppet, options) { - super(puppet); - this.id = options.id; - } - async getData(params) { - return this.invokeMethod("Page.getData", params); - } - async setData(params) { - return this.invokeMethod("Page.setData", params); - } - async callMethod(params) { - return this.invokeMethod("Page.callMethod", params); - } - async getElement(params) { - return this.invokeMethod("Page.getElement", params); - } - async getElements(params) { - return this.invokeMethod("Page.getElements", params); - } - async getWindowProperties(params) { - return this.invokeMethod("Page.getWindowProperties", params); - } - invokeMethod(method, params = {}) { - params.pageId = this.id; - return this.invoke(method, params); - } -} -__decorate([ - runtime -], Page.prototype, "getData", null); -__decorate([ - runtime -], Page.prototype, "setData", null); -__decorate([ - runtime -], Page.prototype, "callMethod", null); -__decorate([ - devtool -], Page.prototype, "getElement", null); -__decorate([ - devtool -], Page.prototype, "getElements", null); -__decorate([ - devtool -], Page.prototype, "getWindowProperties", null); - -const util$1 = require("util"); -class Page$1 { - constructor(puppet, options) { - this.puppet = puppet; - this.id = options.id; - this.path = options.path; - this.query = options.query; - this.elementMap = new Map(); - this.api = new Page(puppet, options); - } - toJSON() { - return JSON.stringify({ id: this.id, path: this.path, query: this.query }); - } - toString() { - return this.toJSON(); - } - [util$1.inspect.custom]() { - return this.toJSON(); - } - async waitFor(condition) { - if (isNum(condition)) { - return await sleep$1(condition); - } - else if (isFn(condition)) { - return waitUntil(condition); - } - else if (isStr(condition)) { - return waitUntil(async () => { - const elms = await this.$$(condition); - return elms.length > 0; - }); - } - } - async $(selector) { - try { - const page = await this.api.getElement({ selector }); - return Element$1.create(this.puppet, Object.assign({ - selector, - }, page, { - pageId: this.id, - }), this.elementMap); - } - catch (t) { - return null; - } - } - async $$(selector) { - const { elements } = await this.api.getElements({ selector }); - return elements.map((elem) => Element$1.create(this.puppet, Object.assign({ - selector, - }, elem, { - pageId: this.id, - }), this.elementMap)); - } - async data(path) { - const payload = {}; - if (path) { - payload.path = path; - } - return (await this.api.getData(payload)).data; - } - async setData(data) { - return this.api.setData({ data }); - } - async size() { - const [width, height] = await this.windowProperty([ - "document.documentElement.scrollWidth", - "document.documentElement.scrollHeight", - ]); - return { - width, - height, - }; - } - async callMethod(method, ...args) { - return (await this.api.callMethod({ - method, - args, - })).result; - } - async scrollTop() { - return this.windowProperty("document.documentElement.scrollTop"); - } - async windowProperty(names) { - const isSingle = isStr(names); - if (isSingle) { - names = [names]; - } - const { properties } = await this.api.getWindowProperties({ - names: names, - }); - return isSingle ? properties[0] : properties; - } - static create(puppet, options, pageMap) { - let page = pageMap.get(options.id); - if (page) { - //update query (部分页面id被锁定,如tabBar页面) - page.query = options.query; - return page; - } - page = new Page$1(puppet, options); - pageMap.set(options.id, page); - return page; - } -} - -class App extends Base { - async getPageStack() { - return this.invoke("App.getPageStack"); - } - async callUniMethod(params) { - return this.invoke("App.callUniMethod", params); - } - async getCurrentPage() { - return this.invoke("App.getCurrentPage"); - } - async mockUniMethod(params) { - return this.invoke("App.mockUniMethod", params); - } - async callFunction(params) { - return this.invoke("App.callFunction", params); - } - async captureScreenshot(params) { - return this.invoke("App.captureScreenshot", params); - } - async exit() { - return this.invoke("App.exit"); - } - async addBinding(params) { - return this.invoke("App.addBinding", params); - } - async enableLog() { - return this.invoke("App.enableLog"); - } - onLogAdded(listener) { - return this.on("App.logAdded", listener); - } - onBindingCalled(listener) { - return this.on("App.bindingCalled", listener); - } - onExceptionThrown(listener) { - return this.on("App.exceptionThrown", listener); - } -} -__decorate([ - runtime -], App.prototype, "getPageStack", null); -__decorate([ - runtime -], App.prototype, "callUniMethod", null); -__decorate([ - runtime -], App.prototype, "getCurrentPage", null); -__decorate([ - runtime -], App.prototype, "mockUniMethod", null); -__decorate([ - devtool -], App.prototype, "callFunction", null); -__decorate([ - devtool -], App.prototype, "captureScreenshot", null); -__decorate([ - devtool -], App.prototype, "exit", null); -__decorate([ - devtool -], App.prototype, "addBinding", null); -__decorate([ - devtool -], App.prototype, "enableLog", null); - -class Tool extends Base { - async getInfo() { - return this.invoke("Tool.getInfo"); - } - async enableRemoteDebug(params) { - return this.invoke("Tool.enableRemoteDebug"); - } - async close() { - return this.invoke("Tool.close"); - } - async getTestAccounts() { - return this.invoke("Tool.getTestAccounts"); - } - onRemoteDebugConnected(listener) { - this.puppet.once("Tool.onRemoteDebugConnected", listener); - // mp-baidu - this.puppet.once("Tool.onPreviewConnected", listener); - } -} -__decorate([ - devtool -], Tool.prototype, "getInfo", null); -__decorate([ - devtool -], Tool.prototype, "enableRemoteDebug", null); -__decorate([ - devtool -], Tool.prototype, "close", null); -__decorate([ - devtool -], Tool.prototype, "getTestAccounts", null); - -function sleep(timeout) { - return new Promise((e) => setTimeout(e, timeout)); -} -function isFnStr(str) { - return (isStr(str) && - ((str = trim(str)), startWith(str, "function") || startWith(str, "() =>"))); -} -class Program extends events.EventEmitter { - constructor(puppet, options) { - super(); - this.puppet = puppet; - this.options = options; - this.pageMap = new Map(); - this.appBindings = new Map(); - this.appApi = new App(puppet); - this.toolApi = new Tool(puppet); - this.appApi.onLogAdded((msg) => { - this.emit("console", msg); - }); - this.appApi.onBindingCalled(({ name, args }) => { - try { - const fn = this.appBindings.get(name); - fn && fn(...args); - } - catch (t) { } - }); - this.appApi.onExceptionThrown((error) => { - this.emit("exception", error); - }); - } - async pageStack() { - return (await this.appApi.getPageStack()).pageStack.map((page) => Page$1.create(this.puppet, page, this.pageMap)); - } - async navigateTo(url) { - return this.changeRoute("navigateTo", url); - } - async redirectTo(url) { - return this.changeRoute("redirectTo", url); - } - async navigateBack() { - return this.changeRoute("navigateBack"); - } - async reLaunch(url) { - return this.changeRoute("reLaunch", url); - } - async switchTab(url) { - return this.changeRoute("switchTab", url); - } - async currentPage() { - const { id, path, query } = await this.appApi.getCurrentPage(); - return Page$1.create(this.puppet, { id, path, query }, this.pageMap); - } - async systemInfo() { - return this.callUniMethod("getSystemInfoSync"); - } - async callUniMethod(method, ...args) { - return (await this.appApi.callUniMethod({ method, args })).result; - } - async mockUniMethod(method, result, ...args) { - if (isFn(result) || isFnStr(result)) { - return this.appApi.mockUniMethod({ - method, - functionDeclaration: result.toString(), - args, - }); - } - return this.appApi.mockUniMethod({ method, result }); - } - async restoreUniMethod(method) { - return this.appApi.mockUniMethod({ method }); - } - async evaluate(appFunction, // tslint:disable-line - ...args) { - return (await this.appApi.callFunction({ - functionDeclaration: appFunction.toString(), - args, - })).result; - } - async pageScrollTo(scrollTop) { - await this.callUniMethod("pageScrollTo", { - scrollTop, - duration: 0, - }); - } - async close() { - try { - await this.appApi.exit(); - } - catch (t) { } - await sleep(1e3); - this.puppet.disposeRuntimeServer(); - await this.toolApi.close(); - this.disconnect(); - } - async teardown() { - return this[this.options.teardown === "disconnect" ? "disconnect" : "close"](); - } - async remote(auto) { - if (!this.puppet.devtools.remote) { - return console.warn(`Failed to enable remote, ${this.puppet.devtools.name} is unimplemented`); - } - const { qrCode } = await this.toolApi.enableRemoteDebug({ auto }); - qrCode && (await printQrCode(qrCode)); - const connectedPromise = new Promise((resolve) => { - this.toolApi.onRemoteDebugConnected(async () => { - await sleep(1e3); - resolve(); - }); - }); - const runtimePromise = new Promise((resolve) => { - this.puppet.setRemoteRuntimeConnectionCallback(() => { - resolve(); - }); - }); - return Promise.all([connectedPromise, runtimePromise]); - } - disconnect() { - this.puppet.dispose(); - } - on(event, listener) { - if (event === "console") { - this.appApi.enableLog(); - } - super.on(event, listener); - return this; - } - async exposeFunction(name, bindingFunction) { - if (this.appBindings.has(name)) { - throw Error(`Failed to expose function with name ${name}: already exists!`); - } - this.appBindings.set(name, bindingFunction); - await this.appApi.addBinding({ name }); - } - async checkVersion() { } - async screenshot(options) { - const { data } = await this.appApi.captureScreenshot({ - fullPage: options === null || options === void 0 ? void 0 : options.fullPage, - }); - if (!(options === null || options === void 0 ? void 0 : options.path)) - return data; - await fs$1.writeFile(options.path, data, "base64"); - } - async testAccounts() { - return (await this.toolApi.getTestAccounts()).accounts; - } - async changeRoute(method, url) { - await this.callUniMethod(method, { - url, - }); - await sleep(3e3); - return this.currentPage(); - } -} - -class Adapter { - constructor(options) { - this.options = options; - } - has(method) { - return !!this.options[method]; - } - send(connection, method, params) { - const option = this.options[method]; - if (!option) { - return Promise.reject(Error(`adapter for ${method} not found`)); - } - const reflect = option.reflect; - if (!reflect) { - return Promise.reject(Error(`${method}'s reflect is required`)); - } - if (option.params) { - params = option.params(params); - } - if (typeof reflect === "function") { - return reflect(connection.send.bind(connection), params); - } - else { - method = reflect; - } - return connection.send(method, params); - } -} - -const debugPuppet = debug("automator:puppet"); -const AUTOMATOR_JSON_FILE = ".automator.json"; -function tryRequire(path) { - try { - return require(path); - } - catch (e) { } -} -function resolveAutomatorJson(projectPath, platform, mode) { - let json; - let jsonPath; - if (process.env.UNI_OUTPUT_DIR) { - jsonPath = path.join(process.env.UNI_OUTPUT_DIR, `../.automator/${platform}`, AUTOMATOR_JSON_FILE); - json = tryRequire(jsonPath); - } - else { - jsonPath = path.join(projectPath, `dist/${mode}/.automator/${platform}`, AUTOMATOR_JSON_FILE); - json = tryRequire(jsonPath); - if (!json) { - jsonPath = path.join(projectPath, `unpackage/dist/${mode}/.automator/${platform}`, AUTOMATOR_JSON_FILE); - json = tryRequire(jsonPath); - } - } - debugPuppet(`${jsonPath}=>${JSON.stringify(json)}`); - return json; -} -function equalWsEndpoint(projectPath, port, platform, mode) { - const json = resolveAutomatorJson(projectPath, platform, mode); - if (!json || !json.wsEndpoint) { - return false; - } - const version = require("../package.json").version; - if (json.version !== version) { - debugPuppet(`unmet=>${json.version}!==${version}`); - return false; - } - const wsEndpoint = getWsEndpoint(port); - debugPuppet(`wsEndpoint=>${wsEndpoint}`); - return json.wsEndpoint === wsEndpoint; -} -class Puppet extends events.EventEmitter { - constructor(platform, target) { - super(); - if (target) { - this.target = target; - } - else { - this.target = require(`@dcloudio/uni-${platform === "app" ? "app-plus" : platform}/lib/uni.automator.js`); - } - if (!this.target) { - throw Error("puppet is not provided"); - } - this.platform = platform; - this.adapter = new Adapter(this.target.adapter || {}); - } - setCompiler(compiler) { - this.compiler = compiler; - } - setRuntimeServer(wss) { - this.wss = wss; - } - setRemoteRuntimeConnectionCallback(callback) { - this.remoteRuntimeConnectionCallback = callback; - } - setRuntimeConnection(connection) { - this.runtimeConnection = connection; - if (this.remoteRuntimeConnectionCallback) { - this.remoteRuntimeConnectionCallback(); - this.remoteRuntimeConnectionCallback = null; - } - } - setDevtoolConnection(connection) { - this.devtoolConnection = connection; - } - disposeRuntimeServer() { - this.wss && this.wss.close(); - } - disposeRuntime() { - this.runtimeConnection.dispose(); - } - disposeDevtool() { - this.compiler && this.compiler.stop(); - this.devtoolConnection && this.devtoolConnection.dispose(); - } - dispose() { - this.disposeRuntime(); - this.disposeDevtool(); - this.disposeRuntimeServer(); - } - send(method, params) { - return this.runtimeConnection.send(method, params); - } - validateProject(projectPath) { - const required = this.target.devtools.required; - if (!required) { - return true; - } - return !required.find((file) => !fs.existsSync(path.join(projectPath, file))); - } - validateDevtools(opions) { - const validate = this.target.devtools.validate; - if (validate) { - return validate(opions, this); - } - return Promise.resolve(opions); - } - createDevtools(devtoolsProjectPath, options, timeout) { - const create = this.target.devtools.create; - if (create) { - options.timeout = timeout; - return create(devtoolsProjectPath, options, this); - } - return Promise.resolve(); - } - shouldCompile(projectPath, port, options, devtoolsOptions) { - this.compiled = true; - const shouldCompile = this.target.shouldCompile; - if (shouldCompile) { - this.compiled = shouldCompile(options, devtoolsOptions); - } - else { - if (options.compile === true) { - this.compiled = true; - } - else { - //自动检测 - this.compiled = !equalWsEndpoint(projectPath, port, this.platform, this.mode); - } - } - return this.compiled; - } - get checkProperty() { - return this.platform === "mp-weixin"; - } - get devtools() { - return this.target.devtools; - } - get mode() { - const mode = this.target.mode; - if (mode) { - return mode; - } - return process.env.NODE_ENV === "production" ? "build" : "dev"; - } -} - -const debugCompiler = debug("automator:compiler"); -const SIGNAL_DONE = "DONE Build complete"; -const SIGNAL_DONE_H5 = "- Network"; -const SIGNAL_DONE_VITE_H5 = "> Network"; -const PATH_RE = /The\s+(.*)\s+directory is ready/; -class Compiler { - constructor(puppet) { - this.puppet = puppet; - this.puppet.setCompiler(this); - } - compile(options) { - const mode = this.puppet.mode; - const platform = this.puppet.platform; - let silent = options.silent; - const autoPort = options.port; - const autoHost = options.host; - const npmScript = `${mode}:${platform}`; - const projectPath = options.projectPath; - const [command, cliArgs] = this.getSpawnArgs(options, npmScript); - cliArgs.push("--auto-port"); - cliArgs.push(toStr(autoPort)); - if (autoHost) { - cliArgs.push("--auto-host"); - cliArgs.push(autoHost); - } - const cliOptions = { - cwd: options.cliPath, - env: Object.assign(Object.assign({}, process.env), { NODE_ENV: mode === "build" ? "production" : "development" }), - }; - return new Promise((resolve, reject) => { - const onError = (err) => { - reject(err); - }; - const onStdoutData = (data) => { - const msg = data.toString().trim(); - !silent && console.log(msg); - if (msg.includes(SIGNAL_DONE_H5) || msg.includes(SIGNAL_DONE_VITE_H5)) { - const networkUrl = msg.match(/Network:(.*)/)[1].trim(); - // H5 DONE - debugCompiler(`url: ${networkUrl}`); - resolve({ path: networkUrl }); - } - else if (msg.includes(SIGNAL_DONE)) { - const matches = msg.match(PATH_RE); - let outputDir = ""; - if (matches && matches.length > 1) { - outputDir = path.join(projectPath, matches[1]); - } - else { - outputDir = path.join(projectPath, `dist/${mode}/${platform}`); - if (!fs.existsSync(outputDir)) { - outputDir = path.join(projectPath, `unpackage/dist/${mode}/${platform}`); - } - } - silent = true; // 编译已完成 - this.stop(); - resolve({ - path: outputDir, - }); - } - }; - debugCompiler(`${command} ${cliArgs.join(" ")} %o`, cliOptions); - this.cliProcess = child_process.spawn(command, cliArgs, cliOptions); - this.cliProcess.on("error", onError); - this.cliProcess.stdout.on("data", onStdoutData); - this.cliProcess.stderr.on("data", onStdoutData); - }); - } - stop() { - this.cliProcess && this.cliProcess.kill("SIGTERM"); - } - getSpawnArgs(options, npmScript) { - let pkg; - const cliPath = options.cliPath; - try { - pkg = require(path.join(cliPath, "package.json")); - } - catch (e) { } - if (pkg && pkg.scripts && pkg.scripts[npmScript]) { - return [ - process.env.UNI_NPM_PATH || - (/^win/.test(process.platform) ? "npm.cmd" : "npm"), - ["run", npmScript, "--"], - ]; - } - process.env.UNI_INPUT_DIR = options.projectPath; - process.env.UNI_OUTPUT_DIR = path.join(options.projectPath, `unpackage/dist/${this.puppet.mode}/${this.puppet.platform}`); - return [ - process.env.UNI_NODE_PATH || "node", - [path.join(cliPath, "bin/uniapp-cli.js")], - ]; - } -} - -const PORT = 9520; -const TIMEOUT = 6e4; -function exit(msg) { - throw Error(msg); -} -class Launcher { - async launch(options) { - let devtools = (options.platform === "app" - ? options.app || options["app-plus"] - : options[options.platform]) || {}; - this.puppet = new Puppet(options.platform, devtools.puppet); - // 1.校验参数 - const { port, cliPath, timeout, projectPath } = await this.validate(options); - devtools = await this.puppet.validateDevtools(devtools); - // 2.编译 - let shouldCompile = this.puppet.shouldCompile(projectPath, port, options, devtools); - let devtoolsProjectPath = process.env.UNI_OUTPUT_DIR || projectPath; - if (!shouldCompile) { - if (!this.puppet.validateProject(devtoolsProjectPath)) { - devtoolsProjectPath = path.join(projectPath, "dist/" + this.puppet.mode + "/" + this.puppet.platform); - if (!this.puppet.validateProject(devtoolsProjectPath)) { - devtoolsProjectPath = path.join(projectPath, "unpackage/dist/" + this.puppet.mode + "/" + this.puppet.platform); - if (!this.puppet.validateProject(devtoolsProjectPath)) { - shouldCompile = true; - } - } - } - } - if (shouldCompile) { - this.puppet.compiled = options.compile = true; - this.compiler = new Compiler(this.puppet); - const compilerResult = await this.compiler.compile({ - host: options.host, - port, - cliPath, - projectPath, - silent: !!options.silent, - }); - if (compilerResult.path) { - devtoolsProjectPath = compilerResult.path; - } - } - const promises = []; - // 3.runtime - promises.push(this.createRuntimeConnection(port, timeout)); - // 4.devtool - promises.push(this.puppet.createDevtools(devtoolsProjectPath, devtools, timeout)); - return new Promise((resolve, reject) => { - Promise.all(promises) - .then(([runtimeConnection, devtoolConnection]) => { - runtimeConnection && - this.puppet.setRuntimeConnection(runtimeConnection); - devtoolConnection && - this.puppet.setDevtoolConnection(devtoolConnection); - debug("automator:program")("ready"); - const teardown = devtools.teardown || "disconnect"; - resolve(new Program(this.puppet, { teardown, port })); - }) - .catch((err) => reject(err)); - }); - } - resolveCliPath(cliPath) { - if (!cliPath) { - return cliPath; - } - try { - const { dependencies, devDependencies } = require(path.join(cliPath, "package.json")); - if (hasCliDeps(devDependencies) || hasCliDeps(dependencies)) { - return cliPath; - } - } - catch (e) { } - } - resolveProjectPath(projectPath, options) { - if (!projectPath) { - projectPath = process.env.UNI_INPUT_DIR || process.cwd(); - } - if (isRelative(projectPath)) { - projectPath = path.resolve(projectPath); - } - if (!fs.existsSync(projectPath)) { - exit(`Project path ${projectPath} doesn't exist`); - } - return projectPath; - } - async validate(options) { - const projectPath = this.resolveProjectPath(options.projectPath, options); - let cliPath = process.env.UNI_CLI_PATH || options.cliPath; - cliPath = this.resolveCliPath(cliPath || ""); - !cliPath && (cliPath = this.resolveCliPath(process.cwd())); - !cliPath && (cliPath = this.resolveCliPath(projectPath)); - if (!cliPath) { - throw Error("cliPath is not provided"); - } - const port = await resolvePort(options.port || PORT); - const timeout = options.timeout || TIMEOUT; - return { - port, - cliPath, - timeout, - projectPath, - }; - } - async createRuntimeConnection(port, timeout) { - return Connection.createRuntimeConnection(port, this.puppet, timeout); - } -} -function hasCliDeps(deps) { - if (!deps) { - return false; - } - return !!(deps["@dcloudio/vue-cli-plugin-uni"] || deps["@dcloudio/vite-plugin-uni"]); -} - -class Automator { - constructor() { - this.launcher = new Launcher(); - } - // async connect(options: IConnectOptions) { - // return this.launcher.connect(options); - // } - async launch(options) { - return this.launcher.launch(options); - } -} - -module.exports = Automator; +"use strict";function t(t){return t&&"object"==typeof t&&"default"in t?t.default:t}var e=t(require("fs")),n=t(require("path")),s=t(require("debug")),i=t(require("licia/isRelative")),o=t(require("ws")),r=require("events"),a=t(require("licia/uuid")),c=t(require("licia/stringify")),p=t(require("licia/dateFormat")),l=t(require("licia/waitUntil")),u=t(require("licia/fs")),h=t(require("licia/isFn")),d=t(require("licia/trim")),m=t(require("licia/isStr")),g=t(require("licia/startWith")),y=t(require("licia/isNum")),v=t(require("licia/sleep")),w=t(require("licia/isUndef")),f=t(require("address")),P=t(require("default-gateway")),M=t(require("licia/getPort")),k=require("child_process"),E=t(require("licia/toStr"));class b extends r.EventEmitter{constructor(t){super(),this.ws=t,this.ws.addEventListener("message",t=>{this.emit("message",t.data)}),this.ws.addEventListener("close",()=>{this.emit("close")})}send(t){this.ws.send(t)}close(){this.ws.close()}}class I extends r.EventEmitter{constructor(t,e,n){super(),this.puppet=e,this.namespace=n,this.callbacks=new Map,this.transport=t,this.debug=s("automator:protocol:"+this.namespace),this.onMessage=t=>{this.debug(`${p("yyyy-mm-dd HH:MM:ss:l")} ◀ RECV ${t}`);const{id:e,method:n,error:s,result:i,params:o}=JSON.parse(t);if(!e)return this.puppet.emit(n,o);const{callbacks:r}=this;if(e&&r.has(e)){const t=r.get(e);r.delete(e),s?t.reject(Error(s.message)):t.resolve(i)}},this.onClose=()=>{this.callbacks.forEach(t=>{t.reject(Error("Connection closed"))})},this.transport.on("message",this.onMessage),this.transport.on("close",this.onClose)}send(t,e={},n=!0){if(n&&this.puppet.adapter.has(t))return this.puppet.adapter.send(this,t,e);const s=a(),i=c({id:s,method:t,params:e});return this.debug(`${p("yyyy-mm-dd HH:MM:ss:l")} SEND ► ${i}`),new Promise((t,e)=>{try{this.transport.send(i)}catch(t){e(Error("Connection closed"))}this.callbacks.set(s,{resolve:t,reject:e})})}dispose(){this.transport.close()}static createDevtoolConnection(t,e){return new Promise((n,s)=>{const i=new o(t);i.addEventListener("open",()=>{n(new I(new b(i),e,"devtool"))}),i.addEventListener("error",s)})}static createRuntimeConnection(t,e,n){return new Promise((i,r)=>{s("automator:runtime")(`${p("yyyy-mm-dd HH:MM:ss:l")} port=${t}`);const a=new o.Server({port:t});l(async()=>{if(e.runtimeConnection)return!0},n,1e3).catch(()=>{a.close(),r("Failed to connect to runtime, please make sure the project is running")}),a.on("connection",(function(t){s("automator:runtime")(p("yyyy-mm-dd HH:MM:ss:l")+" connected");const n=new I(new b(t),e,"runtime");e.setRuntimeConnection(n),i(n)})),e.setRuntimeServer(a)})}}const C=require("qrcode-terminal");require("qrcode-reader"),/^win/.test(process.platform);async function T(t,e){const[n,s]=function(t){return m(t)?[!0,[t]]:[!1,t]}(e),i=await t(s);return n?i[0]:i} +/*! ***************************************************************************** +Copyright (c) Microsoft Corporation. All rights reserved. +Licensed 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 + +THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +MERCHANTABLITY OR NON-INFRINGEMENT. + +See the Apache Version 2.0 License for specific language governing permissions +and limitations under the License. +***************************************************************************** */ +function D(t,e,n,s){var i,o=arguments.length,r=o<3?e:null===s?s=Object.getOwnPropertyDescriptor(e,n):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(t,e,n,s);else for(var a=t.length-1;a>=0;a--)(i=t[a])&&(r=(o<3?i(r):o>3?i(e,n,r):i(e,n))||r);return o>3&&r&&Object.defineProperty(e,n,r),r}var j;function A(t,e){const n=e.value;return e.value=async function(e){return(await(null==n?void 0:n.call(this,e)))(t)},e}function R(t,e,n){return A(j.RUNTIME,n)}function S(t,e,n){return A(j.DEVTOOL,n)}!function(t){t.RUNTIME="runtime",t.DEVTOOL="devtool"}(j||(j={}));class q{constructor(t){this.puppet=t}invoke(t,e){return async n=>this.puppet.devtoolConnection?(n===j.DEVTOOL?this.puppet.devtoolConnection:this.puppet.runtimeConnection).send(t,e):this.puppet.runtimeConnection.send(t,e)}on(t,e){this.puppet.on(t,e)}}class x extends q{constructor(t,e){super(t),this.id=e.elementId,this.pageId=e.pageId,this.nodeId=e.nodeId,this.videoId=e.videoId}async getData(t){return this.invokeMethod("Element.getData",t)}async setData(t){return this.invokeMethod("Element.setData",t)}async callMethod(t){return this.invokeMethod("Element.callMethod",t)}async getElement(t){return this.invokeMethod("Element.getElement",t)}async getElements(t){return this.invokeMethod("Element.getElements",t)}async getOffset(){return this.invokeMethod("Element.getOffset")}async getHTML(t){return this.invokeMethod("Element.getHTML",t)}async getAttributes(t){return this.invokeMethod("Element.getAttributes",t)}async getStyles(t){return this.invokeMethod("Element.getStyles",t)}async getDOMProperties(t){return this.invokeMethod("Element.getDOMProperties",t)}async getProperties(t){return this.invokeMethod("Element.getProperties",t)}async tap(){return this.invokeMethod("Element.tap")}async longpress(){return this.invokeMethod("Element.longpress")}async touchstart(t){return this.invokeMethod("Element.touchstart",t)}async touchmove(t){return this.invokeMethod("Element.touchmove",t)}async touchend(t){return this.invokeMethod("Element.touchend",t)}async triggerEvent(t){return this.invokeMethod("Element.triggerEvent",t)}async callFunction(t){return this.invokeMethod("Element.callFunction",t)}async callContextMethod(t){return this.invokeMethod("Element.callContextMethod",t)}invokeMethod(t,e={}){return e.elementId=this.id,e.pageId=this.pageId,this.nodeId&&(e.nodeId=this.nodeId),this.videoId&&(e.videoId=this.videoId),this.invoke(t,e)}}D([R],x.prototype,"getData",null),D([R],x.prototype,"setData",null),D([R],x.prototype,"callMethod",null),D([S],x.prototype,"getElement",null),D([S],x.prototype,"getElements",null),D([S],x.prototype,"getOffset",null),D([S],x.prototype,"getHTML",null),D([S],x.prototype,"getAttributes",null),D([S],x.prototype,"getStyles",null),D([S],x.prototype,"getDOMProperties",null),D([S],x.prototype,"getProperties",null),D([S],x.prototype,"tap",null),D([S],x.prototype,"longpress",null),D([S],x.prototype,"touchstart",null),D([S],x.prototype,"touchmove",null),D([S],x.prototype,"touchend",null),D([S],x.prototype,"triggerEvent",null),D([S],x.prototype,"callFunction",null),D([S],x.prototype,"callContextMethod",null);const N=require("util");class O{constructor(t,e,n){this.puppet=t,this.id=e.elementId,this.pageId=e.pageId,this.nodeId=e.nodeId||null,this.videoId=e.videoId||null,this.tagName=e.tagName,this.nvue=e.nvue,this.elementMap=n,"body"!==this.tagName&&"page-body"!==this.tagName||(this.tagName="page"),this.api=new x(t,e)}toJSON(){return JSON.stringify({id:this.id,tagName:this.tagName,pageId:this.pageId,nodeId:this.nodeId,videoId:this.videoId})}toString(){return this.toJSON()}[N.inspect.custom](){return this.toJSON()}async $(t){try{const e=await this.api.getElement({selector:t});return O.create(this.puppet,Object.assign({},e,{pageId:this.pageId}),this.elementMap)}catch(t){return null}}async $$(t){const{elements:e}=await this.api.getElements({selector:t});return e.map(t=>O.create(this.puppet,Object.assign({},t,{pageId:this.pageId}),this.elementMap))}async size(){const[t,e]=await this.domProperty(["offsetWidth","offsetHeight"]);return{width:t,height:e}}async offset(){const{left:t,top:e}=await this.api.getOffset();return{left:t,top:e}}async text(){return this.domProperty("innerText")}async attribute(t){if(!m(t))throw Error("name must be a string");return(await this.api.getAttributes({names:[t]})).attributes[0]}async value(){return this.property("value")}async property(t){if(!m(t))throw Error("name must be a string");if(this.puppet.checkProperty){let e=this.publicProps;if(e||(this.publicProps=e=await this._property("__propPublic")),!e[t])throw Error(`${this.tagName}.${t} not exists`)}return this._property(t)}async html(){return(await this.api.getHTML({type:"inner"})).html}async outerHtml(){return(await this.api.getHTML({type:"outer"})).html}async style(t){if(!m(t))throw Error("name must be a string");return(await this.api.getStyles({names:[t]})).styles[0]}async tap(){return this.api.tap()}async longpress(){return this.nvue?this.api.longpress():(await this.touchstart(),await v(350),this.touchend())}async trigger(t,e){const n={type:t};return w(e)||(n.detail=e),this.api.triggerEvent(n)}async touchstart(t){return this.api.touchstart(t)}async touchmove(t){return this.api.touchmove(t)}async touchend(t){return this.api.touchend(t)}async domProperty(t){return T(async t=>(await this.api.getDOMProperties({names:t})).properties,t)}_property(t){return T(async t=>(await this.api.getProperties({names:t})).properties,t)}send(t,e){return e.elementId=this.id,e.pageId=this.pageId,this.nodeId&&(e.nodeId=this.nodeId),this.videoId&&(e.videoId=this.videoId),this.puppet.send(t,e)}async callFunction(t,...e){return(await this.api.callFunction({functionName:t,args:e})).result}static create(t,e,n){let s,i=n.get(e.elementId);if(i)return i;if(e.nodeId)s=$;else switch(e.tagName){case"input":s=U;break;case"textarea":s=_;break;case"scroll-view":s=F;break;case"swiper":s=L;break;case"movable-view":s=H;break;case"switch":s=B;break;case"slider":s=J;break;case"video":s=W;break;default:s=O}return i=new s(t,e,n),n.set(e.elementId,i),i}}class $ extends O{async setData(t){return this.api.setData({data:t})}async data(t){const e={};return t&&(e.path=t),(await this.api.getData(e)).data}async callMethod(t,...e){return(await this.api.callMethod({method:t,args:e})).result}}class U extends O{async input(t){return this.callFunction("input.input",t)}}class _ extends O{async input(t){return this.callFunction("textarea.input",t)}}class F extends O{async scrollTo(t,e){return this.callFunction("scroll-view.scrollTo",t,e)}async property(t){return"scrollTop"===t?this.callFunction("scroll-view.scrollTop"):"scrollLeft"===t?this.callFunction("scroll-view.scrollLeft"):super.property(t)}async scrollWidth(){return this.callFunction("scroll-view.scrollWidth")}async scrollHeight(){return this.callFunction("scroll-view.scrollHeight")}}class L extends O{async swipeTo(t){return this.callFunction("swiper.swipeTo",t)}}class H extends O{async moveTo(t,e){return this.callFunction("movable-view.moveTo",t,e)}async property(t){return"x"===t?this._property("_translateX"):"y"===t?this._property("_translateY"):super.property(t)}}class B extends O{async tap(){return this.callFunction("switch.tap")}}class J extends O{async slideTo(t){return this.callFunction("slider.slideTo",t)}}class W extends O{async callContextMethod(t,...e){return await this.api.callContextMethod({method:t,args:e})}}class V extends q{constructor(t,e){super(t),this.id=e.id}async getData(t){return this.invokeMethod("Page.getData",t)}async setData(t){return this.invokeMethod("Page.setData",t)}async callMethod(t){return this.invokeMethod("Page.callMethod",t)}async getElement(t){return this.invokeMethod("Page.getElement",t)}async getElements(t){return this.invokeMethod("Page.getElements",t)}async getWindowProperties(t){return this.invokeMethod("Page.getWindowProperties",t)}invokeMethod(t,e={}){return e.pageId=this.id,this.invoke(t,e)}}D([R],V.prototype,"getData",null),D([R],V.prototype,"setData",null),D([R],V.prototype,"callMethod",null),D([S],V.prototype,"getElement",null),D([S],V.prototype,"getElements",null),D([S],V.prototype,"getWindowProperties",null);const z=require("util");class G{constructor(t,e){this.puppet=t,this.id=e.id,this.path=e.path,this.query=e.query,this.elementMap=new Map,this.api=new V(t,e)}toJSON(){return JSON.stringify({id:this.id,path:this.path,query:this.query})}toString(){return this.toJSON()}[z.inspect.custom](){return this.toJSON()}async waitFor(t){return y(t)?await v(t):h(t)?l(t):m(t)?l(async()=>(await this.$$(t)).length>0):void 0}async $(t){try{const e=await this.api.getElement({selector:t});return O.create(this.puppet,Object.assign({selector:t},e,{pageId:this.id}),this.elementMap)}catch(t){return null}}async $$(t){const{elements:e}=await this.api.getElements({selector:t});return e.map(e=>O.create(this.puppet,Object.assign({selector:t},e,{pageId:this.id}),this.elementMap))}async data(t){const e={};return t&&(e.path=t),(await this.api.getData(e)).data}async setData(t){return this.api.setData({data:t})}async size(){const[t,e]=await this.windowProperty(["document.documentElement.scrollWidth","document.documentElement.scrollHeight"]);return{width:t,height:e}}async callMethod(t,...e){return(await this.api.callMethod({method:t,args:e})).result}async scrollTop(){return this.windowProperty("document.documentElement.scrollTop")}async windowProperty(t){const e=m(t);e&&(t=[t]);const{properties:n}=await this.api.getWindowProperties({names:t});return e?n[0]:n}static create(t,e,n){let s=n.get(e.id);return s?(s.query=e.query,s):(s=new G(t,e),n.set(e.id,s),s)}}class X extends q{async getPageStack(){return this.invoke("App.getPageStack")}async callUniMethod(t){return this.invoke("App.callUniMethod",t)}async getCurrentPage(){return this.invoke("App.getCurrentPage")}async mockUniMethod(t){return this.invoke("App.mockUniMethod",t)}async callFunction(t){return this.invoke("App.callFunction",t)}async captureScreenshot(t){return this.invoke("App.captureScreenshot",t)}async exit(){return this.invoke("App.exit")}async addBinding(t){return this.invoke("App.addBinding",t)}async enableLog(){return this.invoke("App.enableLog")}onLogAdded(t){return this.on("App.logAdded",t)}onBindingCalled(t){return this.on("App.bindingCalled",t)}onExceptionThrown(t){return this.on("App.exceptionThrown",t)}}D([R],X.prototype,"getPageStack",null),D([R],X.prototype,"callUniMethod",null),D([R],X.prototype,"getCurrentPage",null),D([R],X.prototype,"mockUniMethod",null),D([S],X.prototype,"callFunction",null),D([S],X.prototype,"captureScreenshot",null),D([S],X.prototype,"exit",null),D([S],X.prototype,"addBinding",null),D([S],X.prototype,"enableLog",null);class Y extends q{async getInfo(){return this.invoke("Tool.getInfo")}async enableRemoteDebug(t){return this.invoke("Tool.enableRemoteDebug")}async close(){return this.invoke("Tool.close")}async getTestAccounts(){return this.invoke("Tool.getTestAccounts")}onRemoteDebugConnected(t){this.puppet.once("Tool.onRemoteDebugConnected",t),this.puppet.once("Tool.onPreviewConnected",t)}}function K(t){return new Promise(e=>setTimeout(e,t))}D([S],Y.prototype,"getInfo",null),D([S],Y.prototype,"enableRemoteDebug",null),D([S],Y.prototype,"close",null),D([S],Y.prototype,"getTestAccounts",null);class Q extends r.EventEmitter{constructor(t,e){super(),this.puppet=t,this.options=e,this.pageMap=new Map,this.appBindings=new Map,this.appApi=new X(t),this.toolApi=new Y(t),this.appApi.onLogAdded(t=>{this.emit("console",t)}),this.appApi.onBindingCalled(({name:t,args:e})=>{try{const n=this.appBindings.get(t);n&&n(...e)}catch(t){}}),this.appApi.onExceptionThrown(t=>{this.emit("exception",t)})}async pageStack(){return(await this.appApi.getPageStack()).pageStack.map(t=>G.create(this.puppet,t,this.pageMap))}async navigateTo(t){return this.changeRoute("navigateTo",t)}async redirectTo(t){return this.changeRoute("redirectTo",t)}async navigateBack(){return this.changeRoute("navigateBack")}async reLaunch(t){return this.changeRoute("reLaunch",t)}async switchTab(t){return this.changeRoute("switchTab",t)}async currentPage(){const{id:t,path:e,query:n}=await this.appApi.getCurrentPage();return G.create(this.puppet,{id:t,path:e,query:n},this.pageMap)}async systemInfo(){return this.callUniMethod("getSystemInfoSync")}async callUniMethod(t,...e){return(await this.appApi.callUniMethod({method:t,args:e})).result}async mockUniMethod(t,e,...n){return h(e)||m(s=e)&&(s=d(s),g(s,"function")||g(s,"() =>"))?this.appApi.mockUniMethod({method:t,functionDeclaration:e.toString(),args:n}):this.appApi.mockUniMethod({method:t,result:e});var s}async restoreUniMethod(t){return this.appApi.mockUniMethod({method:t})}async evaluate(t,...e){return(await this.appApi.callFunction({functionDeclaration:t.toString(),args:e})).result}async pageScrollTo(t){await this.callUniMethod("pageScrollTo",{scrollTop:t,duration:0})}async close(){try{await this.appApi.exit()}catch(t){}await K(1e3),this.puppet.disposeRuntimeServer(),await this.toolApi.close(),this.disconnect()}async teardown(){return this["disconnect"===this.options.teardown?"disconnect":"close"]()}async remote(t){if(!this.puppet.devtools.remote)return console.warn(`Failed to enable remote, ${this.puppet.devtools.name} is unimplemented`);const{qrCode:e}=await this.toolApi.enableRemoteDebug({auto:t});var n;e&&await(n=e,new Promise(t=>{C.generate(n,{small:!0},e=>{process.stdout.write(e),t(void 0)})}));const s=new Promise(t=>{this.toolApi.onRemoteDebugConnected(async()=>{await K(1e3),t(void 0)})}),i=new Promise(t=>{this.puppet.setRemoteRuntimeConnectionCallback(()=>{t(void 0)})});return Promise.all([s,i])}disconnect(){this.puppet.dispose()}on(t,e){return"console"===t&&this.appApi.enableLog(),super.on(t,e),this}async exposeFunction(t,e){if(this.appBindings.has(t))throw Error(`Failed to expose function with name ${t}: already exists!`);this.appBindings.set(t,e),await this.appApi.addBinding({name:t})}async checkVersion(){}async screenshot(t){const{data:e}=await this.appApi.captureScreenshot({fullPage:null==t?void 0:t.fullPage});if(!(null==t?void 0:t.path))return e;await u.writeFile(t.path,e,"base64")}async testAccounts(){return(await this.toolApi.getTestAccounts()).accounts}async changeRoute(t,e){return await this.callUniMethod(t,{url:e}),await K(3e3),this.currentPage()}}class Z{constructor(t){this.options=t}has(t){return!!this.options[t]}send(t,e,n){const s=this.options[e];if(!s)return Promise.reject(Error(`adapter for ${e} not found`));const i=s.reflect;return i?(s.params&&(n=s.params(n)),"function"==typeof i?i(t.send.bind(t),n):(e=i,t.send(e,n))):Promise.reject(Error(e+"'s reflect is required"))}}const tt=s("automator:puppet");function et(t){try{return require(t)}catch(t){}}function nt(t,e,s,i){const o=function(t,e,s){let i,o;return process.env.UNI_OUTPUT_DIR?(o=n.join(process.env.UNI_OUTPUT_DIR,"../.automator/"+e,".automator.json"),i=et(o)):(o=n.join(t,`dist/${s}/.automator/${e}`,".automator.json"),i=et(o),i||(o=n.join(t,`unpackage/dist/${s}/.automator/${e}`,".automator.json"),i=et(o))),tt(`${o}=>${JSON.stringify(i)}`),i}(t,s,i);if(!o||!o.wsEndpoint)return!1;const r=require("../package.json").version;if(o.version!==r)return tt(`unmet=>${o.version}!==${r}`),!1;const a=function(t){let e;try{const t=P.v4.sync();e=f.ip(t&&t.interface),e&&(/^10[.]|^172[.](1[6-9]|2[0-9]|3[0-1])[.]|^192[.]168[.]/.test(e)||(e=void 0))}catch(t){}return"ws://"+(e||"localhost")+":"+t}(e);return tt("wsEndpoint=>"+a),o.wsEndpoint===a}class st extends r.EventEmitter{constructor(t,e){if(super(),e)this.target=e;else{if(this.target=null,"h5"===t)try{this.target=require("@dcloudio/uni-h5/lib/h5/uni.automator.js")}catch(t){}this.target||(this.target=require(`@dcloudio/uni-${"app"===t?"app-plus":t}/lib/uni.automator.js`))}if(!this.target)throw Error("puppet is not provided");this.platform=t,this.adapter=new Z(this.target.adapter||{})}setCompiler(t){this.compiler=t}setRuntimeServer(t){this.wss=t}setRemoteRuntimeConnectionCallback(t){this.remoteRuntimeConnectionCallback=t}setRuntimeConnection(t){this.runtimeConnection=t,this.remoteRuntimeConnectionCallback&&(this.remoteRuntimeConnectionCallback(),this.remoteRuntimeConnectionCallback=null)}setDevtoolConnection(t){this.devtoolConnection=t}disposeRuntimeServer(){this.wss&&this.wss.close()}disposeRuntime(){this.runtimeConnection.dispose()}disposeDevtool(){this.compiler&&this.compiler.stop(),this.devtoolConnection&&this.devtoolConnection.dispose()}dispose(){this.disposeRuntime(),this.disposeDevtool(),this.disposeRuntimeServer()}send(t,e){return this.runtimeConnection.send(t,e)}validateProject(t){const s=this.target.devtools.required;return!s||!s.find(s=>!e.existsSync(n.join(t,s)))}validateDevtools(t){const e=this.target.devtools.validate;return e?e(t,this):Promise.resolve(t)}createDevtools(t,e,n){const s=this.target.devtools.create;return s?(e.timeout=n,s(t,e,this)):Promise.resolve()}shouldCompile(t,e,n,s){this.compiled=!0;const i=this.target.shouldCompile;return i?this.compiled=i(n,s):!0===n.compile?this.compiled=!0:this.compiled=!nt(t,e,this.platform,this.mode),this.compiled}get checkProperty(){return"mp-weixin"===this.platform}get devtools(){return this.target.devtools}get mode(){const t=this.target.mode;return t||("production"===process.env.NODE_ENV?"build":"dev")}}const it=s("automator:compiler"),ot=/The\s+(.*)\s+directory is ready/;class rt{constructor(t){this.puppet=t,this.puppet.setCompiler(this)}compile(t){const s=this.puppet.mode,i=this.puppet.platform;let o=t.silent;const r=t.port,a=t.host,c=`${s}:${i}`,p=t.projectPath,[l,u]=this.getSpawnArgs(t,c);u.push("--auto-port"),u.push(E(r)),a&&(u.push("--auto-host"),u.push(a));const h={cwd:t.cliPath,env:Object.assign(Object.assign({},process.env),{NODE_ENV:"build"===s?"production":"development"})};return new Promise((t,r)=>{const a=r=>{const a=r.toString().trim();if(!o&&console.log(a),a.includes("- Network")||a.includes("> Network")){const e=a.match(/Network:(.*)/)[1].trim();it("url: "+e),t({path:e})}else if(a.includes("DONE Build complete")){const r=a.match(ot);let c="";r&&r.length>1?c=n.join(p,r[1]):(c=n.join(p,`dist/${s}/${i}`),e.existsSync(c)||(c=n.join(p,`unpackage/dist/${s}/${i}`))),o=!0,this.stop(),t({path:c})}};it(`${l} ${u.join(" ")} %o`,h),this.cliProcess=k.spawn(l,u,h),this.cliProcess.on("error",t=>{r(t)}),this.cliProcess.stdout.on("data",a),this.cliProcess.stderr.on("data",a)})}stop(){this.cliProcess&&this.cliProcess.kill("SIGTERM")}getSpawnArgs(t,e){let s;const i=t.cliPath;try{s=require(n.join(i,"package.json"))}catch(t){}return s&&s.scripts&&s.scripts[e]?[process.env.UNI_NPM_PATH||(/^win/.test(process.platform)?"npm.cmd":"npm"),["run",e,"--"]]:(process.env.UNI_INPUT_DIR=t.projectPath,process.env.UNI_OUTPUT_DIR=n.join(t.projectPath,`unpackage/dist/${this.puppet.mode}/${this.puppet.platform}`),[process.env.UNI_NODE_PATH||"node",[n.join(i,"bin/uniapp-cli.js")]])}}class at{async launch(t){let e=("app"===t.platform?t.app||t["app-plus"]:t[t.platform])||{};this.puppet=new st(t.platform,e.puppet);const{port:i,cliPath:o,timeout:r,projectPath:a}=await this.validate(t);e=await this.puppet.validateDevtools(e);let c=this.puppet.shouldCompile(a,i,t,e),p=process.env.UNI_OUTPUT_DIR||a;if(c||this.puppet.validateProject(p)||(p=n.join(a,"dist/"+this.puppet.mode+"/"+this.puppet.platform),this.puppet.validateProject(p)||(p=n.join(a,"unpackage/dist/"+this.puppet.mode+"/"+this.puppet.platform),this.puppet.validateProject(p)||(c=!0))),c){this.puppet.compiled=t.compile=!0,this.compiler=new rt(this.puppet);const e=await this.compiler.compile({host:t.host,port:i,cliPath:o,projectPath:a,silent:!!t.silent});e.path&&(p=e.path)}const l=[];return l.push(this.createRuntimeConnection(i,r)),l.push(this.puppet.createDevtools(p,e,r)),new Promise((t,n)=>{Promise.all(l).then(([n,o])=>{n&&this.puppet.setRuntimeConnection(n),o&&this.puppet.setDevtoolConnection(o),s("automator:program")("ready");const r=e.teardown||"disconnect";t(new Q(this.puppet,{teardown:r,port:i}))}).catch(t=>n(t))})}resolveCliPath(t){if(!t)return t;try{const{dependencies:e,devDependencies:s}=require(n.join(t,"package.json"));if(ct(s)||ct(e))return t}catch(t){}}resolveProjectPath(t,s){return t||(t=process.env.UNI_INPUT_DIR||process.cwd()),i(t)&&(t=n.resolve(t)),e.existsSync(t)||function(t){throw Error(t)}(`Project path ${t} doesn't exist`),t}async validate(t){const e=this.resolveProjectPath(t.projectPath,t);let n=process.env.UNI_CLI_PATH||t.cliPath;if(n=this.resolveCliPath(n||""),!n&&(n=this.resolveCliPath(process.cwd())),!n&&(n=this.resolveCliPath(e)),!n)throw Error("cliPath is not provided");return{port:await async function(t,e){const n=await M(t||e);if(t&&n!==t)throw Error(`Port ${t} is in use, please specify another port`);return n}(t.port||9520),cliPath:n,timeout:t.timeout||6e4,projectPath:e}}async createRuntimeConnection(t,e){return I.createRuntimeConnection(t,this.puppet,e)}}function ct(t){return!!t&&!(!t["@dcloudio/vue-cli-plugin-uni"]&&!t["@dcloudio/vite-plugin-uni"])}module.exports=class{constructor(){this.launcher=new at}async launch(t){return this.launcher.launch(t)}}; diff --git a/packages/uni-automator/dist/teardown.js b/packages/uni-automator/dist/teardown.js index a2a3de34d..7c1aa864b 100644 --- a/packages/uni-automator/dist/teardown.js +++ b/packages/uni-automator/dist/teardown.js @@ -1,13 +1 @@ -'use strict'; - -async function teardown() { - const program = global.program; - program && program.teardown(); - await new Promise((resolve) => { - setTimeout(() => { - resolve(); - }, 3000); - }); -} - -module.exports = teardown; +"use strict";module.exports=async function(){const o=global.program;o&&o.teardown(),await new Promise(o=>{setTimeout(()=>{o(void 0)},3e3)})}; diff --git a/packages/uni-h5/lib/automator.js b/packages/uni-h5/lib/automator.js index 3f5ee394f..5cc2a4c05 100644 --- a/packages/uni-h5/lib/automator.js +++ b/packages/uni-h5/lib/automator.js @@ -1,85 +1,3 @@ -function initPage(adapter) { - return { - 'Page.getElement': function (params) { - return adapter.querySelector( - adapter.getDocument(params.pageId), - params.selector - ) - }, - 'Page.getElements': function (params) { - return adapter.querySelectorAll( - adapter.getDocument(params.pageId), - params.selector - ) - }, - 'Page.getWindowProperties': function (params) { - return adapter.queryProperties( - adapter.getWindow(params.pageId), - params.names - ) - }, - } -} - -function initElement(adapter) { - var getEl = function (params) { - return adapter.getEl(params.elementId, params.pageId) - } - return { - 'Element.getElement': function (params) { - return adapter.querySelector(getEl(params), params.selector) - }, - 'Element.getElements': function (params) { - return adapter.querySelectorAll(getEl(params), params.selector) - }, - 'Element.getDOMProperties': function (params) { - return adapter.queryProperties(getEl(params), params.names) - }, - 'Element.getProperties': function (params) { - var el = getEl(params) - var ctx = el.__vue__ || el.attr || {} - return adapter.queryProperties(ctx, params.names) - }, - 'Element.getOffset': function (params) { - return adapter.getOffset(getEl(params)) - }, - 'Element.getAttributes': function (params) { - return adapter.queryAttributes(getEl(params), params.names) - }, - 'Element.getStyles': function (params) { - return adapter.queryStyles(getEl(params), params.names) - }, - 'Element.getHTML': function (params) { - return adapter.queryHTML(getEl(params), params.type) - }, - 'Element.tap': function (params) { - return adapter.dispatchTapEvent(getEl(params)) - }, - 'Element.longpress': function (params) { - return adapter.dispatchLongpressEvent(getEl(params)) - }, - 'Element.touchstart': function (params) { - return adapter.dispatchTouchEvent(getEl(params), 'touchstart', params) - }, - 'Element.touchmove': function (params) { - return adapter.dispatchTouchEvent(getEl(params), 'touchmove', params) - }, - 'Element.touchend': function (params) { - return adapter.dispatchTouchEvent(getEl(params), 'touchend', params) - }, - 'Element.callFunction': function (params) { - return adapter.callFunction( - getEl(params), - params.functionName, - params.args - ) - }, - 'Element.triggerEvent': function (params) { - return adapter.triggerEvent(getEl(params), params.type, params.detail) - }, - } -} - /*! ***************************************************************************** Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use @@ -94,419 +12,354 @@ MERCHANTABLITY OR NON-INFRINGEMENT. See the Apache Version 2.0 License for specific language governing permissions and limitations under the License. ***************************************************************************** */ - -function __spreadArrays() { - for (var s = 0, i = 0, il = arguments.length; i < il; i++) - s += arguments[i].length - for (var r = Array(s), k = 0, i = 0; i < il; i++) - for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++) - r[k] = a[j] +function e() { + for (var e = 0, t = 0, n = arguments.length; t < n; t++) + e += arguments[t].length + var r = Array(e), + o = 0 + for (t = 0; t < n; t++) + for (var u = arguments[t], i = 0, a = u.length; i < a; i++, o++) r[o] = u[i] return r } - -// Unique ID creation requires a high quality random # generator. In the browser we therefore -// require the crypto API and do not support built-in fallback to lower quality random number -// generators (like Math.random()). -// getRandomValues needs to be invoked in a context where "this" is a Crypto implementation. Also, -// find the complete implementation of crypto (msCrypto) on IE11. -var getRandomValues = - (typeof crypto != 'undefined' && - crypto.getRandomValues && - crypto.getRandomValues.bind(crypto)) || - (typeof msCrypto != 'undefined' && - typeof msCrypto.getRandomValues == 'function' && - msCrypto.getRandomValues.bind(msCrypto)) -var rnds8 = new Uint8Array(16) // eslint-disable-line no-undef - -function rng() { - if (!getRandomValues) { +var t = + ('undefined' != typeof crypto && + crypto.getRandomValues && + crypto.getRandomValues.bind(crypto)) || + ('undefined' != typeof msCrypto && + 'function' == typeof msCrypto.getRandomValues && + msCrypto.getRandomValues.bind(msCrypto)), + n = new Uint8Array(16) +function r() { + if (!t) throw new Error( 'crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported' ) - } - - return getRandomValues(rnds8) -} - -/** - * Convert array of 16 byte values to UUID string format of the form: - * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX - */ -var byteToHex = [] - -for (var i = 0; i < 256; ++i) { - byteToHex[i] = (i + 0x100).toString(16).substr(1) -} - -function bytesToUuid(buf, offset) { - var i = offset || 0 - var bth = byteToHex // join used to fix memory issue caused by concatenation: https://bugs.chromium.org/p/v8/issues/detail?id=3175#c4 - - return [ - bth[buf[i++]], - bth[buf[i++]], - bth[buf[i++]], - bth[buf[i++]], - '-', - bth[buf[i++]], - bth[buf[i++]], - '-', - bth[buf[i++]], - bth[buf[i++]], - '-', - bth[buf[i++]], - bth[buf[i++]], - '-', - bth[buf[i++]], - bth[buf[i++]], - bth[buf[i++]], - bth[buf[i++]], - bth[buf[i++]], - bth[buf[i++]], - ].join('') -} - -function v4(options, buf, offset) { - var i = (buf && offset) || 0 - - if (typeof options == 'string') { - buf = options === 'binary' ? new Array(16) : null - options = null - } - - options = options || {} - var rnds = options.random || (options.rng || rng)() // Per 4.4, set bits for version and `clock_seq_hi_and_reserved` - - rnds[6] = (rnds[6] & 0x0f) | 0x40 - rnds[8] = (rnds[8] & 0x3f) | 0x80 // Copy bytes to buffer, if provided - - if (buf) { - for (var ii = 0; ii < 16; ++ii) { - buf[i + ii] = rnds[ii] - } - } - - return buf || bytesToUuid(rnds) -} - -var hasOwnProperty = Object.prototype.hasOwnProperty -var hasOwn = function (val, key) { - return hasOwnProperty.call(val, key) -} -var isUndef = function (v) { - return v === undefined || v === null -} -var isArray = Array.isArray -var isPromise = function (obj) { + return t(n) +} +for (var o = [], u = 0; u < 256; ++u) o[u] = (u + 256).toString(16).substr(1) +function i(e, t, n) { + var u = (t && n) || 0 + 'string' == typeof e && + ((t = 'binary' === e ? new Array(16) : null), (e = null)) + var i = (e = e || {}).random || (e.rng || r)() + if (((i[6] = (15 & i[6]) | 64), (i[8] = (63 & i[8]) | 128), t)) + for (var a = 0; a < 16; ++a) t[u + a] = i[a] return ( - !!obj && - (typeof obj === 'object' || typeof obj === 'function') && - typeof obj.then === 'function' + t || + (function (e, t) { + var n = t || 0, + r = o + return [ + r[e[n++]], + r[e[n++]], + r[e[n++]], + r[e[n++]], + '-', + r[e[n++]], + r[e[n++]], + '-', + r[e[n++]], + r[e[n++]], + '-', + r[e[n++]], + r[e[n++]], + '-', + r[e[n++]], + r[e[n++]], + r[e[n++]], + r[e[n++]], + r[e[n++]], + r[e[n++]], + ].join('') + })(i) ) } -var cacheStringFunction = function (fn) { - var cache = Object.create(null) - return function (str) { - var hit = cache[str] - return hit || (cache[str] = fn(str)) - } -} -var camelizeRE = /-(\w)/g -var camelize = cacheStringFunction(function (str) { - return str.replace(camelizeRE, function (_, c) { - return c ? c.toUpperCase() : '' - }) -}) -var capitalize = cacheStringFunction(function (str) { - return str.charAt(0).toUpperCase() + str.slice(1) -}) -var PATH_RE = - /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g -function getPaths(path, data) { - if (isArray(path)) { - return path - } - if (data && hasOwn(data, path)) { - return [path] - } - var res = [] - path.replace(PATH_RE, function (match, p1, offset, string) { - res.push(offset ? string.replace(/\\(\\)?/g, '$1') : p1 || match) - return string - }) - return res -} -function getDataByPath(data, path) { - var paths = getPaths(path, data) - var dataPath - for (dataPath = paths.shift(); !isUndef(dataPath); ) { - if (null == (data = data[dataPath])) { - return - } - dataPath = paths.shift() - } - return data -} -function getVmNodeId(vm) { - //@ts-ignore - { - return vm._uid - } -} - -var elementMap = new Map() -function getElId(element) { - var elementId = element._id - if (!elementId) { - elementId = v4() - element._id = elementId - elementMap.set(elementId, { id: elementId, element: element }) - } - return elementId -} -function isValidEl(el) { - if (el) { - var tagName = el.tagName - return tagName.indexOf('UNI-') === 0 || tagName === 'BODY' - } - return false -} -function transEl(el) { - if (!isValidEl(el)) { - throw Error('no such element') - } - var elem = { - elementId: getElId(el), - tagName: el.tagName.toLocaleLowerCase().replace('uni-', ''), - } - var vm = el.__vue__ - if (vm) { - if (vm.$parent && vm.$parent.$el === el) { - vm = vm.$parent - } - if (vm && !vm.$options.isReserved) { - elem.nodeId = getVmNodeId(vm) +var a = Object.prototype.hasOwnProperty, + c = function (e) { + return null == e + }, + s = Array.isArray, + f = function (e) { + var t = Object.create(null) + return function (n) { + return t[n] || (t[n] = e(n)) } - } - if (elem.tagName === 'video') { - elem.videoId = elem.nodeId - } - return elem + }, + l = /-(\w)/g, + g = f(function (e) { + return e.replace(l, function (e, t) { + return t ? t.toUpperCase() : '' + }) + }), + p = f(function (e) { + return e.charAt(0).toUpperCase() + e.slice(1) + }), + d = + /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g +function m(e, t) { + if (s(e)) return e + if (t && ((n = t), (r = e), a.call(n, r))) return [e] + var n, + r, + o = [] + return ( + e.replace(d, function (e, t, n, r) { + return o.push(n ? r.replace(/\\(\\)?/g, '$1') : t || e), r + }), + o + ) } -function formatHTML(html) { - return html - .replace(/\n/g, '') - .replace( - /(]*>)(]*>[^<]*<\/span>)(.*?<\/uni-text>)/g, - '$1$3' - ) - .replace(/<\/?[^>]*>/g, function (replacement) { - if (-1 < replacement.indexOf('' - } else if ('' === replacement) { - return '' - } else if ( - 0 !== replacement.indexOf(']*>)(]*>[^<]*<\/span>)(.*?<\/uni-text>)/g, + '$1$3' + ) + .replace(/<\/?[^>]*>/g, function (e) { + return -1 < e.indexOf('' + : '' === e + ? '' + : 0 !== e.indexOf(' { - if (selector.type === 'tag') { - const value = selector.value - if (value === 'page') { - //@ts-ignore - { - selector.value = 'uni-page-body' - } - } else { - selector.value = 'uni-' + value - } +var t = e(require('debug')), + o = e(require('postcss-selector-parser')) +const n = t('automator:devtool') +function r(e) { + e.walk((e) => { + if ('tag' === e.type) { + const t = e.value + e.value = 'page' === t ? 'uni-page-body' : 'uni-' + t } }) } -function transSelector(method) { - return { - reflect: async (send, params) => send(method, params, false), - params(params) { - if (params.selector) { - params.selector = parser(transform).processSync(params.selector) - } - return params - }, - } -} -const methods = [ +const s = [ 'Page.getElement', 'Page.getElements', 'Element.getElement', 'Element.getElements', ] -function initAdapter(adapter) { - methods.forEach((method) => { - adapter[method] = transSelector(method) - }) -} - -const debugDevtools = debug('automator:devtool') -async function validateDevtools(options) { - options.options = options.options || {} - if (options.executablePath && !options.options.executablePath) { - options.options.executablePath = options.executablePath - } - options.options.defaultViewport = Object.assign( - { - width: 375, - height: 667, - deviceScaleFactor: 2, - hasTouch: true, - isMobile: true, - }, - options.options.defaultViewport || {} +const i = ['chromium', 'firefox', 'webkit'] +let a = !1 +try { + a = !!require('playwright') +} catch (e) {} +const c = new Map() +function p(e = 'chromium') { + const t = e && i.includes(e) ? e : i[0] + let o = c.get(t) + return ( + o || + ((o = (function (e) { + if ('webkit' === e) return l('webkit') + if ('firefox' === e) return l('firefox') + return a + ? l('chromium') + : (function () { + const e = require('puppeteer') + let t, o + return { + type: 'chromium', + provider: 'puppeteer', + async open(r, s, i) { + t = await e.launch(s.options) + const a = t.process() + a ? n('%s %o', a.spawnfile, s.options) : n('%o', s.options), + (o = await t.newPage()), + o.on('console', (e) => { + i.emit('App.logAdded', { + type: e.type(), + args: [e.text()], + }) + }), + o.on('pageerror', (e) => { + i.emit('App.exceptionThrown', e) + }), + await o.goto(s.url || r), + await o.waitFor(1e3) + }, + close: () => t.close(), + screenshot: (e = !1) => + o.screenshot({ encoding: 'base64', fullPage: e }), + } + })() + })(t)), + c.set(t, o)), + o ) - if (!options.teardown) { - options.teardown = - options.options.headless === false ? 'disconnect' : 'close' - } - return options } -let browser -let page -async function createDevtools(url, options, puppet) { - browser = await puppeteer.launch(options.options) - const process = browser.process() - if (process) { - debugDevtools('%s %o', process.spawnfile, options.options) - } else { - debugDevtools('%o', options.options) +function l(e) { + const t = require('playwright') + let o, r + return { + type: e, + provider: 'playwright', + async open(s, i, a) { + ;(o = await t[e].launch(i.options)), + 'firefox' === e && (i.contextOptions.isMobile = !1), + n('browser.newContext ' + JSON.stringify(i.contextOptions)) + const c = await o.newContext(i.contextOptions) + ;(r = await c.newPage()), + r.on('console', (e) => { + a.emit('App.logAdded', { type: e.type(), args: [e.text()] }) + }), + r.on('pageerror', (e) => { + a.emit('App.exceptionThrown', e) + }), + await r.goto(i.url || s), + await r.waitForTimeout(1e3) + }, + close: () => o.close(), + screenshot: (e = !1) => + r.screenshot({ fullPage: e }).then((e) => e.toString('base64')), } - page = await browser.newPage() - page.on('console', (msg) => { - puppet.emit('App.logAdded', { type: msg.type(), args: [msg.text()] }) - }) - page.on('pageerror', (err) => { - puppet.emit('App.exceptionThrown', err) - }) - await page.goto(options.url || url) - await page.waitFor(1000) } -const adapter = { +let u +const f = { 'Tool.close': { reflect: async () => { - await browser.close() + await u.close() }, }, - 'App.exit': { - reflect: async () => {}, - }, - 'App.enableLog': { - reflect: () => Promise.resolve(), - }, + 'App.exit': { reflect: async () => {} }, + 'App.enableLog': { reflect: () => Promise.resolve() }, 'App.captureScreenshot': { - reflect: async (send, params) => { - const data = await page.screenshot({ - encoding: 'base64', - fullPage: !!params.fullPage, - }) - debugDevtools(`App.captureScreenshot ${data.length}`) - return { - data, - } + reflect: async (e, t) => { + const o = await u.screenshot(!!t.fullPage) + return n('App.captureScreenshot ' + o.length), { data: o } }, }, } -initAdapter(adapter) -const puppet = { +!(function (e) { + s.forEach((t) => { + e[t] = (function (e) { + return { + reflect: async (t, o) => t(e, o, !1), + params: (e) => ( + e.selector && (e.selector = o(r).processSync(e.selector)), e + ), + } + })(t) + }) +})(f) +const h = { devtools: { - name: 'google chrome', + name: 'browser', paths: [], - validate: validateDevtools, - create: createDevtools, - }, - shouldCompile(options, devtoolsOptions) { - if (devtoolsOptions.url) { - return false - } - return true + validate: async function (e) { + return ( + (e.options = e.options || {}), + e.executablePath && + !e.options.executablePath && + (e.options.executablePath = e.executablePath), + (e.contextOptions = { + viewport: Object.assign( + { width: 375, height: 667 }, + e.options.defaultViewport || {} + ), + hasTouch: !0, + isMobile: !0, + deviceScaleFactor: 2, + }), + (e.options.defaultViewport = Object.assign( + { + width: 375, + height: 667, + deviceScaleFactor: 2, + hasTouch: !0, + isMobile: !0, + }, + e.options.defaultViewport || {} + )), + e.teardown || + (e.teardown = !1 === e.options.headless ? 'disconnect' : 'close'), + e + ) + }, + create: async function (e, t, o) { + ;(u = p(process.env.BROWSER)), + n( + 'createDevtools ' + + (u.provider + ' ' + u.type + ' ' + JSON.stringify(t)) + ), + await u.open(e, t, o) + }, }, - adapter, + shouldCompile: (e, t) => !t.url, + adapter: f, } - -module.exports = puppet +module.exports = h diff --git a/packages/uni-mp-baidu/lib/automator.js b/packages/uni-mp-baidu/lib/automator.js index 748c83f0e..f277a1e46 100644 --- a/packages/uni-mp-baidu/lib/automator.js +++ b/packages/uni-mp-baidu/lib/automator.js @@ -1,488 +1 @@ -var hasOwnProperty = Object.prototype.hasOwnProperty -var hasOwn = function (val, key) { - return hasOwnProperty.call(val, key) -} -var isUndef = function (v) { - return v === undefined || v === null -} -var isArray = Array.isArray -var isPromise = function (obj) { - return ( - !!obj && - (typeof obj === 'object' || typeof obj === 'function') && - typeof obj.then === 'function' - ) -} -var cacheStringFunction = function (fn) { - var cache = Object.create(null) - return function (str) { - var hit = cache[str] - return hit || (cache[str] = fn(str)) - } -} -var camelizeRE = /-(\w)/g -var camelize = cacheStringFunction(function (str) { - return str.replace(camelizeRE, function (_, c) { - return c ? c.toUpperCase() : '' - }) -}) -var capitalize = cacheStringFunction(function (str) { - return str.charAt(0).toUpperCase() + str.slice(1) -}) -var PATH_RE = - /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g -function getPaths(path, data) { - if (isArray(path)) { - return path - } - if (data && hasOwn(data, path)) { - return [path] - } - var res = [] - path.replace(PATH_RE, function (match, p1, offset, string) { - res.push(offset ? string.replace(/\\(\\)?/g, '$1') : p1 || match) - return string - }) - return res -} -function getDataByPath(data, path) { - var paths = getPaths(path, data) - var dataPath - for (dataPath = paths.shift(); !isUndef(dataPath); ) { - if (null == (data = data[dataPath])) { - return - } - dataPath = paths.shift() - } - return data -} - -function getPageId(page) { - if (page.__wxWebviewId__) { - //mp-weixin - return page.__wxWebviewId__ - } - if (page.privateProperties) { - //mp-baidu - return page.privateProperties.slaveId - } - if (page.$page) { - //h5 and app-plus - return page.$page.id - } -} -function getPagePath(page) { - return page.route || page.uri -} -function getPageQuery(page) { - return page.options || (page.$page && page.$page.options) || {} -} -function parsePage(page) { - return { - id: getPageId(page), - path: getPagePath(page), - query: getPageQuery(page), - } -} -function getPageById(id) { - return getCurrentPages().find(function (page) { - return getPageId(page) === id - }) -} -function getPageVm(id) { - var page = getPageById(id) - return page && page.$vm -} -function getNodeId(scope) { - return scope.__wxExparserNodeId__ || scope.nodeId || scope.id -} -function matchNodeId(vm, nodeId) { - return vm.$scope && getNodeId(vm.$scope) === nodeId -} -function findComponentVm(vm, nodeId) { - var res - if (vm) { - if (matchNodeId(vm, nodeId)) { - res = vm - } else { - vm.$children.find(function (child) { - res = findComponentVm(child, nodeId) - return res - }) - } - } - return res -} -function getComponentVm(pageId, nodeId) { - var pageVm = getPageVm(pageId) - return pageVm && findComponentVm(pageVm, nodeId) -} -function getData(vm, path) { - var data - if (vm) { - data = path ? getDataByPath(vm.$data, path) : Object.assign({}, vm.$data) - } - return Promise.resolve({ data: data }) -} -function setData(vm, data) { - if (vm) { - Object.keys(data).forEach(function (name) { - vm[name] = data[name] - }) - } - return Promise.resolve() -} -var CALL_METHOD_ERROR -;(function (CALL_METHOD_ERROR) { - CALL_METHOD_ERROR['VM_NOT_EXISTS'] = 'VM_NOT_EXISTS' - CALL_METHOD_ERROR['METHOD_NOT_EXISTS'] = 'METHOD_NOT_EXISTS' -})(CALL_METHOD_ERROR || (CALL_METHOD_ERROR = {})) -function callMethod(vm, method, args) { - return new Promise(function (resolve, reject) { - if (!vm) { - return reject(CALL_METHOD_ERROR.VM_NOT_EXISTS) - } - if (!vm[method]) { - return reject(CALL_METHOD_ERROR.VM_NOT_EXISTS) - } - var ret = vm[method].apply(vm, args) - isPromise(ret) - ? ret.then(function (res) { - resolve({ result: res }) - }) - : resolve({ result: ret }) - }) -} - -var SYNC_APIS = [ - 'stopRecord', - 'getRecorderManager', - 'pauseVoice', - 'stopVoice', - 'pauseBackgroundAudio', - 'stopBackgroundAudio', - 'getBackgroundAudioManager', - 'createAudioContext', - 'createInnerAudioContext', - 'createVideoContext', - 'createCameraContext', - 'createMapContext', - 'canIUse', - 'startAccelerometer', - 'stopAccelerometer', - 'startCompass', - 'stopCompass', - 'hideToast', - 'hideLoading', - 'showNavigationBarLoading', - 'hideNavigationBarLoading', - 'navigateBack', - 'createAnimation', - 'pageScrollTo', - 'createSelectorQuery', - 'createCanvasContext', - 'createContext', - 'drawCanvas', - 'hideKeyboard', - 'stopPullDownRefresh', - 'arrayBufferToBase64', - 'base64ToArrayBuffer', -] -var originUni = {} -var SYNC_API_RE = /Sync$/ -var MOCK_API_BLACKLIST_RE = /^on|^off/ -function isSyncApi(method) { - return SYNC_API_RE.test(method) || SYNC_APIS.indexOf(method) !== -1 -} -function canIMock(method) { - return !MOCK_API_BLACKLIST_RE.test(method) -} -var App = { - getPageStack: function () { - return Promise.resolve({ - pageStack: getCurrentPages().map(function (page) { - return parsePage(page) - }), - }) - }, - getCurrentPage: function () { - var pages = getCurrentPages() - var len = pages.length - return new Promise(function (resolve, reject) { - if (!len) { - reject(Error('getCurrentPages().length=0')) - } else { - resolve(parsePage(pages[len - 1])) - } - }) - }, - callUniMethod: function (params) { - var method = params.method - var args = params.args - return new Promise(function (resolve, reject) { - if (!uni[method]) { - return reject(Error('uni.' + method + ' not exists')) - } - if (isSyncApi(method)) { - return resolve({ - result: uni[method].apply(uni, args), - }) - } - var params = [ - Object.assign({}, args[0] || {}, { - success: function (result) { - var timeout = method === 'pageScrollTo' ? 350 : 0 - setTimeout(function () { - resolve({ result: result }) - }, timeout) - }, - fail: function (res) { - reject(Error(res.errMsg.replace(method + ':fail ', ''))) - }, - }), - ] - uni[method].apply(uni, params) - }) - }, - mockUniMethod: function (params) { - var method = params.method - if (!uni[method]) { - throw Error('uni.' + method + ' not exists') - } - if (!canIMock(method)) { - throw Error("You can't mock uni." + method) - } - // TODO getOwnPropertyDescriptor? - var result = params.result - if (isUndef(result)) { - // restoreUniMethod - if (originUni[method]) { - uni[method] = originUni[method] - delete originUni[method] - } - return Promise.resolve() - } - var mockFn = isSyncApi(method) - ? function () { - return result - } - : function (params) { - setTimeout(function () { - var isFail = result.errMsg && result.errMsg.indexOf(':fail') !== -1 - if (isFail) { - params.fail && params.fail(result) - } else { - params.success && params.success(result) - } - params.complete && params.complete(result) - }, 4) - } - // mockFn.origin = originUni[method] || uni[method]; - if (!originUni[method]) { - originUni[method] = uni[method] - } - uni[method] = mockFn - return Promise.resolve() - }, -} - -var Page = { - getData: function (params) { - return getData(getPageVm(params.pageId), params.path) - }, - setData: function (params) { - return setData(getPageVm(params.pageId), params.data) - }, - callMethod: function (params) { - var _a - var err = - ((_a = {}), - (_a[CALL_METHOD_ERROR.VM_NOT_EXISTS] = - 'Page[' + params.pageId + '] not exists'), - (_a[CALL_METHOD_ERROR.METHOD_NOT_EXISTS] = - 'page.' + params.method + ' not exists'), - _a) - return new Promise(function (resolve, reject) { - callMethod(getPageVm(params.pageId), params.method, params.args) - .then(function (res) { - return resolve(res) - }) - .catch(function (type) { - reject(Error(err[type])) - }) - }) - }, -} - -function getNodeId$1(params) { - return params.nodeId || params.elementId -} -var Element = { - getData: function (params) { - return getData( - getComponentVm(params.pageId, getNodeId$1(params)), - params.path - ) - }, - setData: function (params) { - return setData( - getComponentVm(params.pageId, getNodeId$1(params)), - params.data - ) - }, - callMethod: function (params) { - var _a - var nodeId = getNodeId$1(params) - var err = - ((_a = {}), - (_a[CALL_METHOD_ERROR.VM_NOT_EXISTS] = - 'Component[' + params.pageId + ':' + nodeId + '] not exists'), - (_a[CALL_METHOD_ERROR.METHOD_NOT_EXISTS] = - 'component.' + params.method + ' not exists'), - _a) - return new Promise(function (resolve, reject) { - callMethod( - getComponentVm(params.pageId, nodeId), - params.method, - params.args - ) - .then(function (res) { - return resolve(res) - }) - .catch(function (type) { - reject(Error(err[type])) - }) - }) - }, -} - -// Unique ID creation requires a high quality random # generator. In the browser we therefore -// require the crypto API and do not support built-in fallback to lower quality random number -// generators (like Math.random()). -// getRandomValues needs to be invoked in a context where "this" is a Crypto implementation. Also, -// find the complete implementation of crypto (msCrypto) on IE11. -var getRandomValues = - (typeof crypto != 'undefined' && - crypto.getRandomValues && - crypto.getRandomValues.bind(crypto)) || - (typeof msCrypto != 'undefined' && - typeof msCrypto.getRandomValues == 'function' && - msCrypto.getRandomValues.bind(msCrypto)) - -/** - * Convert array of 16 byte values to UUID string format of the form: - * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX - */ -var byteToHex = [] - -for (var i = 0; i < 256; ++i) { - byteToHex[i] = (i + 0x100).toString(16).substr(1) -} - -var BUILITIN = [ - 'movable-view', - 'picker', - 'ad', - 'button', - 'checkbox-group', - 'checkbox', - 'form', - 'icon', - 'label', - 'movable-area', - 'navigator', - 'picker-view-column', - 'picker-view', - 'progress', - 'radio-group', - 'radio', - 'rich-text', - 'u-slider', - 'swiper-item', - 'swiper', - 'switch', -] -var BUILITIN_ALIAS = BUILITIN.map(function (tag) { - return capitalize(camelize(tag)) -}) - -var Api = {} -Object.keys(App).forEach(function (method) { - Api['App.' + method] = App[method] -}) -Object.keys(Page).forEach(function (method) { - Api['Page.' + method] = Page[method] -}) -Object.keys(Element).forEach(function (method) { - Api['Element.' + method] = Element[method] -}) -var wsEndpoint = process.env.UNI_AUTOMATOR_WS_ENDPOINT -var socketTask -function send(data) { - socketTask.send({ data: JSON.stringify(data) }) -} -function onMessage(res) { - var _a = JSON.parse(res.data), - id = _a.id, - method = _a.method, - params = _a.params - var data = { id: id } - var fn = Api[method] - if (!fn) { - if (!fn) { - data.error = { - message: method + ' unimplemented', - } - return send(data) - } - } - try { - fn(params) - .then(function (res) { - res && (data.result = res) - }) - .catch(function (err) { - data.error = { - message: err.message, - } - }) - .finally(function () { - send(data) - }) - } catch (err) { - data.error = { - message: err.message, - } - send(data) - } -} -function initRuntimeAutomator(options) { - if (options === void 0) { - options = {} - } - socketTask = uni.connectSocket({ - url: wsEndpoint, - complete: function () {}, - }) - socketTask.onMessage(onMessage) - socketTask.onOpen(function (res) { - options.success && options.success() - console.log('已开启自动化测试...') - }) - socketTask.onError(function (res) { - console.log('automator.onError', res) - }) - socketTask.onClose(function () { - options.fail && options.fail({ errMsg: '$$initRuntimeAutomator:fail' }) - console.log('automator.onClose') - }) -} -//@ts-ignore -{ - //@ts-ignore - swan.$$initRuntimeAutomator = initRuntimeAutomator - setTimeout(function () { - //@ts-ignore - swan.$$initRuntimeAutomator() - }, 500) -} +var e,t=Object.prototype.hasOwnProperty,n=function(e){return null==e},r=Array.isArray,o=function(e){var t=Object.create(null);return function(n){return t[n]||(t[n]=e(n))}},a=/-(\w)/g,i=o((function(e){return e.replace(a,(function(e,t){return t?t.toUpperCase():""}))})),u=o((function(e){return e.charAt(0).toUpperCase()+e.slice(1)})),c=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g;function s(e,n){if(r(e))return e;if(n&&(o=n,a=e,t.call(o,a)))return[e];var o,a,i=[];return e.replace(c,(function(e,t,n,r){return i.push(n?r.replace(/\\(\\)?/g,"$1"):t||e),r})),i}function f(e){return e.__wxWebviewId__?e.__wxWebviewId__:e.privateProperties?e.privateProperties.slaveId:e.$page?e.$page.id:void 0}function p(e){return e.route||e.uri}function d(e){return e.options||e.$page&&e.$page.options||{}}function l(e){return{id:f(e),path:p(e),query:d(e)}}function g(e){var t=function(e){return getCurrentPages().find((function(t){return f(t)===e}))}(e);return t&&t.$vm}function m(e,t){var n=g(e);return n&&function e(t,n){var r;return t&&(!function(e,t){return e.$scope&&((n=e.$scope).__wxExparserNodeId__||n.nodeId||n.id)===t;var n}(t,n)?t.$children.find((function(t){return r=e(t,n)})):r=t),r}(n,t)}function v(e,t){var r;return e&&(r=t?function(e,t){var r,o=s(t,e);for(r=o.shift();!n(r);){if(null==(e=e[r]))return;r=o.shift()}return e}(e.$data,t):Object.assign({},e.$data)),Promise.resolve({data:r})}function h(e,t){return e&&Object.keys(t).forEach((function(n){e[n]=t[n]})),Promise.resolve()}function T(t,n,r){return new Promise((function(o,a){if(!t)return a(e.VM_NOT_EXISTS);if(!t[n])return a(e.VM_NOT_EXISTS);var i,u=t[n].apply(t,r);!(i=u)||"object"!=typeof i&&"function"!=typeof i||"function"!=typeof i.then?o({result:u}):u.then((function(e){o({result:e})}))}))}!function(e){e.VM_NOT_EXISTS="VM_NOT_EXISTS",e.METHOD_NOT_EXISTS="METHOD_NOT_EXISTS"}(e||(e={}));var _=["stopRecord","getRecorderManager","pauseVoice","stopVoice","pauseBackgroundAudio","stopBackgroundAudio","getBackgroundAudioManager","createAudioContext","createInnerAudioContext","createVideoContext","createCameraContext","createMapContext","canIUse","startAccelerometer","stopAccelerometer","startCompass","stopCompass","hideToast","hideLoading","showNavigationBarLoading","hideNavigationBarLoading","navigateBack","createAnimation","pageScrollTo","createSelectorQuery","createCanvasContext","createContext","drawCanvas","hideKeyboard","stopPullDownRefresh","arrayBufferToBase64","base64ToArrayBuffer"],y={},O=/Sync$/,S=/^on|^off/;function E(e){return O.test(e)||-1!==_.indexOf(e)}var I={getPageStack:function(){return Promise.resolve({pageStack:getCurrentPages().map((function(e){return l(e)}))})},getCurrentPage:function(){var e=getCurrentPages(),t=e.length;return new Promise((function(n,r){t?n(l(e[t-1])):r(Error("getCurrentPages().length=0"))}))},callUniMethod:function(e){var t=e.method,n=e.args;return new Promise((function(e,r){if(!uni[t])return r(Error("uni."+t+" not exists"));if(E(t))return e({result:uni[t].apply(uni,n)});var o=[Object.assign({},n[0]||{},{success:function(n){setTimeout((function(){e({result:n})}),"pageScrollTo"===t?350:0)},fail:function(e){r(Error(e.errMsg.replace(t+":fail ","")))}})];uni[t].apply(uni,o)}))},mockUniMethod:function(e){var t=e.method;if(!uni[t])throw Error("uni."+t+" not exists");if(!function(e){return!S.test(e)}(t))throw Error("You can't mock uni."+t);var r=e.result;if(n(r))return y[t]&&(uni[t]=y[t],delete y[t]),Promise.resolve();var o=E(t)?function(){return r}:function(e){setTimeout((function(){r.errMsg&&-1!==r.errMsg.indexOf(":fail")?e.fail&&e.fail(r):e.success&&e.success(r),e.complete&&e.complete(r)}),4)};return y[t]||(y[t]=uni[t]),uni[t]=o,Promise.resolve()}},C={getData:function(e){return v(g(e.pageId),e.path)},setData:function(e){return h(g(e.pageId),e.data)},callMethod:function(t){var n,r=((n={})[e.VM_NOT_EXISTS]="Page["+t.pageId+"] not exists",n[e.METHOD_NOT_EXISTS]="page."+t.method+" not exists",n);return new Promise((function(e,n){T(g(t.pageId),t.method,t.args).then((function(t){return e(t)})).catch((function(e){n(Error(r[e]))}))}))}};function w(e){return e.nodeId||e.elementId}for(var M={getData:function(e){return v(m(e.pageId,w(e)),e.path)},setData:function(e){return h(m(e.pageId,w(e)),e.data)},callMethod:function(t){var n,r=w(t),o=((n={})[e.VM_NOT_EXISTS]="Component["+t.pageId+":"+r+"] not exists",n[e.METHOD_NOT_EXISTS]="component."+t.method+" not exists",n);return new Promise((function(e,n){T(m(t.pageId,r),t.method,t.args).then((function(t){return e(t)})).catch((function(e){n(Error(o[e]))}))}))}},P=("undefined"!=typeof crypto&&crypto.getRandomValues&&crypto.getRandomValues.bind(crypto)||"undefined"!=typeof msCrypto&&"function"==typeof msCrypto.getRandomValues&&msCrypto.getRandomValues.bind(msCrypto),[]),b=0;b<256;++b)P[b]=(b+256).toString(16).substr(1);["movable-view","picker","ad","button","checkbox-group","checkbox","form","icon","label","movable-area","navigator","picker-view-column","picker-view","progress","radio-group","radio","rich-text","u-slider","swiper-item","swiper","switch"].map((function(e){return u(i(e))}));var x={};Object.keys(I).forEach((function(e){x["App."+e]=I[e]})),Object.keys(C).forEach((function(e){x["Page."+e]=C[e]})),Object.keys(M).forEach((function(e){x["Element."+e]=M[e]}));var $,k=process.env.UNI_AUTOMATOR_WS_ENDPOINT;function A(e){$.send({data:JSON.stringify(e)})}function N(e){var t=JSON.parse(e.data),n=t.id,r=t.method,o=t.params,a={id:n},i=x[r];if(!i&&!i)return a.error={message:r+" unimplemented"},A(a);try{i(o).then((function(e){e&&(a.result=e)})).catch((function(e){a.error={message:e.message}})).finally((function(){A(a)}))}catch(e){a.error={message:e.message},A(a)}}swan.$$initRuntimeAutomator=function(e){void 0===e&&(e={}),($=uni.connectSocket({url:k,complete:function(){}})).onMessage(N),$.onOpen((function(t){e.success&&e.success(),console.log("已开启自动化测试...")})),$.onError((function(e){console.log("automator.onError",e)})),$.onClose((function(){e.fail&&e.fail({errMsg:"$$initRuntimeAutomator:fail"}),console.log("automator.onClose")}))},setTimeout((function(){swan.$$initRuntimeAutomator()}),500); diff --git a/packages/uni-mp-baidu/lib/uni.automator.js b/packages/uni-mp-baidu/lib/uni.automator.js index 744e20604..4bd975a11 100644 --- a/packages/uni-mp-baidu/lib/uni.automator.js +++ b/packages/uni-mp-baidu/lib/uni.automator.js @@ -1,556 +1 @@ -'use strict' - -function _interopDefault(ex) { - return ex && typeof ex === 'object' && 'default' in ex ? ex['default'] : ex -} - -var os = _interopDefault(require('os')) -var path = _interopDefault(require('path')) -var debug = _interopDefault(require('debug')) -var isWindows = _interopDefault(require('licia/isWindows')) -var fs = _interopDefault(require('fs')) -var child_process = _interopDefault(require('child_process')) -var sleep = _interopDefault(require('licia/sleep')) -var toStr = _interopDefault(require('licia/toStr')) -var waitUntil = _interopDefault(require('licia/waitUntil')) -var concat = _interopDefault(require('licia/concat')) -var getPort = _interopDefault(require('licia/getPort')) -var dateFormat = _interopDefault(require('licia/dateFormat')) -require('address') -require('default-gateway') -require('licia/isStr') -var WebSocket = _interopDefault(require('ws')) -var events = require('events') -var uuid = _interopDefault(require('licia/uuid')) -var stringify = _interopDefault(require('licia/stringify')) - -const TAGNAME_REGEX = /(^[a-z][a-z0-9-]*)/i -const NAVIGATOR_SELECTOR_REGEX = /^navigator/i -const NAVIGATOR_TAGNAME_REGEX = /^swan-nav$/i -var TYPES -;(function (TYPES) { - TYPES['SELECTOR'] = 'selector' - TYPES['TAGNAME'] = 'tagName' -})(TYPES || (TYPES = {})) -const argsProcessors = { - [TYPES.SELECTOR]: [ - { - test: NAVIGATOR_SELECTOR_REGEX, - processor: (str) => str.replace(NAVIGATOR_SELECTOR_REGEX, 'nav'), - }, - { - test: TAGNAME_REGEX, - processor: (str) => `swan-${str}`, - }, - ], - [TYPES.TAGNAME]: [ - { - test: NAVIGATOR_TAGNAME_REGEX, - processor: (str) => - str.replace(NAVIGATOR_TAGNAME_REGEX, 'swan-navigator'), - }, - { - test: TAGNAME_REGEX, - processor: (str) => str.toLocaleLowerCase().replace('swan-', ''), - }, - ], -} -const getProcess = (arg) => { - return (str) => { - const processors = (argsProcessors[arg] || []).filter((processor) => - processor.test.test(str) - ) - for (const processor of processors) { - str = processor.processor(str) - } - return str - } -} -const processSingleSelector = getProcess(TYPES.SELECTOR) -const processTagName = getProcess(TYPES.TAGNAME) -const processSelector = (selector) => - selector - .split(' ') - .map((selector) => processSingleSelector(selector)) - .join(' ') -const addElementId = (params) => - Object.assign({}, params, { - type: 'id', - info: { - id: params.elementId, - }, - }) - -const qrCodeTerminal = require('qrcode-terminal') -const QrCodeReader = require('qrcode-reader') -const isWin = /^win/.test(process.platform) -async function resolvePort(port, defaultPort) { - const newPort = await getPort(port || defaultPort) - if (port && newPort !== port) { - throw Error(`Port ${port} is in use, please specify another port`) - } - return newPort -} - -class Transport extends events.EventEmitter { - constructor(ws) { - super() - this.ws = ws - this.ws.addEventListener('message', (event) => { - this.emit('message', event.data) - }) - this.ws.addEventListener('close', () => { - this.emit('close') - }) - } - send(message) { - this.ws.send(message) - } - close() { - this.ws.close() - } -} - -const CLOSE_ERR_TIP = 'Connection closed' -class Connection extends events.EventEmitter { - constructor(transport, puppet, namespace) { - super() - this.puppet = puppet - this.namespace = namespace - this.callbacks = new Map() - this.transport = transport - this.debug = debug('automator:protocol:' + this.namespace) - this.onMessage = (msg) => { - this.debug(`${dateFormat('yyyy-mm-dd HH:MM:ss:l')} ◀ RECV ${msg}`) - const { id, method, error, result, params } = JSON.parse(msg) - if (!id) { - return this.puppet.emit(method, params) - } - const { callbacks } = this - if (id && callbacks.has(id)) { - const promise = callbacks.get(id) - callbacks.delete(id) - error ? promise.reject(Error(error.message)) : promise.resolve(result) - } - } - this.onClose = () => { - this.callbacks.forEach((promise) => { - promise.reject(Error(CLOSE_ERR_TIP)) - }) - } - this.transport.on('message', this.onMessage) - this.transport.on('close', this.onClose) - } - send(method, params = {}, reflect = true) { - if (reflect && this.puppet.adapter.has(method)) { - return this.puppet.adapter.send(this, method, params) - } - const id = uuid() - const data = stringify({ - id, - method, - params, - }) - this.debug(`${dateFormat('yyyy-mm-dd HH:MM:ss:l')} SEND ► ${data}`) - return new Promise((resolve, reject) => { - try { - this.transport.send(data) - } catch (e) { - reject(Error(CLOSE_ERR_TIP)) - } - this.callbacks.set(id, { - resolve, - reject, - }) - }) - } - dispose() { - this.transport.close() - } - static createDevtoolConnection(url, puppet) { - return new Promise((resolve, reject) => { - const ws = new WebSocket(url) - ws.addEventListener('open', () => { - resolve(new Connection(new Transport(ws), puppet, 'devtool')) - }) - ws.addEventListener('error', reject) - }) - } - static createRuntimeConnection(port, puppet, timeout) { - return new Promise((resolve, reject) => { - debug('automator:runtime')( - `${dateFormat('yyyy-mm-dd HH:MM:ss:l')} port=${port}` - ) - const wss = new WebSocket.Server({ - port, - }) - waitUntil( - async () => { - if (puppet.runtimeConnection) { - return true - } - }, - timeout, - 1e3 - ).catch(() => { - wss.close() - reject( - 'Failed to connect to runtime, please make sure the project is running' - ) - }) - wss.on('connection', function connection(ws) { - debug('automator:runtime')( - `${dateFormat('yyyy-mm-dd HH:MM:ss:l')} connected` - ) - const connection = new Connection(new Transport(ws), puppet, 'runtime') - // 可能会被重新连接,刷新成最新的 - puppet.setRuntimeConnection(connection) - resolve(connection) - }) - puppet.setRuntimeServer(wss) - }) - } -} - -const debugDevtools = debug('automator:devtool') -function resolveDevtoolsPath(cliPath, puppet) { - const paths = puppet.devtools.paths.slice(0) - if (cliPath) { - paths.unshift(cliPath) - } - for (const cliPath of paths) { - if (fs.existsSync(cliPath)) { - return cliPath - } - } - throw Error( - `${puppet.devtools.name} not found, please specify executablePath option` - ) -} -async function validateDevtools(options, puppet) { - const cliPath = resolveDevtoolsPath(options.executablePath, puppet) - let port = options.port || puppet.devtools.defaultPort - if (options.launch !== false) { - try { - port = await resolvePort(port) - } catch (e) { - // console.log(`Port ${port} is in use, try to connect directly`); - options.launch = false - } - } else { - const newPort = await getPort(port) - if (port === newPort) { - options.launch = true - // console.log(`try to launch ${this.puppet.devtools.name}`); - } - } - return Object.assign(Object.assign({}, options), { port, cliPath }) -} -async function connectTool(options, puppet) { - let connection - try { - connection = await Connection.createDevtoolConnection( - options.wsEndpoint, - puppet - ) - } catch (e) { - throw Error( - `Failed connecting to ${options.wsEndpoint}, check if target project window is opened with automation enabled` - ) - } - return connection -} -async function createDevtools(projectPath, options, puppet) { - const { - port, - cliPath, - timeout, - cwd = '', - account = '', - args = [], - launch = true, - } = options - let launchFailed = false - let connectFailed = false - if (launch !== false) { - const spawnOptions = { - stdio: 'ignore', - } - cwd && (spawnOptions.cwd = cwd) - let spawnArgs = concat(args, []) - //@ts-ignore - { - spawnArgs = concat(spawnArgs, ['--auto']) - } - spawnArgs = concat(spawnArgs, [projectPath, '--auto-port', toStr(port)]) - account && (spawnArgs = concat(spawnArgs, ['--auto-account', account])) - try { - debugDevtools('%s %o %o', cliPath, spawnArgs, spawnOptions) - const cliProcess = child_process.spawn(cliPath, spawnArgs, spawnOptions) - cliProcess.on('error', (err) => { - launchFailed = true - }) - cliProcess.on('exit', () => { - setTimeout(() => { - connectFailed = true - }, 15e3) - }) - // TODO unref? - cliProcess.unref() - } catch (err) { - launchFailed = false - } - } else { - setTimeout(() => { - connectFailed = true - }, 15e3) - } - const connection = await waitUntil( - async () => { - try { - if (launchFailed || connectFailed) { - return true - } - const connection = await connectTool( - { wsEndpoint: `ws://127.0.0.1:${port}` }, - puppet - ) - return connection - } catch (err) {} - }, - timeout, - 1e3 - ) - if (launchFailed) { - throw Error( - `Failed to launch ${puppet.devtools.name}, please make sure cliPath is correctly specified` - ) - } - if (connectFailed) { - throw Error( - `Failed to launch ${puppet.devtools.name} , please make sure http port is open` - ) - } - await sleep(5e3) - debugDevtools(`${dateFormat('yyyy-mm-dd HH:MM:ss:l')} connected`) - return connection -} - -const paths = [] -;['', '-rc'].forEach((v) => { - if (isWindows) { - paths.push( - path.join(os.homedir(), `AppData/Local/Programs/swan-ide-gui${v}/cli.bat`) - ) - paths.push(`C:/Program Files/swan-ide-gui${v}/cli.bat`) - } else { - paths.push(`/Applications/百度开发者工具${v}.app/Contents/MacOS/cli`) - } -}) -const puppet = { - devtools: { - name: 'Baidu DevTools', - remote: true, - automator: true, - paths, - required: ['project.swan.json', 'app.json', 'app.js'], - defaultPort: 9430, - validate: validateDevtools, - async create(projectPath, options, puppet) { - const connection = await createDevtools(projectPath, options, puppet) - if (!puppet.compiled) { - debug('automator:devtool')('initRuntimeAutomator') - connection.send('smartapp.swan', { - api: '$$initRuntimeAutomator', - params: [], - }) - } else { - debug('automator:devtool')('Waiting for runtime automator') - } - return connection - }, - }, - adapter: { - 'Tool.enableRemoteDebug': { - reflect: async (send) => { - return { qrCode: (await send('Tool.enablePreview')).url } - }, - }, - 'App.exit': { - reflect: async () => Promise.resolve(), - }, - // "App.callUniMethod": { - // reflect: "smartapp.swan", - // params: (params) => - // Object.assign( - // { - // api: params.method, - // params: params.args, - // }, - // params - // ), - // }, - 'Page.getElement': { - reflect: async (send, params) => { - return (await send('Page.getElements', params)).elements[0] - }, - }, - 'Page.getElements': { - reflect: async (send, params) => { - return { - elements: ( - await send( - 'smartapp.element.getBySelector', - Object.assign(Object.assign({}, params), { - properties: ['id', 'tagName'], - selector: processSelector(params.selector), - }) - ) - ).map((element) => { - const properties = element.properties - return { - elementId: properties.id, - nodeId: properties.id, - tagName: processTagName(properties.tagName), - } - }), - } - }, - }, - 'Page.getWindowProperties': { - reflect: async (send, params) => { - const properties = params.names.map((name) => - name.replace('document.documentElement.', '') - ) - const elem = ( - await send('smartapp.element.getBySelector', { - properties, - selector: 'html', - }) - )[0] - return { - properties: properties.map((name) => elem.properties[name]), - } - }, - }, - 'Element.getHTML': { - reflect: async (send, params) => { - const names = [params.type + 'HTML'] - return { - html: ( - await send( - 'Element.getDOMProperties', - Object.assign(Object.assign({}, params), { names }) - ) - ).properties[0], - } - }, - }, - 'Element.getElement': { - reflect: async (send, params) => { - return (await send('Element.getElements', params)).elements[0] - }, - }, - 'Element.getElements': { - reflect: async (send, params) => { - const { elements } = await send( - 'Page.getElements', - Object.assign(Object.assign({}, params), { - selector: `#${params.elementId} ${params.selector}`, - }) - ) - elements.forEach((element) => { - element.nodeId = element.id - }) - return { elements } - }, - }, - 'Element.getAttributes': { - reflect: async (send, params) => { - const attributes = [] - for (const attribute of params.names) { - attributes.push( - await send( - 'smartapp.element.getAttribute', - Object.assign({ attribute }, params) - ) - ) - } - return { - attributes, - } - }, - params: addElementId, - }, - 'Element.getStyles': { - reflect: async (send, params) => { - const styles = [] - for (const style of params.names) { - styles.push( - await send( - 'smartapp.element.getComputedStyle', - Object.assign({ style }, params) - ) - ) - } - return { - styles, - } - }, - params: addElementId, - }, - 'Element.getDOMProperties': { - reflect: async (send, params) => { - const properties = [] - for (const property of params.names) { - properties.push( - await send( - 'smartapp.element.getProperty', - Object.assign({ property }, params) - ) - ) - } - return { - properties, - } - }, - params: addElementId, - }, - 'Element.getProperties': { - reflect: async (send, params) => { - const properties = [] - for (const attribute of params.names) { - properties.push( - await send( - 'smartapp.element.getAttribute', - Object.assign({ attribute }, params) - ) - ) - } - return { - properties, - } - }, - params: addElementId, - }, - 'Element.getOffset': { - reflect: async (send, params) => ({ - left: await send( - 'smartapp.element.getProperty', - Object.assign({ property: 'offsetLeft' }, params) - ), - top: await send( - 'smartapp.element.getProperty', - Object.assign({ property: 'offsetTop' }, params) - ), - }), - params: addElementId, - }, - 'Element.tap': { - reflect: 'smartapp.element.touch', - params: addElementId, - }, - }, -} - -module.exports = puppet +"use strict";function e(e){return e&&"object"==typeof e&&"default"in e?e.default:e}var t=e(require("os")),r=e(require("path")),s=e(require("debug")),a=e(require("licia/isWindows")),n=e(require("fs")),o=e(require("child_process")),i=e(require("licia/sleep")),c=e(require("licia/toStr")),l=e(require("licia/waitUntil")),p=e(require("licia/concat")),u=e(require("licia/getPort")),m=e(require("licia/dateFormat"));require("address"),require("default-gateway"),require("licia/isStr");var d=e(require("ws")),h=require("events"),f=e(require("licia/uuid")),g=e(require("licia/stringify"));const w=/(^[a-z][a-z0-9-]*)/i,y=/^navigator/i,E=/^swan-nav$/i;var b;!function(e){e.SELECTOR="selector",e.TAGNAME="tagName"}(b||(b={}));const v={[b.SELECTOR]:[{test:y,processor:e=>e.replace(y,"nav")},{test:w,processor:e=>"swan-"+e}],[b.TAGNAME]:[{test:E,processor:e=>e.replace(E,"swan-navigator")},{test:w,processor:e=>e.toLocaleLowerCase().replace("swan-","")}]},P=e=>t=>{const r=(v[e]||[]).filter(e=>e.test.test(t));for(const e of r)t=e.processor(t);return t},j=P(b.SELECTOR),q=P(b.TAGNAME),O=e=>Object.assign({},e,{type:"id",info:{id:e.elementId}});require("qrcode-terminal"),require("qrcode-reader"),/^win/.test(process.platform);class M extends h.EventEmitter{constructor(e){super(),this.ws=e,this.ws.addEventListener("message",e=>{this.emit("message",e.data)}),this.ws.addEventListener("close",()=>{this.emit("close")})}send(e){this.ws.send(e)}close(){this.ws.close()}}class C extends h.EventEmitter{constructor(e,t,r){super(),this.puppet=t,this.namespace=r,this.callbacks=new Map,this.transport=e,this.debug=s("automator:protocol:"+this.namespace),this.onMessage=e=>{this.debug(`${m("yyyy-mm-dd HH:MM:ss:l")} ◀ RECV ${e}`);const{id:t,method:r,error:s,result:a,params:n}=JSON.parse(e);if(!t)return this.puppet.emit(r,n);const{callbacks:o}=this;if(t&&o.has(t)){const e=o.get(t);o.delete(t),s?e.reject(Error(s.message)):e.resolve(a)}},this.onClose=()=>{this.callbacks.forEach(e=>{e.reject(Error("Connection closed"))})},this.transport.on("message",this.onMessage),this.transport.on("close",this.onClose)}send(e,t={},r=!0){if(r&&this.puppet.adapter.has(e))return this.puppet.adapter.send(this,e,t);const s=f(),a=g({id:s,method:e,params:t});return this.debug(`${m("yyyy-mm-dd HH:MM:ss:l")} SEND ► ${a}`),new Promise((e,t)=>{try{this.transport.send(a)}catch(e){t(Error("Connection closed"))}this.callbacks.set(s,{resolve:e,reject:t})})}dispose(){this.transport.close()}static createDevtoolConnection(e,t){return new Promise((r,s)=>{const a=new d(e);a.addEventListener("open",()=>{r(new C(new M(a),t,"devtool"))}),a.addEventListener("error",s)})}static createRuntimeConnection(e,t,r){return new Promise((a,n)=>{s("automator:runtime")(`${m("yyyy-mm-dd HH:MM:ss:l")} port=${e}`);const o=new d.Server({port:e});l(async()=>{if(t.runtimeConnection)return!0},r,1e3).catch(()=>{o.close(),n("Failed to connect to runtime, please make sure the project is running")}),o.on("connection",(function(e){s("automator:runtime")(m("yyyy-mm-dd HH:MM:ss:l")+" connected");const r=new C(new M(e),t,"runtime");t.setRuntimeConnection(r),a(r)})),t.setRuntimeServer(o)})}}const $=s("automator:devtool");async function S(e,t,r){const{port:s,cliPath:a,timeout:n,cwd:u="",account:d="",args:h=[],launch:f=!0}=t;let g=!1,w=!1;if(!1!==f){const t={stdio:"ignore"};u&&(t.cwd=u);let r=p(h,[]);r=p(r,["--auto"]),r=p(r,[e,"--auto-port",c(s)]),d&&(r=p(r,["--auto-account",d]));try{$("%s %o %o",a,r,t);const e=o.spawn(a,r,t);e.on("error",e=>{g=!0}),e.on("exit",()=>{setTimeout(()=>{w=!0},15e3)}),e.unref()}catch(e){g=!1}}else setTimeout(()=>{w=!0},15e3);const y=await l(async()=>{try{if(g||w)return!0;return await async function(e,t){let r;try{r=await C.createDevtoolConnection(e.wsEndpoint,t)}catch(t){throw Error(`Failed connecting to ${e.wsEndpoint}, check if target project window is opened with automation enabled`)}return r}({wsEndpoint:"ws://127.0.0.1:"+s},r)}catch(e){}},n,1e3);if(g)throw Error(`Failed to launch ${r.devtools.name}, please make sure cliPath is correctly specified`);if(w)throw Error(`Failed to launch ${r.devtools.name} , please make sure http port is open`);return await i(5e3),$(m("yyyy-mm-dd HH:MM:ss:l")+" connected"),y}const A=[];["","-rc"].forEach(e=>{a?(A.push(r.join(t.homedir(),`AppData/Local/Programs/swan-ide-gui${e}/cli.bat`)),A.push(`C:/Program Files/swan-ide-gui${e}/cli.bat`)):A.push(`/Applications/百度开发者工具${e}.app/Contents/MacOS/cli`)});const T={devtools:{name:"Baidu DevTools",remote:!0,automator:!0,paths:A,required:["project.swan.json","app.json","app.js"],defaultPort:9430,validate:async function(e,t){const r=function(e,t){const r=t.devtools.paths.slice(0);e&&r.unshift(e);for(const e of r)if(n.existsSync(e))return e;throw Error(t.devtools.name+" not found, please specify executablePath option")}(e.executablePath,t);let s=e.port||t.devtools.defaultPort;if(!1!==e.launch)try{s=await async function(e,t){const r=await u(e||t);if(e&&r!==e)throw Error(`Port ${e} is in use, please specify another port`);return r}(s)}catch(t){e.launch=!1}else{s===await u(s)&&(e.launch=!0)}return Object.assign(Object.assign({},e),{port:s,cliPath:r})},async create(e,t,r){const a=await S(e,t,r);return r.compiled?s("automator:devtool")("Waiting for runtime automator"):(s("automator:devtool")("initRuntimeAutomator"),a.send("smartapp.swan",{api:"$$initRuntimeAutomator",params:[]})),a}},adapter:{"Tool.enableRemoteDebug":{reflect:async e=>({qrCode:(await e("Tool.enablePreview")).url})},"App.exit":{reflect:async()=>Promise.resolve()},"Page.getElement":{reflect:async(e,t)=>(await e("Page.getElements",t)).elements[0]},"Page.getElements":{reflect:async(e,t)=>{return{elements:(await e("smartapp.element.getBySelector",Object.assign(Object.assign({},t),{properties:["id","tagName"],selector:(r=t.selector,r.split(" ").map(e=>j(e)).join(" "))}))).map(e=>{const t=e.properties;return{elementId:t.id,nodeId:t.id,tagName:q(t.tagName)}})};var r}},"Page.getWindowProperties":{reflect:async(e,t)=>{const r=t.names.map(e=>e.replace("document.documentElement.","")),s=(await e("smartapp.element.getBySelector",{properties:r,selector:"html"}))[0];return{properties:r.map(e=>s.properties[e])}}},"Element.getHTML":{reflect:async(e,t)=>{const r=[t.type+"HTML"];return{html:(await e("Element.getDOMProperties",Object.assign(Object.assign({},t),{names:r}))).properties[0]}}},"Element.getElement":{reflect:async(e,t)=>(await e("Element.getElements",t)).elements[0]},"Element.getElements":{reflect:async(e,t)=>{const{elements:r}=await e("Page.getElements",Object.assign(Object.assign({},t),{selector:`#${t.elementId} ${t.selector}`}));return r.forEach(e=>{e.nodeId=e.id}),{elements:r}}},"Element.getAttributes":{reflect:async(e,t)=>{const r=[];for(const s of t.names)r.push(await e("smartapp.element.getAttribute",Object.assign({attribute:s},t)));return{attributes:r}},params:O},"Element.getStyles":{reflect:async(e,t)=>{const r=[];for(const s of t.names)r.push(await e("smartapp.element.getComputedStyle",Object.assign({style:s},t)));return{styles:r}},params:O},"Element.getDOMProperties":{reflect:async(e,t)=>{const r=[];for(const s of t.names)r.push(await e("smartapp.element.getProperty",Object.assign({property:s},t)));return{properties:r}},params:O},"Element.getProperties":{reflect:async(e,t)=>{const r=[];for(const s of t.names)r.push(await e("smartapp.element.getAttribute",Object.assign({attribute:s},t)));return{properties:r}},params:O},"Element.getOffset":{reflect:async(e,t)=>({left:await e("smartapp.element.getProperty",Object.assign({property:"offsetLeft"},t)),top:await e("smartapp.element.getProperty",Object.assign({property:"offsetTop"},t))}),params:O},"Element.tap":{reflect:"smartapp.element.touch",params:O}}};module.exports=T; diff --git a/packages/uni-mp-weixin/lib/automator.js b/packages/uni-mp-weixin/lib/automator.js index 894696fec..c3ecc9557 100644 --- a/packages/uni-mp-weixin/lib/automator.js +++ b/packages/uni-mp-weixin/lib/automator.js @@ -1,489 +1 @@ -var hasOwnProperty = Object.prototype.hasOwnProperty -var hasOwn = function (val, key) { - return hasOwnProperty.call(val, key) -} -var isUndef = function (v) { - return v === undefined || v === null -} -var isArray = Array.isArray -var isPromise = function (obj) { - return ( - !!obj && - (typeof obj === 'object' || typeof obj === 'function') && - typeof obj.then === 'function' - ) -} -var cacheStringFunction = function (fn) { - var cache = Object.create(null) - return function (str) { - var hit = cache[str] - return hit || (cache[str] = fn(str)) - } -} -var camelizeRE = /-(\w)/g -var camelize = cacheStringFunction(function (str) { - return str.replace(camelizeRE, function (_, c) { - return c ? c.toUpperCase() : '' - }) -}) -var capitalize = cacheStringFunction(function (str) { - return str.charAt(0).toUpperCase() + str.slice(1) -}) -var PATH_RE = - /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g -function getPaths(path, data) { - if (isArray(path)) { - return path - } - if (data && hasOwn(data, path)) { - return [path] - } - var res = [] - path.replace(PATH_RE, function (match, p1, offset, string) { - res.push(offset ? string.replace(/\\(\\)?/g, '$1') : p1 || match) - return string - }) - return res -} -function getDataByPath(data, path) { - var paths = getPaths(path, data) - var dataPath - for (dataPath = paths.shift(); !isUndef(dataPath); ) { - if (null == (data = data[dataPath])) { - return - } - dataPath = paths.shift() - } - return data -} - -function getPageId(page) { - if (page.__wxWebviewId__) { - //mp-weixin - return page.__wxWebviewId__ - } - if (page.privateProperties) { - //mp-baidu - return page.privateProperties.slaveId - } - if (page.$page) { - //h5 and app-plus - return page.$page.id - } -} -function getPagePath(page) { - return page.route || page.uri -} -function getPageQuery(page) { - return page.options || (page.$page && page.$page.options) || {} -} -function parsePage(page) { - return { - id: getPageId(page), - path: getPagePath(page), - query: getPageQuery(page), - } -} -function getPageById(id) { - return getCurrentPages().find(function (page) { - return getPageId(page) === id - }) -} -function getPageVm(id) { - var page = getPageById(id) - return page && page.$vm -} -function getNodeId(scope) { - return scope.__wxExparserNodeId__ || scope.nodeId || scope.id -} -function matchNodeId(vm, nodeId) { - return vm.$scope && getNodeId(vm.$scope) === nodeId -} -function findComponentVm(vm, nodeId) { - var res - if (vm) { - if (matchNodeId(vm, nodeId)) { - res = vm - } else { - vm.$children.find(function (child) { - res = findComponentVm(child, nodeId) - return res - }) - } - } - return res -} -function getComponentVm(pageId, nodeId) { - var pageVm = getPageVm(pageId) - return pageVm && findComponentVm(pageVm, nodeId) -} -function getData(vm, path) { - var data - if (vm) { - data = path ? getDataByPath(vm.$data, path) : Object.assign({}, vm.$data) - } - return Promise.resolve({ data: data }) -} -function setData(vm, data) { - if (vm) { - Object.keys(data).forEach(function (name) { - vm[name] = data[name] - }) - } - return Promise.resolve() -} -var CALL_METHOD_ERROR -;(function (CALL_METHOD_ERROR) { - CALL_METHOD_ERROR['VM_NOT_EXISTS'] = 'VM_NOT_EXISTS' - CALL_METHOD_ERROR['METHOD_NOT_EXISTS'] = 'METHOD_NOT_EXISTS' -})(CALL_METHOD_ERROR || (CALL_METHOD_ERROR = {})) -function callMethod(vm, method, args) { - return new Promise(function (resolve, reject) { - if (!vm) { - return reject(CALL_METHOD_ERROR.VM_NOT_EXISTS) - } - if (!vm[method]) { - return reject(CALL_METHOD_ERROR.VM_NOT_EXISTS) - } - var ret = vm[method].apply(vm, args) - isPromise(ret) - ? ret.then(function (res) { - resolve({ result: res }) - }) - : resolve({ result: ret }) - }) -} - -var SYNC_APIS = [ - 'stopRecord', - 'getRecorderManager', - 'pauseVoice', - 'stopVoice', - 'pauseBackgroundAudio', - 'stopBackgroundAudio', - 'getBackgroundAudioManager', - 'createAudioContext', - 'createInnerAudioContext', - 'createVideoContext', - 'createCameraContext', - 'createMapContext', - 'canIUse', - 'startAccelerometer', - 'stopAccelerometer', - 'startCompass', - 'stopCompass', - 'hideToast', - 'hideLoading', - 'showNavigationBarLoading', - 'hideNavigationBarLoading', - 'navigateBack', - 'createAnimation', - 'pageScrollTo', - 'createSelectorQuery', - 'createCanvasContext', - 'createContext', - 'drawCanvas', - 'hideKeyboard', - 'stopPullDownRefresh', - 'arrayBufferToBase64', - 'base64ToArrayBuffer', -] -var originUni = {} -var SYNC_API_RE = /Sync$/ -var MOCK_API_BLACKLIST_RE = /^on|^off/ -function isSyncApi(method) { - return SYNC_API_RE.test(method) || SYNC_APIS.indexOf(method) !== -1 -} -function canIMock(method) { - return !MOCK_API_BLACKLIST_RE.test(method) -} -var App = { - getPageStack: function () { - return Promise.resolve({ - pageStack: getCurrentPages().map(function (page) { - return parsePage(page) - }), - }) - }, - getCurrentPage: function () { - var pages = getCurrentPages() - var len = pages.length - return new Promise(function (resolve, reject) { - if (!len) { - reject(Error('getCurrentPages().length=0')) - } else { - resolve(parsePage(pages[len - 1])) - } - }) - }, - callUniMethod: function (params) { - var method = params.method - var args = params.args - return new Promise(function (resolve, reject) { - if (!uni[method]) { - return reject(Error('uni.' + method + ' not exists')) - } - if (isSyncApi(method)) { - return resolve({ - result: uni[method].apply(uni, args), - }) - } - var params = [ - Object.assign({}, args[0] || {}, { - success: function (result) { - var timeout = method === 'pageScrollTo' ? 350 : 0 - setTimeout(function () { - resolve({ result: result }) - }, timeout) - }, - fail: function (res) { - reject(Error(res.errMsg.replace(method + ':fail ', ''))) - }, - }), - ] - uni[method].apply(uni, params) - }) - }, - mockUniMethod: function (params) { - var method = params.method - if (!uni[method]) { - throw Error('uni.' + method + ' not exists') - } - if (!canIMock(method)) { - throw Error("You can't mock uni." + method) - } - // TODO getOwnPropertyDescriptor? - var result = params.result - if (isUndef(result)) { - // restoreUniMethod - if (originUni[method]) { - uni[method] = originUni[method] - delete originUni[method] - } - return Promise.resolve() - } - var mockFn = isSyncApi(method) - ? function () { - return result - } - : function (params) { - setTimeout(function () { - var isFail = result.errMsg && result.errMsg.indexOf(':fail') !== -1 - if (isFail) { - params.fail && params.fail(result) - } else { - params.success && params.success(result) - } - params.complete && params.complete(result) - }, 4) - } - // mockFn.origin = originUni[method] || uni[method]; - if (!originUni[method]) { - originUni[method] = uni[method] - } - uni[method] = mockFn - return Promise.resolve() - }, -} - -var Page = { - getData: function (params) { - return getData(getPageVm(params.pageId), params.path) - }, - setData: function (params) { - return setData(getPageVm(params.pageId), params.data) - }, - callMethod: function (params) { - var _a - var err = - ((_a = {}), - (_a[CALL_METHOD_ERROR.VM_NOT_EXISTS] = - 'Page[' + params.pageId + '] not exists'), - (_a[CALL_METHOD_ERROR.METHOD_NOT_EXISTS] = - 'page.' + params.method + ' not exists'), - _a) - return new Promise(function (resolve, reject) { - callMethod(getPageVm(params.pageId), params.method, params.args) - .then(function (res) { - return resolve(res) - }) - .catch(function (type) { - reject(Error(err[type])) - }) - }) - }, -} - -function getNodeId$1(params) { - return params.nodeId || params.elementId -} -var Element = { - getData: function (params) { - return getData( - getComponentVm(params.pageId, getNodeId$1(params)), - params.path - ) - }, - setData: function (params) { - return setData( - getComponentVm(params.pageId, getNodeId$1(params)), - params.data - ) - }, - callMethod: function (params) { - var _a - var nodeId = getNodeId$1(params) - var err = - ((_a = {}), - (_a[CALL_METHOD_ERROR.VM_NOT_EXISTS] = - 'Component[' + params.pageId + ':' + nodeId + '] not exists'), - (_a[CALL_METHOD_ERROR.METHOD_NOT_EXISTS] = - 'component.' + params.method + ' not exists'), - _a) - return new Promise(function (resolve, reject) { - callMethod( - getComponentVm(params.pageId, nodeId), - params.method, - params.args - ) - .then(function (res) { - return resolve(res) - }) - .catch(function (type) { - reject(Error(err[type])) - }) - }) - }, -} - -// Unique ID creation requires a high quality random # generator. In the browser we therefore -// require the crypto API and do not support built-in fallback to lower quality random number -// generators (like Math.random()). -// getRandomValues needs to be invoked in a context where "this" is a Crypto implementation. Also, -// find the complete implementation of crypto (msCrypto) on IE11. -var getRandomValues = - (typeof crypto != 'undefined' && - crypto.getRandomValues && - crypto.getRandomValues.bind(crypto)) || - (typeof msCrypto != 'undefined' && - typeof msCrypto.getRandomValues == 'function' && - msCrypto.getRandomValues.bind(msCrypto)) - -/** - * Convert array of 16 byte values to UUID string format of the form: - * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX - */ -var byteToHex = [] - -for (var i = 0; i < 256; ++i) { - byteToHex[i] = (i + 0x100).toString(16).substr(1) -} - -var BUILITIN = [ - 'movable-view', - 'picker', - 'ad', - 'button', - 'checkbox-group', - 'checkbox', - 'form', - 'icon', - 'label', - 'movable-area', - 'navigator', - 'picker-view-column', - 'picker-view', - 'progress', - 'radio-group', - 'radio', - 'rich-text', - 'u-slider', - 'swiper-item', - 'swiper', - 'switch', -] -var BUILITIN_ALIAS = BUILITIN.map(function (tag) { - return capitalize(camelize(tag)) -}) - -var Api = {} -Object.keys(App).forEach(function (method) { - Api['App.' + method] = App[method] -}) -Object.keys(Page).forEach(function (method) { - Api['Page.' + method] = Page[method] -}) -Object.keys(Element).forEach(function (method) { - Api['Element.' + method] = Element[method] -}) -var wsEndpoint = process.env.UNI_AUTOMATOR_WS_ENDPOINT -var socketTask -function send(data) { - socketTask.send({ data: JSON.stringify(data) }) -} -function onMessage(res) { - var _a = JSON.parse(res.data), - id = _a.id, - method = _a.method, - params = _a.params - var data = { id: id } - var fn = Api[method] - if (!fn) { - if (!fn) { - data.error = { - message: method + ' unimplemented', - } - return send(data) - } - } - try { - fn(params) - .then(function (res) { - res && (data.result = res) - }) - .catch(function (err) { - data.error = { - message: err.message, - } - }) - .finally(function () { - send(data) - }) - } catch (err) { - data.error = { - message: err.message, - } - send(data) - } -} -function initRuntimeAutomator(options) { - if (options === void 0) { - options = {} - } - socketTask = uni.connectSocket({ - url: wsEndpoint, - complete: function () {}, - }) - socketTask.onMessage(onMessage) - socketTask.onOpen(function (res) { - options.success && options.success() - console.log('已开启自动化测试...') - }) - socketTask.onError(function (res) { - console.log('automator.onError', res) - }) - socketTask.onClose(function () { - options.fail && options.fail({ errMsg: '$$initRuntimeAutomator:fail' }) - console.log('automator.onClose') - }) -} -//@ts-ignore -{ - //@ts-ignore - wx.$$initRuntimeAutomator = initRuntimeAutomator - setTimeout(function () { - //@ts-ignore - wx.$$initRuntimeAutomator() - }, 500) - //@ts-ignore -} +var e,t=Object.prototype.hasOwnProperty,n=function(e){return null==e},r=Array.isArray,o=function(e){var t=Object.create(null);return function(n){return t[n]||(t[n]=e(n))}},i=/-(\w)/g,a=o((function(e){return e.replace(i,(function(e,t){return t?t.toUpperCase():""}))})),u=o((function(e){return e.charAt(0).toUpperCase()+e.slice(1)})),c=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g;function s(e,n){if(r(e))return e;if(n&&(o=n,i=e,t.call(o,i)))return[e];var o,i,a=[];return e.replace(c,(function(e,t,n,r){return a.push(n?r.replace(/\\(\\)?/g,"$1"):t||e),r})),a}function f(e){return e.__wxWebviewId__?e.__wxWebviewId__:e.privateProperties?e.privateProperties.slaveId:e.$page?e.$page.id:void 0}function p(e){return e.route||e.uri}function d(e){return e.options||e.$page&&e.$page.options||{}}function l(e){return{id:f(e),path:p(e),query:d(e)}}function g(e){var t=function(e){return getCurrentPages().find((function(t){return f(t)===e}))}(e);return t&&t.$vm}function m(e,t){var n=g(e);return n&&function e(t,n){var r;return t&&(!function(e,t){return e.$scope&&((n=e.$scope).__wxExparserNodeId__||n.nodeId||n.id)===t;var n}(t,n)?t.$children.find((function(t){return r=e(t,n)})):r=t),r}(n,t)}function v(e,t){var r;return e&&(r=t?function(e,t){var r,o=s(t,e);for(r=o.shift();!n(r);){if(null==(e=e[r]))return;r=o.shift()}return e}(e.$data,t):Object.assign({},e.$data)),Promise.resolve({data:r})}function h(e,t){return e&&Object.keys(t).forEach((function(n){e[n]=t[n]})),Promise.resolve()}function T(t,n,r){return new Promise((function(o,i){if(!t)return i(e.VM_NOT_EXISTS);if(!t[n])return i(e.VM_NOT_EXISTS);var a,u=t[n].apply(t,r);!(a=u)||"object"!=typeof a&&"function"!=typeof a||"function"!=typeof a.then?o({result:u}):u.then((function(e){o({result:e})}))}))}!function(e){e.VM_NOT_EXISTS="VM_NOT_EXISTS",e.METHOD_NOT_EXISTS="METHOD_NOT_EXISTS"}(e||(e={}));var _=["stopRecord","getRecorderManager","pauseVoice","stopVoice","pauseBackgroundAudio","stopBackgroundAudio","getBackgroundAudioManager","createAudioContext","createInnerAudioContext","createVideoContext","createCameraContext","createMapContext","canIUse","startAccelerometer","stopAccelerometer","startCompass","stopCompass","hideToast","hideLoading","showNavigationBarLoading","hideNavigationBarLoading","navigateBack","createAnimation","pageScrollTo","createSelectorQuery","createCanvasContext","createContext","drawCanvas","hideKeyboard","stopPullDownRefresh","arrayBufferToBase64","base64ToArrayBuffer"],y={},O=/Sync$/,S=/^on|^off/;function E(e){return O.test(e)||-1!==_.indexOf(e)}var I={getPageStack:function(){return Promise.resolve({pageStack:getCurrentPages().map((function(e){return l(e)}))})},getCurrentPage:function(){var e=getCurrentPages(),t=e.length;return new Promise((function(n,r){t?n(l(e[t-1])):r(Error("getCurrentPages().length=0"))}))},callUniMethod:function(e){var t=e.method,n=e.args;return new Promise((function(e,r){if(!uni[t])return r(Error("uni."+t+" not exists"));if(E(t))return e({result:uni[t].apply(uni,n)});var o=[Object.assign({},n[0]||{},{success:function(n){setTimeout((function(){e({result:n})}),"pageScrollTo"===t?350:0)},fail:function(e){r(Error(e.errMsg.replace(t+":fail ","")))}})];uni[t].apply(uni,o)}))},mockUniMethod:function(e){var t=e.method;if(!uni[t])throw Error("uni."+t+" not exists");if(!function(e){return!S.test(e)}(t))throw Error("You can't mock uni."+t);var r=e.result;if(n(r))return y[t]&&(uni[t]=y[t],delete y[t]),Promise.resolve();var o=E(t)?function(){return r}:function(e){setTimeout((function(){r.errMsg&&-1!==r.errMsg.indexOf(":fail")?e.fail&&e.fail(r):e.success&&e.success(r),e.complete&&e.complete(r)}),4)};return y[t]||(y[t]=uni[t]),uni[t]=o,Promise.resolve()}},C={getData:function(e){return v(g(e.pageId),e.path)},setData:function(e){return h(g(e.pageId),e.data)},callMethod:function(t){var n,r=((n={})[e.VM_NOT_EXISTS]="Page["+t.pageId+"] not exists",n[e.METHOD_NOT_EXISTS]="page."+t.method+" not exists",n);return new Promise((function(e,n){T(g(t.pageId),t.method,t.args).then((function(t){return e(t)})).catch((function(e){n(Error(r[e]))}))}))}};function w(e){return e.nodeId||e.elementId}for(var x={getData:function(e){return v(m(e.pageId,w(e)),e.path)},setData:function(e){return h(m(e.pageId,w(e)),e.data)},callMethod:function(t){var n,r=w(t),o=((n={})[e.VM_NOT_EXISTS]="Component["+t.pageId+":"+r+"] not exists",n[e.METHOD_NOT_EXISTS]="component."+t.method+" not exists",n);return new Promise((function(e,n){T(m(t.pageId,r),t.method,t.args).then((function(t){return e(t)})).catch((function(e){n(Error(o[e]))}))}))}},M=("undefined"!=typeof crypto&&crypto.getRandomValues&&crypto.getRandomValues.bind(crypto)||"undefined"!=typeof msCrypto&&"function"==typeof msCrypto.getRandomValues&&msCrypto.getRandomValues.bind(msCrypto),[]),P=0;P<256;++P)M[P]=(P+256).toString(16).substr(1);["movable-view","picker","ad","button","checkbox-group","checkbox","form","icon","label","movable-area","navigator","picker-view-column","picker-view","progress","radio-group","radio","rich-text","u-slider","swiper-item","swiper","switch"].map((function(e){return u(a(e))}));var b={};Object.keys(I).forEach((function(e){b["App."+e]=I[e]})),Object.keys(C).forEach((function(e){b["Page."+e]=C[e]})),Object.keys(x).forEach((function(e){b["Element."+e]=x[e]}));var $,k=process.env.UNI_AUTOMATOR_WS_ENDPOINT;function A(e){$.send({data:JSON.stringify(e)})}function N(e){var t=JSON.parse(e.data),n=t.id,r=t.method,o=t.params,i={id:n},a=b[r];if(!a&&!a)return i.error={message:r+" unimplemented"},A(i);try{a(o).then((function(e){e&&(i.result=e)})).catch((function(e){i.error={message:e.message}})).finally((function(){A(i)}))}catch(e){i.error={message:e.message},A(i)}}wx.$$initRuntimeAutomator=function(e){void 0===e&&(e={}),($=uni.connectSocket({url:k,complete:function(){}})).onMessage(N),$.onOpen((function(t){e.success&&e.success(),console.log("已开启自动化测试...")})),$.onError((function(e){console.log("automator.onError",e)})),$.onClose((function(){e.fail&&e.fail({errMsg:"$$initRuntimeAutomator:fail"}),console.log("automator.onClose")}))},setTimeout((function(){wx.$$initRuntimeAutomator()}),500); diff --git a/packages/uni-mp-weixin/lib/uni.automator.js b/packages/uni-mp-weixin/lib/uni.automator.js index 98a27b90e..b402266d7 100644 --- a/packages/uni-mp-weixin/lib/uni.automator.js +++ b/packages/uni-mp-weixin/lib/uni.automator.js @@ -1,361 +1 @@ -'use strict' - -function _interopDefault(ex) { - return ex && typeof ex === 'object' && 'default' in ex ? ex['default'] : ex -} - -var debug = _interopDefault(require('debug')) -var isWindows = _interopDefault(require('licia/isWindows')) -require('address') -require('default-gateway') -require('licia/isStr') -var getPort = _interopDefault(require('licia/getPort')) -var fs = _interopDefault(require('fs')) -var child_process = _interopDefault(require('child_process')) -var sleep = _interopDefault(require('licia/sleep')) -var toStr = _interopDefault(require('licia/toStr')) -var waitUntil = _interopDefault(require('licia/waitUntil')) -var concat = _interopDefault(require('licia/concat')) -var dateFormat = _interopDefault(require('licia/dateFormat')) -var WebSocket = _interopDefault(require('ws')) -var events = require('events') -var uuid = _interopDefault(require('licia/uuid')) -var stringify = _interopDefault(require('licia/stringify')) - -const qrCodeTerminal = require('qrcode-terminal') -const QrCodeReader = require('qrcode-reader') -const isWin = /^win/.test(process.platform) -function decodeQrCode(qrCode) { - const buffer = new Buffer(qrCode, 'base64') - return new Promise(async (resolve, reject) => { - const img = await require('jimp').read(buffer) - const qrCodeReader = new QrCodeReader() - qrCodeReader.callback = function (error, value) { - if (error) { - return reject(error) - } - resolve(value.result) - } - qrCodeReader.decode(img.bitmap) - }) -} -async function resolvePort(port, defaultPort) { - const newPort = await getPort(port || defaultPort) - if (port && newPort !== port) { - throw Error(`Port ${port} is in use, please specify another port`) - } - return newPort -} - -class Transport extends events.EventEmitter { - constructor(ws) { - super() - this.ws = ws - this.ws.addEventListener('message', (event) => { - this.emit('message', event.data) - }) - this.ws.addEventListener('close', () => { - this.emit('close') - }) - } - send(message) { - this.ws.send(message) - } - close() { - this.ws.close() - } -} - -const CLOSE_ERR_TIP = 'Connection closed' -class Connection extends events.EventEmitter { - constructor(transport, puppet, namespace) { - super() - this.puppet = puppet - this.namespace = namespace - this.callbacks = new Map() - this.transport = transport - this.debug = debug('automator:protocol:' + this.namespace) - this.onMessage = (msg) => { - this.debug(`${dateFormat('yyyy-mm-dd HH:MM:ss:l')} ◀ RECV ${msg}`) - const { id, method, error, result, params } = JSON.parse(msg) - if (!id) { - return this.puppet.emit(method, params) - } - const { callbacks } = this - if (id && callbacks.has(id)) { - const promise = callbacks.get(id) - callbacks.delete(id) - error ? promise.reject(Error(error.message)) : promise.resolve(result) - } - } - this.onClose = () => { - this.callbacks.forEach((promise) => { - promise.reject(Error(CLOSE_ERR_TIP)) - }) - } - this.transport.on('message', this.onMessage) - this.transport.on('close', this.onClose) - } - send(method, params = {}, reflect = true) { - if (reflect && this.puppet.adapter.has(method)) { - return this.puppet.adapter.send(this, method, params) - } - const id = uuid() - const data = stringify({ - id, - method, - params, - }) - this.debug(`${dateFormat('yyyy-mm-dd HH:MM:ss:l')} SEND ► ${data}`) - return new Promise((resolve, reject) => { - try { - this.transport.send(data) - } catch (e) { - reject(Error(CLOSE_ERR_TIP)) - } - this.callbacks.set(id, { - resolve, - reject, - }) - }) - } - dispose() { - this.transport.close() - } - static createDevtoolConnection(url, puppet) { - return new Promise((resolve, reject) => { - const ws = new WebSocket(url) - ws.addEventListener('open', () => { - resolve(new Connection(new Transport(ws), puppet, 'devtool')) - }) - ws.addEventListener('error', reject) - }) - } - static createRuntimeConnection(port, puppet, timeout) { - return new Promise((resolve, reject) => { - debug('automator:runtime')( - `${dateFormat('yyyy-mm-dd HH:MM:ss:l')} port=${port}` - ) - const wss = new WebSocket.Server({ - port, - }) - waitUntil( - async () => { - if (puppet.runtimeConnection) { - return true - } - }, - timeout, - 1e3 - ).catch(() => { - wss.close() - reject( - 'Failed to connect to runtime, please make sure the project is running' - ) - }) - wss.on('connection', function connection(ws) { - debug('automator:runtime')( - `${dateFormat('yyyy-mm-dd HH:MM:ss:l')} connected` - ) - const connection = new Connection(new Transport(ws), puppet, 'runtime') - // 可能会被重新连接,刷新成最新的 - puppet.setRuntimeConnection(connection) - resolve(connection) - }) - puppet.setRuntimeServer(wss) - }) - } -} - -const debugDevtools = debug('automator:devtool') -function resolveDevtoolsPath(cliPath, puppet) { - const paths = puppet.devtools.paths.slice(0) - if (cliPath) { - paths.unshift(cliPath) - } - for (const cliPath of paths) { - if (fs.existsSync(cliPath)) { - return cliPath - } - } - throw Error( - `${puppet.devtools.name} not found, please specify executablePath option` - ) -} -async function validateDevtools(options, puppet) { - const cliPath = resolveDevtoolsPath(options.executablePath, puppet) - let port = options.port || puppet.devtools.defaultPort - if (options.launch !== false) { - try { - port = await resolvePort(port) - } catch (e) { - // console.log(`Port ${port} is in use, try to connect directly`); - options.launch = false - } - } else { - const newPort = await getPort(port) - if (port === newPort) { - options.launch = true - // console.log(`try to launch ${this.puppet.devtools.name}`); - } - } - return Object.assign(Object.assign({}, options), { port, cliPath }) -} -async function connectTool(options, puppet) { - let connection - try { - connection = await Connection.createDevtoolConnection( - options.wsEndpoint, - puppet - ) - } catch (e) { - throw Error( - `Failed connecting to ${options.wsEndpoint}, check if target project window is opened with automation enabled` - ) - } - return connection -} -async function createDevtools(projectPath, options, puppet) { - const { - port, - cliPath, - timeout, - cwd = '', - account = '', - args = [], - launch = true, - } = options - let launchFailed = false - let connectFailed = false - if (launch !== false) { - const spawnOptions = { - stdio: 'ignore', - } - //@ts-ignore - { - spawnOptions.detached = true - } - cwd && (spawnOptions.cwd = cwd) - let spawnArgs = concat(args, []) - //@ts-ignore - { - spawnArgs = concat(spawnArgs, ['auto', '--project']) - } - spawnArgs = concat(spawnArgs, [projectPath, '--auto-port', toStr(port)]) - account && (spawnArgs = concat(spawnArgs, ['--auto-account', account])) - try { - debugDevtools('%s %o %o', cliPath, spawnArgs, spawnOptions) - const cliProcess = child_process.spawn(cliPath, spawnArgs, spawnOptions) - cliProcess.on('error', (err) => { - launchFailed = true - }) - cliProcess.on('exit', () => { - setTimeout(() => { - connectFailed = true - }, 15e3) - }) - // TODO unref? - cliProcess.unref() - } catch (err) { - launchFailed = false - } - } else { - setTimeout(() => { - connectFailed = true - }, 15e3) - } - const connection = await waitUntil( - async () => { - try { - if (launchFailed || connectFailed) { - return true - } - const connection = await connectTool( - { wsEndpoint: `ws://127.0.0.1:${port}` }, - puppet - ) - return connection - } catch (err) {} - }, - timeout, - 1e3 - ) - if (launchFailed) { - throw Error( - `Failed to launch ${puppet.devtools.name}, please make sure cliPath is correctly specified` - ) - } - if (connectFailed) { - throw Error( - `Failed to launch ${puppet.devtools.name} , please make sure http port is open` - ) - } - await sleep(5e3) - debugDevtools(`${dateFormat('yyyy-mm-dd HH:MM:ss:l')} connected`) - return connection -} - -function wrapper(fnStr) { - if (fnStr[fnStr.length - 1] === '}') { - return fnStr.replace('{', '{\nvar uni = wx;\n') - } - return fnStr.replace('=>', '=>{\nvar uni = wx;\nreturn ') + '}' -} -const puppet = { - devtools: { - name: 'Wechat web devTools', - remote: true, - automator: true, - paths: [ - isWindows - ? 'C:/Program Files (x86)/Tencent/微信web开发者工具/cli.bat' - : '/Applications/wechatwebdevtools.app/Contents/MacOS/cli', - ], - required: ['project.config.json', 'app.json', 'app.js'], - defaultPort: 9420, - validate: validateDevtools, - async create(projectPath, options, puppet) { - const connection = await createDevtools(projectPath, options, puppet) - if (!puppet.compiled) { - debug('automator:devtool')('initRuntimeAutomator') - connection.send('App.callWxMethod', { - method: '$$initRuntimeAutomator', - args: [], - }) - } else { - debug('automator:devtool')('Waiting for runtime automator') - } - return connection - }, - }, - adapter: { - 'Tool.enableRemoteDebug': { - reflect: async (send, params) => { - let { qrCode } = await send('Tool.enableRemoteDebug', params, false) - qrCode && (qrCode = await decodeQrCode(qrCode)) - return { qrCode } - }, - }, - // "App.callUniMethod": { - // reflect: "App.callWxMethod", - // }, - 'App.callFunction': { - reflect: async (send, params) => { - return send( - 'App.callFunction', - Object.assign(Object.assign({}, params), { - functionDeclaration: wrapper(params.functionDeclaration), - }), - false - ) - }, - }, - 'Element.getHTML': { - reflect: async (send, params) => { - return { html: (await send('Element.getWXML', params, false)).wxml } - }, - }, - }, -} - -module.exports = puppet +"use strict";function e(e){return e&&"object"==typeof e&&"default"in e?e.default:e}var t=e(require("debug")),r=e(require("licia/isWindows"));require("address"),require("default-gateway"),require("licia/isStr");var o=e(require("licia/getPort")),n=e(require("fs")),s=e(require("child_process")),a=e(require("licia/sleep")),i=e(require("licia/toStr")),c=e(require("licia/waitUntil")),u=e(require("licia/concat")),l=e(require("licia/dateFormat")),d=e(require("ws")),p=require("events"),m=e(require("licia/uuid")),h=e(require("licia/stringify"));require("qrcode-terminal");const w=require("qrcode-reader");/^win/.test(process.platform);class f extends p.EventEmitter{constructor(e){super(),this.ws=e,this.ws.addEventListener("message",e=>{this.emit("message",e.data)}),this.ws.addEventListener("close",()=>{this.emit("close")})}send(e){this.ws.send(e)}close(){this.ws.close()}}class y extends p.EventEmitter{constructor(e,r,o){super(),this.puppet=r,this.namespace=o,this.callbacks=new Map,this.transport=e,this.debug=t("automator:protocol:"+this.namespace),this.onMessage=e=>{this.debug(`${l("yyyy-mm-dd HH:MM:ss:l")} ◀ RECV ${e}`);const{id:t,method:r,error:o,result:n,params:s}=JSON.parse(e);if(!t)return this.puppet.emit(r,s);const{callbacks:a}=this;if(t&&a.has(t)){const e=a.get(t);a.delete(t),o?e.reject(Error(o.message)):e.resolve(n)}},this.onClose=()=>{this.callbacks.forEach(e=>{e.reject(Error("Connection closed"))})},this.transport.on("message",this.onMessage),this.transport.on("close",this.onClose)}send(e,t={},r=!0){if(r&&this.puppet.adapter.has(e))return this.puppet.adapter.send(this,e,t);const o=m(),n=h({id:o,method:e,params:t});return this.debug(`${l("yyyy-mm-dd HH:MM:ss:l")} SEND ► ${n}`),new Promise((e,t)=>{try{this.transport.send(n)}catch(e){t(Error("Connection closed"))}this.callbacks.set(o,{resolve:e,reject:t})})}dispose(){this.transport.close()}static createDevtoolConnection(e,t){return new Promise((r,o)=>{const n=new d(e);n.addEventListener("open",()=>{r(new y(new f(n),t,"devtool"))}),n.addEventListener("error",o)})}static createRuntimeConnection(e,r,o){return new Promise((n,s)=>{t("automator:runtime")(`${l("yyyy-mm-dd HH:MM:ss:l")} port=${e}`);const a=new d.Server({port:e});c(async()=>{if(r.runtimeConnection)return!0},o,1e3).catch(()=>{a.close(),s("Failed to connect to runtime, please make sure the project is running")}),a.on("connection",(function(e){t("automator:runtime")(l("yyyy-mm-dd HH:MM:ss:l")+" connected");const o=new y(new f(e),r,"runtime");r.setRuntimeConnection(o),n(o)})),r.setRuntimeServer(a)})}}const g=t("automator:devtool");async function v(e,t,r){const{port:o,cliPath:n,timeout:d,cwd:p="",account:m="",args:h=[],launch:w=!0}=t;let f=!1,v=!1;if(!1!==w){const t={stdio:"ignore",detached:!0};p&&(t.cwd=p);let r=u(h,[]);r=u(r,["auto","--project"]),r=u(r,[e,"--auto-port",i(o)]),m&&(r=u(r,["--auto-account",m]));try{g("%s %o %o",n,r,t);const e=s.spawn(n,r,t);e.on("error",e=>{f=!0}),e.on("exit",()=>{setTimeout(()=>{v=!0},15e3)}),e.unref()}catch(e){f=!1}}else setTimeout(()=>{v=!0},15e3);const b=await c(async()=>{try{if(f||v)return!0;return await async function(e,t){let r;try{r=await y.createDevtoolConnection(e.wsEndpoint,t)}catch(t){throw Error(`Failed connecting to ${e.wsEndpoint}, check if target project window is opened with automation enabled`)}return r}({wsEndpoint:"ws://127.0.0.1:"+o},r)}catch(e){}},d,1e3);if(f)throw Error(`Failed to launch ${r.devtools.name}, please make sure cliPath is correctly specified`);if(v)throw Error(`Failed to launch ${r.devtools.name} , please make sure http port is open`);return await a(5e3),g(l("yyyy-mm-dd HH:MM:ss:l")+" connected"),b}const b={devtools:{name:"Wechat web devTools",remote:!0,automator:!0,paths:[r?"C:/Program Files (x86)/Tencent/微信web开发者工具/cli.bat":"/Applications/wechatwebdevtools.app/Contents/MacOS/cli"],required:["project.config.json","app.json","app.js"],defaultPort:9420,validate:async function(e,t){const r=function(e,t){const r=t.devtools.paths.slice(0);e&&r.unshift(e);for(const e of r)if(n.existsSync(e))return e;throw Error(t.devtools.name+" not found, please specify executablePath option")}(e.executablePath,t);let s=e.port||t.devtools.defaultPort;if(!1!==e.launch)try{s=await async function(e,t){const r=await o(e||t);if(e&&r!==e)throw Error(`Port ${e} is in use, please specify another port`);return r}(s)}catch(t){e.launch=!1}else{s===await o(s)&&(e.launch=!0)}return Object.assign(Object.assign({},e),{port:s,cliPath:r})},async create(e,r,o){const n=await v(e,r,o);return o.compiled?t("automator:devtool")("Waiting for runtime automator"):(t("automator:devtool")("initRuntimeAutomator"),n.send("App.callWxMethod",{method:"$$initRuntimeAutomator",args:[]})),n}},adapter:{"Tool.enableRemoteDebug":{reflect:async(e,t)=>{let{qrCode:r}=await e("Tool.enableRemoteDebug",t,!1);return r&&(r=await function(e){const t=new Buffer(e,"base64");return new Promise(async(e,r)=>{const o=await require("jimp").read(t),n=new w;n.callback=function(t,o){if(t)return r(t);e(o.result)},n.decode(o.bitmap)})}(r)),{qrCode:r}}},"App.callFunction":{reflect:async(e,t)=>{return e("App.callFunction",Object.assign(Object.assign({},t),{functionDeclaration:(r=t.functionDeclaration,"}"===r[r.length-1]?r.replace("{","{\nvar uni = wx;\n"):r.replace("=>","=>{\nvar uni = wx;\nreturn ")+"}")}),!1);var r}},"Element.getHTML":{reflect:async(e,t)=>({html:(await e("Element.getWXML",t,!1)).wxml})}}};module.exports=b; -- GitLab