提交 50e40624 编写于 作者: Q qiang

fix: 完善快手小程序编译配置

上级 2f18d68e
......@@ -134,7 +134,7 @@ function queue (hooks, data) {
for (let i = 0; i < hooks.length; i++) {
const hook = hooks[i];
if (promise) {
promise = Promise.then(wrapperHook(hook));
promise = Promise.resolve(wrapperHook(hook));
} else {
const res = hook(data);
if (isPromise(res)) {
......@@ -231,17 +231,23 @@ const promiseInterceptor = {
};
const SYNC_API_RE =
/^\$|restoreGlobal|getCurrentSubNVue|getMenuButtonBoundingClientRect|^report|interceptors|Interceptor$|getSubNVueById|requireNativePlugin|upx2px|hideKeyboard|canIUse|^create|Sync$|Manager$|base64ToArrayBuffer|arrayBufferToBase64/;
/^\$|sendNativeEvent|restoreGlobal|getCurrentSubNVue|getMenuButtonBoundingClientRect|^report|interceptors|Interceptor$|getSubNVueById|requireNativePlugin|upx2px|hideKeyboard|canIUse|^create|Sync$|Manager$|base64ToArrayBuffer|arrayBufferToBase64/;
const CONTEXT_API_RE = /^create|Manager$/;
const CALLBACK_API_RE = /^on/;
// Context例外情况
const CONTEXT_API_RE_EXC = ['createBLEConnection'];
// 同步例外情况
const ASYNC_API = ['createBLEConnection'];
const CALLBACK_API_RE = /^on|^off/;
function isContextApi (name) {
return CONTEXT_API_RE.test(name)
return CONTEXT_API_RE.test(name) && CONTEXT_API_RE_EXC.indexOf(name) === -1
}
function isSyncApi (name) {
return SYNC_API_RE.test(name)
return SYNC_API_RE.test(name) && ASYNC_API.indexOf(name) === -1
}
function isCallbackApi (name) {
......@@ -266,6 +272,19 @@ function shouldPromise (name) {
return true
}
/* eslint-disable no-extend-native */
if (!Promise.prototype.finally) {
Promise.prototype.finally = function (callback) {
const promise = this.constructor;
return this.then(
value => promise.resolve(callback()).then(() => value),
reason => promise.resolve(callback()).then(() => {
throw reason
})
)
};
}
function promisify (name, api) {
if (!shouldPromise(name)) {
return api
......@@ -279,18 +298,6 @@ function promisify (name, api) {
success: resolve,
fail: reject
}), ...params);
/* eslint-disable no-extend-native */
if (!Promise.prototype.finally) {
Promise.prototype.finally = function (callback) {
const promise = this.constructor;
return this.then(
value => promise.resolve(callback()).then(() => value),
reason => promise.resolve(callback()).then(() => {
throw reason
})
)
};
}
})))
}
}
......@@ -322,18 +329,18 @@ function upx2px (number, newDeviceWidth) {
if (number === 0) {
return 0
}
let result = (number / BASE_DEVICE_WIDTH) * (newDeviceWidth || deviceWidth);
if (result < 0) {
result = -result;
}
result = Math.floor(result + EPS);
if (result === 0) {
if (deviceDPR === 1 || !isIOS) {
return 1
} else {
return 0.5
}
}
let result = (number / BASE_DEVICE_WIDTH) * (newDeviceWidth || deviceWidth);
if (result < 0) {
result = -result;
}
result = Math.floor(result + EPS);
if (result === 0) {
if (deviceDPR === 1 || !isIOS) {
result = 1;
} else {
result = 0.5;
}
}
return number < 0 ? -result : result
}
......@@ -341,14 +348,12 @@ const interceptors = {
promiseInterceptor
};
var baseApi = /*#__PURE__*/Object.freeze({
__proto__: null,
upx2px: upx2px,
interceptors: interceptors,
addInterceptor: addInterceptor,
removeInterceptor: removeInterceptor
removeInterceptor: removeInterceptor,
interceptors: interceptors
});
var previewImage = {
......@@ -407,7 +412,7 @@ function processArgs (methodName, fromArgs, argsOption = {}, returnValue = {}, k
if (isFn(argsOption)) {
argsOption = argsOption(fromArgs, toArgs) || {};
}
for (let key in fromArgs) {
for (const key in fromArgs) {
if (hasOwn(argsOption, key)) {
let keyOption = argsOption[key];
if (isFn(keyOption)) {
......@@ -421,7 +426,9 @@ function processArgs (methodName, fromArgs, argsOption = {}, returnValue = {}, k
toArgs[keyOption.name ? keyOption.name : key] = keyOption.value;
}
} else if (CALLBACKS.indexOf(key) !== -1) {
toArgs[key] = processCallback(methodName, fromArgs[key], returnValue);
if (isFn(fromArgs[key])) {
toArgs[key] = processCallback(methodName, fromArgs[key], returnValue);
}
} else {
if (!keepFromArgs) {
toArgs[key] = fromArgs[key];
......@@ -536,10 +543,6 @@ var extraApi = /*#__PURE__*/Object.freeze({
});
const getEmitter = (function () {
if (typeof getUniEmitter === 'function') {
/* eslint-disable no-undef */
return getUniEmitter
}
let Emitter;
return function getUniEmitter () {
if (!Emitter) {
......@@ -574,8 +577,6 @@ var eventApi = /*#__PURE__*/Object.freeze({
$emit: $emit
});
var api = /*#__PURE__*/Object.freeze({
__proto__: null
});
......@@ -623,6 +624,8 @@ Component = function (options = {}) {
const PAGE_EVENT_HOOKS = [
'onPullDownRefresh',
'onReachBottom',
'onAddToFavorites',
'onShareTimeline',
'onShareAppMessage',
'onPageScroll',
'onResize',
......@@ -685,10 +688,10 @@ function initVueComponent (Vue, vueOptions) {
let VueComponent;
if (isFn(vueOptions)) {
VueComponent = vueOptions;
vueOptions = VueComponent.extendOptions;
} else {
VueComponent = Vue.extend(vueOptions);
}
vueOptions = VueComponent.options;
return [VueComponent, vueOptions]
}
......@@ -757,14 +760,14 @@ function createObserver (name) {
}
function initBehaviors (vueOptions, initBehavior) {
const vueBehaviors = vueOptions['behaviors'];
const vueExtends = vueOptions['extends'];
const vueMixins = vueOptions['mixins'];
const vueBehaviors = vueOptions.behaviors;
const vueExtends = vueOptions.extends;
const vueMixins = vueOptions.mixins;
let vueProps = vueOptions['props'];
let vueProps = vueOptions.props;
if (!vueProps) {
vueOptions['props'] = vueProps = [];
vueOptions.props = vueProps = [];
}
const behaviors = [];
......@@ -776,11 +779,11 @@ function initBehaviors (vueOptions, initBehavior) {
vueProps.push('name');
vueProps.push('value');
} else {
vueProps['name'] = {
vueProps.name = {
type: String,
default: ''
};
vueProps['value'] = {
vueProps.value = {
type: [String, Number, Boolean, Array, Object, Date],
default: ''
};
......@@ -824,6 +827,11 @@ function initProperties (props, isBehavior = false, file = '') {
type: String,
value: ''
};
// 用于字节跳动小程序模拟抽象节点
properties.generic = {
type: Object,
value: null
};
properties.vueSlots = { // 小程序不能直接定义 $slots 的 props,所以通过 vueSlots 转换到 $slots
type: null,
value: [],
......@@ -849,7 +857,7 @@ function initProperties (props, isBehavior = false, file = '') {
Object.keys(props).forEach(key => {
const opts = props[key];
if (isPlainObject(opts)) { // title:{type:String,default:''}
let value = opts['default'];
let value = opts.default;
if (isFn(value)) {
value = value();
}
......@@ -888,6 +896,11 @@ function wrapper$1 (event) {
event.detail = {};
}
if (hasOwn(event, 'markerId')) {
event.detail = typeof event.detail === 'object' ? event.detail : {};
event.detail.markerId = event.markerId;
}
if (isPlainObject(event.detail)) {
event.target = Object.assign({}, event.target, event.detail);
}
......@@ -904,7 +917,18 @@ function getExtraValue (vm, dataPathsArray) {
const propPath = dataPathArray[1];
const valuePath = dataPathArray[3];
const vFor = dataPath ? vm.__get_value(dataPath, context) : context;
let vFor;
if (Number.isInteger(dataPath)) {
vFor = dataPath;
} else if (!dataPath) {
vFor = context;
} else if (typeof dataPath === 'string' && dataPath) {
if (dataPath.indexOf('#s#') === 0) {
vFor = dataPath.substr(3);
} else {
vFor = vm.__get_value(dataPath, context);
}
}
if (Number.isInteger(vFor)) {
context = value;
......@@ -954,6 +978,12 @@ function processEventExtra (vm, extra, event) {
} else {
if (dataPath === '$event') { // $event
extraObj['$' + index] = event;
} else if (dataPath === 'arguments') {
if (event.detail && event.detail.__args__) {
extraObj['$' + index] = event.detail.__args__;
} else {
extraObj['$' + index] = [event];
}
} else if (dataPath.indexOf('$event.') === 0) { // $event.target.value
extraObj['$' + index] = vm.__get_value(dataPath.replace('$event.', ''), event);
} else {
......@@ -1034,17 +1064,26 @@ function isMatchEventType (eventType, optType) {
)
}
function getContextVm (vm) {
let $parent = vm.$parent;
// 父组件是 scoped slots 或者其他自定义组件时继续查找
while ($parent && $parent.$parent && ($parent.$options.generic || $parent.$parent.$options.generic || $parent.$scope._$vuePid)) {
$parent = $parent.$parent;
}
return $parent && $parent.$parent
}
function handleEvent (event) {
event = wrapper$1(event);
// [['tap',[['handle',[1,2,a]],['handle1',[1,2,a]]]]]
const dataset = (event.currentTarget || event.target).dataset;
if (!dataset) {
return console.warn(`事件信息不存在`)
return console.warn('事件信息不存在')
}
const eventOpts = dataset.eventOpts || dataset['event-opts']; // 支付宝 web-view 组件 dataset 非驼峰
if (!eventOpts) {
return console.warn(`事件信息不存在`)
return console.warn('事件信息不存在')
}
// [['handle',[1,2,a]],['handle1',[1,2,a]]]
......@@ -1066,24 +1105,20 @@ function handleEvent (event) {
const methodName = eventArray[0];
if (methodName) {
let handlerCtx = this.$vm;
if (
handlerCtx.$options.generic &&
handlerCtx.$parent &&
handlerCtx.$parent.$parent
) { // mp-weixin,mp-toutiao 抽象节点模拟 scoped slots
handlerCtx = handlerCtx.$parent.$parent;
}
if (methodName === '$emit') {
handlerCtx.$emit.apply(handlerCtx,
processEventArgs(
this.$vm,
event,
eventArray[1],
eventArray[2],
isCustom,
methodName
));
return
if (handlerCtx.$options.generic) { // mp-weixin,mp-toutiao 抽象节点模拟 scoped slots
handlerCtx = getContextVm(handlerCtx) || handlerCtx;
}
if (methodName === '$emit') {
handlerCtx.$emit.apply(handlerCtx,
processEventArgs(
this.$vm,
event,
eventArray[1],
eventArray[2],
isCustom,
methodName
));
return
}
const handler = handlerCtx[methodName];
if (!isFn(handler)) {
......@@ -1095,14 +1130,17 @@ function handleEvent (event) {
}
handler.once = true;
}
ret.push(handler.apply(handlerCtx, processEventArgs(
const params = processEventArgs(
this.$vm,
event,
eventArray[1],
eventArray[2],
isCustom,
methodName
)));
) || [];
// 参数尾部增加原始事件对象用于复杂表达式内获取额外数据
// eslint-disable-next-line no-sparse-arrays
ret.push(handler.apply(handlerCtx, params.concat([, , , , , , , , , , event])));
}
});
}
......@@ -1286,7 +1324,7 @@ function parseBaseComponent (vueComponentOptions, {
isPage,
initRelation
} = {}) {
let [VueComponent, vueOptions] = initVueComponent(Vue, vueComponentOptions);
const [VueComponent, vueOptions] = initVueComponent(Vue, vueComponentOptions);
const options = {
multipleSlots: true,
......@@ -1436,7 +1474,7 @@ let uni = {};
if (typeof Proxy !== 'undefined' && "mp-kuaishou" !== 'app-plus') {
uni = new Proxy({}, {
get (target, name) {
if (target[name]) {
if (hasOwn(target, name)) {
return target[name]
}
if (baseApi[name]) {
......@@ -1462,7 +1500,7 @@ if (typeof Proxy !== 'undefined' && "mp-kuaishou" !== 'app-plus') {
return promisify(name, wrapper(name, ks[name]))
},
set (target, name, value) {
target[name] = value;
target[name] = value;
return true
}
});
......
const compiler = require('@dcloudio/uni-mp-weixin/lib/uni.compiler.js')
module.exports = Object.assign({}, compiler, {
directive: 'ks:'
})
module.exports = {
options: {
cssVars: {
'--status-bar-height': '25px',
'--window-top': '0px',
'--window-bottom': '0px'
},
extnames: {
style: '.css',
template: '.ksml'
},
project: 'project.ks.json'
},
copyWebpackOptions (platformOptions, vueOptions) {
return ['kscomponents']
}
}
......@@ -23,14 +23,14 @@ describe('mp:compiler-mp-kuaishou', () => {
it('generate scoped slot', () => {
assertCodegen(
'<foo><template slot-scope="{bar}">{{ bar.foo }}</template></foo>',
'<foo generic:scoped-slots-default="test-foo-default" vue-id="1" bind:__l="__l" vue-slots="{{[\'default\']}}"></foo>',
'<foo generic:scoped-slots-default="test-foo-default" vue-id="551070e6-1" bind:__l="__l" vue-slots="{{[\'default\']}}"></foo>',
function (res) {
expect(res.generic[0]).toBe('test-foo-default')
}
)
assertCodegen(
'<foo><view slot-scope="{bar}">{{ bar.foo }}</view></foo>',
'<foo generic:scoped-slots-default="test-foo-default" vue-id="1" bind:__l="__l" vue-slots="{{[\'default\']}}"></foo>',
'<foo generic:scoped-slots-default="test-foo-default" vue-id="551070e6-1" bind:__l="__l" vue-slots="{{[\'default\']}}"></foo>',
function (res) {
expect(res.generic[0]).toBe('test-foo-default')
}
......@@ -40,14 +40,14 @@ describe('mp:compiler-mp-kuaishou', () => {
it('generate named scoped slot', () => {
assertCodegen(
'<foo><template slot="foo" slot-scope="{bar}">{{ bar.foo }}</template></foo>',
'<foo generic:scoped-slots-foo="test-foo-foo" vue-id="1" bind:__l="__l" vue-slots="{{[\'foo\']}}"></foo>',
'<foo generic:scoped-slots-foo="test-foo-foo" vue-id="551070e6-1" bind:__l="__l" vue-slots="{{[\'foo\']}}"></foo>',
function (res) {
expect(res.generic[0]).toBe('test-foo-foo')
}
)
assertCodegen(
'<foo><view slot="foo" slot-scope="{bar}">{{ bar.foo }}</view></foo>',
'<foo generic:scoped-slots-foo="test-foo-foo" vue-id="1" bind:__l="__l" vue-slots="{{[\'foo\']}}"></foo>',
'<foo generic:scoped-slots-foo="test-foo-foo" vue-id="551070e6-1" bind:__l="__l" vue-slots="{{[\'foo\']}}"></foo>',
function (res) {
expect(res.generic[0]).toBe('test-foo-foo')
}
......@@ -57,14 +57,14 @@ describe('mp:compiler-mp-kuaishou', () => {
it('generate scoped slot with multiline v-if', () => {
assertCodegen(
'<foo><template v-if="\nshow\n" slot-scope="{bar}">{{ bar.foo }}</template></foo>',
'<foo generic:scoped-slots-default="test-foo-default" vue-id="1" bind:__l="__l" vue-slots="{{[\'default\']}}"></foo>',
'<foo generic:scoped-slots-default="test-foo-default" vue-id="551070e6-1" bind:__l="__l" vue-slots="{{[\'default\']}}"></foo>',
function (res) {
expect(res.generic[0]).toBe('test-foo-default')
}
)
assertCodegen(
'<foo><view v-if="\nshow\n" slot="foo" slot-scope="{bar}">{{ bar.foo }}</view></foo>',
'<foo generic:scoped-slots-foo="test-foo-foo" vue-id="1" bind:__l="__l" vue-slots="{{[\'foo\']}}"></foo>',
'<foo generic:scoped-slots-foo="test-foo-foo" vue-id="551070e6-1" bind:__l="__l" vue-slots="{{[\'foo\']}}"></foo>',
function (res) {
expect(res.generic[0]).toBe('test-foo-foo')
}
......@@ -74,14 +74,14 @@ describe('mp:compiler-mp-kuaishou', () => {
it('generate scoped slot', () => {
assertCodegen(// TODO vue-id
'<span><slot v-bind:user="user">{{ user.lastName }}</slot></span>',
'<label class="_span"><block wx:if="{{$slots.default}}"><scoped-slots-default user="{{user}}" bind:__l="__l"></scoped-slots-default></block><block wx:else>{{user.lastName}}</block></label>',
'<label class="_span"><block ks:if="{{$slots.default}}"><slot></slot><scoped-slots-default user="{{user}}" bind:__l="__l"></scoped-slots-default></block><block ks:else>{{user.lastName}}</block></label>',
function (res) {
expect(res.componentGenerics['scoped-slots-default']).toBe(true)
}
)
assertCodegen(
'<span><slot name="header" v-bind:user="user">{{ user.lastName }}</slot></span>',
'<label class="_span"><block wx:if="{{$slots.header}}"><scoped-slots-header user="{{user}}" bind:__l="__l"></scoped-slots-header></block><block wx:else>{{user.lastName}}</block></label>',
'<label class="_span"><block ks:if="{{$slots.header}}"><slot name="header"></slot><scoped-slots-header user="{{user}}" bind:__l="__l"></scoped-slots-header></block><block ks:else>{{user.lastName}}</block></label>',
function (res) {
expect(res.componentGenerics['scoped-slots-header']).toBe(true)
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册